summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/.cvsignore8
-rw-r--r--src/.gitignore7
-rw-r--r--src/CMakeLists.txt221
-rw-r--r--src/ability_type.hpp47
-rw-r--r--src/activation.hpp13
-rw-r--r--src/alloc.hpp29
-rw-r--r--src/alloc_entry.hpp20
-rw-r--r--src/alloc_entry_fwd.hpp3
-rw-r--r--src/angband.h20
-rw-r--r--src/angband.rc21
-rw-r--r--src/artifact_type.hpp50
-rw-r--r--src/between_exit.hpp18
-rw-r--r--src/birth.cc (renamed from src/birth.c)2047
-rw-r--r--src/birth.hpp11
-rw-r--r--src/birther.hpp29
-rw-r--r--src/bldg.cc (renamed from src/bldg.c)1131
-rw-r--r--src/bldg.hpp10
-rw-r--r--src/body.hpp12
-rw-r--r--src/carbon/Angband.icnsbin66668 -> 0 bytes
-rw-r--r--src/carbon/Carbon.r1568
-rw-r--r--src/carbon/Data.icnsbin36416 -> 0 bytes
-rw-r--r--src/carbon/Edit.icnsbin35735 -> 0 bytes
-rw-r--r--src/carbon/Image-DS_Storebin6148 -> 0 bytes
-rw-r--r--src/carbon/Info.plist39
-rw-r--r--src/carbon/Save.icnsbin43952 -> 0 bytes
-rwxr-xr-xsrc/carbon/getversion2
-rw-r--r--src/cave.cc (renamed from src/cave.c)1599
-rw-r--r--src/cave.hpp57
-rw-r--r--src/cave_type.hpp63
-rw-r--r--src/cave_type_fwd.hpp3
-rw-r--r--src/cli_comm.hpp13
-rw-r--r--src/cli_comm_fwd.hpp3
-rw-r--r--src/cmd1.cc (renamed from src/cmd1.c)1500
-rw-r--r--src/cmd1.hpp25
-rw-r--r--src/cmd2.cc (renamed from src/cmd2.c)1757
-rw-r--r--src/cmd2.hpp32
-rw-r--r--src/cmd3.cc (renamed from src/cmd3.c)1088
-rw-r--r--src/cmd3.hpp23
-rw-r--r--src/cmd4.cc (renamed from src/cmd4.c)1816
-rw-r--r--src/cmd4.hpp28
-rw-r--r--src/cmd5.cc (renamed from src/cmd5.c)1885
-rw-r--r--src/cmd5.hpp23
-rw-r--r--src/cmd6.cc (renamed from src/cmd6.c)5640
-rw-r--r--src/cmd6.hpp18
-rw-r--r--src/cmd7.c7652
-rw-r--r--src/cmd7.cc3314
-rw-r--r--src/cmd7.hpp25
-rw-r--r--src/cmovie.c496
-rw-r--r--src/config.h185
-rw-r--r--src/corrupt.cc998
-rw-r--r--src/corrupt.hpp49
-rw-r--r--src/defines.h2403
-rw-r--r--src/deity_type.hpp11
-rw-r--r--src/deity_type_fwd.hpp3
-rw-r--r--src/device_allocation.cc20
-rw-r--r--src/device_allocation.hpp17
-rw-r--r--src/device_allocation_fwd.hpp8
-rw-r--r--src/dice.cc98
-rw-r--r--src/dice.hpp13
-rw-r--r--src/dice_fwd.hpp12
-rw-r--r--src/dungeon.cc (renamed from src/dungeon.c)1800
-rw-r--r--src/dungeon.h12
-rw-r--r--src/dungeon.hpp6
-rw-r--r--src/dungeon.pkg1607
-rw-r--r--src/dungeon_flag.hpp12
-rw-r--r--src/dungeon_flag_list.hpp55
-rw-r--r--src/dungeon_flag_set.hpp7
-rw-r--r--src/dungeon_info_type.hpp78
-rw-r--r--src/dungeon_info_type_fwd.hpp3
-rw-r--r--src/effect_type.hpp17
-rw-r--r--src/ego_flag.hpp12
-rw-r--r--src/ego_flag_list.hpp38
-rw-r--r--src/ego_flag_set.hpp7
-rw-r--r--src/ego_item_type.hpp62
-rw-r--r--src/externs.h1851
-rw-r--r--src/fate.hpp22
-rw-r--r--src/feature_flag.hpp12
-rw-r--r--src/feature_flag_list.hpp25
-rw-r--r--src/feature_flag_set.hpp7
-rw-r--r--src/feature_type.hpp34
-rw-r--r--src/files.cc (renamed from src/files.c)3135
-rw-r--r--src/files.h15
-rw-r--r--src/files.hpp33
-rw-r--r--src/flag_set.hpp201
-rw-r--r--src/flags_group.hpp17
-rw-r--r--src/game.cc3
-rw-r--r--src/game.hpp97
-rw-r--r--src/game_edit_data.hpp138
-rw-r--r--src/game_edit_data_fwd.hpp3
-rw-r--r--src/game_fwd.hpp4
-rw-r--r--src/gen_evol.cc (renamed from src/gen_evol.c)36
-rw-r--r--src/gen_evol.hpp6
-rw-r--r--src/gen_maze.cc (renamed from src/gen_maze.c)24
-rw-r--r--src/gen_maze.hpp5
-rw-r--r--src/generate.cc (renamed from src/generate.c)1987
-rw-r--r--src/generate.hpp12
-rw-r--r--src/gf_name_type.hpp10
-rw-r--r--src/gods.cc (renamed from src/gods.c)110
-rw-r--r--src/gods.hpp13
-rw-r--r--src/grid.hpp72
-rw-r--r--src/h-basic.h10
-rw-r--r--src/h-config.h208
-rw-r--r--src/h-define.h19
-rw-r--r--src/h-system.h56
-rw-r--r--src/h-type.h23
-rw-r--r--src/help.c23
-rw-r--r--src/help.cc705
-rw-r--r--src/help.hpp13
-rw-r--r--src/help_info.hpp17
-rw-r--r--src/hiscore.cc85
-rw-r--r--src/hiscore.hpp82
-rw-r--r--src/hook_build_room1_in.hpp8
-rw-r--r--src/hook_calculate_hp_in.hpp7
-rw-r--r--src/hook_calculate_hp_out.hpp7
-rw-r--r--src/hook_chardump_in.hpp7
-rw-r--r--src/hook_chat_in.hpp7
-rw-r--r--src/hook_drop_in.hpp5
-rw-r--r--src/hook_eat_in.hpp7
-rw-r--r--src/hook_eat_out.hpp7
-rw-r--r--src/hook_enter_dungeon_in.hpp7
-rw-r--r--src/hook_get_in.hpp8
-rw-r--r--src/hook_give_in.hpp6
-rw-r--r--src/hook_identify_in.hpp9
-rw-r--r--src/hook_init_quest_in.hpp5
-rw-r--r--src/hook_mon_speak_in.hpp8
-rw-r--r--src/hook_monster_ai_in.hpp9
-rw-r--r--src/hook_monster_ai_out.hpp8
-rw-r--r--src/hook_monster_death_in.hpp7
-rw-r--r--src/hook_move_in.hpp6
-rw-r--r--src/hook_new_monster_end_in.hpp7
-rw-r--r--src/hook_new_monster_in.hpp7
-rw-r--r--src/hook_player_level_in.hpp5
-rw-r--r--src/hook_quest_fail_in.hpp7
-rw-r--r--src/hook_quest_finish_in.hpp7
-rw-r--r--src/hook_stair_in.hpp7
-rw-r--r--src/hook_stair_out.hpp7
-rw-r--r--src/hook_wield_in.hpp7
-rw-r--r--src/hook_wild_gen_in.hpp7
-rw-r--r--src/hooks.cc113
-rw-r--r--src/hooks.hpp10
-rw-r--r--src/identify_mode.hpp3
-rw-r--r--src/include/tome/enum_string_map.hpp55
-rw-r--r--src/include/tome/make_array.hpp13
-rw-r--r--src/include/tome/pp/global_constexpr.hpp21
-rw-r--r--src/include/tome/squelch/automatizer.hpp154
-rw-r--r--src/include/tome/squelch/automatizer_fwd.hpp10
-rw-r--r--src/include/tome/squelch/condition.hpp632
-rw-r--r--src/include/tome/squelch/condition_fwd.hpp15
-rw-r--r--src/include/tome/squelch/condition_metadata.hpp12
-rw-r--r--src/include/tome/squelch/condition_metadata_fwd.hpp14
-rw-r--r--src/include/tome/squelch/cursor.hpp50
-rw-r--r--src/include/tome/squelch/cursor_fwd.hpp10
-rw-r--r--src/include/tome/squelch/object_status.hpp28
-rw-r--r--src/include/tome/squelch/object_status_fwd.hpp12
-rw-r--r--src/include/tome/squelch/rule.hpp162
-rw-r--r--src/include/tome/squelch/rule_fwd.hpp16
-rw-r--r--src/include/tome/squelch/tree_printer.hpp51
-rw-r--r--src/include/tome/squelch/tree_printer_fwd.hpp10
-rw-r--r--src/init1.c11819
-rw-r--r--src/init1.cc6941
-rw-r--r--src/init1.hpp27
-rw-r--r--src/init2.c2918
-rw-r--r--src/init2.cc1278
-rw-r--r--src/init2.h13
-rw-r--r--src/init2.hpp9
-rw-r--r--src/inscription_info_type.hpp13
-rw-r--r--src/inventory.hpp35
-rw-r--r--src/iso/.cvsignore1
-rw-r--r--src/joke.cc40
-rw-r--r--src/joke.hpp5
-rw-r--r--src/lauxlib.h100
-rw-r--r--src/level_marker.cc12
-rw-r--r--src/level_marker.hpp25
-rw-r--r--src/levels.cc (renamed from src/levels.c)40
-rw-r--r--src/levels.hpp13
-rw-r--r--src/loadsave.c3288
-rw-r--r--src/loadsave.cc2630
-rw-r--r--src/loadsave.h15
-rw-r--r--src/loadsave.hpp6
-rw-r--r--src/lua/.cvsignore2
-rw-r--r--src/lua/.gitignore2
-rw-r--r--src/lua/CMakeLists.txt11
-rw-r--r--src/lua/array.lua203
-rw-r--r--src/lua/basic.lua190
-rw-r--r--src/lua/class.lua85
-rw-r--r--src/lua/clean.lua74
-rw-r--r--src/lua/code.lua73
-rw-r--r--src/lua/container.lua311
-rw-r--r--src/lua/declaration.lua399
-rw-r--r--src/lua/define.lua72
-rw-r--r--src/lua/doit.lua73
-rw-r--r--src/lua/enumerate.lua93
-rw-r--r--src/lua/feature.lua72
-rw-r--r--src/lua/function.lua317
-rw-r--r--src/lua/lapi.c499
-rw-r--r--src/lua/lapi.h17
-rw-r--r--src/lua/lauxlib.c216
-rw-r--r--src/lua/lauxlib.h100
-rw-r--r--src/lua/lbaselib.c651
-rw-r--r--src/lua/lcode.c701
-rw-r--r--src/lua/lcode.h70
-rw-r--r--src/lua/ldblib.c188
-rw-r--r--src/lua/ldebug.c466
-rw-r--r--src/lua/ldebug.h21
-rw-r--r--src/lua/ldo.c385
-rw-r--r--src/lua/ldo.h33
-rw-r--r--src/lua/lfunc.c109
-rw-r--r--src/lua/lfunc.h24
-rw-r--r--src/lua/lgc.c353
-rw-r--r--src/lua/lgc.h18
-rw-r--r--src/lua/liolib.c710
-rw-r--r--src/lua/llex.c411
-rw-r--r--src/lua/llex.h72
-rw-r--r--src/lua/llimits.h204
-rw-r--r--src/lua/lmem.c150
-rw-r--r--src/lua/lmem.h42
-rw-r--r--src/lua/lobject.c125
-rw-r--r--src/lua/lobject.h204
-rw-r--r--src/lua/lopcodes.h168
-rw-r--r--src/lua/lparser.c1129
-rw-r--r--src/lua/lparser.h60
-rw-r--r--src/lua/lstate.c121
-rw-r--r--src/lua/lstate.h77
-rw-r--r--src/lua/lstring.c155
-rw-r--r--src/lua/lstring.h37
-rw-r--r--src/lua/lstrlib.c621
-rw-r--r--src/lua/ltable.c303
-rw-r--r--src/lua/ltable.h34
-rw-r--r--src/lua/ltests.c543
-rw-r--r--src/lua/ltm.c163
-rw-r--r--src/lua/ltm.h59
-rw-r--r--src/lua/lua.h248
-rw-r--r--src/lua/lua2c.lua29
-rw-r--r--src/lua/luadebug.h46
-rw-r--r--src/lua/lualib.h34
-rw-r--r--src/lua/lundump.c244
-rw-r--r--src/lua/lundump.h35
-rw-r--r--src/lua/lvm.c710
-rw-r--r--src/lua/lvm.h32
-rw-r--r--src/lua/lzio.c84
-rw-r--r--src/lua/lzio.h53
-rw-r--r--src/lua/module.lua69
-rw-r--r--src/lua/operator.lua111
-rw-r--r--src/lua/package.lua222
-rw-r--r--src/lua/print.h55
-rw-r--r--src/lua/tolua.c149
-rw-r--r--src/lua/tolua.h127
-rw-r--r--src/lua/tolua_bd.c214
-rw-r--r--src/lua/tolua_eh.c66
-rw-r--r--src/lua/tolua_eh.h24
-rw-r--r--src/lua/tolua_gp.c197
-rw-r--r--src/lua/tolua_lb.c160
-rw-r--r--src/lua/tolua_rg.c243
-rw-r--r--src/lua/tolua_rg.h22
-rw-r--r--src/lua/tolua_tm.c585
-rw-r--r--src/lua/tolua_tm.h32
-rw-r--r--src/lua/tolua_tt.c316
-rw-r--r--src/lua/tolua_tt.h31
-rw-r--r--src/lua/tolualua.c2975
-rw-r--r--src/lua/tolualua.h2713
-rw-r--r--src/lua/tolualua.pkg21
-rw-r--r--src/lua/typedef.lua59
-rw-r--r--src/lua/variable.lua192
-rw-r--r--src/lua/verbatim.lua77
-rw-r--r--src/lua_bind.c691
-rw-r--r--src/lua_bind.cc265
-rw-r--r--src/lua_bind.hpp32
-rw-r--r--src/magic_power.hpp15
-rwxr-xr-xsrc/maid-x11.c855
-rw-r--r--src/main-crb.c6402
-rw-r--r--src/main-gcu.c235
-rw-r--r--src/main-gtk2.c3101
-rw-r--r--src/main-sdl.c238
-rw-r--r--src/main-sla.c455
-rw-r--r--src/main-win.c1096
-rw-r--r--src/main-x11.c851
-rw-r--r--src/main-xaw.c1888
-rw-r--r--src/main-xxx.c785
-rw-r--r--src/main.c691
-rw-r--r--src/main.cc270
-rw-r--r--src/main.h11
-rw-r--r--src/martial_arts.hpp18
-rw-r--r--src/melee1.cc (renamed from src/melee1.c)590
-rw-r--r--src/melee1.hpp7
-rw-r--r--src/melee2.cc (renamed from src/melee2.c)3894
-rw-r--r--src/melee2.hpp12
-rw-r--r--src/message.cc15
-rw-r--r--src/message.hpp31
-rw-r--r--src/messages.cc53
-rw-r--r--src/messages.hpp56
-rw-r--r--src/mimic.cc725
-rw-r--r--src/mimic.hpp10
-rw-r--r--src/module_type.hpp61
-rw-r--r--src/modules.c274
-rw-r--r--src/modules.cc1272
-rw-r--r--src/modules.hpp14
-rw-r--r--src/monoid.hpp37
-rw-r--r--src/monster.pkg2324
-rw-r--r--src/monster1.c1908
-rw-r--r--src/monster1.cc1671
-rw-r--r--src/monster1.hpp5
-rw-r--r--src/monster2.cc (renamed from src/monster2.c)1354
-rw-r--r--src/monster2.hpp50
-rw-r--r--src/monster3.cc (renamed from src/monster3.c)179
-rw-r--r--src/monster3.hpp20
-rw-r--r--src/monster_blow.hpp19
-rw-r--r--src/monster_ego.hpp69
-rw-r--r--src/monster_power.hpp16
-rw-r--r--src/monster_power_fwd.hpp3
-rw-r--r--src/monster_race.hpp84
-rw-r--r--src/monster_race_flag.hpp12
-rw-r--r--src/monster_race_flag_list.hpp152
-rw-r--r--src/monster_race_flag_set.hpp7
-rw-r--r--src/monster_race_fwd.hpp3
-rw-r--r--src/monster_spell.cc36
-rw-r--r--src/monster_spell.hpp91
-rw-r--r--src/monster_spell_flag.hpp20
-rw-r--r--src/monster_spell_flag_list.hpp101
-rw-r--r--src/monster_spell_flag_set.hpp7
-rw-r--r--src/monster_type.cc8
-rw-r--r--src/monster_type.hpp94
-rw-r--r--src/monster_type_fwd.hpp3
-rw-r--r--src/move_info_type.hpp15
-rw-r--r--src/music.hpp17
-rw-r--r--src/notes.cc (renamed from src/notes.c)59
-rw-r--r--src/notes.hpp6
-rw-r--r--src/obj_theme.hpp52
-rw-r--r--src/obj_theme_fwd.hpp3
-rw-r--r--src/object.pkg1169
-rw-r--r--src/object1.cc (renamed from src/object1.c)3463
-rw-r--r--src/object1.hpp49
-rw-r--r--src/object2.cc (renamed from src/object2.c)2162
-rw-r--r--src/object2.hpp69
-rw-r--r--src/object_filter.cc75
-rw-r--r--src/object_filter.hpp90
-rw-r--r--src/object_flag.hpp12
-rw-r--r--src/object_flag_list.hpp185
-rw-r--r--src/object_flag_meta.cc59
-rw-r--r--src/object_flag_meta.hpp75
-rw-r--r--src/object_flag_set.hpp7
-rw-r--r--src/object_kind.hpp73
-rw-r--r--src/object_proto.hpp12
-rw-r--r--src/object_type.hpp96
-rw-r--r--src/object_type_fwd.hpp3
-rw-r--r--src/option_type.hpp34
-rw-r--r--src/options.cc10
-rw-r--r--src/options.hpp215
-rw-r--r--src/owner_type.hpp41
-rw-r--r--src/player.pkg3519
-rw-r--r--src/player_c.pkg1060
-rw-r--r--src/player_class.hpp49
-rw-r--r--src/player_class_fwd.hpp3
-rw-r--r--src/player_defs.hpp6
-rw-r--r--src/player_level_flag.hpp13
-rw-r--r--src/player_race.hpp46
-rw-r--r--src/player_race_ability_type.hpp9
-rw-r--r--src/player_race_flag.hpp12
-rw-r--r--src/player_race_flag_list.hpp26
-rw-r--r--src/player_race_flag_set.hpp7
-rw-r--r--src/player_race_fwd.hpp3
-rw-r--r--src/player_race_mod.hpp52
-rw-r--r--src/player_race_mod_fwd.hpp3
-rw-r--r--src/player_shared.hpp16
-rw-r--r--src/player_spec.hpp29
-rw-r--r--src/player_spec_fwd.hpp3
-rw-r--r--src/player_type.cc28
-rw-r--r--src/player_type.hpp428
-rw-r--r--src/player_type_fwd.hpp3
-rw-r--r--src/plots.c473
-rw-r--r--src/plots.h48
-rw-r--r--src/point.hpp24
-rw-r--r--src/power_type.hpp19
-rw-r--r--src/powers.cc (renamed from src/powers.c)404
-rw-r--r--src/powers.hpp73
-rw-r--r--src/q_betwen.cc (renamed from src/q_betwen.c)132
-rw-r--r--src/q_betwen.hpp5
-rw-r--r--src/q_bounty.cc180
-rw-r--r--src/q_bounty.hpp10
-rw-r--r--src/q_dragons.cc (renamed from src/q_dragons.c)82
-rw-r--r--src/q_dragons.hpp5
-rw-r--r--src/q_eol.c195
-rw-r--r--src/q_eol.cc243
-rw-r--r--src/q_eol.hpp5
-rw-r--r--src/q_evil.cc (renamed from src/q_evil.c)81
-rw-r--r--src/q_evil.hpp5
-rw-r--r--src/q_fireprof.cc514
-rw-r--r--src/q_fireprof.hpp9
-rw-r--r--src/q_god.cc1234
-rw-r--r--src/q_god.hpp8
-rw-r--r--src/q_haunted.cc (renamed from src/q_haunted.c)107
-rw-r--r--src/q_haunted.hpp5
-rw-r--r--src/q_hobbit.c195
-rw-r--r--src/q_hobbit.cc241
-rw-r--r--src/q_hobbit.hpp5
-rw-r--r--src/q_invas.cc (renamed from src/q_invas.c)141
-rw-r--r--src/q_invas.hpp5
-rw-r--r--src/q_library.cc514
-rw-r--r--src/q_library.hpp10
-rw-r--r--src/q_main.c176
-rw-r--r--src/q_main.cc231
-rw-r--r--src/q_main.hpp7
-rw-r--r--src/q_narsil.c108
-rw-r--r--src/q_narsil.cc130
-rw-r--r--src/q_narsil.hpp5
-rw-r--r--src/q_nazgul.c116
-rw-r--r--src/q_nazgul.cc161
-rw-r--r--src/q_nazgul.hpp5
-rw-r--r--src/q_nirna.cc (renamed from src/q_nirna.c)79
-rw-r--r--src/q_nirna.hpp5
-rw-r--r--src/q_one.cc (renamed from src/q_one.c)276
-rw-r--r--src/q_one.hpp5
-rw-r--r--src/q_poison.c238
-rw-r--r--src/q_poison.cc339
-rw-r--r--src/q_poison.hpp5
-rw-r--r--src/q_rand.c465
-rw-r--r--src/q_rand.cc687
-rw-r--r--src/q_rand.hpp10
-rw-r--r--src/q_shroom.c293
-rw-r--r--src/q_shroom.cc349
-rw-r--r--src/q_shroom.hpp5
-rw-r--r--src/q_spider.cc (renamed from src/q_spider.c)85
-rw-r--r--src/q_spider.hpp5
-rw-r--r--src/q_thief.cc (renamed from src/q_thief.c)106
-rw-r--r--src/q_thief.hpp5
-rw-r--r--src/q_thrain.cc (renamed from src/q_thrain.c)181
-rw-r--r--src/q_thrain.hpp5
-rw-r--r--src/q_troll.cc (renamed from src/q_troll.c)118
-rw-r--r--src/q_troll.hpp5
-rw-r--r--src/q_ultrae.c11
-rw-r--r--src/q_ultrae.cc8
-rw-r--r--src/q_ultrae.hpp5
-rw-r--r--src/q_ultrag.cc (renamed from src/q_ultrag.c)151
-rw-r--r--src/q_ultrag.hpp5
-rw-r--r--src/q_wight.c156
-rw-r--r--src/q_wight.cc195
-rw-r--r--src/q_wight.hpp5
-rw-r--r--src/q_wolves.cc (renamed from src/q_wolves.c)89
-rw-r--r--src/q_wolves.hpp5
-rw-r--r--src/quest.cc16
-rw-r--r--src/quest.hpp3
-rwxr-xr-xsrc/quest.pkg170
-rw-r--r--src/quest_type.hpp29
-rw-r--r--src/randart.cc (renamed from src/randart.c)200
-rw-r--r--src/randart.hpp8
-rw-r--r--src/randart_gen_type.hpp9
-rw-r--r--src/randart_part_type.hpp44
-rw-r--r--src/random_artifact.hpp20
-rw-r--r--src/random_quest.hpp10
-rw-r--r--src/random_spell.hpp20
-rw-r--r--src/random_spell_fwd.hpp3
-rw-r--r--src/range.cc11
-rw-r--r--src/range.hpp15
-rw-r--r--src/range_fwd.hpp4
-rw-r--r--src/readdib.c342
-rw-r--r--src/readdib.h21
-rw-r--r--src/rule_type.hpp17
-rw-r--r--src/school_book.hpp15
-rw-r--r--src/school_book_fwd.hpp3
-rw-r--r--src/school_type.hpp21
-rw-r--r--src/school_type_fwd.hpp3
-rw-r--r--src/script.c535
-rw-r--r--src/seed.cc53
-rw-r--r--src/seed.hpp51
-rw-r--r--src/seed_fwd.hpp3
-rw-r--r--src/set_component.hpp16
-rw-r--r--src/set_type.hpp20
-rw-r--r--src/skill_descriptor.hpp37
-rw-r--r--src/skill_flag.hpp12
-rw-r--r--src/skill_flag_list.hpp9
-rw-r--r--src/skill_flag_set.hpp7
-rw-r--r--src/skill_modifier.hpp12
-rw-r--r--src/skill_modifiers.hpp17
-rw-r--r--src/skill_modifiers_fwd.hpp3
-rw-r--r--src/skill_type.hpp32
-rw-r--r--src/skills.c1661
-rw-r--r--src/skills.cc1918
-rw-r--r--src/skills.hpp28
-rw-r--r--src/skills_defs.hpp61
-rw-r--r--src/spell_type.cc433
-rw-r--r--src/spell_type.hpp86
-rw-r--r--src/spell_type_fwd.hpp16
-rw-r--r--src/spellbinder.hpp21
-rw-r--r--src/spells.pkg2448
-rw-r--r--src/spells1.cc (renamed from src/spells1.c)1786
-rw-r--r--src/spells1.hpp35
-rw-r--r--src/spells2.c8076
-rw-r--r--src/spells2.cc5579
-rw-r--r--src/spells2.hpp112
-rw-r--r--src/spells3.cc4570
-rw-r--r--src/spells3.hpp444
-rw-r--r--src/spells4.cc537
-rw-r--r--src/spells4.hpp42
-rw-r--r--src/spells5.cc2370
-rw-r--r--src/spells5.hpp9
-rw-r--r--src/spells6.cc407
-rw-r--r--src/spells6.hpp7
-rw-r--r--src/squelch/CMakeLists.txt9
-rw-r--r--src/squelch/automatizer.cc281
-rw-r--r--src/squelch/condition.cc1106
-rw-r--r--src/squelch/condition_metadata.cc494
-rw-r--r--src/squelch/cursor.cc96
-rw-r--r--src/squelch/object_status.cc153
-rw-r--r--src/squelch/rule.cc316
-rw-r--r--src/squelch/tree_printer.cc94
-rw-r--r--src/squeltch.c553
-rw-r--r--src/squeltch.cc601
-rw-r--r--src/squeltch.hpp13
-rw-r--r--src/stairs_direction.hpp3
-rw-r--r--src/stats.hpp11
-rw-r--r--src/status.c773
-rw-r--r--src/store.cc (renamed from src/store.c)2135
-rw-r--r--src/store.hpp12
-rw-r--r--src/store_action_type.hpp17
-rw-r--r--src/store_action_type_fwd.hpp3
-rw-r--r--src/store_flag.hpp12
-rw-r--r--src/store_flag_list.hpp17
-rw-r--r--src/store_flag_set.hpp7
-rw-r--r--src/store_info_type.hpp31
-rw-r--r--src/store_item.hpp18
-rw-r--r--src/store_type.hpp40
-rw-r--r--src/store_type_fwd.hpp3
-rw-r--r--src/tables.cc (renamed from src/tables.c)1654
-rw-r--r--src/tables.h12
-rw-r--r--src/tables.hpp80
-rw-r--r--src/tactic_info_type.hpp16
-rw-r--r--src/terrain.hpp19
-rw-r--r--src/timer_type.hpp81
-rw-r--r--src/timer_type_fwd.hpp3
-rw-r--r--src/town_type.hpp25
-rw-r--r--src/town_type_fwd.hpp3
-rw-r--r--src/traps.c3169
-rw-r--r--src/tval_desc.hpp17
-rw-r--r--src/types.h2522
-rw-r--r--src/util.cc (renamed from src/util.c)1410
-rw-r--r--src/util.h19
-rw-r--r--src/util.hpp86
-rw-r--r--src/util.pkg2683
-rw-r--r--src/variable.c1604
-rw-r--r--src/variable.cc649
-rw-r--r--src/variable.h31
-rw-r--r--src/variable.hpp195
-rw-r--r--src/vault_type.hpp25
-rw-r--r--src/wild.cc (renamed from src/wild.c)396
-rw-r--r--src/wild.hpp6
-rw-r--r--src/wilderness_map.hpp15
-rw-r--r--src/wilderness_map_fwd.hpp3
-rw-r--r--src/wilderness_type_info.hpp24
-rw-r--r--src/wizard1.c2756
-rw-r--r--src/wizard2.cc (renamed from src/wizard2.c)622
-rw-r--r--src/wizard2.hpp10
-rw-r--r--src/xtra1.cc (renamed from src/xtra1.c)2034
-rw-r--r--src/xtra1.hpp27
-rw-r--r--src/xtra2.cc (renamed from src/xtra2.c)2221
-rw-r--r--src/xtra2.hpp89
-rw-r--r--src/z-form.c191
-rw-r--r--src/z-form.h29
-rw-r--r--src/z-rand.c355
-rw-r--r--src/z-rand.cc254
-rw-r--r--src/z-rand.h96
-rw-r--r--src/z-rand.hpp105
-rw-r--r--src/z-term.c1094
-rw-r--r--src/z-term.h204
-rw-r--r--src/z-util.c172
-rw-r--r--src/z-util.h70
-rw-r--r--src/z-virt.c187
-rw-r--r--src/z-virt.h168
-rw-r--r--src/z_pack.pkg398
567 files changed, 75993 insertions, 146641 deletions
diff --git a/src/.cvsignore b/src/.cvsignore
deleted file mode 100644
index d99b4ed2..00000000
--- a/src/.cvsignore
+++ /dev/null
@@ -1,8 +0,0 @@
-.sconsign
-.gdb_history
-makefile
-tome
-tolua
-w_*.c
-TOME.EXE
-TOLUA.EXE
diff --git a/src/.gitignore b/src/.gitignore
new file mode 100644
index 00000000..485f14c6
--- /dev/null
+++ b/src/.gitignore
@@ -0,0 +1,7 @@
+/harness
+/tome-gcu
+/tome-gtk2
+/tome-sdl
+/tome-x11
+/tome-win
+*.plist
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 932fef4b..30ceb76c 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,31 +1,140 @@
-# Lua support code.
-ADD_SUBDIRECTORY(lua)
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include)
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../vendor/bandit)
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../vendor/fmt)
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../vendor/pcg-cpp/include)
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../vendor/jsoncons)
+
+# Add subdirectories
+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
- melee1.c melee2.c modules.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
- spells1.c spells2.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
- 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
- # 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
+# Sources (common)
+SET(SRCS_COMMON
+ birth.cc
+ bldg.cc
+ cave.cc
+ cmd1.cc
+ cmd2.cc
+ cmd3.cc
+ cmd4.cc
+ cmd5.cc
+ cmd6.cc
+ cmd7.cc
+ corrupt.cc
+ device_allocation.cc
+ dice.cc
+ dungeon.cc
+ files.cc
+ game.cc
+ gen_evol.cc
+ gen_maze.cc
+ generate.cc
+ gods.cc
+ help.cc
+ hiscore.cc
+ hooks.cc
+ init1.cc
+ init2.cc
+ joke.cc
+ level_marker.cc
+ levels.cc
+ loadsave.cc
+ lua_bind.cc
+ melee1.cc
+ melee2.cc
+ message.cc
+ messages.cc
+ mimic.cc
+ modules.cc
+ monster_spell.cc
+ monster_type.cc
+ monster1.cc
+ monster2.cc
+ monster3.cc
+ notes.cc
+ object1.cc
+ object2.cc
+ object_filter.cc
+ object_flag_meta.cc
+ options.cc
+ player_type.cc
+ powers.cc
+ q_betwen.cc
+ q_bounty.cc
+ q_dragons.cc
+ q_eol.cc
+ q_evil.cc
+ q_fireprof.cc
+ q_god.cc
+ q_god.cc
+ q_haunted.cc
+ q_hobbit.cc
+ q_invas.cc
+ q_library.cc
+ q_main.cc
+ q_narsil.cc
+ q_nazgul.cc
+ q_nirna.cc
+ q_one.cc
+ q_poison.cc
+ q_rand.cc
+ q_shroom.cc
+ q_spider.cc
+ q_thief.cc
+ q_thrain.cc
+ q_troll.cc
+ q_ultrae.cc
+ q_ultrag.cc
+ q_wight.cc
+ q_wolves.cc
+ quest.cc
+ randart.cc
+ range.cc
+ skills.cc
+ spell_type.cc
+ spells1.cc
+ spells2.cc
+ spells3.cc
+ spells4.cc
+ spells5.cc
+ spells6.cc
+ squeltch.cc
+ store.cc
+ tables.cc
+ util.cc
+ variable.cc
+ wild.cc
+ wizard2.cc
+ seed.cc
+ xtra1.cc
+ xtra2.cc
+ z-form.c
+ z-rand.cc
+ z-term.c
+ z-util.c
)
+# Sources (TEST)
+SET(SRCS_TESTS
+ ../tests/get_level_device.cc
+ ../tests/harness.cc
+ ../tests/lua_get_level.cc
+ ../tests/flag_set.cc
+ ../tests/grid.cc
+)
+
+ADD_LIBRARY(game
+ ${SRCS_COMMON} ${SRCS_VENDOR}
+)
+
+ADD_LIBRARY(game_main
+ main.cc)
+
# Need a few additional source files for Windows.
-if(WIN32)
- SET(SRCS ${SRCS} main-win.c readdib.c)
+IF(WIN32)
+ SET(SRCS ${SRCS} main-win.c)
# Resource files require a little workaround.
- if(MINGW)
+ IF(MINGW)
# Workaround for resource compilation for mingw on CMake.
# See http://www.cmake.org/Bug/view.php?id=4068
ADD_CUSTOM_COMMAND(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/angband_rc.o
@@ -33,40 +142,44 @@ if(WIN32)
-i${CMAKE_CURRENT_SOURCE_DIR}/angband.rc
-o ${CMAKE_CURRENT_BINARY_DIR}/angband_rc.o)
SET(SRCS ${SRCS} ${CMAKE_CURRENT_BINARY_DIR}/angband_rc.o)
- else(MINGW)
+ ELSE(MINGW)
SET(SRCS ${SRCS} angband.rc)
- endif(MINGW)
-endif(WIN32)
+ ENDIF(MINGW)
+ # Executable for Win32
+ ADD_EXECUTABLE(tome-win WIN32 main-win.c)
+ TARGET_LINK_LIBRARIES(tome-win game squelch ${LIBS} winmm wsock32)
+ INSTALL(TARGETS tome-win RUNTIME DESTINATION bin)
+ENDIF(WIN32)
+# tome executables
+IF(X11_FOUND)
+ INCLUDE_DIRECTORIES(${X11_INCLUDE_DIR})
+ ADD_EXECUTABLE(tome-x11 main-x11.c)
+ TARGET_LINK_LIBRARIES(tome-x11 game_main game squelch ${LIBS} ${X11_LIBRARIES})
+ INSTALL(TARGETS tome-x11 RUNTIME DESTINATION bin)
+ENDIF()
-# 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)
+IF(SDL_FOUND AND SDLIMAGE_FOUND AND SDLTTF_FOUND)
+ INCLUDE_DIRECTORIES(${SDL_INCLUDE_DIR} ${SDLIMAGE_INCLUDE_DIR} ${SDLTTF_INCLUDE_DIR})
+ ADD_EXECUTABLE(tome-sdl main-sdl.c)
+ TARGET_LINK_LIBRARIES(tome-sdl game_main game squelch ${LIBS} ${SDLIMAGE_LIBRARY} ${SDLTTF_LIBRARY} ${SDL_LIBRARY} m)
+ INSTALL(TARGETS tome-sdl RUNTIME DESTINATION bin)
+ENDIF()
-# 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(quest w_quest.c)
-TOLUA_FILE(dungeon w_dun.c)
+IF(CURSES_FOUND)
+ INCLUDE_DIRECTORIES(${CURSES_INCLUDE_DIR})
+ ADD_EXECUTABLE(tome-gcu main-gcu.c)
+ TARGET_LINK_LIBRARIES(tome-gcu game_main game squelch ${LIBS} ${CURSES_LIBRARIES})
+ INSTALL(TARGETS tome-gcu RUNTIME DESTINATION bin)
+ENDIF()
-# tome executable
-INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
-INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/lua)
-ADD_EXECUTABLE(tome ${EXECUTABLE_OPTIONS} ${SRCS})
-TARGET_LINK_LIBRARIES(tome lua ${LIBS})
+IF(GTK2_FOUND)
+ INCLUDE_DIRECTORIES(${GTK2_INCLUDE_DIRS})
+ ADD_EXECUTABLE(tome-gtk2 main-gtk2.c)
+ TARGET_LINK_LIBRARIES(tome-gtk2 game_main game squelch ${LIBS} ${GTK2_LIBRARIES})
+ INSTALL(TARGETS tome-gtk2 RUNTIME DESTINATION bin)
+ENDIF()
-# Installation
-INSTALL(TARGETS tome
- RUNTIME DESTINATION games
-)
+# test harness executable
+ADD_EXECUTABLE(harness ${SRCS_TESTS})
+TARGET_LINK_LIBRARIES(harness game squelch ${LIBS})
diff --git a/src/ability_type.hpp b/src/ability_type.hpp
new file mode 100644
index 00000000..0ec596ba
--- /dev/null
+++ b/src/ability_type.hpp
@@ -0,0 +1,47 @@
+#pragma once
+
+#include <string>
+#include <vector>
+
+#include "h-basic.h"
+
+/**
+ * Abilities.
+ */
+struct ability_type
+{
+public:
+ struct skill_requirement {
+ s16b skill_idx = 0;
+ s16b level = 0;
+ };
+
+public:
+ std::string name; /* Name */
+ std::string desc; /* Description */
+
+ std::string action_desc; /* Action Description */
+
+ s16b action_mkey = 0; /* Action do to */
+
+ s16b cost = 0; /* Skill points cost */
+
+ std::vector<skill_requirement> need_skills; /* List of prereq skills */
+
+ s16b stat[6] { }; /* List of prereq stats */
+
+ std::vector<s16b> need_abilities; /* List of prereq abilities */
+
+ /**
+ * Default constructor
+ */
+ ability_type()
+ {
+ for (auto &stat_ref: stat)
+ {
+ // Requirement is always met unless otherwise specified.
+ stat_ref = -1;
+ }
+ }
+
+};
diff --git a/src/activation.hpp b/src/activation.hpp
new file mode 100644
index 00000000..adb9d8bc
--- /dev/null
+++ b/src/activation.hpp
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * Activation descriptor.
+ */
+struct activation
+{
+ char desc[80]; /* Desc of the activation */
+ u32b cost; /* costs value */
+ s16b spell; /* Spell. */
+};
diff --git a/src/alloc.hpp b/src/alloc.hpp
new file mode 100644
index 00000000..1d4ce815
--- /dev/null
+++ b/src/alloc.hpp
@@ -0,0 +1,29 @@
+#pragma once
+
+#include "h-basic.h"
+#include "alloc_entry.hpp"
+
+#include <vector>
+
+/**
+ * Allocations of object kinds and monster races.
+ */
+struct Alloc {
+
+ /*
+ * The entries in the "kind allocator table"
+ */
+ std::vector<alloc_entry> kind_table;
+
+ /*
+ * The flag to tell if kind_table contains valid entries
+ * for normal (i.e. kind_is_legal) object allocation
+ */
+ bool kind_table_valid = false;
+
+ /*
+ * The entries in the "race allocator table"
+ */
+ std::vector<alloc_entry> race_table;
+
+};
diff --git a/src/alloc_entry.hpp b/src/alloc_entry.hpp
new file mode 100644
index 00000000..5e0e547f
--- /dev/null
+++ b/src/alloc_entry.hpp
@@ -0,0 +1,20 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * An entry for the object/monster allocation functions
+ *
+ * Pass 1 is determined from allocation information
+ * Pass 2 is determined from allocation restriction
+ * Pass 3 is determined from allocation calculation
+ */
+struct alloc_entry
+{
+ s16b index = -1; /* The actual index */
+
+ byte level = 0; /* Base dungeon level */
+ byte prob1 = 0; /* Probability, pass 1 */
+ byte prob2 = 0; /* Probability, pass 2 */
+ byte prob3 = 0; /* Probability, pass 3 */
+};
diff --git a/src/alloc_entry_fwd.hpp b/src/alloc_entry_fwd.hpp
new file mode 100644
index 00000000..167af118
--- /dev/null
+++ b/src/alloc_entry_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct alloc_entry;
diff --git a/src/angband.h b/src/angband.h
index cac38122..5fbc94e5 100644
--- a/src/angband.h
+++ b/src/angband.h
@@ -1,9 +1,4 @@
-/* File: angband.h */
-
-/* Main "Angband" header file */
-
-#ifndef INCLUDED_ANGBAND_H
-#define INCLUDED_ANGBAND_H
+#pragma once
/*
* Copyright (c) 1989 James E. Wilson
@@ -13,7 +8,6 @@
* included in all such copies.
*/
-
/*
* C++ guard.
*/
@@ -32,9 +26,7 @@ extern "C" {
* Then, include the header files for the low-level code
*/
#include "z-util.h"
-#include "z-virt.h"
#include "z-form.h"
-#include "z-rand.h"
#include "z-term.h"
@@ -45,12 +37,9 @@ extern "C" {
/*
- * Now, include the define's, the type's, and the extern's
+ * Now, include the defines and the types
*/
#include "defines.h"
-#include "types.h"
-#include "externs.h"
-#include "plots.h"
/***** Some copyright messages follow below *****/
@@ -103,8 +92,3 @@ extern "C" {
#ifdef __cplusplus
} /* extern "C" */
#endif
-
-#endif
-
-
-
diff --git a/src/angband.rc b/src/angband.rc
index 00e16516..37856f4a 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
}
@@ -107,25 +101,10 @@ ANGBAND MENU
POPUP "&Options"
{
- POPUP "&Graphics"
- {
- MENUITEM "&Old tiles", 400
- MENUITEM "&New tiles", 401
- MENUITEM "ASCII &Text", 403
- MENUITEM "&Bigtile mode", 409
- }
-
- MENUITEM "&Sound", 402
- MENUITEM SEPARATOR
MENUITEM "Unused menu option", 410
MENUITEM "Activate Screensaver", 411
}
- POPUP "&Help"
- {
- MENUITEM "&General", 901
- MENUITEM "&Spoilers", 902
- }
}
ANGBAND ICON "angband.ico"
diff --git a/src/artifact_type.hpp b/src/artifact_type.hpp
new file mode 100644
index 00000000..9f866aa7
--- /dev/null
+++ b/src/artifact_type.hpp
@@ -0,0 +1,50 @@
+#pragma once
+
+#include "h-basic.h"
+#include "object_flag_set.hpp"
+
+/**
+ * Artifact descriptor.
+ *
+ * Note that the save-file only writes "cur_num" to the savefile.
+ *
+ * Note that "max_num" is always "1" (if that artifact "exists")
+ */
+struct artifact_type
+{
+ char const *name = nullptr; /* Artifact name */
+ char *text = nullptr; /* Artifact description */
+
+ byte tval = 0; /* Artifact type */
+ byte sval = 0; /* Artifact sub type */
+
+ s16b pval = 0; /* Artifact extra info */
+
+ s16b to_h = 0; /* Bonus to hit */
+ s16b to_d = 0; /* Bonus to damage */
+ s16b to_a = 0; /* Bonus to armor */
+
+ s16b activate = 0; /* Activation Number */
+
+ s16b ac = 0; /* Base armor */
+
+ byte dd = 0; /* Damage dice */
+ byte ds = 0; /* Damage sides */
+
+ s16b weight = 0; /* Weight */
+
+ s32b cost = 0; /* Artifact "cost" */
+
+ object_flag_set flags; /* Artifact Flags */
+ object_flag_set oflags; /* Obvious Flags */
+
+ byte level = 0; /* Artifact level */
+ byte rarity = 0; /* Artifact rarity */
+
+ byte cur_num = 0; /* Number created (0 or 1) */
+
+ s16b power = 0; /* Power granted, if any */
+
+ s16b set = 0; /* Which set does it belong it, if any? */
+
+};
diff --git a/src/between_exit.hpp b/src/between_exit.hpp
new file mode 100644
index 00000000..7ea686d7
--- /dev/null
+++ b/src/between_exit.hpp
@@ -0,0 +1,18 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * Surface-level void gates descriptor.
+ */
+struct between_exit
+{
+ s16b corresp; /* Corresponding between gate */
+ bool_ dungeon; /* Do we exit in a dungeon or in the wild ? */
+
+ s16b wild_x, wild_y; /* Wilderness spot to land onto */
+ s16b px, py; /* Location of the map */
+
+ s16b d_idx; /* Dungeon to land onto */
+ s16b level;
+};
diff --git a/src/birth.c b/src/birth.cc
index f073b2f6..f677e6e1 100644
--- a/src/birth.c
+++ b/src/birth.cc
@@ -1,7 +1,3 @@
-/* File: birth.c */
-
-/* Purpose: create a player character */
-
/*
* Copyright (c) 1989 James E. Wilson, Robert A. Koeneke
*
@@ -9,8 +5,62 @@
* not for profit purposes provided that this copyright and statement are
* included in all such copies.
*/
-
-#include "angband.h"
+#include "birth.hpp"
+
+#include "ability_type.hpp"
+#include "artifact_type.hpp"
+#include "corrupt.hpp"
+#include "cmd4.hpp"
+#include "cmd5.hpp"
+#include "dungeon_flag.hpp"
+#include "dungeon_info_type.hpp"
+#include "files.h"
+#include "files.hpp"
+#include "game.hpp"
+#include "gods.hpp"
+#include "help.hpp"
+#include "hooks.hpp"
+#include "init2.hpp"
+#include "mimic.hpp"
+#include "messages.hpp"
+#include "modules.hpp"
+#include "monster2.hpp"
+#include "monster_race.hpp"
+#include "monster_race_flag.hpp"
+#include "notes.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_kind.hpp"
+#include "options.hpp"
+#include "player_class.hpp"
+#include "player_race.hpp"
+#include "player_race_flag.hpp"
+#include "player_race_mod.hpp"
+#include "player_type.hpp"
+#include "q_rand.hpp"
+#include "skill_type.hpp"
+#include "skills.hpp"
+#include "spells2.hpp"
+#include "spells3.hpp"
+#include "spells5.hpp"
+#include "stats.hpp"
+#include "store.hpp"
+#include "tables.hpp"
+#include "town_type.hpp"
+#include "util.hpp"
+#include "util.h"
+#include "variable.h"
+#include "variable.hpp"
+#include "wilderness_map.hpp"
+#include "xtra1.hpp"
+#include "xtra2.hpp"
+#include "z-rand.hpp"
+
+#include <algorithm>
+#include <boost/filesystem.hpp>
+#include <fmt/format.h>
+#include <numeric>
+#include <string>
/*
* How often the autoroller will update the display and pause
@@ -54,73 +104,48 @@ static s32b auto_round;
*/
static s32b last_round;
-/* Human */
-static 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 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 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)
+static std::string create_random_name()
{
- 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);
+ static const std::vector<std::string> 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 std::vector<std::string> 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 std::vector<std::string> 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",
+ };
+
+ auto const &syl1 = *uniform_element(human_syllable1);
+ auto const &syl2 = *uniform_element(human_syllable2);
+ auto const &syl3 = *uniform_element(human_syllable3);
+
+ return syl1 + syl2 + syl3;
}
@@ -151,15 +176,13 @@ void print_desc(cptr txt)
/*
* Save the current data for later
*/
-static void save_prev_data(void)
+static void save_prev_data()
{
- int i;
-
+ auto &previous_char = game->previous_char;
/*** 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;
@@ -170,30 +193,14 @@ static void save_prev_data(void)
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++)
+ for (int i = 0; i < 6; i++)
{
previous_char.stat[i] = p_ptr->stat_max[i];
}
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;
-
- /* Save the history */
- for (i = 0; i < 4; i++)
- {
- strcpy(previous_char.history[i], history[i]);
- }
}
@@ -202,51 +209,29 @@ static void save_prev_data(void)
*/
static void load_prev_data(bool_ save)
{
- int i;
-
+ auto &previous_char = game->previous_char;
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++)
+ for (int i = 0; i < 6; i++)
{
temp.stat[i] = p_ptr->stat_max[i];
}
temp.luck = p_ptr->luck_base;
- /* Save the chaos patron */
- temp.chaos_patron = p_ptr->chaos_patron;
-
- /* 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++)
+ for (int i = 0; i < 6; i++)
{
p_ptr->stat_max[i] = previous_char.stat[i];
p_ptr->stat_cur[i] = previous_char.stat[i];
@@ -254,44 +239,19 @@ 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++)
- {
- 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++)
+ for (int 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]);
- }
}
@@ -341,22 +301,10 @@ static int adjust_stat(int value, int amount, int auto_roll)
{
value++;
}
- else if (p_ptr->maximize)
+ else
{
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++;
- }
}
}
@@ -372,7 +320,7 @@ static int adjust_stat(int value, int amount, int auto_roll)
*
* For efficiency, we include a chunk of "calc_bonuses()".
*/
-static void get_stats(void)
+static void get_stats()
{
int i, j;
@@ -423,27 +371,13 @@ static void get_stats(void)
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];
+ bonus = rp_ptr->ps.adj[i] + rmp_ptr->ps.adj[i] + cp_ptr->ps.adj[i];
- /* Variable stat maxes */
- if (p_ptr->maximize)
- {
- /* Start fully healed */
- p_ptr->stat_cur[i] = p_ptr->stat_max[i];
+ /* 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];
- }
+ /* Efficiency -- Apply the racial/class bonuses */
+ stat_use[i] = modify_stat_value(p_ptr->stat_max[i], bonus);
/* No temporary drain (yet...) */
p_ptr->stat_cnt[i] = 0;
@@ -457,308 +391,121 @@ static void get_stats(void)
/*
- * Roll for some info that the auto-roller ignores
+ * Roll for player HP
*/
-static void get_extra(void)
+void roll_player_hp()
{
- int i, j, min_value, max_value;
-
-#ifdef SHOW_LIFE_RATE
-
- int percent;
-
-#endif
-
-
- /* 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;
+ auto &player_hp = game->player_hp;
- /* Minimum hitpoints at highest level */
- min_value = (PY_MAX_LEVEL * (p_ptr->hitdie - 1) * 3) / 8;
- min_value += PY_MAX_LEVEL;
+ // Minimum hitpoints at highest level
+ int const min_value =
+ (PY_MAX_LEVEL * (p_ptr->hitdie - 1) * 3) / 8 + PY_MAX_LEVEL;
- /* Maximum hitpoints at highest level */
- max_value = (PY_MAX_LEVEL * (p_ptr->hitdie - 1) * 5) / 8;
- max_value += PY_MAX_LEVEL;
+ // Maximum hitpoints at highest level
+ int const max_value =
+ (PY_MAX_LEVEL * (p_ptr->hitdie - 1) * 5) / 8 + PY_MAX_LEVEL;
- /* Pre-calculate level 1 hitdice */
+ // Pre-calculate level 1 hitdice; first roll is always maximal
player_hp[0] = p_ptr->hitdie;
- /* Roll out the hitpoints */
- while (TRUE)
+ // 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;
- }
+ // Roll the hitpoint values
+ std::generate(
+ player_hp.begin() + 1,
+ player_hp.end(),
+ []() { return randint(p_ptr->hitdie); });
- /* XXX Could also require acceptable "mid-level" hitpoints */
+ // Sum along
+ std::partial_sum(
+ player_hp.begin(),
+ player_hp.end(),
+ player_hp.begin());
- /* 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;
+ // Require "valid" hitpoints at highest level
+ if (player_hp.back() < min_value) continue;
+ if (player_hp.back() > max_value) continue;
- /* Acceptable */
+ // Acceptable
break;
}
-
- 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 */
}
/*
- * Get the racial history, and social class, using the "history charts".
+ * Roll for some info that the auto-roller ignores
*/
-static void get_history(void)
+static void get_extra()
{
- 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);
+ /* Level one */
+ p_ptr->max_plv = p_ptr->lev = 1;
- /* All done */
- break;
- }
+ /* Experience factor */
+ p_ptr->expfact = rp_ptr->ps.exp + rmp_ptr->ps.exp + cp_ptr->ps.exp;
- /* Find a reasonable break-point */
- for (n = 60; ((n > 0) && (s[n - 1] != ' ')); n--) /* loop */;
+ /* Initialize quest */
+ p_ptr->inside_quest = 0;
- /* Save next location */
- t = s + n;
+ /* Hitdice */
+ p_ptr->hitdie = rp_ptr->ps.mhp + rmp_ptr->ps.mhp + cp_ptr->ps.mhp;
- /* Wipe trailing spaces */
- while ((n > 0) && (s[n - 1] == ' ')) s[--n] = '\0';
+ /* Initial hitpoints */
+ p_ptr->mhp = p_ptr->hitdie;
- /* Save one line of history */
- strcpy(history[i++], s);
+ /* Roll for HP */
+ roll_player_hp();
- /* Start next line */
- for (s = t; *s == ' '; s++) /* loop */;
- }
+ /* Set tactics and movement */
+ p_ptr->tactic = 4;
+ p_ptr->movement = 4;
}
/*
* Fill the random_artifacts array with relevant info.
*/
-errr init_randart(void)
+static errr init_randart()
{
- int i;
-
- long cost;
-
- random_artifact* ra_ptr;
-
char buf[80];
-
- for (i = 0; i < MAX_RANDARTS; i++)
+ for (int 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);
+ // Generate a 'cost'
+ auto cost = randnor(0, 250);
+ if (cost < 0)
+ {
+ cost = 0;
+ }
- if (cost < 0) cost = 0;
+ // Generate the random artifact
+ random_artifact ra;
+ ra.name_short = get_line("rart_s.txt", ANGBAND_DIR_FILE, buf, i);
+ ra.name_full = get_line("rart_f.txt", ANGBAND_DIR_FILE, buf, i);
+ ra.attr = randint(15);
+ ra.activation = rand_int(MAX_T_ACT);
+ ra.generated = FALSE;
+ ra.cost = cost;
- ra_ptr->cost = cost;
+ // Push
+ game->random_artifacts.push_back(ra);
}
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)
+static void get_money()
{
- int i, gold;
-
-
- /* Social Class determines starting gold */
- gold = (p_ptr->sc * 6) + randint(100) + 300;
+ /* Starting gold */
+ int gold = randint(100) + 300;
/* Process the stats */
- for (i = 0; i < 6; i++)
+ for (int i = 0; i < 6; i++)
{
/* Mega-Hack -- reduce gold for high stats */
if (stat_use[i] >= 18 + 50) gold -= 300;
@@ -781,7 +528,7 @@ static void get_money(void)
*
* See 'display_player()' for basic method.
*/
-static void birth_put_stats(void)
+static void birth_put_stats()
{
int i, p;
@@ -818,85 +565,57 @@ static void birth_put_stats(void)
/*
* Clear all the global "character" data
*/
-static void player_wipe(void)
+static void player_wipe()
{
- int i, j;
-
- bool_ *powers;
- bool_ *corruptions;
-
+ auto const &d_info = game->edit_data.d_info;
+ auto &r_info = game->edit_data.r_info;
+ auto &k_info = game->edit_data.k_info;
+ auto &a_info = game->edit_data.a_info;
+ auto &level_markers = game->level_markers;
/* Wipe special levels */
wipe_saved();
- /* Save the powers & corruptions */
- powers = p_ptr->powers;
- corruptions = p_ptr->corruptions;
-
/* Hack -- zero the struct */
- p_ptr = WIPE(p_ptr, player_type);
+ *p_ptr = player_type();
- /* Restore the powers & corruptions */
- p_ptr->powers = powers;
- p_ptr->corruptions = corruptions;
+ /* Level 1 is the first level */
+ p_ptr->lev = 1;
/* 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++)
- {
- 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 (auto &&i: level_markers)
{
- for (j = 0; j < MAX_DUNGEON_DEPTH; j++)
+ for (auto &&j: i)
{
- special_lvl[j][i] = 0;
+ j = level_marker::NORMAL;
}
}
/* Wipe the towns */
- for (i = max_real_towns + 1; i < max_towns; i++)
+ for (std::size_t i = max_real_towns + 1; i < max_towns; i++)
{
town_info[i].flags = 0;
}
/* Wipe the quests */
- for (i = 0; i < MAX_Q_IDX_INIT; i++)
+ for (std::size_t i = 0; i < MAX_Q_IDX; i++)
{
quest[i].status = QUEST_STATUS_UNTAKEN;
- for (j = 0; j < 4; j++)
+ for (auto &quest_data : quest[i].data)
{
- quest[i].data[j] = 0;
+ quest_data = 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++)
+ for (std::size_t i = 0; i < INVEN_TOTAL; i++)
{
object_wipe(&p_ptr->inventory[i]);
}
@@ -905,35 +624,29 @@ static void player_wipe(void)
init_randart();
/* Start with no artifacts made yet */
- for (i = 0; i < max_a_idx; i++)
+ for (auto &a_ref: a_info)
{
- artifact_type *a_ptr = &a_info[i];
- a_ptr->cur_num = 0;
+ a_ref.cur_num = 0;
}
/* Reset the "objects" */
- for (i = 1; i < max_k_idx; i++)
+ for (auto &k_ref: k_info)
{
- object_kind *k_ptr = &k_info[i];
-
/* Reset "tried" */
- k_ptr->tried = FALSE;
+ k_ref.tried = FALSE;
/* Reset "aware" */
- k_ptr->aware = FALSE;
-
- /* Reset "know" */
- k_ptr->know = FALSE;
+ k_ref.aware = FALSE;
/* Reset "artifact" */
- k_ptr->artifact = 0;
+ k_ref.artifact = 0;
}
/* Reset the "monsters" */
- for (i = 1; i < max_r_idx; i++)
+ for (auto &r_ref: r_info)
{
- monster_race *r_ptr = &r_info[i];
+ auto r_ptr = &r_ref;
/* Hack -- Reset the counter */
r_ptr->cur_num = 0;
@@ -942,8 +655,7 @@ static void player_wipe(void)
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;
+ if (r_ptr->flags & RF_UNIQUE) r_ptr->max_num = 1;
/* Clear player kills */
r_ptr->r_pkills = 0;
@@ -956,20 +668,8 @@ static void player_wipe(void)
/* 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;
+ options->reset_cheat_options();
/* Assume no winning game */
total_winner = 0;
@@ -979,11 +679,8 @@ static void player_wipe(void)
noscore = 0;
wizard = 0;
- /* Assume no innate spells */
- spell_num = 0;
-
/* Clear the fate */
- for (i = 0; i < MAX_FATES; i++)
+ for (std::size_t i = 0; i < MAX_FATES; i++)
{
fates[i].fate = 0;
}
@@ -1001,12 +698,6 @@ static void player_wipe(void)
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;
@@ -1017,22 +708,15 @@ static void player_wipe(void)
doppleganger = 0;
/* Wipe the recall depths */
- for (i = 0; i < max_d_idx; i++)
+ for (std::size_t i = 0; i < d_info.size(); 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++)
+ for (auto &inscription_known: p_ptr->inscriptions)
{
- t_info[i].known = 0;
- t_info[i].ident = FALSE;
+ inscription_known = false;
}
/* Reset wild_mode to FALSE */
@@ -1042,43 +726,86 @@ static void player_wipe(void)
/* 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_INIT; i++)
+ for (std::size_t 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)
+static void outfit_obj(object_proto const *proto)
{
object_type forge;
- object_type *q_ptr;
/* Get local object */
- q_ptr = &forge;
+ auto 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));
+ object_prep(q_ptr, lookup_kind(proto->tval, proto->sval));
- if (pval)
- q_ptr->pval = pval;
+ if (proto->pval)
+ {
+ q_ptr->pval = proto->pval;
+ }
/* These objects are "storebought" */
q_ptr->ident |= IDENT_MENTAL;
- q_ptr->number = damroll(dd, ds);
+ q_ptr->number = damroll(proto->dd, proto->ds);
object_aware(q_ptr);
object_known(q_ptr);
- (void)inven_carry(q_ptr, FALSE);
+ inven_carry(q_ptr, FALSE);
+}
+
+
+static void outfit_objs(std::vector<object_proto> const &protos)
+{
+ for (auto const &proto: protos)
+ {
+ outfit_obj(&proto);
+ }
+}
+
+
+/*
+ * 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);
+ 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);
}
@@ -1087,239 +814,192 @@ void outfit_obj(int tv, int sv, int pval, int dd, int ds)
*
* Having an item makes the player "aware" of its purpose.
*/
-static void player_outfit(void)
+static void player_outfit()
{
- int i;
+ // Shorthand names for convenience
+ cptr class_name = spp_ptr->title;
+ auto const &subrace_name = rmp_ptr->title;
/*
* 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)
{
- object_type forge;
- object_type *q_ptr = &forge;
- /* 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);
+ if (streq(class_name, "Ranger"))
+ {
+ player_outfit_spellbook("Phase Door");
+ }
}
-
+ if (streq(class_name, "Geomancer"))
{
- 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);
+ player_outfit_spellbook("Geyser");
}
-
- /* Rogues have a better knowledge of traps */
- if (has_ability(AB_TRAPPING))
+ if (streq(class_name, "Priest(Eru)"))
{
- 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);
+ player_outfit_spellbook("See the Music");
}
-
- /* 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++)
+ if (streq(class_name, "Priest(Manwe)"))
{
- 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++)
+ 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"))
{
- 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;
- }
+ player_outfit_spellbook("Firebrand");
}
-
- q_ptr->type = random_quests_types[rand_int(MAX_RANDOM_QUESTS_TYPES)];
-
- /* XXX XXX XXX Try until valid choice is found */
- while (tries)
+ if (streq(class_name, "Priest(Varda)"))
{
- 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;
+ 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");
+ }
- /* Accept only monsters that are not good */
- if (r_ptr->flags3 & RF3_GOOD) continue;
+ /* Dragons */
+ if (subrace_name == "Red")
+ {
+ player_outfit_spellbook("Globe of Light");
+ }
+ if (subrace_name == "Black")
+ {
+ player_outfit_spellbook("Geyser");
+ }
+ if (subrace_name == "Green")
+ {
+ player_outfit_spellbook("Noxious Cloud");
+ }
+ if (subrace_name == "Blue")
+ {
+ player_outfit_spellbook("Stone Skin");
+ }
+ if (subrace_name == "White")
+ {
+ player_outfit_spellbook("Sense Monsters");
+ }
+ if (subrace_name == "Ethereal")
+ {
+ player_outfit_spellbook("Recharge");
+ }
- /* Assume no explosion attacks */
- ok = TRUE;
+ /* Demons */
+ if (subrace_name == "(Aewrog)")
+ {
+ player_outfit_spellbook("Charm");
+ }
+ if (subrace_name == "(Narrog)")
+ {
+ player_outfit_spellbook("Phase Door");
+ }
- /* Reject monsters with exploding attacks */
- for (k = 0; k < 4; k++)
- {
- if (r_ptr->blow[k].method == RBM_EXPLODE) ok = FALSE;
- }
- if (!ok) continue;
+ /* Peace-mages */
+ if (streq(class_name, "Peace-mage"))
+ {
+ player_outfit_spellbook("Phase Door");
+ }
- /* No mutliple uniques */
- if ((r_ptr->flags1 & RF1_UNIQUE) &&
- ((q_ptr->type != 1) || (r_ptr->max_num == -1))) continue;
+ /* Wainriders */
+ if (streq(class_name, "Wainrider"))
+ {
+ player_outfit_spellbook("Curse");
+ }
+ }
- /* No single non uniques */
- if ((!(r_ptr->flags1 & RF1_UNIQUE)) && (q_ptr->type == 1)) continue;
+ 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);
+ }
- /* Level restriction */
- min_level = (rl > RQ_LEVEL_CAP) ? RQ_LEVEL_CAP : rl;
+ if (game_module_idx == MODULE_THEME)
+ {
+ /* Give everyone a scroll of WoR. */
+ player_outfit_object(1, TV_SCROLL, SV_SCROLL_WORD_OF_RECALL);
- /* Accept monsters matching the level restriction */
- if (r_ptr->level > min_level) break;
- }
+ /* Identify everything in pack. */
+ identify_pack_fully();
+ }
- /* 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);
- q_ptr->type = 0;
- }
- else
- {
- if (r_ptr->flags1 & RF1_UNIQUE)
- {
- r_ptr->max_num = -1;
- }
+ if (rmp_ptr->title == "Vampire")
+ {
+ player_gain_corruption(CORRUPT_VAMPIRE_TEETH);
+ player_gain_corruption(CORRUPT_VAMPIRE_STRENGTH);
+ player_gain_corruption(CORRUPT_VAMPIRE_VAMPIRE);
+ }
- q_ptr->done = FALSE;
+ process_hooks_new(HOOK_BIRTH_OBJECTS, NULL, NULL);
+ meta_inertia_control_hook_birth_objects();
- if (wizard) message_add(MESSAGE_MSG,
- format("Quest for %d on lvl %d",
- q_ptr->r_idx, rl), TERM_RED);
- }
+ {
+ /* Hack -- Give the player some food */
+ int qty = (byte)rand_range(3, 7);
+ player_outfit_object(qty, TV_FOOD, SV_FOOD_RATION);
+ }
- lvl += step;
+ {
+ 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);
+ inven_carry(q_ptr, FALSE);
}
- dungeon_type = old_type;
+ /* Outfit the player with starting items */
+ outfit_objs(rp_ptr->object_protos);
+ outfit_objs(rmp_ptr->object_protos);
+ outfit_objs(cp_ptr->object_protos);
+ outfit_objs(cp_ptr->spec[p_ptr->pspec].object_protos);
}
-int dump_classes(s16b *classes, int sel, u32b *restrictions)
+
+static void dump_classes(std::vector<u16b> const &classes, int sel, u32b *restrictions)
{
- int n = 0;
+ auto const &class_info = game->edit_data.class_info;
char buf[80];
- char *desc;
-
- cptr str;
-
- C_MAKE(desc, c_head->text_size, char);
/* Clean up */
clear_from(12);
- while (classes[n] != -1)
+ int n_max = static_cast<int>(classes.size()); // Warning avoidance
+
+ for (int n = 0; n < n_max; n++)
{
cptr mod = "";
char p2 = ')', p1 = ' ';
@@ -1327,7 +1007,6 @@ int dump_classes(s16b *classes, int sel, u32b *restrictions)
/* Analyze */
p_ptr->pclass = classes[n];
cp_ptr = &class_info[p_ptr->pclass];
- str = cp_ptr->title + c_name;
if (sel == n)
{
@@ -1337,17 +1016,23 @@ int dump_classes(s16b *classes, int sel, u32b *restrictions)
/* Display */
strnfmt(buf, 80, "%c%c%c %s%s", p1,
- (n <= 25) ? I2A(n) : I2D(n - 26), p2, str, mod);
+ (n <= 25) ? I2A(n) : I2D(n - 26), p2, cp_ptr->title.c_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);
+ std::string desc;
+
+ desc += cp_ptr->desc;
+ if (cp_ptr->flags & PR_EXPERIMENTAL)
+ {
+ desc += "\nEXPERIMENTAL";
+ }
+
+ print_desc(desc.c_str());
if (!(restrictions[classes[n] / 32] & BIT(classes[n])) ||
- cp_ptr->flags1 & PR1_EXPERIMENTAL)
+ (cp_ptr->flags & PR_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));
@@ -1355,44 +1040,34 @@ int dump_classes(s16b *classes, int sel, u32b *restrictions)
else
{
if (!(restrictions[classes[n] / 32] & BIT(classes[n])) ||
- cp_ptr->flags1 & PR1_EXPERIMENTAL)
+ (cp_ptr->flags & PR_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)
+static void dump_specs(int sel_)
{
- int n = 0;
+ auto const &class_info = game->edit_data.class_info;
- char buf[80];
- char *desc;
+ assert(sel_ >= 0);
+ std::size_t sel = sel_;
- 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 = ' ';
+ auto specs = &class_info[p_ptr->pclass].spec;
- /* Found the last one ? */
- if (!class_info[p_ptr->pclass].spec[n].title) break;
+ for (std::size_t n = 0; n < specs->size(); n++)
+ {
+ char p2 = ')';
+ char p1 = ' ';
/* Analyze */
p_ptr->pspec = n;
- spp_ptr = &class_info[p_ptr->pclass].spec[p_ptr->pspec];
- str = spp_ptr->title + c_name;
+ spp_ptr = &(*specs)[p_ptr->pspec];
if (sel == n)
{
@@ -1401,56 +1076,63 @@ int dump_specs(int sel)
}
/* Display */
- strnfmt(buf, 80, "%c%c%c %s", p1, I2A(n), p2, str);
+ char buf[80];
+ strnfmt(buf, 80, "%c%c%c %s", p1, I2A(n), p2, spp_ptr->title);
/* 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);
+ std::string desc;
+
+ desc += spp_ptr->desc;
+ if (spp_ptr->flags & PR_EXPERIMENTAL)
+ {
+ desc += "\nEXPERIMENTAL";
+ }
+
+ print_desc(desc.c_str());
- if (spp_ptr->flags1 & PR1_EXPERIMENTAL)
+ if (spp_ptr->flags & PR_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)
+ if (spp_ptr->flags & PR_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)
+static int dump_races(int sel)
{
+ auto const &race_info = game->edit_data.race_info;
+
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++)
+ for (n = 0; n < static_cast<int>(race_info.size()); 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)
{
@@ -1459,45 +1141,46 @@ int dump_races(int sel)
}
/* Display */
- strnfmt(buf, 80, "%c%c%c %s", p1, I2A(n), p2, str);
+ strnfmt(buf, 80, "%c%c%c %s", p1, I2A(n), p2, rp_ptr->title.c_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);
+ std::string desc;
+
+ desc += rp_ptr->desc;
+ if (rp_ptr->flags & PR_EXPERIMENTAL)
+ {
+ desc += "\nEXPERIMENTAL";
+ }
- if (rp_ptr->flags1 & PR1_EXPERIMENTAL)
+ print_desc(desc.c_str());
+
+ if (rp_ptr->flags & PR_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)
+ if (rp_ptr->flags & PR_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)
+static int dump_rmods(int sel, int *racem, int max)
{
+ auto const &race_mod_info = game->edit_data.race_mod_info;
+
int n = 0;
char buf[80];
- char *desc;
-
- cptr str;
-
- C_MAKE(desc, rmp_head->text_size, char);
/* Clean up */
clear_from(12);
@@ -1510,7 +1193,6 @@ int dump_rmods(int sel, int *racem, int max)
/* Analyze */
p_ptr->pracem = racem[n];
rmp_ptr = &race_mod_info[p_ptr->pracem];
- str = rmp_ptr->title + rmp_name;
if (sel == n)
{
@@ -1520,37 +1202,41 @@ int dump_rmods(int sel, int *racem, int max)
/* Display */
if (racem[n])
- strnfmt(buf, 80, "%c%c%c %s", p1, I2A(n), p2, str);
+ strnfmt(buf, 80, "%c%c%c %s", p1, I2A(n), p2, rmp_ptr->title.c_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);
+ std::string desc;
+
+ desc += rmp_ptr->description;
+ if (rmp_ptr->flags & PR_EXPERIMENTAL)
+ {
+ desc += "\nEXPERIMENTAL";
+ }
+
+ print_desc(desc.c_str());
- if (rmp_ptr->flags1 & PR1_EXPERIMENTAL)
+ if (rmp_ptr->flags & PR_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)
+ if (rmp_ptr->flags & PR_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)
+static int dump_gods(int sel, int *choice, int max)
{
int i, j;
char buf[80];
@@ -1613,26 +1299,25 @@ static bool_ do_quick_start = FALSE;
static bool_ player_birth_aux_ask()
{
- int i, k, n, v, sel;
+ auto &class_info = game->edit_data.class_info;
+ auto const &race_info = game->edit_data.race_info;
+ auto const &race_mod_info = game->edit_data.race_mod_info;
+ auto const &d_info = game->edit_data.d_info;
- s32b tmp;
+ int 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;
-
- s32b allow_quest;
+ int const NAME_ROW = 2;
+ int const RACE_ROW = 3;
+ int const CLASS_ROW = 4;
/*** Intro ***/
@@ -1640,14 +1325,12 @@ static bool_ player_birth_aux_ask()
Term_clear();
/* Title everything */
- put_str("Name :", 2, 1);
- put_str("Sex :", 3, 1);
- put_str("Race :", 4, 1);
- put_str("Class :", 5, 1);
+ put_str("Name :", NAME_ROW, 1);
+ c_put_str(TERM_L_BLUE, game->player_name.c_str(), NAME_ROW, 9);
- /* Dump the default name */
- c_put_str(TERM_L_BLUE, player_name, 2, 9);
+ put_str("Race :", RACE_ROW, 1);
+ put_str("Class :", CLASS_ROW, 1);
/*** Instructions ***/
@@ -1664,16 +1347,12 @@ static bool_ player_birth_aux_ask()
/*** Quick Start ***/
- if (previous_char.quick_ok)
+ if (game->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);
+ put_str("Use same character as last time (y/n)? ", 20, 2);
c = inkey();
if (c == 'Q') quit(NULL);
else if (c == 'S') return (FALSE);
@@ -1693,86 +1372,27 @@ static bool_ player_birth_aux_ask()
/* 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;
+ k = game->previous_char.race;
}
else
{
/* Only one choice = instant choice */
- if (max_rp_idx == 1)
+ if (race_info.size() == 1)
+ {
k = 0;
+ }
else
{
/* Extra info */
Term_putstr(5, 16, -1, TERM_WHITE,
"Your 'race' determines various intrinsic factors and bonuses.");
- hack_corruption = FALSE;
/* Dump races */
sel = 0;
@@ -1782,7 +1402,7 @@ static bool_ player_birth_aux_ask()
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));
+ I2A(0), I2A(race_info.size() - 1));
put_str(buf, 17, 2);
c = inkey();
@@ -1790,12 +1410,15 @@ static bool_ player_birth_aux_ask()
if (c == 'S') return (FALSE);
if (c == '*')
{
- k = rand_int(max_rp_idx);
+ k = rand_int(race_info.size());
break;
}
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);
+ }
else if (c == '=')
{
screen_save();
@@ -1840,16 +1463,18 @@ static bool_ player_birth_aux_ask()
/* 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);
+ c_put_str(TERM_L_BLUE, rp_ptr->title.c_str(), RACE_ROW, 9);
/* Get a random name */
- if (!do_quick_start) create_random_name(p_ptr->prace, player_name);
+ if (!do_quick_start)
+ {
+ game->player_name = create_random_name();
+ }
/* Display */
- c_put_str(TERM_L_BLUE, player_name, 2, 9);
+ c_put_str(TERM_L_BLUE, game->player_name.c_str(), NAME_ROW, 9);
/* Clean up */
clear_from(12);
@@ -1858,21 +1483,23 @@ static bool_ player_birth_aux_ask()
/*** Player race mod ***/
if (do_quick_start)
{
- k = previous_char.rmod;
+ k = game->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)
+ if (race_mod_info.size() == 1)
+ {
k = 0;
+ }
else
{
for (n = 0; n < 100; n++) racem[n] = 0;
max_racem = 0;
- for (n = 0; n < max_rmp_idx; n++)
+ for (n = 0; n < static_cast<int>(race_mod_info.size()); n++)
{
/* Analyze */
p_ptr->pracem = n;
@@ -1911,14 +1538,25 @@ static bool_ player_birth_aux_ask()
if (c == 'S') return (FALSE);
if (c == '*')
{
- do
- {
- k = rand_int(max_racem);
+ // Which choices are legal?
+ std::vector<int> valid_choices(max_racem);
+ for (int i = 0; i < max_racem; i++) {
+ if ((BIT(racem[i]) & rmp_ptr->choice[racem[i] / 32]))
+ {
+ valid_choices.push_back(i);
+ }
}
- while (!(BIT(racem[k]) & rmp_ptr->choice[racem[k] / 32]));
+
+ // Choose
+ assert(!valid_choices.empty());
+ k = *uniform_element(valid_choices);
+
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.c_str());
+ }
k = (islower(c) ? A2I(c) : -1);
if ((k >= 0) && (k < max_racem) &&
@@ -1968,7 +1606,8 @@ static bool_ player_birth_aux_ask()
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);
+ auto const race_name = get_player_race_name(p_ptr->prace, p_ptr->pracem);
+ c_put_str(TERM_L_BLUE, race_name.c_str(), RACE_ROW, 9);
}
}
@@ -1979,72 +1618,49 @@ static bool_ player_birth_aux_ask()
/*** Player class ***/
if (do_quick_start)
{
- k = previous_char.pclass;
+ k = game->previous_char.pclass;
p_ptr->pclass = k;
cp_ptr = &class_info[p_ptr->pclass];
- k = previous_char.spec;
+ k = game->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++)
+ for (int z = 0; z < 2; z++)
+ {
restrictions[z] = (rp_ptr->choice[z] | rmp_ptr->pclass[z]) & (~rmp_ptr->mclass[z]);
+ }
- if (max_mc_idx > 1)
+ // Get list of all the classes.
+ std::vector<u16b> class_types;
+ for (std::size_t i = 0; i < class_info.size(); i++)
{
- /* Extra info */
- Term_putstr(5, 13, -1, TERM_WHITE,
- "Your 'class' determines various intrinsic abilities and bonuses.");
+ class_types.push_back(i);
+ }
- /* 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();
+ // Sort into display order
+ std::stable_sort(
+ class_types.begin(),
+ class_types.end(),
+ [&class_info](auto i, auto j) {
+ return class_info[i].display_order_idx < class_info[j].display_order_idx;
}
- }
- else
- {
- k = 0;
- }
- class_types = meta_class_info[k].classes;
- clear_from(15);
+ );
/* Count classes */
- n = 0;
- while (class_types[n] != -1) n++;
+ n = class_types.size();
/* Only one choice = instant choice */
if (n == 1)
+ {
k = 0;
+ }
else
{
/* Dump classes */
sel = 0;
- n = dump_classes(class_types, sel, restrictions);
+ dump_classes(class_types, sel, restrictions);
/* Get a class */
while (1)
@@ -2061,7 +1677,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);
+ }
else if (c == '=')
{
screen_save();
@@ -2110,11 +1729,7 @@ static bool_ player_birth_aux_ask()
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;
- }
+ n = class_info[p_ptr->pclass].spec.size();
/* Only one choice = auto choice */
if (n == 1)
@@ -2123,7 +1738,7 @@ static bool_ player_birth_aux_ask()
{
/* Dump classes spec */
sel = 0;
- n = dump_specs(sel);
+ dump_specs(sel);
/* Get a class */
while (1)
@@ -2140,7 +1755,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);
+ }
else if (c == '=')
{
screen_save();
@@ -2185,10 +1803,9 @@ static bool_ player_birth_aux_ask()
}
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);
+ c_put_str(TERM_L_BLUE, spp_ptr->title, CLASS_ROW, 9);
/* Clean up */
clear_from(15);
@@ -2196,26 +1813,27 @@ static bool_ player_birth_aux_ask()
/*** Player god ***/
if (do_quick_start)
{
- k = previous_char.god;
+ k = game->previous_char.god;
p_ptr->pgod = k;
- set_grace(previous_char.grace);
+ set_grace(game->previous_char.grace);
}
- else if (PRACE_FLAG(PR1_NO_GOD))
+ else if (race_flags_p(PR_NO_GOD))
{
p_ptr->pgod = GOD_NONE;
}
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)
@@ -2243,8 +1861,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 == '*')
@@ -2258,7 +1874,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();
@@ -2299,15 +1918,13 @@ static bool_ player_birth_aux_ask()
else bell();
}
- C_FREE(choice, max_gods, int);
-
/* Set god */
p_ptr->pgod = k;
p_ptr->grace = 0;
}
/* A god that like us ? more grace ! */
- if (PRACE_FLAGS(PR1_GOD_FRIEND))
+ if (race_flags_p(PR_GOD_FRIEND))
{
set_grace(200);
}
@@ -2334,11 +1951,8 @@ static bool_ player_birth_aux_ask()
}
}
- /* 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;
+ /* Is the player an "astral" being? */
+ p_ptr->astral = (race_flags_p(PR_ASTRAL)) ? TRUE : FALSE;
/*
* A note by pelpel. (remove this please)
@@ -2354,23 +1968,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,12 +1986,11 @@ 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 (!options->ironman_rooms)
{
if (do_quick_start)
{
- v = previous_char.quests;
+ v = game->previous_char.quests;
}
else
{
@@ -2437,16 +2043,13 @@ static bool_ player_birth_aux_ask()
/* 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);
+ /* Generate random quests */
+ initialize_random_quests(v);
max_quests = v;
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;
@@ -2469,7 +2072,7 @@ static bool_ player_birth_aux_ask()
plots[PLOT_OTHER] = QUEST_NULL;
}
- quest_random_init_hook(QUEST_RANDOM);
+ quest_random_init_hook();
/* Ok */
return (TRUE);
@@ -2501,7 +2104,7 @@ static const int birth_stat_costs[(18-10) + 1] =
*
* Taken from V 2.9.0
*/
-static bool_ player_birth_aux_point(void)
+static bool_ player_birth_aux_point()
{
int i;
@@ -2519,8 +2122,6 @@ static bool_ player_birth_aux_point(void)
char buf[80];
- int mode = 0;
-
/* Initialize stats */
for (i = 0; i < 6; i++)
@@ -2533,18 +2134,6 @@ static bool_ player_birth_aux_point(void)
/* Roll for base hitpoints */
get_extra();
- /* Roll for age/height/weight */
- get_ahw();
-
- /* Roll for social class */
- get_history();
-
- /*** 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;
@@ -2558,24 +2147,8 @@ static bool_ player_birth_aux_point(void)
/* 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);
- }
+ /* Reset stats */
+ p_ptr->stat_cur[i] = p_ptr->stat_max[i] = stats[i];
/* Total cost */
cost += birth_stat_costs[stats[i] - 10];
@@ -2613,7 +2186,7 @@ static bool_ player_birth_aux_point(void)
p_ptr->csp = p_ptr->msp;
/* Display the player */
- display_player(mode);
+ display_player(0);
/* Display the costs header */
put_str("Cost", row - 2, col + 32);
@@ -2683,8 +2256,6 @@ static bool_ player_birth_aux_auto()
{
int i, j, m, v;
- int mode = 0;
-
bool_ flag = FALSE;
bool_ prev = FALSE;
@@ -2700,10 +2271,8 @@ static bool_ player_birth_aux_auto()
char inp[80];
-#ifdef ALLOW_AUTOROLLER
-
/* Initialize */
- if (autoroll)
+ if (options->autoroll)
{
int mval[6];
@@ -2727,7 +2296,7 @@ static bool_ player_birth_aux_auto()
stat_match[i] = 0;
/* Race/Class bonus */
- j = rp_ptr->r_adj[i] + rmp_ptr->r_adj[i] + cp_ptr->c_adj[i];
+ j = rp_ptr->ps.adj[i] + rmp_ptr->ps.adj[i] + cp_ptr->ps.adj[i];
/* Obtain the "maximal" stat */
m = adjust_stat(17, j, TRUE);
@@ -2766,7 +2335,7 @@ static bool_ player_birth_aux_auto()
if (!askfor_aux(inp, 8)) inp[0] = '\0';
/* Weirdos stat display .. erm .. I mean, original stat display */
- if (!linear_stats)
+ if (!options->linear_stats)
{
/* Hack -- add a fake slash */
strcat(inp, "/");
@@ -2802,26 +2371,23 @@ static bool_ player_birth_aux_auto()
}
}
-#endif /* ALLOW_AUTOROLLER */
-
/* Roll */
while (TRUE)
{
/* Feedback */
- if (autoroll)
+ if (options->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, game->player_name.c_str(), 2, 9);
+
+ put_str("Race :", 3, 1);
+ auto const player_race_name = get_player_race_name(p_ptr->prace, p_ptr->pracem);
+ c_put_str(TERM_L_BLUE, player_race_name.c_str(), 3, 9);
- 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);
+ put_str("Class:", 4, 1);
+ c_put_str(TERM_L_BLUE, spp_ptr->title, 4, 9);
/* Label stats */
put_str("STR:", 2 + A_STR, 61);
@@ -2849,7 +2415,7 @@ static bool_ player_birth_aux_auto()
}
/* Auto-roll */
- while (autoroll)
+ while (options->autoroll)
{
bool_ accept = TRUE;
@@ -2896,17 +2462,8 @@ 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;
-
/* Check for a keypress */
- if (inkey()) break;
+ if (inkey_scan()) break;
}
}
@@ -2916,27 +2473,12 @@ static bool_ player_birth_aux_auto()
/*** 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, "()");
-
- /* 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)
{
@@ -2953,15 +2495,13 @@ static bool_ player_birth_aux_auto()
p_ptr->csp = p_ptr->msp;
/* Display the player */
- display_player(mode);
+ display_player(0);
/* 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);
@@ -2987,13 +2527,6 @@ static bool_ player_birth_aux_auto()
continue;
}
- /* Toggle the display */
- if ((c == 'H') || (c == 'h'))
- {
- mode = ((mode != 0) ? 0 : 1);
- continue;
- }
-
/* Help */
if (c == '?')
{
@@ -3031,20 +2564,20 @@ static bool_ player_birth_aux_auto()
*/
static bool_ player_birth_aux()
{
- char c;
+ auto const &s_descriptors = game->edit_data.s_descriptors;
+ auto &s_info = game->s_info;
- int i, j;
-
- int y = 0, x = 0;
-
- char old_history[4][60];
+ char c;
/* 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++)
+ for (std::size_t i = 1; i < s_descriptors.size(); i++)
+ {
+ s_info[i].dev = false;
+ }
+
+ for (std::size_t i = 1; i < s_descriptors.size(); i++)
{
s32b value = 0, mod = 0;
@@ -3055,14 +2588,18 @@ static bool_ player_birth_aux()
/* Develop only revelant branches */
if (s_info[i].value || s_info[i].mod)
{
- int z = s_info[i].father;
+ int z = s_descriptors[i].father;
while (z != -1)
{
- s_info[z].dev = TRUE;
- z = s_info[z].father;
+ // Mark as developed
+ s_info[z].dev = true;
+ // Next node up the tree
+ z = s_descriptors[z].father;
if (z == 0)
+ {
break;
+ }
}
}
}
@@ -3089,7 +2626,7 @@ static bool_ player_birth_aux()
else
{
/* Point based */
- if (point_based)
+ if (options->point_based)
{
if (!player_birth_aux_point()) return FALSE;
}
@@ -3099,83 +2636,9 @@ static bool_ player_birth_aux()
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();
@@ -3193,7 +2656,7 @@ static bool_ player_birth_aux()
}
/* Save this for the next character */
- previous_char.quick_ok = TRUE;
+ game->previous_char.quick_ok = TRUE;
save_prev_data();
/* Accept */
@@ -3202,105 +2665,9 @@ static bool_ player_birth_aux()
/*
- * 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)
+static void init_town(int t_idx)
{
town_type *t_ptr = &town_info[t_idx];
@@ -3311,10 +2678,7 @@ void init_town(int t_idx, int level)
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;
+ t_ptr->seed = seed_t::system();
}
/*
@@ -3323,12 +2687,14 @@ void init_town(int t_idx, int level)
* 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)
+void player_birth()
{
- int i, j, rtown = TOWN_RANDOM;
+ auto const &st_info = game->edit_data.st_info;
+ auto &d_info = game->edit_data.d_info;
+ auto &messages = game->messages;
- /* Validate the bg[] table */
- validate_bg();
+ /* Starting index for generated towns */
+ std::size_t rtown = TOWN_RANDOM;
/* Create a new character */
while (1)
@@ -3347,38 +2713,36 @@ void player_birth(void)
recalc_skills(FALSE);
/* grab level 1 abilities */
- for (i = 0; i < max_ab_idx; i++)
- ab_info[i].acquired = FALSE;
+ p_ptr->abilities.clear();
apply_level_abilities(1);
/* Complete the god */
- i = p_ptr->pgod;
- p_ptr->pgod = 0;
- follow_god(i, TRUE);
+ {
+ byte 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 */
- if (take_notes)
- {
- add_note_type(NOTE_BIRTH);
- }
+ add_note_type(NOTE_BIRTH);
/* 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);
+ messages.add(" ", TERM_L_BLUE);
+ messages.add(" ", TERM_L_BLUE);
+ messages.add("====================", TERM_L_BLUE);
+ messages.add(" ", TERM_L_BLUE);
+ messages.add(" ", TERM_L_BLUE);
/* Hack -- outfit the player */
player_outfit();
/* Initialize random towns in the dungeons */
- for (i = 0; i < max_d_idx; i++)
+ for (std::size_t i = 0; i < d_info.size(); i++)
{
- dungeon_info_type *d_ptr = &d_info[i];
+ auto d_ptr = &d_info[i];
int num = 0, z;
d_ptr->t_num = 0;
@@ -3387,7 +2751,7 @@ void player_birth(void)
d_ptr->t_idx[z] = 0;
d_ptr->t_level[z] = 0;
}
- if (!(d_ptr->flags1 & DF1_RANDOM_TOWNS)) continue;
+ if (!(d_ptr->flags & DF_RANDOM_TOWNS)) continue;
/* Can we add a town ? */
while (magik(TOWN_CHANCE - (num * 10)))
@@ -3399,15 +2763,17 @@ void player_birth(void)
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++)
+ for (int j = 0; j < num; j++)
{
- if (d_ptr->t_level[j] == lev) ok = FALSE;
+ if (d_ptr->t_level[j] == lev)
+ {
+ ok = FALSE;
+ }
}
/* Ok found one */
@@ -3415,10 +2781,13 @@ 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)
+ {
+ messages.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]);
+ init_town(d_ptr->t_idx[num]);
num++;
@@ -3430,7 +2799,7 @@ void player_birth(void)
}
/* Init the towns */
- for (i = 1; i < max_towns; i++)
+ for (std::size_t i = 1; i < max_towns; i++)
{
/* Not destroyed ! yet .. ;) */
town_info[i].destroyed = FALSE;
@@ -3441,7 +2810,7 @@ void player_birth(void)
create_stores_stock(i);
/* Init the stores */
- for (j = 0; j < max_st_idx; j++)
+ for (std::size_t j = 0; j < st_info.size(); j++)
{
/* Initialize */
store_init(i, j);
@@ -3449,28 +2818,27 @@ void player_birth(void)
}
/* Init wilderness seeds */
- for (i = 0; i < max_wild_x; i++)
+ auto &wilderness = game->wilderness;
+ for (std::size_t y = 0; y < wilderness.height(); y++)
{
- for (j = 0; j < max_wild_y; j++)
+ for (std::size_t x = 0; x < wilderness.width(); x++)
{
- wild_map[j][i].seed = rand_int(0x10000000);
- wild_map[j][i].entrance = 0;
- wild_map[j][i].known = FALSE;
+ auto &w = wilderness(x, y);
+ w.seed = seed_t::system();
+ w.entrance = 0;
+ w.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];
+static char savefile_module[46][80];
+static char savefile_names[46][30];
+static char savefile_desc[46][80];
+static bool_ savefile_alive[46];
+static int savefile_idx[46];
/*
* Grab all the names from an index
@@ -3480,7 +2848,7 @@ int load_savefile_names()
FILE *fff;
char buf[1024];
char tmp[50];
- char player_base_save[32];
+ std::string player_base_save;
int max = 0, fd;
@@ -3488,9 +2856,6 @@ int load_savefile_names()
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");
@@ -3499,7 +2864,7 @@ int load_savefile_names()
/* Save the current 'player_base' */
- strncpy(player_base_save, player_base, 32);
+ player_base_save = game->player_base;
/*
@@ -3558,12 +2923,9 @@ int load_savefile_names()
strcpy(savefile_desc[max], buf + i);
/* Build platform-dependent savefile name */
- strncpy(player_base, savefile_names[max], 32);
+ game->player_base = savefile_names[max];
process_player_name(TRUE);
- /* File type is 'SAVE' */
- FILE_TYPE(FILE_TYPE_SAVE);
-
/* Try to open the savefile */
fd = fd_open(savefile, O_RDONLY);
@@ -3578,7 +2940,7 @@ int load_savefile_names()
my_fclose(fff);
/* Restore the values of 'player_base' and 'savefile' */
- strncpy(player_base, player_base_save, 32);
+ game->player_base = player_base_save;
process_player_name(TRUE);
return (max);
@@ -3600,9 +2962,6 @@ void save_savefile_names()
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");
@@ -3613,15 +2972,16 @@ void save_savefile_names()
* Save, use '@' intead of ':' as a separator because it cannot exists
* in savefiles
*/
+ auto const player_race_name = get_player_race_name(p_ptr->prace, p_ptr->pracem);
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) ? '0' : '1', game->player_base.c_str(), game->player_name.c_str(),
+ player_race_name.c_str(),
+ spp_ptr->title,
(!death) ? "alive" : "dead");
for (i = 0; i < max; i++)
{
- if (!strcmp(savefile_names[i], player_base)) continue;
+ if (!strcmp(savefile_names[i], game->player_base.c_str())) continue;
fprintf(fff, "%s@%c%s@%s\n", savefile_module[i],
(savefile_alive[i]) ? '1' : '0', savefile_names[i], savefile_desc[i]);
}
@@ -3694,7 +3054,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;
@@ -3752,22 +3112,20 @@ savefile_try_again:
}
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);
+ std::string player_base_save = game->player_base;
/* Build platform-dependent save file name */
- strncpy(player_base, savefile_names[savefile_idx[sel - 2]], 32);
+ game->player_base = savefile_names[savefile_idx[sel - 2]];
process_player_name(TRUE);
/* Remove the savefile */
fd_kill(savefile);
/* Restore 'player_base' and 'savefile' */
- strncpy(player_base, player_base_save, 32);
+ game->player_base = player_base_save;
process_player_name(TRUE);
/* Reload, gods I hate using goto .. */
@@ -3776,18 +3134,49 @@ savefile_try_again:
continue;
}
+ //
+ // React
+ //
+
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;
+ if (!askfor_aux(&game->player_base, 15)) continue;
/* Process the player name */
process_player_name(TRUE);
- return (TRUE);
+ // If the savefile already exists, we do *NOT* want to
+ // create a new game, so we'll need to return FALSE for
+ // that.
+ if (boost::filesystem::exists(savefile))
+ {
+ // Show a message so user doesn't get confused.
+ msg_print(NULL);
+
+ // Prompt for it
+ prt(fmt::format(
+ "Character '{}' already exists! Press any key to load.",
+ game->player_base),
+ 0, 0);
+
+ // Wait
+ inkey();
+
+ // Erase the prompt
+ prt("", 0, 0);
+
+ // Load character
+ return FALSE;
+ }
+ else
+ {
+ // Start new game
+ return TRUE;
+ }
}
if (k == 'b')
{
@@ -3795,7 +3184,7 @@ savefile_try_again:
prt("Enter the name of a savefile: ", 23, 0);
/* Ask the user for a string */
- if (!askfor_aux(player_base, 15)) continue;
+ if (!askfor_aux(&game->player_base, 15)) continue;
/* Process the player name */
process_player_name(TRUE);
@@ -3811,7 +3200,7 @@ savefile_try_again:
if ((x < 2) || (x >= max)) continue;
- strnfmt(player_base, 32, "%s", savefile_names[savefile_idx[x - 2]]);
+ game->player_base = savefile_names[savefile_idx[x - 2]];
/* Process the player name */
process_player_name(TRUE);
diff --git a/src/birth.hpp b/src/birth.hpp
new file mode 100644
index 00000000..82bdfcf6
--- /dev/null
+++ b/src/birth.hpp
@@ -0,0 +1,11 @@
+#pragma once
+
+#include "h-basic.h"
+
+void print_desc_aux(cptr txt, int y, int x);
+void save_savefile_names();
+bool_ begin_screen();
+void player_birth();
+void roll_player_hp();
+
+extern bool_ no_begin_screen;
diff --git a/src/birther.hpp b/src/birther.hpp
new file mode 100644
index 00000000..0c28b513
--- /dev/null
+++ b/src/birther.hpp
@@ -0,0 +1,29 @@
+#pragma once
+
+#include "h-basic.h"
+
+#include <string>
+#include <vector>
+
+/**
+ * Player information during the birth process.
+ */
+struct birther
+{
+ s16b race;
+ s16b rmod;
+ s16b pclass;
+ s16b spec;
+
+ byte quests;
+
+ byte god;
+ s32b grace;
+
+ s32b au;
+
+ s16b stat[6];
+ s16b luck;
+
+ bool_ quick_ok;
+};
diff --git a/src/bldg.c b/src/bldg.cc
index 48e94e9f..9b3750a6 100644
--- a/src/bldg.c
+++ b/src/bldg.cc
@@ -13,10 +13,37 @@
* Heavily modified for ToME by DarkGod
*/
-#include "angband.h"
-
-/* hack as in leave_store in store.c */
-static bool_ leave_bldg = FALSE;
+#include "cave_type.hpp"
+#include "cmd3.hpp"
+#include "files.hpp"
+#include "game.hpp"
+#include "hooks.hpp"
+#include "hook_quest_finish_in.hpp"
+#include "hook_quest_fail_in.hpp"
+#include "hook_init_quest_in.hpp"
+#include "mimic.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_flag.hpp"
+#include "owner_type.hpp"
+#include "player_race_flag.hpp"
+#include "player_type.hpp"
+#include "q_library.hpp"
+#include "q_fireprof.hpp"
+#include "q_bounty.hpp"
+#include "spells2.hpp"
+#include "stats.hpp"
+#include "store.hpp"
+#include "store_action_type.hpp"
+#include "store_info_type.hpp"
+#include "store_type.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "util.h"
+#include "variable.hpp"
+#include "xtra1.hpp"
+#include "xtra2.hpp"
+#include "z-rand.hpp"
/* remember building location */
static int building_loc = 0;
@@ -25,10 +52,11 @@ static int building_loc = 0;
/*
* A helper function for is_state
*/
-bool_ is_state_aux(store_type *s_ptr, int state)
+static bool_ is_state_aux(store_type const *s_ptr, int state)
{
- owner_type *ow_ptr = &ow_info[s_ptr->owner];
+ auto const &ow_info = game->edit_data.ow_info;
+ auto ow_ptr = &ow_info[s_ptr->owner];
/* Check race */
if (ow_ptr->races[state][p_ptr->prace / 32] & (1 << p_ptr->prace))
@@ -50,7 +78,7 @@ bool_ is_state_aux(store_type *s_ptr, int state)
/*
* Test if the state accords with the player
*/
-bool_ is_state(store_type *s_ptr, int state)
+bool_ is_state(store_type const *s_ptr, int state)
{
if (state == STORE_NORMAL)
{
@@ -84,218 +112,95 @@ static void clear_bldg(int min_row, int max_row)
/*
* Display a building.
*/
-void show_building(store_type *s_ptr)
+void show_building(store_type const *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];
+ auto const &ba_info = game->edit_data.ba_info;
+ auto const &st_info = game->edit_data.st_info;
- store_action_type *ba_ptr;
+ auto st_ptr = &st_info[s_ptr->st_idx];
-
- for (i = 0; i < 6; i++)
+ for (std::size_t i = 0; i < st_ptr->actions.size(); i++)
{
- ba_ptr = &ba_info[st_ptr->actions[i]];
+ auto ba_ptr = &ba_info[st_ptr->actions[i]];
+
+ byte action_color;
+ char buff[20];
- if (ba_ptr->letter != '.')
+ if (ba_ptr->action_restr == 0)
{
- 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)))
{
- 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]);
- }
+ action_color = TERM_WHITE;
+ buff[0] = '\0';
}
- else if (ba_ptr->action_restr == 1)
+ else if (is_state(s_ptr, STORE_LIKED))
{
- 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]);
- }
+ 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
{
- 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)");
- }
+ action_color = TERM_YELLOW;
+ strnfmt(buff, 20, "(%dgp)", ba_ptr->costs[STORE_NORMAL]);
}
-
- 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:
+ else if (ba_ptr->action_restr == 1)
{
- if (p_ptr->arena_number == MAX_ARENA_MONS)
+ 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)))
{
- 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++;
+ action_color = TERM_WHITE;
+ buff[0] = '\0';
}
- else if (p_ptr->arena_number > MAX_ARENA_MONS)
+ else if (is_state(s_ptr, STORE_LIKED))
{
- msg_print("You enter the arena briefly and bask in your glory.");
- msg_print(NULL);
+ 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
{
- 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;
+ action_color = TERM_YELLOW;
+ strnfmt(buff, 20, "(%dgp)", ba_ptr->costs[STORE_NORMAL]);
}
-
- break;
}
-
- case BACT_POSTER:
+ else
{
- 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.");
+ 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
{
- 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);
+ action_color = TERM_L_DARK;
+ strnfmt(buff, 20, "(closed)");
}
-
- break;
}
- case BACT_ARENA_RULES:
- {
- /* Save screen */
- screen_save();
-
- /* Peruse the arena help file */
- (void)show_file("arena.txt", NULL, 0, 0);
+ char tmp_str[80];
- /* Load screen */
- screen_load();
+ strnfmt(tmp_str, 80, " %c", ba_ptr->letter);
+ c_put_str(TERM_YELLOW, tmp_str, 21 + (i / 2), 17 + (30 * (i % 2)));
- break;
- }
+ strnfmt(tmp_str, 80, ") %s %s", ba_ptr->name.c_str(), buff);
+ c_put_str(action_color, tmp_str, 21 + (i / 2), 2 + 17 + (30 * (i % 2)));
}
}
@@ -427,7 +332,7 @@ static bool_ gamble_comm(int cmd)
if (cmd == BACT_GAMBLE_RULES)
{
/* Peruse the gambling help file */
- (void)show_file("gambling.txt", NULL, 0, 0);
+ show_file("gambling.txt", NULL);
}
else
{
@@ -541,40 +446,6 @@ static bool_ gamble_comm(int cmd)
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);
@@ -670,7 +541,7 @@ static bool_ inn_comm(int cmd)
/* Extract race info */
- vampire = ((PRACE_FLAG(PR1_VAMPIRE)) || (p_ptr->mimic_form == resolve_mimic_name("Vampire")));
+ vampire = ((race_flags_p(PR_VAMPIRE)) || (p_ptr->mimic_form == resolve_mimic_name("Vampire")));
switch (cmd)
{
@@ -680,7 +551,7 @@ static bool_ inn_comm(int cmd)
{
msg_print("The barkeep gives you some gruel and a beer.");
msg_print(NULL);
- (void) set_food(PY_FOOD_MAX - 1);
+ set_food(PY_FOOD_MAX - 1);
}
else
msg_print("You're a vampire and I don't have any food for you!");
@@ -760,9 +631,6 @@ static bool_ inn_comm(int cmd)
p_ptr->oldpx = p_ptr->px;
p_ptr->oldpy = p_ptr->py;
- /* Select new bounties. */
- select_bounties();
-
break;
}
@@ -834,7 +702,8 @@ static bool_ castle_quest(int y, int x)
/* Rewarded quest */
q_ptr->status = QUEST_STATUS_FINISHED;
- process_hooks(HOOK_QUEST_FINISH, "(d)", plots[plot]);
+ struct hook_quest_finish_in in = { plots[plot] };
+ process_hooks_new(HOOK_QUEST_FINISH, &in, NULL);
return (TRUE);
}
@@ -854,14 +723,19 @@ static bool_ castle_quest(int y, int x)
/* Mark quest as done (but failed) */
q_ptr->status = QUEST_STATUS_FAILED_DONE;
- process_hooks(HOOK_QUEST_FAIL, "(d)", plots[plot]);
+ hook_quest_fail_in in = { plots[plot] };
+ process_hooks_new(HOOK_QUEST_FAIL, &in, NULL);
return (FALSE);
}
/* No quest yet */
else if (q_ptr->status == QUEST_STATUS_UNTAKEN)
{
- if (process_hooks(HOOK_INIT_QUEST, "(d)", plots[plot])) return (FALSE);
+ struct hook_init_quest_in in = { plots[plot] };
+ if (process_hooks_new(HOOK_INIT_QUEST, &in, NULL))
+ {
+ return (FALSE);
+ }
q_ptr->status = QUEST_STATUS_TAKEN;
@@ -869,7 +743,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();
return (TRUE);
}
@@ -880,13 +754,13 @@ static bool_ castle_quest(int y, int x)
/*
* Displaying town history -KMW-
*/
-static void town_history(void)
+static void town_history()
{
/* Save screen */
screen_save();
/* Peruse the building help file */
- (void)show_file("bldg.txt", NULL, 0, 0);
+ show_file("bldg.txt", NULL);
/* Load screen */
screen_load();
@@ -896,7 +770,7 @@ static void town_history(void)
/*
* 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)
+static void compare_weapon_aux2(object_type *o_ptr, int numblows, int r, int c, int mult, const char *attr, byte color)
{
char tmp_str[80];
@@ -914,80 +788,77 @@ static void compare_weapon_aux2(object_type *o_ptr, int numblows, int r, int c,
*/
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);
-
+ auto const f = object_flags(o_ptr);
- if (f1 & (TR1_SLAY_ANIMAL))
+ if (f & TR_SLAY_ANIMAL)
{
compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 2, "Animals:",
- f1, f2, f3, TERM_YELLOW);
+ TERM_YELLOW);
}
- if (f1 & (TR1_SLAY_EVIL))
+ if (f & TR_SLAY_EVIL)
{
compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 2, "Evil:",
- f1, f2, f3, TERM_YELLOW);
+ TERM_YELLOW);
}
- if (f1 & (TR1_SLAY_UNDEAD))
+ if (f & TR_SLAY_UNDEAD)
{
compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Undead:",
- f1, f2, f3, TERM_YELLOW);
+ TERM_YELLOW);
}
- if (f1 & (TR1_SLAY_DEMON))
+ if (f & TR_SLAY_DEMON)
{
compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Demons:",
- f1, f2, f3, TERM_YELLOW);
+ TERM_YELLOW);
}
- if (f1 & (TR1_SLAY_ORC))
+ if (f & TR_SLAY_ORC)
{
compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Orcs:",
- f1, f2, f3, TERM_YELLOW);
+ TERM_YELLOW);
}
- if (f1 & (TR1_SLAY_TROLL))
+ if (f & TR_SLAY_TROLL)
{
compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Trolls:",
- f1, f2, f3, TERM_YELLOW);
+ TERM_YELLOW);
}
- if (f1 & (TR1_SLAY_GIANT))
+ if (f & TR_SLAY_GIANT)
{
compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Giants:",
- f1, f2, f3, TERM_YELLOW);
+ TERM_YELLOW);
}
- if (f1 & (TR1_SLAY_DRAGON))
+ if (f & TR_SLAY_DRAGON)
{
compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Dragons:",
- f1, f2, f3, TERM_YELLOW);
+ TERM_YELLOW);
}
- if (f1 & (TR1_KILL_DRAGON))
+ if (f & TR_KILL_DRAGON)
{
compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 5, "Dragons:",
- f1, f2, f3, TERM_YELLOW);
+ TERM_YELLOW);
}
- if (f1 & (TR1_BRAND_ACID))
+ if (f & TR_BRAND_ACID)
{
compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Acid:",
- f1, f2, f3, TERM_RED);
+ TERM_RED);
}
- if (f1 & (TR1_BRAND_ELEC))
+ if (f & TR_BRAND_ELEC)
{
compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Elec:",
- f1, f2, f3, TERM_RED);
+ TERM_RED);
}
- if (f1 & (TR1_BRAND_FIRE))
+ if (f & TR_BRAND_FIRE)
{
compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Fire:",
- f1, f2, f3, TERM_RED);
+ TERM_RED);
}
- if (f1 & (TR1_BRAND_COLD))
+ if (f & TR_BRAND_COLD)
{
compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Cold:",
- f1, f2, f3, TERM_RED);
+ TERM_RED);
}
- if (f1 & (TR1_BRAND_POIS))
+ if (f & TR_BRAND_POIS)
{
compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Poison:",
- f1, f2, f3, TERM_RED);
+ TERM_RED);
}
}
@@ -1023,7 +894,7 @@ static void list_weapon(object_type *o_ptr, int row, int col)
/*
* Select melee weapons
*/
-static bool_ item_tester_hook_melee_weapon(object_type *o_ptr)
+static bool item_tester_hook_melee_weapon(object_type const *o_ptr)
{
return (wield_slot(o_ptr) == INVEN_WIELD);
}
@@ -1031,36 +902,30 @@ static bool_ item_tester_hook_melee_weapon(object_type *o_ptr)
/*
* compare_weapons -KMW-
*/
-static bool_ compare_weapons(void)
+static bool_ compare_weapons()
{
- int item, item2, i;
+ int item, 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];
+ object_type *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)))
+ /* Get first weapon */
+ if (!get_item(&item,
+ "What is your first melee weapon? ",
+ "You have nothing to compare.",
+ (USE_EQUIP | USE_INVEN),
+ item_tester_hook_melee_weapon))
{
object_wipe(orig_ptr);
return (FALSE);
@@ -1071,12 +936,12 @@ static bool_ compare_weapons(void)
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)))
+ int item2;
+ if (!get_item(&item2,
+ "What is your second melee weapon? ",
+ "You have nothing to compare.",
+ (USE_EQUIP | USE_INVEN),
+ item_tester_hook_melee_weapon))
{
object_wipe(orig_ptr);
return (FALSE);
@@ -1121,8 +986,7 @@ static bool_ compare_weapons(void)
* sharpen arrows, repair armor, repair weapon
* -KMW-
*/
-static bool_ fix_item(int istart, int iend, int ispecific, bool_ iac,
- int ireward, bool_ set_reward)
+static bool_ fix_item(int istart, int iend, int ispecific, bool_ iac)
{
int i;
@@ -1216,403 +1080,25 @@ static bool_ fix_item(int istart, int iend, int ispecific, bool_ iac,
/*
* Research Item
*/
-static bool_ research_item(void)
+static bool_ research_item()
{
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)
+bool_ bldg_process_command(const store_type *s_ptr, store_action_type const *ba_ptr)
{
- 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;
@@ -1638,22 +1124,6 @@ bool_ bldg_process_command(store_type *s_ptr, int i)
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)
{
@@ -1662,8 +1132,6 @@ bool_ bldg_process_command(store_type *s_ptr, int i)
return FALSE;
}
- if (!bcost) set_reward = TRUE;
-
switch (bact)
{
case BACT_RESEARCH_ITEM:
@@ -1685,9 +1153,6 @@ bool_ bldg_process_command(store_type *s_ptr, int i)
}
case BACT_QUEST1:
- case BACT_QUEST2:
- case BACT_QUEST3:
- case BACT_QUEST4:
{
int y = 1, x = 1;
bool_ ok = FALSE;
@@ -1721,24 +1186,13 @@ bool_ bldg_process_command(store_type *s_ptr, int i)
}
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:
{
@@ -1754,12 +1208,6 @@ bool_ bldg_process_command(store_type *s_ptr, int i)
break;
}
- case BACT_RESEARCH_MONSTER:
- {
- paid = !research_mon();
- break;
- }
-
case BACT_COMPARE_WEAPONS:
{
paid = compare_weapons();
@@ -1768,15 +1216,13 @@ bool_ bldg_process_command(store_type *s_ptr, int i)
case BACT_ENCHANT_WEAPON:
{
- paid = fix_item(INVEN_WIELD, INVEN_WIELD, 0, FALSE,
- BACT_ENCHANT_WEAPON, set_reward);
+ paid = fix_item(INVEN_WIELD, INVEN_WIELD, 0, FALSE);
break;
}
case BACT_ENCHANT_ARMOR:
{
- paid = fix_item(INVEN_BODY, INVEN_FEET, 0, TRUE,
- BACT_ENCHANT_ARMOR, set_reward);
+ paid = fix_item(INVEN_BODY, INVEN_FEET, 0, TRUE);
break;
}
@@ -1842,15 +1288,13 @@ bool_ bldg_process_command(store_type *s_ptr, int i)
case BACT_ENCHANT_ARROWS:
{
- paid = fix_item(0, INVEN_WIELD, TV_ARROW, FALSE,
- BACT_ENCHANT_ARROWS, set_reward);
+ paid = fix_item(0, INVEN_WIELD, TV_ARROW, FALSE);
break;
}
case BACT_ENCHANT_BOW:
{
- paid = fix_item(INVEN_BOW, INVEN_BOW, TV_BOW, FALSE,
- BACT_ENCHANT_BOW, set_reward);
+ paid = fix_item(INVEN_BOW, INVEN_BOW, TV_BOW, FALSE);
break;
}
@@ -1880,30 +1324,6 @@ bool_ bldg_process_command(store_type *s_ptr, int i)
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;
@@ -1953,92 +1373,41 @@ bool_ bldg_process_command(store_type *s_ptr, int i)
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);
+ case BACT_DROP_ITEM:
+ {
+ quest_bounty_drop_item();
+ break;
+ }
- req = get_quantity(prompt, req);
+ case BACT_GET_ITEM:
+ {
+ quest_bounty_get_item();
+ break;
+ }
- p_ptr->loan -= req;
- p_ptr->au -= req;
+ case BACT_LIBRARY_QUEST:
+ {
+ quest_library_building(&paid, &recreate);
+ break;
+ }
- if (!p_ptr->loan) p_ptr->loan_time = 0;
+ case BACT_FIREPROOF_QUEST:
+ {
+ quest_fireproof_building(&paid, &recreate);
+ break;
+ }
- msg_format("You pay back %i gold pieces", req);
- paid = TRUE;
- 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;
- }
+ printf("Unknown building action %d\n", static_cast<int>(bact));
+ break;
}
if (paid)
@@ -2056,7 +1425,7 @@ bool_ bldg_process_command(store_type *s_ptr, int i)
/*
* Enter quest level
*/
-void enter_quest(void)
+void enter_quest()
{
if (!(cave[p_ptr->py][p_ptr->px].feat == FEAT_QUEST_ENTER))
{
@@ -2078,121 +1447,3 @@ void enter_quest(void)
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.hpp b/src/bldg.hpp
new file mode 100644
index 00000000..3b3412fa
--- /dev/null
+++ b/src/bldg.hpp
@@ -0,0 +1,10 @@
+#pragma once
+
+#include "h-basic.h"
+#include "store_action_type_fwd.hpp"
+#include "store_type_fwd.hpp"
+
+bool_ bldg_process_command(store_type const *s_ptr, store_action_type const *action);
+void show_building(store_type const *s_ptr);
+bool_ is_state(store_type const *s_ptr, int state);
+void enter_quest();
diff --git a/src/body.hpp b/src/body.hpp
new file mode 100644
index 00000000..dd0be282
--- /dev/null
+++ b/src/body.hpp
@@ -0,0 +1,12 @@
+#pragma once
+
+/*
+ * Body parts
+ */
+#define BODY_WEAPON 0
+#define BODY_TORSO 1
+#define BODY_ARMS 2
+#define BODY_FINGER 3
+#define BODY_HEAD 4
+#define BODY_LEGS 5
+#define BODY_MAX 6
diff --git a/src/carbon/Angband.icns b/src/carbon/Angband.icns
deleted file mode 100644
index 3d775739..00000000
--- a/src/carbon/Angband.icns
+++ /dev/null
Binary files differ
diff --git a/src/carbon/Carbon.r b/src/carbon/Carbon.r
deleted file mode 100644
index e3194dd2..00000000
--- a/src/carbon/Carbon.r
+++ /dev/null
@@ -1,1568 +0,0 @@
-/*
- * Minimal Resources for T.o.M.E.
- *
- * Turned into human-readable and programmer-friendly format by pelpel
- *
- *
- * This might help mac/non-mac coders to play, modify, hack and do
- * whatever they like with this file.
- *
- *
- * Header files and reasons for their inclusion:
- *
- * MacTypes.r - 'STR ' and 'STR#'
- * Finder.r - 'BNDL' and 'FREF'
- * Dialogs.r - 'ALRT', 'DITL' and 'DLOG'
- * Menus.r - 'MENU' and 'MBAR'
- * Processes.r - 'SIZE'
- */
-
-#include <MacTypes.r>
-#include <Finder.r>
-#include <Dialogs.r>
-#include <Menus.r>
-#include <Processes.r>
-
-
-#ifndef MACH_O
-
-/*
- * Signature - Who am I?
- * Vanilla uses 'A271'
- * ID should always be 0.
- */
-#define AngbandSignature 'PrnA'
-
-type AngbandSignature as 'STR ';
-
-resource AngbandSignature (0, "Owner resource", purgeable)
-{
- "T.o.M.E. 2.3.4"
-};
-
-
-/* OS X Finder requires this to recognise a Carbon-compatible PEF binary */
-data 'plst' (0)
-{
- "$00";
-};
-
-
-/*
- * Inform system of program's characteristics
- * ID should always be -1.
- */
-resource 'SIZE' (-1)
-{
- /*
- * Flags dumped = 0101 1000 1100 0000
- */
- reserved,
-
- /* accepts/ignores suspend&resume events? */
- acceptSuspendResumeEvents,
-
- reserved,
-
- /* can use background null events */
- canBackground,
-
- /* activates own windows in response to OS events */
- doesActivateOnFGSwitch,
-
- /* app has a user interface */
- backgroundAndForeground,
-
- /* don't return mouse events in front window on resume */
- dontGetFrontClicks,
-
- /* applications use this */
- ignoreAppDiedEvents,
-
- /* works with 24- or 32-bit addr */
- is32BitCompatible,
-
- /* can use high-level events */
- isHighLevelEventAware,
-
- /* only local high-level events */
- onlyLocalHLEvents,
-
- /* can't use stationery documents */
- notStationeryAware,
-
- /* can't use inline services */
- dontUseTextEditServices,
-
- /* all windows redrawn when monitor(s) change */
- notDisplayManagerAware,
-
- reserved,
- reserved,
-
- /* preferred memory size */
- 16 * (1024 * 1024),
-
- /* minimum memory size */
- 4 * (1024 * 1024)
-};
-
-
-/*
- * File types used by Angband
- */
-resource 'FREF' (128, purgeable)
-{
- /* file type */
- 'APPL',
-
- /* maps to icon list resource w/ local ID 0 in bundle resource */
- 0,
-
- /* leave empty string for name */
- ""
-};
-
-resource 'FREF' (129, purgeable)
-{
- /* file type */
- 'SAVE',
-
- /* maps to icon list resource w/ local ID 1 in bundle resource */
- 1,
-
- /* leave empty string for name */
- ""
-};
-
-resource 'FREF' (130, purgeable)
-{
- /* file type */
- 'TEXT',
-
- /* maps to icon list resource w/ local ID 2 in bundle resource */
- 2,
-
- /* leave empty string for name */
- ""
-};
-
-resource 'FREF' (131, purgeable)
-{
- /* file type */
- 'DATA',
-
- /* maps to icon list resource w/ local ID 3 in bundle resource */
- 3,
-
- /* leave empty string for name */
- ""
-};
-
-
-/*
- * Bundle information
- */
-resource 'BNDL' (128, purgeable)
-{
- /* Our signature */
- AngbandSignature,
-
- /* resource ID of signature resource: should always be 0 */
- 0,
-
- {
- /* mapping local IDs in 'FREF's to 'ICN#' IDs */
- 'ICN#',
- {
- /* local ID 0 -> ICN# 128 */
- 0, 128,
-
- /* local ID 1 -> ICN# 129 */
- 1, 129,
-
- /* local ID 2 -> ICN# 130 */
- 2, 130,
-
- /* local ID 3 -> ICN# 131 */
- 3, 131
- },
-
- /* local res IDs for 'FREF's: no duplicates */
- 'FREF',
- {
- /* local ID 0 -> FREF 128 */
- 0, 128,
-
- /* local ID 1 -> FREF 129 */
- 1, 129,
-
- /* local ID 2 -> FREF 130 */
- 2, 130,
-
- /* local ID 3 -> FREF 131 */
- 3, 131
- }
- }
-};
-
-#endif /* !MACH_O */
-
-/*
- * Menu definitions
- */
-resource 'MENU' (128, preload)
-{
- /* menu ID */
- 128,
-
- /* use standard definition proc */
- textMenuProc,
-
- /* everything but the divider is enabled */
- 0b11111111111111111111111111111101,
- /* or we can use 0... */
-
- /* enable the title */
- enabled,
-
- /* menu title */
- apple,
-
- /* its contents */
- {
- /* First item */
- "About T.o.M.E. ...", noicon, nokey, nomark, plain;
-
- /* Second item - divider */
- "-", noicon, nokey, nomark, plain;
- }
-};
-
-resource 'MENU' (129, preload)
-{
- /* menu ID */
- 129,
-
- /* use standard definition proc */
- textMenuProc,
-
- /* let the program enable/disable them */
- 0b00000000000000000000000000011011,
-
- /* enable the title */
- enabled,
-
- /* menu title */
- "File",
-
- /* 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;
-
- /* item #2 (was #5) */
- "Save", noicon, "S", nomark, plain;
-
- /* item #3 (was #6) */
- "-", noicon, nokey, nomark, plain;
-
- /* item #4 (was #7) */
- "Score", noicon, "H", nomark, plain;
-
- /* item #4 (was #7) */
- "Quit", noicon, "Q", nomark, plain;
- }
-};
-
-
-resource 'MENU' (130, preload)
-{
- /* menu ID */
- 130,
-
- /* use standard definition proc */
- textMenuProc,
-
- /* let the program enable/disable them */
- 0b00000000000000000000000000111101,
-
- /* enable the title */
- enabled,
-
- /* menu title */
- "Edit",
-
- /* its contents */
- {
- /* item #1 */
- "Undo", noicon, "Z", nomark, plain;
-
- /* item #2 */
- "-", noicon, nokey, nomark, plain;
-
- /* item #3 */
- "Cut", noicon, "X", nomark, plain;
-
- /* item #4 */
- "Copy", noicon, "C", nomark, plain;
-
- /* item #5 */
- "Paste", noicon, "V", nomark, plain;
-
- /* item #6 */
- "Clear", noicon, nokey, nomark, plain;
- }
-};
-
-resource 'MENU' (131, preload)
-{
- /* menu ID */
- 131,
-
- /* use standard definition proc */
- textMenuProc,
-
- /* let the program enable/disable them */
- 0b00000000000000000000000000000011,
-
- /* enable the title */
- enabled,
-
- /* menu title */
- "Font",
-
- /* its contents */
- {
- /* item #1 */
- "Bold", noicon, nokey, nomark, plain;
-
- /* item #2 */
- "Wide", noicon, nokey, nomark, plain;
-
- /* item #3 */
- "-", noicon, nokey, nomark, plain;
-
- /* the rest are supplied by the program */
- }
-};
-
-resource 'MENU' (132, preload)
-{
- /* menu ID */
- 132,
-
- /* use standard definition proc */
- textMenuProc,
-
- /* let the program enable/disable them */
- 0b00000000000000000000000000000000,
-
- /* enable the title */
- enabled,
-
- /* menu title */
- "Size",
-
- /* its contents */
- {
- /* Let the program fill it in */
- }
-};
-
-resource 'MENU' (133, preload)
-{
- /* menu ID */
- 133,
-
- /* use standard definition proc */
- textMenuProc,
-
- /* let the program enable/disable them */
- 0b00000000000000000000000000000000,
-
- /* enable the title */
- enabled,
-
- /* menu title */
- "Windows",
-
- /* its contents */
- {
- /* Let the program create them for us */
- }
-};
-
-resource 'MENU' (134, preload)
-{
- /* menu ID */
- 134,
-
- /* use standard definition proc */
- textMenuProc,
-
- /* let the program enable/disable them */
- 0b00000000000000000000000000011011,
-
- /* enable the title */
- enabled,
-
- /* menu title */
- "Special",
-
- /* its contents */
- {
- /* item #1 */
- "Sound", noicon, nokey, nomark, plain;
-
- /* item #2 - 0x90 = 144 */
- "Graphics", noicon, hierarchicalMenu, "\0x90", plain;
-
- /* item #3 - 0x91 = 145 */
- "TileWidth", noicon, hierarchicalMenu, "\0x91", plain;
-
- /* item #4 - 0x92 = 146 */
- "TileHeight", noicon, hierarchicalMenu, "\0x92", plain;
-
- /* item #5 */
- "-", noicon, nokey, nomark, plain;
-
- /* item #6 */
- "Fiddle", noicon, nokey, nomark, plain;
-
- /* item #7 */
- "Wizard", noicon, nokey, nomark, plain;
- }
-};
-
-/* Graphics submenu */
-resource 'MENU' (144, preload)
-{
- /* menu ID */
- 144,
-
- /* use standard definition proc */
- textMenuProc,
-
- /* let the program enable/disable them */
- 0b00000000000000000000000000000111,
-
- /* enable the title */
- enabled,
-
- /* menu title (ignored) */
- "Graphics",
-
- /* menu items */
- {
- /* item #1 */
- "None", noicon, nokey, nomark, plain;
-
- /* item #2 */
- "8x8", noicon, nokey, nomark, plain;
-
- /* item #3 */
- "16x16", noicon, nokey, nomark, plain;
-
- /* item #4 */
- "32x32", noicon, nokey, nomark, plain;
-
- /* item #5 */
- "-", noicon, nokey, nomark, plain;
-
- /* item #6 */
- "Enlarge tiles", noicon, nokey, nomark, plain;
- }
-};
-
-/* Tilewidth submenu */
-resource 'MENU' (145, preload)
-{
- /* menu ID */
- 145,
-
- /* use standard definition proc */
- textMenuProc,
-
- /* let the program enable/disable them */
- 0b00000000000000000000000000000000,
-
- /* enable the title */
- enabled,
-
- /* menu title */
- "TileWidth",
-
- /* its contents */
- {
- /* Let the program create them for us */
- }
-};
-
-/* TileHeight submenu */
-resource 'MENU' (146, preload)
-{
- /* menu ID */
- 146,
-
- /* use standard definition proc */
- textMenuProc,
-
- /* let the program enable/disable them */
- 0b00000000000000000000000000000000,
-
- /* enable the title */
- enabled,
-
- /* menu title */
- "TileHeight",
-
- /* its contents */
- {
- /* Let the program create them for us */
- }
-};
-
-/* Menu bar definition */
-resource 'MBAR' (128, preload)
-{
- { 128, 129, 130, 131, 132, 133, 134 }
-};
-
-
-/*
- * Dialogue item lists
- */
-resource 'DITL' (129, purgeable)
-{
- {
- /** item #1 **/
-
- /* bounding rect */
- { 45, 353, 65, 411 },
-
- /* type */
- Button
- {
- /* enable flag */
- enabled,
-
- /* title */
- "OK"
- },
-
- /** item #2 **/
-
- /* bounding rect */
- { 19, 68, 90, 339 },
-
- /* type */
- StaticText
- {
- /* enable flag */
- disabled,
-
- /* title */
- "^0"
- },
-
- /** item #3 **/
-
- /* bounding rect */
- { 38, 21, 70, 53 },
-
- /* type */
- Icon
- {
- /* enable flag */
- disabled,
-
- /* 'ICON' ID */
- 128
- }
- }
-};
-
-
-resource 'DITL' (128, purgeable)
-{
- {
- /** item #1 **/
-
- /* bounding rect */
- { -4, 0, 225, 308 },
-
- /* type */
- UserItem
- {
- /* enable flag */
- enabled
- },
-
- /** item #2 **/
-
- /* bounding rect */
- { 7, 108, 24, 235 },
-
- /* type */
- StaticText
- {
- /* enable flag */
- disabled,
-
- /* title */
- "T.o.M.E. 2.3.3"
- },
-
- /** item #3 **/
-
- /* bounding rect */
- { 36, 80, 53, 275 },
-
- /* type */
- StaticText
- {
- /* enable flag */
- disabled,
-
- /* title */
- "Copyright (c) 1998-2003"
- },
-
- /** item #4 **/
- { 53, 122, 70, 220 },
-
- /* type */
- StaticText
- {
- /* enable flag */
- disabled,
-
- /* title */
- "DarkGod"
- },
-
- /** item #5 **/
-
- /* bounding rect */
- { 70, 81, 87, 255 },
-
- /* type */
- StaticText
- {
- /* enable flag */
- disabled,
-
- /* title */
- "(darkgod@ifrance.com)"
- },
-
- /** item #6 **/
-
- /* bounding rect */
- { 99, 88, 116, 266 },
-
- /* type */
- StaticText
- {
- /* enable flag */
- disabled,
-
- /* title */
- "Original Copyright by"
- },
-
- /** item #7 **/
-
- /* bounding rect */
- { 135, 92, 151, 255 },
-
- /* type */
- StaticText
- {
- /* enable flag */
- disabled,
-
- /* title */
- "Robert A. Koeneke"
- },
-
- /** item #8 **/
-
- /* bounding rect */
- { 119, 103, 135, 255 },
-
- /* type */
- StaticText
- {
- /* enable flag */
- disabled,
-
- /* title */
- "James E. Wilson"
- },
-
- /** item #9 **/
-
- /* bounding rect */
- { 150, 112, 166, 255 },
-
- /* type */
- StaticText
- {
- /* enable flag */
- disabled,
-
- "Ben Harrison"
- },
-
- /** item #10 */
-
- /* bounding rect */
- { 166, 62, 182, 145 },
-
- /* type */
- StaticText
- {
- /* enable flag */
- disabled,
-
- /* title */
- "Topi Ylinen"
- },
-
- /** item #11 **/
-
- /* bounding rect */
- { 166, 148, 182, 294 },
-
- /* type */
- StaticText
- {
- /* enable flag */
- disabled,
-
- /* title */
- "Robert Ruehlmann"
- },
-
- /** item #12 **/
-
- /* bounding rect */
- { 190, 96, 207, 255 },
-
- /* type */
- StaticText
- {
- /* enable flag */
- disabled,
-
- /* title */
- "Macintosh Version"
- }
- }
-};
-
-resource 'ALRT' (130, purgeable)
-{
- /* bounding rect */
- { 144, 154, 283, 384 },
-
- /* 'DITL' ID */
- 130,
-
- /* bold outline, draw alert and beeps */
- {
- /* stage 4 */
- OK, visible, sound1;
-
- /* stage 3 */
- OK, visible, sound1;
-
- /* stage 2 */
- OK, visible, sound1;
-
- /* stage 1 */
- OK, visible, sound1;
- },
-
-#if ALRT_RezTemplateVersion == 1
-
- /* centered to parent window */
- centerParentWindow
-
-#endif /* ALRT_RezTemplateVersion == 1 */
-};
-
-resource 'ALRT' (129, purgeable)
-{
- /* bounding rect */
- { 40, 40, 150, 471 },
-
- /* 'DITL' ID */
- 129,
-
- /* bold outline, draw alert and beeps */
- {
- /* stage 4 */
- OK, visible, sound1;
-
- /* stage 3 */
- OK, visible, sound1;
-
- /* stage 2 */
- OK, visible, sound1;
-
- /* stage 1 */
- OK, visible, sound1;
- },
-
-#if ALRT_RezTemplateVersion == 1
-
- /* centered to parent window */
- centerParentWindow
-
-#endif /* ALRT_RezTemplateVersion == 1 */
-};
-
-resource 'ALRT' (128, purgeable)
-{
- /* bounding rect */
- { 40, 40, 150, 471 },
-
- /* 'DITL' ID */
- 129,
-
- /* bold outline, draw alert and beeps */
- {
- /* stage 4 */
- OK, visible, sound1;
-
- /* stage 3 */
- OK, visible, sound1;
-
- /* stage 2 */
- OK, visible, sound1;
-
- /* stage 1 */
- OK, visible, sound1;
- },
-
-#if ALRT_RezTemplateVersion == 1
-
- /* centered to parent window */
- centerParentWindow
-
-#endif /* ALRT_RezTemplateVersion == 1 */
-};
-
-resource 'DLOG' (128, purgeable)
-{
- /* bounding rect */
- { 112, 202, 341, 512 },
-
- /* procID */
- dBoxProc,
-
- /* visibility */
- invisible,
-
- /* has closebox? */
- noGoAway,
-
- /* refCon */
- 0x0,
-
- /* 'DITL' ID */
- 128,
-
- /* title */
- "",
-
-#if DLOG_RezTemplateVersion == 1
-
- /* position */
- centerMainScreen
-
-#endif /* DLOG_RezTemplateVersion == 1 */
-};
-
-
-/*
- * Additional resources for Carbon
- */
-resource 'STR#' (128, purgeable)
-{
- {
- /* item #1 */
- "Please select the \"lib\" folder"
- }
-};
-
-
-/*
- * Warning Icon (The ! one)
- */
-data 'ICON' (128, purgeable) {
- $"0001 8000 0003 C000 0003 C000 0006 6000"
- $"0006 6000 000C 3000 000C 3000 0018 1800"
- $"0019 9800 0033 CC00 0033 CC00 0063 C600"
- $"0063 C600 00C3 C300 00C3 C300 0183 C180"
- $"0183 C180 0303 C0C0 0303 C0C0 0603 C060"
- $"0601 8060 0C01 8030 0C00 0030 1800 0018"
- $"1801 8018 3003 C00C 3003 C00C 6001 8006"
- $"6000 0006 C000 0003 FFFF FFFF 7FFF FFFE"
-};
-
-
-#ifndef MACH_O
-
-/*
- * The JRRT icons we all know and love: you are not expected to change these,
- * unless you are afraid of Tolkien Estate solicitors...
- */
-
-data 'icl4' (129, purgeable) {
- $"000F FFFF FFFF FFFF FFFF FFF0 0000 0000"
- $"000F 0000 0000 0000 0000 0CFF 0000 0000"
- $"000F 000F FFFF FFFF 0000 0CF0 F000 0000"
- $"000F 000F 0F0F 0F0F 0000 0CF0 0F00 0000"
- $"000F 0FFF FFFF FFFF FFFF FCF0 00F0 0000"
- $"000F 0F0F 0F0F 0F0F 0F0F 0CF0 000F 0000"
- $"000F 0FFF FFFF FFFF FFFF FCFF FFFF F000"
- $"000F 000F 0F0F 0F0F 0000 00CC CCCC FC00"
- $"000F 000F FFFF FFFF 0000 0000 0FF0 FC00"
- $"000F 0000 000F 0F00 0000 0000 0F00 FC00"
- $"000F 0000 000F FF00 0FFF FFFF FFF0 FC00"
- $"000F 0000 000F 0F00 0F0F 0F0F 0F00 FC00"
- $"000F 0FFF FFFF FFFF FFFF FFFF FFF0 FC00"
- $"000F 0F0F 0F0F 0F0F 0F00 0000 0F00 FC00"
- $"000F 0FFF FFFF FFFF F000 FFC0 0000 FC00"
- $"000F 0F0F 0000 0000 00FF FC0F C000 FC00"
- $"000F 0FFF 0000 00FC 000F FC0C 0FC0 FC00"
- $"000F 0F0F 0000 00FF FFFF FFFF FFC0 FC00"
- $"000F 0FFF FFFF 0FFC CFFF FFFC CFFC FC00"
- $"000F 0F0F 0F0F 0CC0 FC0F FC0F CCC0 FC00"
- $"000F 0FFF FFFF 0000 FC0F FC0F C000 FC00"
- $"000F 0F0F 0F0F 0F00 0FFF FFFC 0000 FC00"
- $"000F 0FFF FFFF FFF0 00FF FFC0 0000 FC00"
- $"000F 0F0F 0F0F 0F00 0FCF FCF0 0000 FC00"
- $"000F 0FFF FFFF FF0F FC0F FC0F FC00 FC00"
- $"000F 0F0F 0F0F 0F0C C00F FC0C C000 FC00"
- $"000F 0FFF FFFF FF00 0FCF FC00 0000 FC00"
- $"000F 0F0F 0F0F 0F0F 0C0F FC00 0000 FC00"
- $"000F 0FFF FFFF FFFF 000F CFFC 0000 FC00"
- $"000F 0F0F 0F0F 0F0F 0FFC 0CC0 0000 FC00"
- $"000F 0000 0000 0000 0CC0 0000 0000 FC00"
- $"000F FFFF FFFF FFFF FFFF FFFF FFFF FC00"
-};
-
-data 'icl4' (130, purgeable) {
- $"000F FFFF FFFF FFFF FFFF FFF0 0000 0000"
- $"000F 0000 0000 0000 0000 0CFF 0000 0000"
- $"000F 0000 0000 0000 0000 0CF0 F000 0000"
- $"000F 0000 FFFF FFFF FFFF CCF0 0F00 0000"
- $"000F 0000 CCCC CCCC CCCC CCF0 00F0 0000"
- $"000F 0000 0000 0000 0000 0CF0 000F 0000"
- $"000F 00FF FFFF FFFF FFFF CCFF FFFF F000"
- $"000F 00CC CCCC CCCC CCCC C0CC CCCC FC00"
- $"000F 0000 0000 0000 0000 0000 0000 FC00"
- $"000F 00FF FFFF FFFF FFFF FFFF FFFC FC00"
- $"000F 00CC CCCC CCCC CCCC CCCC CCCC FC00"
- $"000F 0000 0000 0000 0000 0000 0000 FC00"
- $"000F 00FF FFFF FFFF FFFF FFFF FFFC FC00"
- $"000F 00CC CCCC CCCC CCCC CCCC CCCC FC00"
- $"000F 0000 0000 0000 0000 FFC0 0000 FC00"
- $"000F 00FF FFFF C000 00FF FC0F C000 FC00"
- $"000F 00CC CCCC C0FC 000F FC0C 0FC0 FC00"
- $"000F 0000 0000 00FF FFFF FFFF FFC0 FC00"
- $"000F 00FF FFFC 0FFC CFFF FFFC CFFC FC00"
- $"000F 00CC CCCC 0CC0 FC0F FC0F CCC0 FC00"
- $"000F 0000 0000 0000 FC0F FC0F C000 FC00"
- $"000F 0000 FFFF FC00 0FFF FFFC 0000 FC00"
- $"000F 0000 CCCC CC00 00FF FFC0 0000 FC00"
- $"000F 0000 0000 0000 0FCF FCF0 0000 FC00"
- $"000F 00FF FFFF FC0F FC0F FC0F FC00 FC00"
- $"000F 00CC CCCC CC0C C00F FC0C C000 FC00"
- $"000F 0000 0000 0000 0FCF FC00 0000 FC00"
- $"000F 00FF FFFF FFC0 0C0F FC00 0000 FC00"
- $"000F 00CC CCCC CCC0 000F CFFC 0000 FC00"
- $"000F 0000 0000 0000 0FFC 0CC0 0000 FC00"
- $"000F 0000 0000 0000 0CC0 0000 0000 FC00"
- $"000F FFFF FFFF FFFF FFFF FFFF FFFF FC00"
-};
-
-data 'icl4' (128, purgeable) {
- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
- $"F333 3333 3FFF 000F ED00 FFF3 3333 333F"
- $"F333 333F F000 00FE D0ED 00FF F333 333F"
- $"F333 33FF 0000 00DD 0FED 0FDF FF33 333F"
- $"F333 3F00 0000 00FF 0ED0 00FD 00F3 333F"
- $"F333 F000 0000 00CF FED0 00D0 000F 333F"
- $"F33F 000F 0000 000F FED0 0000 0E00 F33F"
- $"F3FF 00FF FFFF FFFF FFFF FFFF FFE0 FF3F"
- $"F3F0 0FFF FFFF FFFF FFFF FFFF FFFE 0F3F"
- $"FF00 FEED DDDD DDDF FEDD DDDD DDFF EDFF"
- $"FF00 FDD0 000F FFFF FEFF FF00 0000 EDFF"
- $"FF00 D000 00FF DDDF FEDD DFF0 0000 D0FF"
- $"F000 0000 0FFD 000F FED0 00FE D000 000F"
- $"F000 0000 0FFD 000F FED0 00FE D000 000F"
- $"F000 0000 0FFD 000F FED0 00FE D000 000F"
- $"F000 0000 00FF D00F FED0 0FFD 0000 000F"
- $"F000 0000 000F FFFF FEFF FFD0 0000 000F"
- $"F000 0000 000D DDFF FEFD DD00 0000 000F"
- $"F000 0000 0000 0FFF FEFF 0000 0000 000F"
- $"F000 0000 0000 FFDF FEDF F000 0000 000F"
- $"FF00 0000 000F FD0F FED0 FF00 0000 00FF"
- $"FF00 000F FFFF D00F FED0 0FFF FFD0 00FF"
- $"FF00 0000 FFFD 000F FED0 00FF FD00 00FF"
- $"F3F0 0000 DDD0 000F FED0 00DD D000 0F3F"
- $"F3FF 0000 0000 F00F FED0 0000 0000 FF3F"
- $"F33F 0000 000F DFDF FED0 0000 0000 F33F"
- $"F333 F000 0000 FD0F FFD0 0000 000F 333F"
- $"F333 3F00 0000 D00F FFF0 FFD0 00F3 333F"
- $"F333 33FF 00F0 00FF FDFF FD00 FF33 333F"
- $"F333 333F F00F FFFF D00D D00F F333 333F"
- $"F333 3333 3FFF FFDD 0000 FFF3 3333 333F"
- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
-};
-
-data 'icl4' (131, purgeable) {
- $"000F FFFF FFFF FFFF FFFF FFF0 0000 0000"
- $"000F 0000 0000 0000 0000 00FF 0000 0000"
- $"000F 0F00 0F00 FF00 0FF0 00FC F000 0000"
- $"000F 0FF0 FF0F 00F0 F00F 00FC 0F00 0000"
- $"000F 0F0F 0F0F 00F0 F000 00FC 00F0 0000"
- $"000F 0F00 0F0F FFF0 F000 00FC 000F 0000"
- $"000F 0F00 0F0F 00F0 F00F 00FF FFFF F000"
- $"000F 0F00 0F0F 00F0 0FF0 000C CCCC FC00"
- $"000F 0000 0000 0000 0000 0000 0000 FC00"
- $"000F FFFF FFFF FFFF FFFF FFFF FFFF FC00"
- $"000F CCCC CCCC CCCC CCCC CCCC CCCC FC00"
- $"000F 0000 0000 0000 0000 0000 0000 FC00"
- $"000F 0000 0000 0000 0000 0000 0000 FC00"
- $"000F 0000 0000 0000 0000 0000 0000 FC00"
- $"000F 0000 0000 0000 0000 FFC0 0000 FC00"
- $"000F 0000 0000 0000 00FF FC0F C000 FC00"
- $"000F 0000 0000 00FC 000F FC0C 0FC0 FC00"
- $"000F 0000 0000 00FF FFFF FFFF FFC0 FC00"
- $"000F 0000 0000 0FFC CFFF FFFC CFFC FC00"
- $"000F 0000 0000 0CC0 FC0F FC0F CCC0 FC00"
- $"000F 0000 0000 0000 FC0F FC0F C000 FC00"
- $"000F 0000 0000 0000 0FFF FFFC 0000 FC00"
- $"000F 0000 0000 0000 00FF FFC0 0000 FC00"
- $"000F 0000 0000 0000 0FCF FCF0 0000 FC00"
- $"000F 0000 0000 000F FC0F FC0F FC00 FC00"
- $"000F 0000 0000 000C C00F FC0C C000 FC00"
- $"000F 0000 0000 0000 0FCF FC00 0000 FC00"
- $"000F 0000 0000 0000 0C0F FC00 0000 FC00"
- $"000F 0000 0000 0000 000F CFFC 0000 FC00"
- $"000F 0000 0000 0000 0FFC 0CC0 0000 FC00"
- $"000F 0000 0000 0000 0CC0 0000 0000 FC00"
- $"000F FFFF FFFF FFFF FFFF FFFF FFFF FC00"
-};
-
-data 'ICN#' (128, purgeable) {
- $"FFFF DFFF FFF1 8FFF FF83 23FF FF00 657F"
- $"FC03 423F F801 C01F F101 C04F F3FF FFEF"
- $"E7FF FFF7 CE01 C03B C81F FC0B C031 C603"
- $"8061 C301 8061 C301 8061 C301 8031 C601"
- $"801F FC01 8003 E001 8007 F001 800D D801"
- $"C019 CC03 C1F1 C7C3 C0E1 C383 E001 C007"
- $"F009 C00F F015 C00F F809 C01F FC01 EC3F"
- $"FF23 B8FF FF9F 01FF FFFC 0FFF FFF3 FFFF"
- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
-};
-
-data 'ICN#' (129, purgeable) {
- $"1FFF FE00 1000 0300 11FF 0280 1155 0240"
- $"17FF FA20 1555 5210 17FF FBF8 1155 0008"
- $"11FF 0068 1014 0048 101C 7FE8 1014 5548"
- $"17FF FFE8 1555 4008 17FF 8C08 1500 3908"
- $"1702 1848 1503 FFC8 17F6 7E68 1550 9908"
- $"17F0 9908 1554 7E08 17FE 3C08 1554 5A08"
- $"17FD 9988 1554 1808 17FC 5808 1555 1808"
- $"17FF 1608 1555 6008 1000 0008 1FFF FFF8"
- $"1FFF FE00 1FFF FF00 1FFF FF80 1FFF FFC0"
- $"1FFF FFE0 1FFF FFF0 1FFF FFF8 1FFF FFFC"
- $"1FFF FFFC 1FFF FFFC 1FFF FFFC 1FFF FFFC"
- $"1FFF FFFC 1FFF FFFC 1FFF FFFC 1FFF FFFC"
- $"1FFF FFFC 1FFF FFFC 1FFF FFFC 1FFF FFFC"
- $"1FFF FFFC 1FFF FFFC 1FFF FFFC 1FFF FFFC"
- $"1FFF FFFC 1FFF FFFC 1FFF FFFC 1FFF FFFC"
- $"1FFF FFFC 1FFF FFFC 1FFF FFFC 1FFF FFFC"
-};
-
-data 'ICN#' (130, purgeable) {
- $"1FFF FE00 1000 0300 1000 0280 10FF F240"
- $"1000 0220 1000 0210 13FF F3F8 1000 0008"
- $"1000 0008 13FF FFE8 1000 0008 1000 0008"
- $"13FF FFE8 1000 0008 1000 0C08 13F0 3908"
- $"1002 1848 1003 FFC8 13E6 7E68 1000 9908"
- $"1000 9908 10F8 7E08 1000 3C08 1000 5A48"
- $"13F9 9988 1000 1808 1000 5808 13FC 1808"
- $"1000 1608 1000 6008 1000 0008 1FFF FFF8"
- $"1FFF FE00 1FFF FF00 1FFF FF80 1FFF FFC0"
- $"1FFF FFE0 1FFF FFF0 1FFF FFF8 1FFF FFFC"
- $"1FFF FFFC 1FFF FFFC 1FFF FFFC 1FFF FFFC"
- $"1FFF FFFC 1FFF FFFC 1FFF FFFC 1FFF FFFC"
- $"1FFF FFFC 1FFF FFFC 1FFF FFFC 1FFF FFFC"
- $"1FFF FFFC 1FFF FFFC 1FFF FFFC 1FFF FFFC"
- $"1FFF FFFC 1FFF FFFC 1FFF FFFC 1FFF FFFC"
- $"1FFF FFFC 1FFF FFFC 1FFF FFFC 1FFF FFFC"
-};
-
-data 'ICN#' (131, purgeable) {
- $"1FFF FE00 1000 0300 144C 6280 16D2 9240"
- $"1552 8220 145E 8210 1452 93F8 1452 6008"
- $"1000 0008 1FFF FFF8 1000 0008 1000 0008"
- $"1000 0008 1000 0008 1000 0C08 1000 3908"
- $"1002 1848 1003 FFC8 1006 7E68 1000 9908"
- $"1000 9908 1000 7E08 1000 3C08 1000 5A48"
- $"1001 9988 1000 1808 1000 5808 1000 1808"
- $"1000 1608 1000 6008 1000 0008 1FFF FFF8"
- $"1FFF FE00 1FFF FF00 1FFF FF80 1FFF FFC0"
- $"1FFF FFE0 1FFF FFF0 1FFF FFF8 1FFF FFFC"
- $"1FFF FFFC 1FFF FFFC 1FFF FFFC 1FFF FFFC"
- $"1FFF FFFC 1FFF FFFC 1FFF FFFC 1FFF FFFC"
- $"1FFF FFFC 1FFF FFFC 1FFF FFFC 1FFF FFFC"
- $"1FFF FFFC 1FFF FFFC 1FFF FFFC 1FFF FFFC"
- $"1FFF FFFC 1FFF FFFC 1FFF FFFC 1FFF FFFC"
- $"1FFF FFFC 1FFF FFFC 1FFF FFFC 1FFF FFFC"
-};
-
-data 'ics#' (128, purgeable) {
- $"FFFF F99F F18F FFFF E7E3 8991 8991 87E1"
- $"83C1 85A1 9999 C183 E587 F18F F97F FFFF"
- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
-};
-
-data 'ics#' (129, purgeable) {
- $"7FF0 4018 5FD4 555E 5FC2 4412 5FFA 5502"
- $"5F12 557E 5F3A 5556 5F3A 551A 4022 7FFE"
- $"7FF0 7FF8 7FFC 7FFE 7FFE 7FFE 7FFE 7FFE"
- $"7FFE 7FFE 7FFE 7FFE 7FFE 7FFE 7FFE 7FFE"
-};
-
-data 'ics#' (130, purgeable) {
- $"7FF0 4018 5FD4 401E 5FC2 4002 5FFA 4002"
- $"5F12 407E 5F3A 4056 5F3A 401A 4022 7FFE"
- $"7FF0 7FF8 7FFC 7FFE 7FFF 7FFF 7FFF 7FFF"
- $"7FFF 7FFF 7FFF 7FFF 7FFF 7FFF 7FFF 7FFF"
-};
-
-data 'ics#' (131, purgeable) {
- $"7FF0 4018 5FD4 5F9E 57C2 4002 7FFE 4002"
- $"4012 407E 403A 4056 403A 401A 4022 7FFE"
- $"7FF0 7FF8 7FFC 7FFE 7FFF 7FFF 7FFF 7FFF"
- $"7FFF 7FFF 7FFF 7FFF 7FFF 7FFF 7FFF 7FFF"
-};
-
-data 'icl8' (129, purgeable) {
- $"0000 00FF FFFF FFFF FFFF FFFF FFFF FFFF"
- $"FFFF FFFF FFFF FF00 0000 0000 0000 0000"
- $"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
- $"F5F5 F5F5 F5F7 FFFF 0000 0000 0000 0000"
- $"0000 00FF F5F5 F5FF FFFF FFFF FFFF FFFF"
- $"F5F5 F5F5 F5F7 FFF5 FF00 0000 0000 0000"
- $"0000 00FF F5F5 F5FF F5FF F5FF F5FF F5FF"
- $"F5F5 F5F5 F5F7 FFF5 F5FF 0000 0000 0000"
- $"0000 00FF F5FF FFFF FFFF FFFF FFFF FFFF"
- $"FFFF FFFF FFF7 FFF5 F5F5 FF00 0000 0000"
- $"0000 00FF F5FF F5FF F5FF F5FF F5FF F5FF"
- $"F5FF F5FF F5F7 FFF5 F5F5 F5FF 0000 0000"
- $"0000 00FF F5FF FFFF FFFF FFFF FFFF FFFF"
- $"FFFF FFFF FFF7 FFFF FFFF FFFF FF00 0000"
- $"0000 00FF F5F5 F5FF F5FF F5FF F5FF F5FF"
- $"F5F5 F5F5 F5F5 F7F7 F7F7 F7F7 FFF7 0000"
- $"0000 00FF F5F5 F5FF FFFF FFFF FFFF FFFF"
- $"F5F5 F5F5 F5F5 F5F5 F5FF FFF5 FFF7 0000"
- $"0000 00FF F5F5 F5F5 F5F5 F5FF F5FF F5F5"
- $"F5F5 F5F5 F5F5 F5F5 F5FF F5F5 FFF7 0000"
- $"0000 00FF F5F5 F5F5 F5F5 F5FF FFFF F5F5"
- $"F5FF FFFF FFFF FFFF FFFF FFF5 FFF7 0000"
- $"0000 00FF F5F5 F5F5 F5F5 F5FF F5FF F5F5"
- $"F5FF F5FF F5FF F5FF F5FF F5F5 FFF7 0000"
- $"0000 00FF F5FF FFFF FFFF FFFF FFFF FFFF"
- $"FFFF FFFF FFFF FFFF FFFF FFF5 FFF7 0000"
- $"0000 00FF F5FF F5FF F5FF F5FF F5FF F5FF"
- $"F5FF F5F5 F5F5 F5F5 F5FF F5F5 FFF7 0000"
- $"0000 00FF F5FF FFFF FFFF FFFF FFFF FFFF"
- $"FFF5 F5F5 FFFF F8F6 F5F5 F5F5 FFF7 0000"
- $"0000 00FF F5FF F5FF F5F5 F5F5 F5F5 F5F5"
- $"F5F5 FFFF FFF8 F7FF F8F6 F5F5 FFF7 0000"
- $"0000 00FF F5FF FFFF F5F5 F5F5 F5F5 FFF8"
- $"F6F5 F5FF FFF8 F6F8 F6FF F8F6 FFF7 0000"
- $"0000 00FF F5FF F5FF F5F5 F5F5 F5F5 FFFF"
- $"FFFF FFFF FFFF FFFF FFFF F8F6 FFF7 0000"
- $"0000 00FF F5FF FFFF FFFF FFFF F5FF FFF8"
- $"F8FF FFFF FFFF FFF8 F6FF FFF8 FFF7 0000"
- $"0000 00FF F5FF F5FF F5FF F5FF F5F8 F8F6"
- $"FFF8 F6FF FFF8 F6FF F8F6 F6F5 FFF7 0000"
- $"0000 00FF F5FF FFFF FFFF FFFF F5F6 F6F5"
- $"FFF8 F6FF FFF8 F6FF F8F6 F5F5 FFF7 0000"
- $"0000 00FF F5FF F5FF F5FF F5FF F5FF F5F5"
- $"F5FF FFFF FFFF FFF8 F6F5 F5F5 FFF7 0000"
- $"0000 00FF F5FF FFFF FFFF FFFF FFFF FFF5"
- $"F5F5 FFFF FFFF F8F6 F5F5 F5F5 FFF7 0000"
- $"0000 00FF F5FF F5FF F5FF F5FF F5FF F5F5"
- $"F5FF F8FF FFF8 FFF5 F5F5 F5F5 FFF7 0000"
- $"0000 00FF F5FF FFFF FFFF FFFF FFFF F5FF"
- $"FFF8 F6FF FFF8 F6FF FFF8 F5F5 FFF7 0000"
- $"0000 00FF F5FF F5FF F5FF F5FF F5FF F5F8"
- $"F8F6 F5FF FFF8 F6F8 F8F5 F5F5 FFF7 0000"
- $"0000 00FF F5FF FFFF FFFF FFFF FFFF F5F6"
- $"F6FF F8FF FFF8 F6F5 F5F5 F5F5 FFF7 0000"
- $"0000 00FF F5FF F5FF F5FF F5FF F5FF F5FF"
- $"F5F8 F6FF FFF8 F6F5 F5F5 F5F5 FFF7 0000"
- $"0000 00FF F5FF FFFF FFFF FFFF FFFF FFFF"
- $"F5F6 F5FF F8FF FFF8 F6F5 F5F5 FFF7 0000"
- $"0000 00FF F5FF F5FF F5FF F5FF F5FF F5FF"
- $"F5FF FFF8 F7F8 F8F6 F5F5 F5F5 FFF7 0000"
- $"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
- $"F5F8 F8F7 F6F6 F6F5 F5F5 F5F5 FFF7 0000"
- $"0000 00FF FFFF FFFF FFFF FFFF FFFF FFFF"
- $"FFFF FFFF FFFF FFFF FFFF FFFF FFF7 0000"
-};
-
-data 'icl8' (128, purgeable) {
- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
- $"FFFF F9FF FFFF FFFF FFFF FFFF FFFF FFFF"
- $"FFD7 D7D7 D7D7 D7D7 D7FF FFFF 0000 00FF"
- $"FCF9 F7F7 FFFF FFD7 D7D7 D7D7 D7D7 6BFF"
- $"FFD7 4747 4747 4747 FF00 0000 F5F5 FFFC"
- $"F9F7 FCF8 F7F5 FFFF FF47 4747 4747 6BFF"
- $"FFD7 4747 4747 FFFF 00F5 F5F5 F5F5 F9F9"
- $"F7FF FCF8 F7FF F7FF F9FF 4747 4747 6BFF"
- $"FFD7 4747 47FF 0000 F5F5 F5F5 F5F5 FFFF"
- $"F7FC F9F7 F5F5 FFF9 F7F5 FF47 4747 6BFF"
- $"FFD7 4747 FF00 F5F5 F5F5 F5F5 F5F5 F7FF"
- $"FFFC F9F7 F5F5 F9F7 F5F5 F5FF 4747 6BFF"
- $"FFD7 47FF 00F5 F5FF F5F5 F5F5 F5F5 F5FF"
- $"FFFC F9F7 F5F5 F5F5 F5FC F5F5 FF47 6BFF"
- $"FFD7 47FF 00F5 FFFF FFFF FFFF FFFF FFFF"
- $"FFFF FFFF FFFF FFFF FFFF FCF5 FF47 6BFF"
- $"FFD7 FF00 F5FF FFFF FFFF FFFF FFFF FFFF"
- $"FFFF FFFF FFFF FFFF FFFF FFFC F5FF 6BFF"
- $"FFFF 00F7 FFFC FCF9 F9F9 F9F9 F9F9 F9FF"
- $"FFFC F9F9 F9F9 F9F9 F9F9 FFFF FCF9 FFFF"
- $"FFFF 00F7 FCF9 F9F7 F7F7 F7FF FFFF FFFF"
- $"FFFC FFFF FFFF F7F7 F7F7 F7F7 FCF9 FFFF"
- $"FFFF 00F7 F9F7 F7F5 F5F5 FFFF F8F8 F8FF"
- $"FFFC F9F9 F9FF FFF7 F7F5 F5F7 F9F7 FFFF"
- $"FFF5 F5F5 F7F5 F5F5 F5FF FFF9 F7F7 F7FF"
- $"FFFC F9F7 F7F7 FFFC F8F7 F5F5 F7F7 F8FF"
- $"FF00 F5F5 F5F5 F5F5 F5FF FFF9 F7F5 F5FF"
- $"FFFC F9F7 F5F5 FFFC F8F7 F5F5 F5F5 F8FF"
- $"FF00 F5F5 F5F5 F5F5 F5FF FFF9 F7F5 F5FF"
- $"FFFC F9F7 F5F5 FFFC F8F7 F5F5 F5F5 F8FF"
- $"FF00 F5F5 F5F5 F5F5 F5F5 FFFF F9F7 F5FF"
- $"FFFC F9F7 F5FF FFF8 F7F5 F5F5 F5F5 F8FF"
- $"FF00 F5F5 F5F5 F5F5 F5F5 F5FF FFFF FFFF"
- $"FFFC FFFF FFFF F8F7 F5F5 F5F5 F5F5 F8FF"
- $"FF00 F5F5 F5F5 F5F5 F5F5 F5F9 F9F9 FFFF"
- $"FFFC FFF9 F9F9 F7F5 F5F5 F5F5 F5F5 F8FF"
- $"FF00 F5F5 F5F5 F5F5 F5F5 F5F5 F5FF FFFF"
- $"FFFC FFFF F7F7 F5F5 F5F5 F5F5 F5F5 F8FF"
- $"FF00 F5F5 F5F5 F5F5 F5F5 F5F5 FFFF F9FF"
- $"FFFC F9FF FFF5 F5F5 F5F5 F5F5 F5F5 F8FF"
- $"FFFF F5F5 F5F5 F5F5 F5F5 F5FF FFF9 F7FF"
- $"FFFC F9F7 FFFF F5F5 F5F5 F5F5 F5F8 FFFF"
- $"FFFF F5F5 F5F5 F7FF FFFF FFFF F9F7 F5FF"
- $"FFFC F9F7 F7FF FFFF FFFF F9F5 F5F8 FFFF"
- $"FFFF F5F5 F5F5 F5F7 FFFF FFF9 F7F5 F5FF"
- $"FFFC F9F7 F5F7 FFFF FFF9 F7F5 F5F8 FFFF"
- $"FFD7 FFF5 F5F5 F5F7 F9F9 F9F7 F5F5 F5FF"
- $"FFFC F9F7 F5F5 F9F9 F9F7 F5F5 F8FF 6BFF"
- $"FFD7 47FF F5F5 F5F5 F7F7 F7F5 FFF6 F5FF"
- $"FFFC F9F7 F5F5 F5F7 F7F5 F5F8 FF47 6BFF"
- $"FFD7 47FF F5F5 F5F5 F5F5 F5FF F7FF F8FF"
- $"FFFC F9F7 F5F5 F5F5 F5F5 F5F8 FF47 6BFF"
- $"FFD7 4747 FFF5 F5F5 F5F5 F5F5 FFF8 F7FF"
- $"FFFF F9F7 F5F5 F5F5 F5F5 F8FF 4747 6BFF"
- $"FFD7 4747 47FF F5F5 F5F5 F5F5 F8F7 F5FF"
- $"FFFF FFF7 FFFF F9F7 F8F8 FF47 4747 6BFF"
- $"FFD7 4747 4747 FFFF F5F5 FFF5 F7F5 FFFF"
- $"FFF8 FFFF FFF9 F7F8 FFFF 4747 4747 6BFF"
- $"FFD7 4747 4747 4747 FFF5 F5FF FFFF FFFF"
- $"F8F6 F5F9 F9F7 F5FF 4747 4747 4747 6BFF"
- $"FFD7 6B6B 6B6B 6B6B 6BFF FFFF FFFF F8F8"
- $"F8F8 F8F5 FFFF FF6B 6B6B 6B6B 6B6B 6BFF"
- $"FFFF FFFF FFFF FFFF FFFF FFFF F8F8 FFFF"
- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
-};
-
-data 'icl8' (130, purgeable) {
- $"0000 00FF FFFF FFFF FFFF FFFF FFFF FFFF"
- $"FFFF FFFF FFFF FF00 0000 0000 0000 0000"
- $"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
- $"F5F5 F5F5 F5F8 FFFF 0000 0000 0000 0000"
- $"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
- $"F5F5 F5F5 F5F8 FFF6 FF00 0000 0000 0000"
- $"0000 00FF F5F5 F5F5 FFFF FFFF FFFF FFFF"
- $"FFFF FFFF F8F8 FFF6 F6FF 0000 0000 0000"
- $"0000 00FF F5F5 F5F5 F8F8 F8F8 F8F8 F8F8"
- $"F8F8 F8F8 F8F8 FFF6 F6F6 FF00 0000 0000"
- $"0000 00FF F5F5 F5F5 F6F6 F6F6 F6F6 F6F6"
- $"F6F6 F6F6 F6F8 FFF6 F6F6 F6FF 0000 0000"
- $"0000 00FF F5F5 FFFF FFFF FFFF FFFF FFFF"
- $"FFFF FFFF F8F8 FFFF FFFF FFFF FF00 0000"
- $"0000 00FF F5F5 F8F8 F8F8 F8F8 F8F8 F8F8"
- $"F8F8 F8F8 F8F5 F8F8 F8F8 F8F8 FFF7 0000"
- $"0000 00FF F5F5 F6F6 F6F6 F6F6 F6F6 F6F6"
- $"F6F6 F6F6 F6F6 F6F6 F6F6 F6F6 FFF7 0000"
- $"0000 00FF F5F5 FFFF FFFF FFFF FFFF FFFF"
- $"FFFF FFFF FFFF FFFF FFFF FFF8 FFF7 0000"
- $"0000 00FF F5F5 F8F8 F8F8 F8F8 F8F8 F8F8"
- $"F8F8 F8F8 F8F8 F8F8 F8F8 F8F8 FFF7 0000"
- $"0000 00FF F5F5 F6F6 F6F6 F6F6 F6F6 F6F6"
- $"F6F6 F6F6 F6F6 F6F6 F6F6 F6F6 FFF7 0000"
- $"0000 00FF F5F5 FFFF FFFF FFFF FFFF FFFF"
- $"FFFF FFFF FFFF FFFF FFFF FFF8 FFF7 0000"
- $"0000 00FF F5F5 F8F8 F8F8 F8F8 F8F8 F8F8"
- $"F8F8 F8F8 F8F8 F8F8 F8F8 F8F8 FFF7 0000"
- $"0000 00FF F5F5 F6F6 F6F6 F6F6 F6F6 F6F6"
- $"F6F6 F6F6 FFFF F8F5 F5F5 F5F5 FFF7 0000"
- $"0000 00FF F5F5 FFFF FFFF FFFF F8F5 F5F5"
- $"F5F5 FFFF FFF8 F6FF F8F5 F5F5 FFF7 0000"
- $"0000 00FF F5F5 F8F8 F8F8 F8F8 F8F5 FFF8"
- $"F5F5 F5FF FFF8 F5F8 F5FF F8F6 FFF7 0000"
- $"0000 00FF F5F5 F6F6 F6F6 F6F6 F6F5 FFFF"
- $"FFFF FFFF FFFF FFFF FFFF F8F6 FFF7 0000"
- $"0000 00FF F5F5 FFFF FFFF FFF8 F6FF FFF8"
- $"F8FF FFFF FFFF FFF8 F8FF FFF8 FFF7 0000"
- $"0000 00FF F5F5 F8F8 F8F8 F8F8 F6F8 F8F5"
- $"FFF8 F6FF FFF8 F6FF F8F8 F8F6 FFF7 0000"
- $"0000 00FF F5F5 F6F6 F6F6 F6F6 F6F5 F5F5"
- $"FFF8 F6FF FFF8 F6FF F8F6 F6F5 FFF7 0000"
- $"0000 00FF F5F5 F5F5 FFFF FFFF FFF8 F6F5"
- $"F5FF FFFF FFFF FFF8 F5F5 F5F5 FFF7 0000"
- $"0000 00FF F5F5 F5F5 F8F8 F8F8 F8F8 F6F5"
- $"F5F5 FFFF FFFF F8F6 F5F5 F5F5 FFF7 0000"
- $"0000 00FF F5F5 F5F5 F6F6 F6F6 F6F6 F6F5"
- $"F5FF F8FF FFF8 FFF6 F5F5 F5F5 FFF7 0000"
- $"0000 00FF F5F5 FFFF FFFF FFFF FFF8 F6FF"
- $"FFF8 F6FF FFF8 F6FF FFF8 F6F5 FFF7 0000"
- $"0000 00FF F5F5 F8F8 F8F8 F8F8 F8F8 F6F8"
- $"F8F6 F5FF FFF8 F6F8 F8F6 F5F5 FFF7 0000"
- $"0000 00FF F5F5 F6F6 F6F6 F6F6 F6F6 F6F5"
- $"F6FF F8FF FFF8 F6F6 F6F5 F5F5 FFF7 0000"
- $"0000 00FF F5F5 FFFF FFFF FFFF FFFF F8F6"
- $"F5F8 F6FF FFF8 F6F5 F5F5 F5F5 FFF7 0000"
- $"0000 00FF F5F5 F8F8 F8F8 F8F8 F8F8 F8F6"
- $"F5F6 F5FF F8FF FFF8 F6F5 F5F5 FFF7 0000"
- $"0000 00FF F5F5 F6F6 F6F6 F6F6 F6F6 F6F6"
- $"F5FF FFF8 F6F8 F8F6 F5F5 F5F5 FFF7 0000"
- $"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
- $"F5F8 F8F6 F5F5 F6F5 F5F5 F5F5 FFF7 0000"
- $"0000 00FF FFFF FFFF FFFF FFFF FFFF FFFF"
- $"FFFF FFFF FFFF FFFF FFFF FFFF FFF7 0000"
-};
-
-data 'icl8' (131, purgeable) {
- $"0000 00FF FFFF FFFF FFFF FFFF FFFF FFFF"
- $"FFFF FFFF FFFF FF00 0000 0000 0000 0000"
- $"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
- $"F5F5 F5F5 F5F5 FFFF 0000 0000 0000 0000"
- $"0000 00FF F5FF F5F5 F5FF F5F5 FFFF F5F5"
- $"F5FF FFF5 F5F5 FFF8 FF00 0000 0000 0000"
- $"0000 00FF F5FF FFF5 FFFF F5FF 00F5 FFF5"
- $"FF00 00FF F5F5 FFF8 F6FF 0000 0000 0000"
- $"0000 00FF F5FF F5FF F5FF F5FF F5F5 FFF5"
- $"FF00 0000 F5F5 FFF8 F6F6 FF00 0000 0000"
- $"0000 00FF F5FF F5F5 F5FF F5FF FFFF FFF5"
- $"FF00 F5F5 F5F5 FFF8 F6F6 F6FF 0000 0000"
- $"0000 00FF F5FF F5F5 F5FF F5FF F5F5 FFF5"
- $"FF00 F5FF 00F5 FFFF FFFF FFFF FF00 0000"
- $"0000 00FF F5FF F5F5 F5FF F5FF F5F5 FFF5"
- $"00FF FF00 0000 F5F8 F8F8 F8F8 FFF7 0000"
- $"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
- $"F500 00F5 F5F5 F5F5 F5F5 F5F5 FFF7 0000"
- $"0000 00FF FFFF FFFF FFFF FFFF FFFF FFFF"
- $"FFFF FFFF FFFF FFFF FFFF FFFF FFF7 0000"
- $"0000 00FF F8F8 F8F8 F8F8 F8F8 F8F8 F8F8"
- $"F8F8 F8F8 F8F8 F8F8 F8F8 F8F8 FFF7 0000"
- $"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
- $"F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 FFF7 0000"
- $"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
- $"F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 FFF7 0000"
- $"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
- $"F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 FFF7 0000"
- $"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
- $"F5F5 F500 FFFF F8F5 F5F5 F5F5 FFF7 0000"
- $"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
- $"F5F5 FFFF FFF8 F6FF F8F5 F5F5 FFF7 0000"
- $"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 FFF8"
- $"F5F5 F5FF FFF8 F5F8 F5FF F8F6 FFF7 0000"
- $"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 FFFF"
- $"FFFF FFFF FFFF FFFF FFFF F8F6 FFF7 0000"
- $"0000 00FF F5F5 F5F5 F5F5 F5F5 F5FF FFF8"
- $"F8FF FFFF FFFF FFF8 F8FF FFF8 FFF7 0000"
- $"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F8 F8F5"
- $"FFF8 F6FF FFF8 F6FF F8F8 F8F6 FFF7 0000"
- $"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
- $"FFF8 F6FF FFF8 F6FF F8F6 F6F5 FFF7 0000"
- $"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
- $"F5FF FFFF FFFF FFF8 F5F5 F5F5 FFF7 0000"
- $"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
- $"F5F5 FFFF FFFF F8F6 F5F5 F5F5 FFF7 0000"
- $"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
- $"F5FF F8FF FFF8 FFF6 F5F5 F5F5 FFF7 0000"
- $"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5FF"
- $"FFF8 F6FF FFF8 F6FF FFF8 F6F5 FFF7 0000"
- $"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F8"
- $"F8F6 F5FF FFF8 F6F8 F8F6 F5F5 FFF7 0000"
- $"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
- $"F6FF F8FF FFF8 F6F6 F6F5 F5F5 FFF7 0000"
- $"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
- $"F5F8 F6FF FFF8 F6F5 F5F5 F5F5 FFF7 0000"
- $"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
- $"F5F6 F5FF F8FF FFF8 F6F5 F5F5 FFF7 0000"
- $"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
- $"F5FF FFF8 F6F8 F8F6 F5F5 F5F5 FFF7 0000"
- $"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
- $"F5F8 F8F6 F5F5 F6F5 F5F5 F5F5 FFF7 0000"
- $"0000 00FF FFFF FFFF FFFF FFFF FFFF FFFF"
- $"FFFF FFFF FFFF FFFF FFFF FFFF FFF7 0000"
-};
-
-data 'ics8' (128, purgeable) {
- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
- $"FF47 4747 FFFF F6FF FFF8 FFFF 4747 47FF"
- $"FF47 47FF F6F6 F6FF FFF8 F6F6 FF47 47FF"
- $"FF47 FFFF FFFF FFFF FFFF FFFF FFFF 47FF"
- $"FF47 FFF8 F8FF FFFF FFFF FFF8 F8F8 47FF"
- $"FFFF F8F6 FFF8 F8FF FFF8 F8FF F8F6 FFFF"
- $"FFF6 F6F6 FFF8 F6FF FFF8 F6FF F8F6 F6FF"
- $"FFF6 F6F6 F6FF FFFF FFFF FFF8 F6F6 F6FF"
- $"FFF6 F6F6 F6F6 FFFF FFFF F8F6 F6F6 F6FF"
- $"FFF6 F6F6 F6FF F8FF FFF8 FFF6 F6F6 F6FF"
- $"FFFF F6FF FFF8 F6FF FFF8 F6FF FFF8 FFFF"
- $"FFFF F6F8 F8F6 F6FF FFF8 F6F8 F8F8 47FF"
- $"FF47 FFF6 F6FF F8FF FFF8 F6F6 F6FF 47FF"
- $"FF47 47FF F6F8 F6FF FFF8 F6F6 FF47 47FF"
- $"FF47 4747 FFFF F6FF F8FF FFFF 4747 47FF"
- $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF"
-};
-
-data 'ics8' (129, purgeable) {
- $"00FF FFFF FFFF FFFF FFFF FFFF 0000 0000"
- $"00FF F5F5 F5F5 F5F5 F5F5 F5FF FF00 0000"
- $"00FF F5FF FFFF FFFF FFFF F5FF F5FF 0000"
- $"00FF F5FF F5FF F5FF F5FF F5FF FFFF FF00"
- $"00FF F5FF FFFF FFFF FFFF F5F5 F5F5 FF00"
- $"00FF F5F5 F5FF F5F5 F5F5 F5FF F5F5 FF00"
- $"00FF F5FF FFFF FFFF FFFF FFFF FFF5 FF00"
- $"00FF F5FF F5FF F5FF F5F5 F5F5 F5F5 FF00"
- $"00FF F5FF FFFF FFFF F5F5 F5FF F5F5 FF00"
- $"00FF F5FF F5FF F5FF F5FF FFFF FFFF FF00"
- $"00FF F5FF FFFF FFFF F5F5 FFFF FF00 FF00"
- $"00FF F5FF F5FF F5FF F5FF 00FF 00FF FF00"
- $"00FF F5FF FFFF FFFF F5F5 FFFF FFF5 FF00"
- $"00FF F5FF F5FF F5FF F5F5 F5FF FFF5 FF00"
- $"00FF F5F5 F5F5 F5F5 F5F5 FFF5 F5F5 FF00"
- $"00FF FFFF FFFF FFFF FFFF FFFF FFFF FF00"
-};
-
-data 'ics8' (130, purgeable) {
- $"00FF FFFF FFFF FFFF FFFF FFFF 0000 0000"
- $"00FF F5F5 F5F5 F5F5 F5F5 F5FF FF00 0000"
- $"00FF F5FF FFFF FFFF FFFF F7FF F5FF 0000"
- $"00FF F5F7 F7F7 F7F7 F7F7 F7FF FFFF FF00"
- $"00FF F5FF FFFF FFFF FFFF F7F5 F5F5 FFF7"
- $"00FF F5F7 F7F7 F7F7 F7F7 F7F5 F5F5 FFF7"
- $"00FF F5FF FFFF FFFF FFFF FFFF FFF7 FFF7"
- $"00FF F5F7 F7F7 F7F7 F7F7 F7F7 F7F7 FFF7"
- $"00FF F5FF FFFF FFFF F7F5 F5FF F5F5 FFF7"
- $"00FF F5F7 F7F7 F7F7 F7FF FFFF FFFF FFF7"
- $"00FF F5FF FFFF FFFF F7F5 FFFF FFF5 FFF7"
- $"00FF F5F7 F7F7 F7F7 F7FF F5FF F5FF FFF7"
- $"00FF F5FF FFFF FFFF F7F5 FFFF FFF5 FFF7"
- $"00FF F5F7 F7F7 F7F7 F7F5 F5FF FFF5 FFF7"
- $"00FF F5F5 F5F5 F5F5 F5F5 FFF5 F5F5 FFF7"
- $"00FF FFFF FFFF FFFF FFFF FFFF FFFF FFF7"
-};
-
-data 'ics8' (131, purgeable) {
- $"00FF FFFF FFFF FFFF FFFF FFFF 0000 0000"
- $"00FF F5F5 F5F5 F5F5 F5F5 F5FF FF00 0000"
- $"00FF F5FF FFFF FFFF FFFF F5FF F5FF 0000"
- $"00FF F5FF FFFF FFFF FF00 F5FF FFFF FF00"
- $"00FF F5FF 00FF FFFF FFFF F5F5 F7F7 FFF7"
- $"00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5 FFF7"
- $"00FF FFFF FFFF FFFF FFFF FFFF FFFF FFF7"
- $"00FF F7F7 F7F7 F7F7 F7F7 F7F7 F7F7 FFF7"
- $"00FF F5F5 F5F5 F5F5 F5F5 F5FF F5F5 FFF7"
- $"00FF F5F5 F5F5 F5F5 F5FF FFFF FFFF FFF7"
- $"00FF F5F5 F5F5 F5F5 F5F5 FFFF FFF5 FFF7"
- $"00FF F5F5 F5F5 F5F5 F5FF F5FF F5FF FFF7"
- $"00FF F5F5 F5F5 F5F5 F5F5 FFFF FFF5 FFF7"
- $"00FF F5F5 F5F5 F5F5 F5F5 F5FF FFF5 FFF7"
- $"00FF F5F5 F5F5 F5F5 F5F5 FFF5 F5F5 FFF7"
- $"00FF FFFF FFFF FFFF FFFF FFFF FFFF FFF7"
-};
-
-data 'ics4' (128, purgeable) {
- $"FFFF FFFF FFFF FFFF F333 FFCF FCFF 333F"
- $"F33F CCCF FCCC F33F F3FF FFFF FFFF FF3F"
- $"FFFC CFFF FFFC CCFF FFCC FCCF FCCF CCFF"
- $"FCCC FCCF FCCF CCCF FCCC CFFF FFFC CCCF"
- $"FCCC CCFF FFCC CCCF FCCC CFCF FCFC CCCF"
- $"FFCF FCCF FCCF FCFF FFCC CCCF FCCC CCFF"
- $"F3FC CFCF FCCC CF3F F33F CCCF FCCC F33F"
- $"F333 FFCF CFFF 333F FFFF FFFF FFFF FFFF"
-};
-
-data 'ics4' (129, purgeable) {
- $"0FFF FFFF FFFF 0000 0F00 0000 000F F000"
- $"0F0F FFFF FF0F 0F00 0F0F 0F0F 0F0F FFF0"
- $"0F0F FFFF FF00 00F0 0F00 0F00 000F 00F0"
- $"0F0F FFFF FFFF F0F0 0F0F 0F0F 0000 00F0"
- $"0F0F FFFF 000F 00F0 0F0F 0F0F 0FFF FFF0"
- $"0F0F FFFF 00FF F0F0 0F0F 0F0F 0F0F 0FF0"
- $"0F0F FFFF 00FF F0F0 0F0F 0F0F 000F F0F0"
- $"0F00 0000 00F0 00F0 0FFF FFFF FFFF FFF0"
-};
-
-data 'ics4' (130, purgeable) {
- $"0FFF FFFF FFFF 0000 0FCC CCCC CCCF F000"
- $"0FCF FFFF FFCF CF00 0FCC CCCC CCCF FFF0"
- $"0FCF FFFF FFCC CCFD 0FCC CCCC CCCC CCFD"
- $"0FCF FFFF FFFF FCFD 0FCC CCCC CCCC CCFD"
- $"0FCF FFFF CCCF CCFD 0FCC CCCC CFFF FFFD"
- $"0FCF FFFF CCFF FCFD 0FCC CCCC CFCF CFFD"
- $"0FCF FFFF CCFF FCFD 0FCC CCCC CCCF FCFD"
- $"0FCC CCCC CCFC CCFD 0FFF FFFF FFFF FFFD"
-};
-
-data 'ics4' (131, purgeable) {
- $"0FFF FFFF FFFF 0000 0FCC CCCC CCCF F000"
- $"0FCF FFFF FFCF CF00 0FCF FFFF FCCF FFF0"
- $"0FCF CFFF FFCC DDFD 0FCC CCCC CCCC CCFD"
- $"0FFF FFFF FFFF FFFD 0FCC CCCC CCCC CCFD"
- $"0FCC CCCC CCCF CCFD 0FCC CCCC CFFF FFFD"
- $"0FCC CCCC CCFF FCFD 0FCC CCCC CFCF CFFD"
- $"0FCC CCCC CCFF FCFD 0FCC CCCC CCCF FCFD"
- $"0FCC CCCC CCFC CCFD 0FFF FFFF FFFF FFFD"
-};
-
-#endif /* !MACH_O */
-
diff --git a/src/carbon/Data.icns b/src/carbon/Data.icns
deleted file mode 100644
index dbaec173..00000000
--- a/src/carbon/Data.icns
+++ /dev/null
Binary files differ
diff --git a/src/carbon/Edit.icns b/src/carbon/Edit.icns
deleted file mode 100644
index 5e55c272..00000000
--- a/src/carbon/Edit.icns
+++ /dev/null
Binary files differ
diff --git a/src/carbon/Image-DS_Store b/src/carbon/Image-DS_Store
deleted file mode 100644
index efd42e72..00000000
--- a/src/carbon/Image-DS_Store
+++ /dev/null
Binary files differ
diff --git a/src/carbon/Info.plist b/src/carbon/Info.plist
deleted file mode 100644
index fff3fb15..00000000
--- a/src/carbon/Info.plist
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<plist version="1.0">
- <dict>
- <key>CFBundleName</key><string>T.o.M.E.</string>
- <key>CFBundleDisplayName</key><string>T.o.M.E. (OS X)</string>
- <key>CFBundleExecutable</key><string>tome</string>
- <key>CFBundlePackageType</key><string>APPL</string>
- <key>CFBundleSignature</key><string>PrnA</string>
- <key>CFBundleVersion</key><string>2.3.4</string>
- <key>CFBundleShortVersionString</key><string>234</string>
- <key>CFBundleIconFile</key><string>Angband</string>
- <key>CFBundleIdentifier</key><string>net.t-o-m-e.tome</string>
- <key>CFBundleInfoDictionaryVersion</key><string>6.0</string>
- <key>CFBundleDocumentTypes</key>
- <array>
- <dict>
- <key>CFBundleTypeExtentions</key><array><string>*</string></array>
- <key>CFBundleTypeIconFile</key><string>Save</string>
- <key>CFBundleTypeName</key><string>Angband game data</string>
- <key>CFBundleTypeOSTypes</key><array><string>SAVE</string></array>
- <key>CFBundleTypeRole</key><string>Editor</string>
- </dict>
- <dict>
- <key>CFBundleTypeExtentions</key><array><string>*</string></array>
- <key>CFBundleTypeIconFile</key><string>Edit</string>
- <key>CFBundleTypeName</key><string>Angband game data</string>
- <key>CFBundleTypeOSTypes</key><array><string>TEXT</string></array>
- <key>CFBundleTypeRole</key><string>Editor</string>
- </dict>
- <dict>
- <key>CFBundleTypeExtentions</key><array><string>*</string></array>
- <key>CFBundleTypeIconFile</key><string>Data</string>
- <key>CFBundleTypeName</key><string>Angband game data</string>
- <key>CFBundleTypeOSTypes</key><array><string>DATA</string></array>
- <key>CFBundleTypeRole</key><string>Editor</string>
- </dict>
- </array>
- </dict>
-</plist>
diff --git a/src/carbon/Save.icns b/src/carbon/Save.icns
deleted file mode 100644
index 362f80f6..00000000
--- a/src/carbon/Save.icns
+++ /dev/null
Binary files differ
diff --git a/src/carbon/getversion b/src/carbon/getversion
deleted file mode 100755
index 786fd14b..00000000
--- a/src/carbon/getversion
+++ /dev/null
@@ -1,2 +0,0 @@
-#! /bin/sh
-grep CFBundleVersion carbon/Info.plist | perl -pe "s,.*<string>([^<]*)<.*,\\1,"
diff --git a/src/cave.c b/src/cave.cc
index d23fc44c..cad1506e 100644
--- a/src/cave.c
+++ b/src/cave.cc
@@ -1,10 +1,35 @@
-/* File: cave.c */
-
-/* Purpose: low level dungeon routines -BEN- */
-
-
-#include "angband.h"
-
+#include "cave.hpp"
+
+#include "cave_type.hpp"
+#include "dungeon_flag.hpp"
+#include "feature_flag.hpp"
+#include "feature_type.hpp"
+#include "game.hpp"
+#include "hook_enter_dungeon_in.hpp"
+#include "monster2.hpp"
+#include "monster_race.hpp"
+#include "monster_race_flag.hpp"
+#include "monster_spell_flag.hpp"
+#include "monster_type.hpp"
+#include "object1.hpp"
+#include "object_flag.hpp"
+#include "object_kind.hpp"
+#include "options.hpp"
+#include "player_type.hpp"
+#include "q_rand.hpp"
+#include "spells1.hpp"
+#include "store_info_type.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "util.h"
+#include "variable.h"
+#include "variable.hpp"
+#include "z-rand.hpp"
+
+#include <cassert>
+#include <vector>
+#include <iterator>
+#include <algorithm>
/*
* Support for Adam Bolt's tileset, lighting and transparency effects
@@ -44,15 +69,15 @@ int distance(int y1, int x1, int y2, int x2)
*/
static bool_ is_wall(cave_type *c_ptr)
{
- byte feat;
-
+ auto const &f_info = game->edit_data.f_info;
/* Handle feature mimics */
- if (c_ptr->mimic) feat = c_ptr->mimic;
- else feat = c_ptr->feat;
+ byte const feat = c_ptr->mimic
+ ? c_ptr->mimic
+ : c_ptr->feat;
/* Paranoia */
- if (feat >= max_f_idx) return FALSE;
+ if (feat >= f_info.size()) return FALSE;
/* Vanilla floors and doors aren't considered to be walls */
if (feat < FEAT_SECRET) return FALSE;
@@ -67,7 +92,7 @@ static bool_ is_wall(cave_type *c_ptr)
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;
+ return (f_info[feat].flags & FF_WALL) ? TRUE : FALSE;
}
@@ -333,7 +358,7 @@ bool_ los(int y1, int x1, int y2, int x2)
/*
* Returns true if the player's grid is dark
*/
-bool_ no_lite(void)
+bool_ no_lite()
{
return (!player_can_see_bold(p_ptr->py, p_ptr->px));
}
@@ -347,27 +372,22 @@ bool_ no_lite(void)
*/
bool_ cave_valid_bold(int y, int x)
{
- cave_type *c_ptr = &cave[y][x];
-
- s16b this_o_idx, next_o_idx = 0;
-
+ cave_type const *c_ptr = &cave[y][x];
/* 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)
+ for (auto const o_idx: c_ptr->o_idxs)
{
- object_type * o_ptr;
-
/* Acquire object */
- o_ptr = &o_list[this_o_idx];
-
- /* Acquire next object */
- next_o_idx = o_ptr->next_o_idx;
+ object_type *o_ptr = &o_list[o_idx];
/* Forbid artifact grids */
- if ((o_ptr->art_name) || artifact_p(o_ptr)) return (FALSE);
+ if (artifact_p(o_ptr))
+ {
+ return (FALSE);
+ }
}
/* Accept */
@@ -376,106 +396,73 @@ bool_ cave_valid_bold(int y, int x)
-
/*
- * 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
+ * Generate visual for 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)]);
+ auto const &r_info = game->edit_data.r_info;
- /* Random color */
- *ap = randint(15);
+ // Cached state which keeps a list of all the "live" monster race entries.
+ static std::vector<size_t> *instance = nullptr;
- break;
- }
-
- /* Normal graphics */
- default:
+ // First-time initialization
+ if (!instance)
+ {
+ // Create the list of "live" indexes
+ instance = new std::vector<size_t>();
+ // Start at 1 to avoid 'player'
+ for (size_t i = 1; i < r_info.size(); i++)
{
- /* Avoid player ghost */
- n = randint(max_r_idx);
-
- *cp = r_info[n].x_char;
-
- *ap = r_info[n].x_attr;
-
- break;
+ if (r_info[i].name)
+ {
+ instance->push_back(i);
+ }
}
}
-}
-
-
+ // Sanity check
+ assert(instance != nullptr);
-/*
- * Hack -- Legal object codes
- */
-static cptr image_object_hack = "?/|\\\"!$()_-=[]{},~";
+ // Select a race at random
+ int n = rand_int(instance->size());
+ *cp = r_info[(*instance)[n]].x_char;
+ *ap = r_info[(*instance)[n]].x_attr;
+}
-/*
- * Hardcoded IBM pseudo-graphics code points have been removed
- * for the same reason as stated above -- pelpel
- */
/*
- * Mega-Hack -- Hallucinatory object
+ * Generate visual for hallucinatory object
*/
static void image_object(byte *ap, char *cp)
{
- int n;
+ auto const &k_info = game->edit_data.k_info;
- switch (graphics_mode)
+ // Cached state which keeps a list of the "live" object_kind entries.
+ static std::vector<size_t> *instance = nullptr;
+
+ // First-time initialization
+ if (!instance)
{
- /* Text mode */
- case GRAPHICS_NONE:
+ // Create the list of "live" indexes
+ instance = new std::vector<size_t>();
+ // Filter all the "live" entries
+ for (size_t i = 0; i < k_info.size(); i++)
{
- n = strlen(image_object_hack);
-
- /* Random symbol from set above */
- *cp = (image_object_hack[rand_int(n)]);
-
- /* Random color */
- *ap = randint(15);
-
- /* Done */
- break;
+ if (k_info[i].name)
+ {
+ instance->push_back(i);
+ }
}
+ }
- /* Normal graphics */
- default:
- {
- n = randint(max_k_idx - 1);
-
- *cp = k_info[n].x_char;
- *ap = k_info[n].x_attr;
+ // Sanity check
+ assert(instance != nullptr);
- break;
- }
- }
+ // Select an object kind at random
+ int n = rand_int(instance->size());
+ *cp = k_info[(*instance)[n]].x_char;
+ *ap = k_info[(*instance)[n]].x_attr;
}
@@ -498,26 +485,8 @@ 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;
-}
-
-#endif
-
-char get_shimmer_color()
+static char get_shimmer_color()
{
switch (randint(7))
{
@@ -542,50 +511,60 @@ char get_shimmer_color()
/*
- * 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.
+ * Breath 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 */
+struct breath_color {
+ std::size_t breath_idx;
+ byte first_color;
+ byte second_color;
};
/*
+ * Breath colors. The value "255" is special. Monsters with
+ * that kind of breath may be any color.
+ */
+static breath_color const *lookup_breath_color(std::size_t i)
+{
+ static breath_color breath_to_attr[] =
+ {
+ { SF_BR_ACID_IDX, TERM_SLATE, TERM_L_DARK },
+ { SF_BR_ELEC_IDX, TERM_BLUE, TERM_L_BLUE },
+ { SF_BR_FIRE_IDX, TERM_RED, TERM_L_RED },
+ { SF_BR_COLD_IDX, TERM_WHITE, TERM_L_WHITE },
+ { SF_BR_POIS_IDX, TERM_GREEN, TERM_L_GREEN },
+ { SF_BR_NETH_IDX, TERM_L_GREEN, TERM_GREEN },
+ { SF_BR_LITE_IDX, TERM_YELLOW, TERM_ORANGE },
+ { SF_BR_DARK_IDX, TERM_L_DARK, TERM_SLATE },
+ { SF_BR_CONF_IDX, TERM_L_UMBER, TERM_UMBER },
+ { SF_BR_SOUN_IDX, TERM_YELLOW, TERM_L_UMBER },
+ { SF_BR_CHAO_IDX, 255, 255 },
+ { SF_BR_DISE_IDX, TERM_VIOLET, TERM_VIOLET },
+ { SF_BR_NEXU_IDX, TERM_L_RED, TERM_VIOLET },
+ { SF_BR_TIME_IDX, TERM_L_BLUE, TERM_L_BLUE },
+ { SF_BR_INER_IDX, TERM_L_WHITE, TERM_SLATE },
+ { SF_BR_GRAV_IDX, TERM_L_WHITE, TERM_SLATE },
+ { SF_BR_SHAR_IDX, TERM_UMBER, TERM_L_UMBER },
+ { SF_BR_PLAS_IDX, TERM_ORANGE, TERM_RED },
+ { SF_BR_WALL_IDX, TERM_UMBER, TERM_L_UMBER },
+ { SF_BR_MANA_IDX, TERM_L_BLUE, TERM_WHITE },
+ { SF_BR_NUKE_IDX, TERM_GREEN, TERM_L_GREEN },
+ { SF_BR_DISI_IDX, TERM_WHITE, TERM_L_RED },
+ };
+
+ for (auto const &breath_color: breath_to_attr)
+ {
+ if (breath_color.breath_idx == i)
+ {
+ return &breath_color;
+ }
+ }
+
+ return nullptr;
+}
+
+
+/*
* Multi-hued monsters shimmer acording to their breaths.
*
* If a monster has only one kind of breath, it uses both colors
@@ -594,13 +573,11 @@ static byte breath_to_attr[32][2] =
*
* If a monster does not breath anything, it can be any color.
*/
-static byte multi_hued_attr(monster_race *r_ptr)
+static byte multi_hued_attr(std::shared_ptr<monster_race> r_ptr)
{
byte allowed_attrs[15];
- int i, j;
-
- int stored_colors = 0;
+ std::size_t stored_colors = 0;
int breaths = 0;
@@ -613,18 +590,22 @@ static byte multi_hued_attr(monster_race *r_ptr)
if (!r_ptr->freq_inate) return (get_shimmer_color());
/* Check breaths */
- for (i = 0; i < 32; i++)
+ for (std::size_t i = 0; i < monster_spell_flag_set::nbits; i++)
{
bool_ stored = FALSE;
/* Don't have that breath */
- if (!(r_ptr->flags4 & (1L << i))) continue;
+ if (!(r_ptr->spells.bit(i))) continue;
- /* Get the first color of this breath */
- first_color = breath_to_attr[i][0];
+ /* Find the breath in our list */
+ auto breath_color = lookup_breath_color(i);
+ if (!breath_color)
+ {
+ continue;
+ }
- /* Breath has no color associated with it */
- if (first_color == 0) continue;
+ /* Get the first color of this breath */
+ first_color = breath_color->first_color;
/* Monster can be of any color */
if (first_color == 255) return (randint(15));
@@ -638,7 +619,7 @@ static byte multi_hued_attr(monster_race *r_ptr)
/* Always store the first color */
- for (j = 0; j < stored_colors; j++)
+ for (std::size_t j = 0; j < stored_colors; j++)
{
/* Already stored */
if (allowed_attrs[j] == first_color) stored = TRUE;
@@ -655,7 +636,7 @@ static byte multi_hued_attr(monster_race *r_ptr)
*/
if (breaths == 1)
{
- second_color = breath_to_attr[i][1];
+ second_color = breath_color->second_color;
}
}
@@ -866,78 +847,36 @@ static byte darker_attrs[16] =
};
-void map_info(int y, int x, byte *ap, char *cp, byte *tap, char *tcp,
- byte *eap, char *ecp)
+static void map_info(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;
+ auto const &st_info = game->edit_data.st_info;
+ auto const &r_info = game->edit_data.r_info;
+ auto const &f_info = game->edit_data.f_info;
+ auto const &k_info = game->edit_data.k_info;
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];
+ cave_type *c_ptr = &cave[y][x];
/* Cache some frequently used values */
/* Grid info */
- info = c_ptr->info;
+ auto 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;
- }
+ auto const feat = c_ptr->mimic
+ ? c_ptr->mimic
+ : f_info[c_ptr->feat].mimic
+ ;
/* Access floor */
- f_ptr = &f_info[feat];
-
-
- /* Reset attr/char */
- *eap = 0;
- *ecp = 0;
+ auto f_ptr = &f_info[feat];
/**** Layer 1 -- Terrain feature ****/
@@ -965,77 +904,13 @@ void map_info(int y, int x, byte *ap, char *cp, byte *tap, char *tcp,
}
/* Mega-Hack 2 -- stair to dungeon branch are purple */
- if (c_ptr->special && attr_mutable &&
- ((feat == FEAT_MORE) || (feat == FEAT_LESS)))
+ 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 (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)
+ if (!options->avoid_other && !options->avoid_shimmer)
{
/* Special terrain effect */
if (c_ptr->effect)
@@ -1044,7 +919,7 @@ void map_info(int y, int x, byte *ap, char *cp, byte *tap, char *tcp,
}
/* Multi-hued attr */
- else if (f_ptr->flags1 & FF1_ATTR_MULTI)
+ else if (f_ptr->flags & FF_ATTR_MULTI)
{
a = f_ptr->shimmer[rand_int(7)];
}
@@ -1057,7 +932,6 @@ void map_info(int y, int x, byte *ap, char *cp, byte *tap, char *tcp,
* 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.
*
@@ -1066,84 +940,50 @@ void map_info(int y, int x, byte *ap, char *cp, byte *tap, char *tcp,
*/
/* view_special_lite: lighting effects for boring features */
- if (view_special_lite &&
- ((f_ptr->flags1 & (FF1_FLOOR | FF1_REMEMBER)) == FF1_FLOOR))
+ if (options->view_special_lite &&
+ ((f_ptr->flags & (FF_FLOOR | FF_REMEMBER)) == FF_FLOOR))
{
- if (!p_ptr->wild_mode && !(info & (CAVE_TRDT)) &&
- (attr_mutable || (graf_new && feat_supports_lighting(feat))))
+ if (!p_ptr->wild_mode)
{
/* Handle "seen" grids */
if (info & (CAVE_SEEN))
{
/* Only lit by "torch" light */
- if (view_yellow_lite && !(info & (CAVE_GLOW)))
+ if (options->view_yellow_lite && !(info & (CAVE_GLOW)))
{
- if (graf_new)
- {
- /* Use a brightly lit tile */
- c += 2;
- }
- else
- {
- /* Use "yellow" */
- a = TERM_YELLOW;
- }
+ /* 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];
- }
+ /* 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;
- }
+ /* Use darkest colour */
+ a = TERM_L_DARK;
}
/* "Out-of-sight" glowing grids -- handle "view_bright_lite" */
- else if (view_bright_lite)
+ else if (options->view_bright_lite)
{
- if (graf_new)
- {
- /* Use a dark tile */
- c++;
- }
- else
- {
- /* Use darker colour */
- a = dark_attrs[a & 0xF];
- }
+ /* 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)))
+ else if (options->view_granite_lite &&
+ (f_ptr->flags & (FF_NO_VISION | FF_DOOR)))
{
- if (!p_ptr->wild_mode && !(info & (CAVE_TRDT)) &&
- (attr_mutable || (graf_new && feat_supports_lighting(feat))))
+ if (!p_ptr->wild_mode)
{
/* Handle "seen" grids */
if (info & (CAVE_SEEN))
@@ -1154,44 +994,20 @@ void map_info(int y, int x, byte *ap, char *cp, byte *tap, char *tcp,
/* Handle "blind" */
else if (p_ptr->blind)
{
- if (graf_new)
- {
- /* Use a dark tile */
- c++;
- }
- else
- {
- /* Use darker colour */
- a = darker_attrs[a & 0xF];
- }
+ /* Use darker colour */
+ a = darker_attrs[a & 0xF];
}
/* Handle "view_bright_lite" */
- else if (view_bright_lite)
+ else if (options->view_bright_lite)
{
- if (graf_new)
- {
- /* Use a dark tile */
- c++;
- }
- else
- {
- /* Use darker colour */
- a = dark_attrs[a & 0xF];
- }
+ /* Use darker colour */
+ a = dark_attrs[a & 0xF];
}
else
{
- if (graf_new)
- {
- /* Use a brightly lit tile */
- c += 2;
- }
- else
- {
- /* Use normal colour */
- }
+ /* Use normal colour */
}
}
}
@@ -1221,10 +1037,6 @@ void map_info(int y, int x, byte *ap, char *cp, byte *tap, char *tcp,
image_random(ap, cp);
}
- /* Save the terrain info for the transparency effects */
- *tap = a;
- *tcp = c;
-
/* Save the info */
*ap = a;
*cp = c;
@@ -1232,40 +1044,31 @@ void map_info(int y, int x, byte *ap, char *cp, byte *tap, char *tcp,
/**** Layer 2 -- Objects ****/
- if (feat != FEAT_MON_TRAP)
+ for (auto const o_idx: c_ptr->o_idxs)
{
- for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
- {
- object_type * o_ptr;
+ /* Acquire object */
+ object_type *o_ptr = &o_list[o_idx];
- /* Acquire object */
- o_ptr = &o_list[this_o_idx];
+ /* Memorized objects */
+ if (o_ptr->marked)
+ {
+ /* Normal char */
+ *cp = object_char(o_ptr);
- /* Acquire next object */
- next_o_idx = o_ptr->next_o_idx;
+ /* Normal attr */
+ *ap = object_attr(o_ptr);
- /* Memorized objects */
- if (o_ptr->marked)
+ /* Multi-hued attr */
+ if (!options->avoid_other && (k_info[o_ptr->k_idx].flags & TR_ATTR_MULTI))
{
- /* 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();
- }
+ *ap = get_shimmer_color();
+ }
- /* Hack -- hallucination */
- if (p_ptr->image) image_object(ap, cp);
+ /* Hack -- hallucination */
+ if (p_ptr->image) image_object(ap, cp);
- /* Done */
- break;
- }
+ /* Done */
+ break;
}
}
@@ -1275,14 +1078,12 @@ void map_info(int y, int x, byte *ap, char *cp, byte *tap, char *tcp,
if (c_ptr->m_idx)
{
monster_type *m_ptr = &m_list[c_ptr->m_idx];
- monster_race *r_ptr = race_inf(m_ptr);
+ auto const r_ptr = m_ptr->race();
- if (r_ptr->flags9 & RF9_MIMIC)
+ if (r_ptr->flags & RF_MIMIC)
{
- object_type *o_ptr;
-
- /* Acquire object */
- o_ptr = &o_list[m_ptr->hold_o_idx];
+ /* Acquire object being mimicked */
+ object_type *o_ptr = &o_list[m_ptr->mimic_o_idx()];
/* Memorized objects */
if (o_ptr->marked)
@@ -1294,8 +1095,7 @@ void map_info(int y, int x, byte *ap, char *cp, byte *tap, char *tcp,
*ap = object_attr(o_ptr);
/* Multi-hued attr */
- if (!avoid_other && attr_mutable &&
- (k_info[o_ptr->k_idx].flags5 & TR5_ATTR_MULTI))
+ if (!options->avoid_other && (k_info[o_ptr->k_idx].flags & TR_ATTR_MULTI))
{
*ap = get_shimmer_color();
}
@@ -1309,46 +1109,12 @@ void map_info(int y, int x, byte *ap, char *cp, byte *tap, char *tcp,
/* 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)
+ if (options->avoid_other)
{
/* Use char */
*cp = c;
@@ -1358,10 +1124,10 @@ void map_info(int y, int x, byte *ap, char *cp, byte *tap, char *tcp,
}
/* Multi-hued monster */
- else if (r_ptr->flags1 & (RF1_ATTR_MULTI))
+ else if (r_ptr->flags & RF_ATTR_MULTI)
{
/* Is it a shapechanger? */
- if (r_ptr->flags2 & (RF2_SHAPECHANGER))
+ if (r_ptr->flags & RF_SHAPECHANGER)
{
image_random(ap, cp);
}
@@ -1369,7 +1135,7 @@ void map_info(int y, int x, byte *ap, char *cp, byte *tap, char *tcp,
*cp = c;
/* Multi-hued attr */
- if (r_ptr->flags2 & (RF2_ATTR_ANY))
+ if (r_ptr->flags & RF_ATTR_ANY)
{
*ap = randint(15);
}
@@ -1380,7 +1146,7 @@ void map_info(int y, int x, byte *ap, char *cp, byte *tap, char *tcp,
}
/* Normal monster (not "clear" in any way) */
- else if (!(r_ptr->flags1 & (RF1_ATTR_CLEAR | RF1_CHAR_CLEAR)))
+ else if (!(r_ptr->flags & (RF_ATTR_CLEAR | RF_CHAR_CLEAR)))
{
/* Use char */
*cp = c;
@@ -1406,14 +1172,14 @@ void map_info(int y, int x, byte *ap, char *cp, byte *tap, char *tcp,
else
{
/* Normal (non-clear char) monster */
- if (!(r_ptr->flags1 & (RF1_CHAR_CLEAR)))
+ if (!(r_ptr->flags & RF_CHAR_CLEAR))
{
/* Normal char */
*cp = c;
}
/* Normal (non-clear attr) monster */
- else if (!(r_ptr->flags1 & (RF1_ATTR_CLEAR)))
+ else if (!(r_ptr->flags & RF_ATTR_CLEAR))
{
/* Normal attr */
*ap = a;
@@ -1434,14 +1200,10 @@ void map_info(int y, int x, byte *ap, char *cp, byte *tap, char *tcp,
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;
+ auto r_ptr = &r_info[p_ptr->body_monster];
/* Get the "player" attr */
- if (!avoid_other && attr_mutable && (r_ptr->flags1 & RF1_ATTR_MULTI))
+ if (!options->avoid_other && (r_ptr->flags & RF_ATTR_MULTI))
{
a = get_shimmer_color();
}
@@ -1453,67 +1215,16 @@ void map_info(int y, int x, byte *ap, char *cp, byte *tap, char *tcp,
/* Get the "player" char */
c = r_ptr->x_char;
-
- /* Mega-Hack -- Apply modifications to player graphics XXX XXX XXX */
- switch (graphics_mode)
+ /* Show player health char instead? */
+ if (options->player_char_health)
{
- 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;
- }
+ int percent = p_ptr->chp * 10 / p_ptr->mhp;
- case GRAPHICS_ISO:
- case GRAPHICS_NEW:
+ if (percent < 7)
{
- 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;
+ c = I2D(percent);
+ if (percent < 3) a = TERM_L_RED;
}
-
}
/* Save the info */
@@ -1525,61 +1236,41 @@ void map_info(int y, int x, byte *ap, char *cp, byte *tap, char *tcp,
/*
- * Special version of map_info, for use by cmovie and HTML converter
+ * Special version of map_info, for use by 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;
+ auto const &st_info = game->edit_data.st_info;
+ auto const &r_info = game->edit_data.r_info;
+ auto const &f_info = game->edit_data.f_info;
+ auto const &k_info = game->edit_data.k_info;
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;
+ /* Shorthand */
+ auto const avoid_other = options->avoid_other;
/**** Preparation ****/
/* Access the grid */
- c_ptr = &cave[y][x];
+ auto const c_ptr = &cave[y][x];
/* Cache some frequently used values */
/* Grid info */
- info = c_ptr->info;
+ auto 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;
- }
+ auto const feat = c_ptr->mimic
+ ? c_ptr->mimic
+ : f_info[c_ptr->feat].mimic;
/* Access floor */
- f_ptr = &f_info[feat];
+ feature_type const *f_ptr = &f_info[feat];
/**** Layer 1 -- Terrain feature ****/
@@ -1613,41 +1304,6 @@ void map_info_default(int y, int x, byte *ap, char *cp)
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)
{
@@ -1658,7 +1314,7 @@ void map_info_default(int y, int x, byte *ap, char *cp)
}
/* Multi-hued attr */
- else if (f_ptr->flags1 & FF1_ATTR_MULTI)
+ else if (f_ptr->flags & FF_ATTR_MULTI)
{
a = f_ptr->shimmer[rand_int(7)];
}
@@ -1671,7 +1327,6 @@ void map_info_default(int y, int x, byte *ap, char *cp)
* 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.
*
@@ -1680,16 +1335,16 @@ void map_info_default(int y, int x, byte *ap, char *cp)
*/
/* view_special_lite: lighting effects for boring features */
- if (view_special_lite &&
- ((f_ptr->flags1 & (FF1_FLOOR | FF1_REMEMBER)) == FF1_FLOOR))
+ if (options->view_special_lite &&
+ ((f_ptr->flags & (FF_FLOOR | FF_REMEMBER)) == FF_FLOOR))
{
- if (!p_ptr->wild_mode && !(info & (CAVE_TRDT)))
+ if (!p_ptr->wild_mode)
{
/* Handle "seen" grids */
if (info & (CAVE_SEEN))
{
/* Only lit by "torch" light */
- if (view_yellow_lite && !(info & (CAVE_GLOW)))
+ if (options->view_yellow_lite && !(info & (CAVE_GLOW)))
{
/* Use "yellow" */
a = TERM_YELLOW;
@@ -1711,7 +1366,7 @@ void map_info_default(int y, int x, byte *ap, char *cp)
}
/* "Out-of-sight" glowing grids -- handle "view_bright_lite" */
- else if (view_bright_lite)
+ else if (options->view_bright_lite)
{
/* Use darker colour */
a = dark_attrs[a & 0xF];
@@ -1720,10 +1375,10 @@ void map_info_default(int y, int x, byte *ap, char *cp)
}
/* view_granite_lite: lighting effects for walls and doors */
- else if (view_granite_lite &&
- (f_ptr->flags1 & (FF1_NO_VISION | FF1_DOOR)))
+ else if (options->view_granite_lite &&
+ (f_ptr->flags & (FF_NO_VISION | FF_DOOR)))
{
- if (!p_ptr->wild_mode && !(info & (CAVE_TRDT)))
+ if (!p_ptr->wild_mode)
{
/* Handle "seen" grids */
if (info & (CAVE_SEEN))
@@ -1739,7 +1394,7 @@ void map_info_default(int y, int x, byte *ap, char *cp)
}
/* Handle "view_bright_lite" */
- else if (view_bright_lite)
+ else if (options->view_bright_lite)
{
/* Use darker colour */
a = dark_attrs[a & 0xF];
@@ -1779,40 +1434,31 @@ void map_info_default(int y, int x, byte *ap, char *cp)
/**** Layer 2 -- Objects ****/
- if (feat != FEAT_MON_TRAP)
+ for (auto const this_o_idx: c_ptr->o_idxs)
{
- for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
- {
- object_type * o_ptr;
+ /* Acquire object */
+ object_type *o_ptr = &o_list[this_o_idx];
- /* Acquire object */
- o_ptr = &o_list[this_o_idx];
+ /* Memorized objects */
+ if (o_ptr->marked)
+ {
+ /* Normal char */
+ *cp = object_char_default(o_ptr);
- /* Acquire next object */
- next_o_idx = o_ptr->next_o_idx;
+ /* Normal attr */
+ *ap = object_attr_default(o_ptr);
- /* Memorized objects */
- if (o_ptr->marked)
+ /* Multi-hued attr */
+ if (!avoid_other && (k_info[o_ptr->k_idx].flags & TR_ATTR_MULTI))
{
- /* 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();
- }
+ *ap = get_shimmer_color();
+ }
- /* Hack -- hallucination */
- if (p_ptr->image) image_object(ap, cp);
+ /* Hack -- hallucination */
+ if (p_ptr->image) image_object(ap, cp);
- /* Done */
- break;
- }
+ /* Done */
+ break;
}
}
@@ -1822,14 +1468,12 @@ void map_info_default(int y, int x, byte *ap, char *cp)
if (c_ptr->m_idx)
{
monster_type *m_ptr = &m_list[c_ptr->m_idx];
- monster_race *r_ptr = race_inf(m_ptr);
+ auto const r_ptr = m_ptr->race();
- if (r_ptr->flags9 & RF9_MIMIC)
+ if (r_ptr->flags & RF_MIMIC)
{
- object_type *o_ptr;
-
- /* Acquire object */
- o_ptr = &o_list[m_ptr->hold_o_idx];
+ /* Acquire object being mimicked */
+ object_type *o_ptr = &o_list[m_ptr->mimic_o_idx()];
/* Memorized objects */
if (o_ptr->marked)
@@ -1841,8 +1485,7 @@ void map_info_default(int y, int x, byte *ap, char *cp)
*ap = object_attr_default(o_ptr);
/* Multi-hued attr */
- if (!avoid_other && !use_graphics &&
- (k_info[o_ptr->k_idx].flags5 & TR5_ATTR_MULTI))
+ if (!avoid_other && (k_info[o_ptr->k_idx].flags & TR_ATTR_MULTI))
{
*ap = get_shimmer_color();
}
@@ -1856,8 +1499,6 @@ void map_info_default(int y, int x, byte *ap, char *cp)
/* 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;
@@ -1873,10 +1514,10 @@ void map_info_default(int y, int x, byte *ap, char *cp)
}
/* Multi-hued monster */
- else if (r_ptr->flags1 & (RF1_ATTR_MULTI))
+ else if (r_ptr->flags & RF_ATTR_MULTI)
{
/* Is it a shapechanger? */
- if (r_ptr->flags2 & (RF2_SHAPECHANGER))
+ if (r_ptr->flags & RF_SHAPECHANGER)
{
image_random(ap, cp);
}
@@ -1884,7 +1525,7 @@ void map_info_default(int y, int x, byte *ap, char *cp)
*cp = c;
/* Multi-hued attr */
- if (r_ptr->flags2 & (RF2_ATTR_ANY))
+ if (r_ptr->flags & RF_ATTR_ANY)
{
*ap = randint(15);
}
@@ -1895,7 +1536,7 @@ void map_info_default(int y, int x, byte *ap, char *cp)
}
/* Normal monster (not "clear" in any way) */
- else if (!(r_ptr->flags1 & (RF1_ATTR_CLEAR | RF1_CHAR_CLEAR)))
+ else if (!(r_ptr->flags & (RF_ATTR_CLEAR | RF_CHAR_CLEAR)))
{
/* Use char */
*cp = c;
@@ -1918,14 +1559,14 @@ void map_info_default(int y, int x, byte *ap, char *cp)
else
{
/* Normal (non-clear char) monster */
- if (!(r_ptr->flags1 & (RF1_CHAR_CLEAR)))
+ if (!(r_ptr->flags & RF_CHAR_CLEAR))
{
/* Normal char */
*cp = c;
}
/* Normal (non-clear attr) monster */
- else if (!(r_ptr->flags1 & (RF1_ATTR_CLEAR)))
+ else if (!(r_ptr->flags & RF_ATTR_CLEAR))
{
/* Normal attr */
*ap = a;
@@ -1948,10 +1589,10 @@ void map_info_default(int y, int x, byte *ap, char *cp)
(!p_ptr->invis ||
(p_ptr->invis && p_ptr->see_inv)))
{
- monster_race *r_ptr = &r_info[p_ptr->body_monster];
+ auto r_ptr = &r_info[p_ptr->body_monster];
/* Get the "player" attr */
- if (!avoid_other && (r_ptr->flags1 & RF1_ATTR_MULTI))
+ if (!avoid_other && (r_ptr->flags & RF_ATTR_MULTI))
{
a = get_shimmer_color();
}
@@ -1968,10 +1609,6 @@ void map_info_default(int y, int x, byte *ap, char *cp)
*cp = c;
}
-
- /* XXX Restore the graphics mode */
- use_graphics = use_graphics_hack;
- graphics_mode = graphics_mode_hack;
}
@@ -1981,7 +1618,6 @@ void map_info_default(int y, int x, byte *ap, char *cp)
static int panel_col_of(int col)
{
col -= panel_col_min;
- if (use_bigtile) col *= 2;
return col + COL_MAP;
}
@@ -2011,24 +1647,6 @@ void print_rel(char c, byte a, int y, int x)
/* 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);
- }
}
@@ -2080,20 +1698,15 @@ void note_spot(int y, int 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)
+ for (auto const this_o_idx: c_ptr->o_idxs)
{
- object_type * o_ptr = &o_list[this_o_idx];
-
- /* Acquire next object */
- next_o_idx = o_ptr->next_o_idx;
+ /* Acquire object */
+ object_type *o_ptr = &o_list[this_o_idx];
/* Memorize objects */
o_ptr->marked = TRUE;
@@ -2102,30 +1715,28 @@ void note_spot(int y, int x)
if (c_ptr->m_idx)
{
monster_type *m_ptr = &m_list[c_ptr->m_idx];
- monster_race *r_ptr = race_inf(m_ptr);
+ auto r_ptr = m_ptr->race();
- if (r_ptr->flags9 & RF9_MIMIC)
+ if (r_ptr->flags & RF_MIMIC)
{
- object_type *o_ptr = &o_list[m_ptr->hold_o_idx];
-
+ object_type *o_ptr = &o_list[m_ptr->mimic_o_idx()];
o_ptr->marked = TRUE;
}
}
/* Hack -- memorize grids */
- if (!(info & (CAVE_MARK)))
+ 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)
+ if (((info & CAVE_GLOW) && options->view_perma_grids) ||
+ options->view_torch_grids)
{
/* Memorize */
- c_ptr->info |= (CAVE_MARK);
+ c_ptr->info |= CAVE_MARK;
}
}
@@ -2133,7 +1744,7 @@ void note_spot(int y, int x)
else
{
/* Memorize */
- c_ptr->info |= (CAVE_MARK);
+ c_ptr->info |= CAVE_MARK;
}
}
}
@@ -2146,39 +1757,17 @@ void note_spot(int y, int x)
*/
void lite_spot(int y, int x)
{
- byte a, a2;
- byte c, c2;
-
- byte ta;
- char tc;
-
- byte ea;
- char ec;
-
+ byte a;
+ char c;
/* Redraw if on screen */
if (panel_contains(y, x))
{
/* Examine the grid */
- map_info(y, x, &a, (char*)&c, &ta, &tc, &ea, &ec);
+ map_info(y, x, &a, &c);
/* 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);
- }
-
+ Term_queue_char(panel_col_of(x), y - panel_row_prt, a, c);
}
}
@@ -2192,17 +1781,17 @@ void lite_spot(int y, int x)
* 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)
+void prt_map()
{
int x, y;
int v;
/* Access the cursor state */
- (void)Term_get_cursor(&v);
+ Term_get_cursor(&v);
/* Hide the cursor */
- (void)Term_set_cursor(0);
+ Term_set_cursor(0);
/* Dump the map */
for (y = panel_row_min; y <= panel_row_max; y++)
@@ -2210,33 +1799,14 @@ void prt_map(void)
/* 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;
+ byte a;
+ char c;
/* Determine what is there */
- map_info(y, x, &a, &c, &ta, &tc, &ea, &ec);
+ map_info(y, x, &a, &c);
/* 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);
- }
+ Term_queue_char(panel_col_of(x), y - panel_row_prt, a, c);
}
}
@@ -2244,7 +1814,7 @@ void prt_map(void)
lite_spot(p_ptr->py, p_ptr->px);
/* Restore the cursor */
- (void)Term_set_cursor(v);
+ Term_set_cursor(v);
}
@@ -2342,9 +1912,9 @@ static byte priority_table[][2] =
*/
static byte priority(byte a, char c)
{
- int i, p0, p1;
+ auto const &f_info = game->edit_data.f_info;
- feature_type *f_ptr;
+ int i, p0, p1;
/* Scan the table */
for (i = 0; TRUE; i++)
@@ -2359,7 +1929,7 @@ static byte priority(byte a, char c)
p0 = priority_table[i][0];
/* Access the feature */
- f_ptr = &f_info[p0];
+ auto f_ptr = &f_info[p0];
/* Check character and attribute, accept matches */
if ((f_ptr->x_char == c) && (f_ptr->x_attr == a)) return (p1);
@@ -2392,23 +1962,12 @@ void display_map(int *cy, int *cx)
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
*/
@@ -2427,40 +1986,30 @@ void display_map(int *cy, int *cx)
/* Save lighting effects */
- old_view_special_lite = view_special_lite;
- old_view_granite_lite = view_granite_lite;
+ auto const old_view_special_lite = options->view_special_lite;
+ auto const old_view_granite_lite = options->view_granite_lite;
/* Disable lighting effects */
- view_special_lite = FALSE;
- view_granite_lite = FALSE;
-
+ options->view_special_lite = FALSE;
+ options->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 */
+ /* Set up initial maps */
+ std::vector<std::vector<byte>> ma;
+ std::vector<std::vector<char>> mc;
+ std::vector<std::vector<byte>> mp;
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);
- }
+ // Nothing there.
+ ma.push_back(std::vector<byte>(wid + 2, TERM_WHITE));
+ mc.push_back(std::vector<char>(wid + 2, ' '));
- /* 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;
- }
+ // No priority.
+ mp.push_back(std::vector<byte>(wid + 2, 0));
}
+ assert(static_cast<int>(ma.size()) == hgt + 2);
+ assert(static_cast<int>(mc.size()) == hgt + 2);
+ assert(static_cast<int>(mp.size()) == hgt + 2);
/* Calculate scaling factors */
yfactor = ((cur_hgt / hgt < 4) && (cur_hgt > hgt)) ? 10 : 1;
@@ -2479,7 +2028,7 @@ void display_map(int *cy, int *cx)
x = i * xfactor / xrat + 1;
/* Extract the current attr/char at that map location */
- map_info(j, i, &ta, &tc, &ta, &tc, &ta, &tc);
+ map_info(j, i, &ta, &tc);
/* Extract the priority of that attr/char */
tp = priority(ta, tc);
@@ -2531,58 +2080,16 @@ void display_map(int *cy, int *cx)
/* 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 *);
-
+ *cx = p_ptr->px * xfactor / xrat + COL_MAP;
/* Restore lighting effects */
- view_special_lite = old_view_special_lite;
- view_granite_lite = old_view_granite_lite;
+ options->view_special_lite = old_view_special_lite;
+ options->view_granite_lite = old_view_granite_lite;
}
@@ -2591,7 +2098,7 @@ void display_map(int *cy, int *cx)
*
* Currently, the "player" is displayed on the map. XXX XXX XXX
*/
-void do_cmd_view_map(void)
+void do_cmd_view_map()
{
int cy, cx;
int wid, hgt;
@@ -3203,38 +2710,6 @@ struct vinfo_hack
/*
- * 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)
@@ -3286,14 +2761,12 @@ static void vinfo_init_aux(vinfo_hack *hack, int y, int x, long m)
* a number which is too high, running this function, and using the
* error messages to obtain the correct values.
*/
-errr vinfo_init(void)
+errr vinfo_init()
{
int i, y, x;
long m;
- vinfo_hack *hack;
-
int num_grids = 0;
int queue_head = 0;
@@ -3302,8 +2775,8 @@ errr vinfo_init(void)
/* Make hack */
- MAKE(hack, vinfo_hack);
-
+ vinfo_hack hack;
+ memset(&hack, 0, sizeof(vinfo_hack));
/* Analyze grids */
for (y = 0; y <= MAX_SIGHT; ++y)
@@ -3314,8 +2787,8 @@ errr vinfo_init(void)
if (distance(0, 0, y, x) > MAX_SIGHT) continue;
/* Default slope range */
- hack->slopes_min[y][x] = 999999999;
- hack->slopes_max[y][x] = 0;
+ hack.slopes_min[y][x] = 999999999;
+ hack.slopes_max[y][x] = 0;
/* Paranoia */
if (num_grids >= VINFO_MAX_GRIDS)
@@ -3331,25 +2804,25 @@ errr vinfo_init(void)
m = SCALE * (1000L * y - 500) / (1000L * x + 500);
/* Handle "legal" slopes */
- vinfo_init_aux(hack, y, x, m);
+ 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);
+ 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);
+ 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);
+ vinfo_init_aux(&hack, y, x, m);
}
}
@@ -3362,21 +2835,15 @@ errr vinfo_init(void)
}
/* Enforce maximal efficiency */
- if (hack->num_slopes < VINFO_MAX_SLOPES)
+ if (hack.num_slopes < VINFO_MAX_SLOPES)
{
quit_fmt("Too few slopes (%d < %d)!",
- hack->num_slopes, VINFO_MAX_SLOPES);
+ 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);
+ std::sort(std::begin(hack.slopes), std::end(hack.slopes));
@@ -3419,14 +2886,14 @@ errr vinfo_init(void)
/* Analyze slopes */
- for (i = 0; i < hack->num_slopes; ++i)
+ for (i = 0; i < hack.num_slopes; ++i)
{
- m = hack->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]))
+ (hack.slopes_min[y][x] < m) &&
+ (m < hack.slopes_max[y][x]))
{
switch (i / 32)
{
@@ -3507,10 +2974,6 @@ errr vinfo_init(void)
}
- /* Kill hack */
- KILL(hack, vinfo_hack);
-
-
/* Success */
return (0);
}
@@ -3520,7 +2983,7 @@ errr vinfo_init(void)
/*
* Forget the "CAVE_VIEW" grids, redrawing as needed
*/
-void forget_view(void)
+void forget_view()
{
int i;
@@ -3628,7 +3091,7 @@ void forget_view(void)
* 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)
+void update_view()
{
int i, o;
int y, x;
@@ -3808,31 +3271,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 */
@@ -3966,7 +3410,7 @@ void update_view(void)
/*
* Clear monster light
*/
-void forget_mon_lite(void)
+void forget_mon_lite()
{
int i, y, x;
@@ -4014,7 +3458,7 @@ void forget_mon_lite(void)
* 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
+ * case is when RF_HAS_LITE monsters have moved or dead. Monster
* creation occurs out of LoS, so I chose not to take this into
* consideration.
*
@@ -4031,8 +3475,10 @@ void forget_mon_lite(void)
* 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)
+void update_mon_lite()
{
+ auto const &f_info = game->edit_data.f_info;
+
int i, y, x, d;
int fy, fx;
@@ -4109,7 +3555,6 @@ void update_mon_lite(void)
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;
@@ -4117,11 +3562,11 @@ void update_mon_lite(void)
/* 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);
+ /* Access monster race */
+ auto r_ptr = m_ptr->race();
/* Skip monsters not carrying light source */
- if (!(r_ptr->flags9 & RF9_HAS_LITE)) continue;
+ if (!(r_ptr->flags & RF_HAS_LITE)) continue;
/* Access the location */
fy = m_ptr->fy;
@@ -4172,7 +3617,7 @@ void update_mon_lite(void)
*
* We don't have four sides for a wall grid, so...
*/
- if (invis && (f_info[c_ptr->feat].flags1 & FF1_NO_VISION)) continue;
+ if (invis && (f_info[c_ptr->feat].flags & FF_NO_VISION)) continue;
/* Give monster light to the location */
c_ptr->info |= (CAVE_MLIT | CAVE_SEEN);
@@ -4287,32 +3732,6 @@ 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;
@@ -4372,12 +3791,12 @@ static void update_flow_aux(int y, int x, int n)
* 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)
+void update_flow()
{
int x, y, d;
/* Hack -- disabled */
- if (!flow_by_sound) return;
+ if (!options->flow_by_sound) return;
/* Paranoia -- make sure the array is empty */
if (temp_n) return;
@@ -4440,31 +3859,14 @@ void update_flow(void)
/*
* Hack -- map the current panel (plus some) ala "magic mapping"
*/
-void map_area(void)
+void map_area()
{
- 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++)
+ /* Scan the whole map */
+ for (int y = 1; y < cur_hgt - 1; y++)
{
- for (x = x1; x <= x2; x++)
+ for (int x = 1; x < cur_wid - 1; x++)
{
- c_ptr = &cave[y][x];
+ auto c_ptr = &cave[y][x];
/* All non-walls are "checked" */
if (!is_wall(c_ptr))
@@ -4477,7 +3879,7 @@ void map_area(void)
}
/* Memorize known walls */
- for (i = 0; i < 8; i++)
+ for (int i = 0; i < 8; i++)
{
c_ptr = &cave[y + ddy_ddd[i]][x + ddx_ddd[i]];
@@ -4517,7 +3919,7 @@ void map_area(void)
* 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)
+void wiz_lite()
{
int i, y, x;
@@ -4548,12 +3950,11 @@ void wiz_lite(void)
if (c_ptr->m_idx)
{
monster_type *m_ptr = &m_list[c_ptr->m_idx];
- monster_race *r_ptr = race_inf(m_ptr);
+ auto const r_ptr = m_ptr->race();
- if (r_ptr->flags9 & RF9_MIMIC)
+ if (r_ptr->flags & RF_MIMIC)
{
- object_type *o_ptr = &o_list[m_ptr->hold_o_idx];
-
+ object_type *o_ptr = &o_list[m_ptr->mimic_o_idx()];
o_ptr->marked = TRUE;
}
}
@@ -4581,7 +3982,7 @@ void wiz_lite(void)
}
/* Normally, memorize floors (see above) */
- if (view_perma_grids && !view_torch_grids)
+ if (options->view_perma_grids && !options->view_torch_grids)
{
/* Memorize the grid */
c_ptr->info |= (CAVE_MARK);
@@ -4601,7 +4002,7 @@ void wiz_lite(void)
p_ptr->window |= (PW_OVERHEAD);
}
-void wiz_lite_extra(void)
+void wiz_lite_extra()
{
int y, x;
for (y = 0; y < cur_hgt; y++)
@@ -4617,7 +4018,7 @@ void wiz_lite_extra(void)
/*
* Forget the dungeon map (ala "Thinking of Maud...").
*/
-void wiz_dark(void)
+void wiz_dark()
{
int i, y, x;
@@ -4888,7 +4289,7 @@ void health_track(int m_idx)
health_who = m_idx;
/* Redraw (later) */
- p_ptr->redraw |= (PR_HEALTH);
+ p_ptr->redraw |= (PR_FRAME);
}
@@ -4927,15 +4328,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()
{
- /* Unused */
- unused_flag = unused_flag;
-
/* Cancel auto-commands */
/* command_new = 0; */
@@ -4946,7 +4342,7 @@ void disturb(int stop_search, int unused_flag)
command_rep = 0;
/* Redraw the state (later) */
- p_ptr->redraw |= (PR_STATE);
+ p_ptr->redraw |= (PR_FRAME);
}
/* Cancel Resting */
@@ -4956,7 +4352,7 @@ void disturb(int stop_search, int unused_flag)
resting = 0;
/* Redraw the state (later) */
- p_ptr->redraw |= (PR_STATE);
+ p_ptr->redraw |= (PR_FRAME);
}
/* Cancel running */
@@ -4969,51 +4365,50 @@ void disturb(int stop_search, int unused_flag)
p_ptr->update |= (PU_TORCH);
}
- /* Cancel searching if requested */
- if (stop_search && p_ptr->searching)
+ /* Flush the input if requested */
+ if (options->flush_disturb)
{
- /* Cancel */
- p_ptr->searching = FALSE;
-
- /* Recalculate bonuses */
- p_ptr->update |= (PU_BONUS);
-
- /* Redraw the state */
- p_ptr->redraw |= (PR_STATE);
+ flush();
}
-
- /* Flush the input if requested */
- if (flush_disturb) flush();
}
+
/*
- * Hack -- Check if a level is a "quest" level
+ * Disturb if option 'disturb_state' is set.
*/
-int is_quest(int level)
+void disturb_on_state()
{
- int i = random_quest_number();
+ if (options->disturb_state)
+ {
+ disturb();
+ }
+}
- /* Check quests */
- if (p_ptr->inside_quest)
- return (p_ptr->inside_quest);
- if (i) return (QUEST_RANDOM);
- /* Nope */
- return (0);
+/*
+ * Disturb if option 'disturb_other' is set.
+ */
+void disturb_on_other()
+{
+ if (options->disturb_other)
+ {
+ disturb();
+ }
}
+
/*
* Return the index of the random quest on this level
* (or zero)
*/
-int random_quest_number()
+static int random_quest_number()
{
if ((dun_level >= 1) && (dun_level < MAX_RANDOM_QUEST) &&
- (dungeon_flags1 & DF1_PRINCIPAL) &&
- (random_quests[dun_level].type) &&
+ (dungeon_flags & DF_PRINCIPAL) &&
+ (random_quests[dun_level].type) &&
(!random_quests[dun_level].done) &&
(!is_randhero(dun_level)))
{
@@ -5025,6 +4420,25 @@ int random_quest_number()
}
+
+/*
+ * 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);
+}
+
+
/*
* handle spell effects
*/
@@ -5053,3 +4467,178 @@ int new_effect(int type, int dam, int time, int cy, int cx, int rad, s32b flags)
effects[i].rad = rad;
return i;
}
+
+/**
+ * Determine if a "legal" grid is a "floor" grid
+ *
+ * Line 1 -- forbid doors, rubble, seams, walls
+ *
+ * Note that the terrain features are split by a one bit test
+ * into those features which block line of sight and those that
+ * do not, allowing an extremely fast single bit check below.
+ *
+ * Add in the fact that some new terrain (water & lava) do NOT block sight
+ * -KMW-
+ */
+bool cave_floor_bold(int y, int x)
+{
+ return cave_floor_grid(&cave[y][x]);
+}
+
+/**
+ * Grid based version of "cave_floor_bold()"
+ */
+bool cave_floor_grid(cave_type const *c)
+{
+ auto const &f_info = game->edit_data.f_info;
+
+ return bool(f_info[c->feat].flags & FF_FLOOR);
+}
+
+
+
+/**
+ * Determine if a "legal" grid is floor without the REMEMBER flag set
+ * Sometimes called "boring" grid
+ */
+bool cave_plain_floor_bold(int y, int x)
+{
+ return cave_plain_floor_grid(&cave[y][x]);
+}
+
+/**
+ * Grid based version of "cave_plain_floor_bold()"
+ */
+bool cave_plain_floor_grid(cave_type const *c)
+{
+ auto const &f_info = game->edit_data.f_info;
+
+ return
+ (f_info[c->feat].flags & FF_FLOOR) &&
+ !(f_info[c->feat].flags & FF_REMEMBER);
+}
+
+
+
+/**
+ * Determine if a "legal" grid isn't a "blocking line of sight" grid
+ *
+ * Line 1 -- forbid doors, rubble, seams, walls
+ *
+ * Note that the terrain features are split by a one bit test
+ * into those features which block line of sight and those that
+ * do not, allowing an extremely fast single bit check below.
+ *
+ * Add in the fact that some new terrain (water & lava) do NOT block sight
+ * -KMW-
+ */
+bool cave_sight_bold(int y, int x)
+{
+ return cave_sight_grid(&cave[y][x]);
+}
+
+bool cave_sight_grid(cave_type const *c)
+{
+ auto const &f_info = game->edit_data.f_info;
+
+ return !(f_info[c->feat].flags & FF_NO_VISION);
+}
+
+
+/**
+ * Determine if a "legal" grid is a "clean" floor grid
+ *
+ * Line 1 -- forbid non-floors
+ * Line 2 -- forbid deep water -KMW-
+ * Line 3 -- forbid deep lava -KMW-
+ * Line 4 -- forbid normal objects
+ */
+bool cave_clean_bold(int y, int x)
+{
+ auto const &f_info = game->edit_data.f_info;
+
+ return
+ (f_info[cave[y][x].feat].flags & FF_FLOOR) &&
+ (cave[y][x].o_idxs.empty()) &&
+ !(f_info[cave[y][x].feat].flags & FF_PERMANENT);
+}
+
+/*
+ * Determine if a "legal" grid is an "empty" floor grid
+ *
+ * Line 1 -- forbid doors, rubble, seams, walls
+ * Line 2 -- forbid normal monsters
+ * Line 3 -- forbid the player
+ */
+bool cave_empty_bold(int y, int x)
+{
+ return
+ cave_floor_bold(y,x) &&
+ !(cave[y][x].m_idx) &&
+ !((y == p_ptr->py) && (x == p_ptr->px));
+}
+
+
+/*
+ * Determine if a "legal" grid is an "naked" floor grid
+ *
+ * Line 1 -- forbid non-floors, non-shallow water & lava -KMW-
+ * Line 2 -- forbid normal objects
+ * Line 3 -- forbid player/monsters
+ */
+bool cave_naked_bold(int y, int x)
+{
+ auto const &f_info = game->edit_data.f_info;
+
+ return
+ (f_info[cave[y][x].feat].flags & FF_FLOOR) &&
+ !(f_info[cave[y][x].feat].flags & FF_PERMANENT) &&
+ (cave[y][x].o_idxs.empty()) &&
+ (cave[y][x].m_idx == 0);
+}
+
+bool cave_naked_bold2(int y, int x)
+{
+ auto const &f_info = game->edit_data.f_info;
+
+ return
+ (f_info[cave[y][x].feat].flags & FF_FLOOR) &&
+ (cave[y][x].o_idxs.empty()) &&
+ (cave[y][x].m_idx == 0);
+}
+
+
+/**
+ * Determine if a "legal" grid is "permanent"
+ */
+bool cave_perma_bold(int y, int x)
+{
+ return cave_perma_grid(&cave[y][x]);
+}
+
+bool cave_perma_grid(cave_type const *c)
+{
+ auto const &f_info = game->edit_data.f_info;
+
+ return bool(f_info[c->feat].flags & FF_PERMANENT);
+}
+
+/*
+ * Determine if a "legal" grid is within "los" of the player
+ *
+ * Note the use of comparison to zero to force a "boolean" result
+ */
+bool player_has_los_bold(int y, int x)
+{
+ return (cave[y][x].info & (CAVE_VIEW)) != 0;
+}
+
+/*
+ * Determine if a "legal" grid can be "seen" by the player
+ *
+ * Note the use of comparison to zero to force a "boolean" result
+ */
+bool player_can_see_bold(int y, int x)
+{
+ return (cave[y][x].info & (CAVE_SEEN)) != 0;
+}
diff --git a/src/cave.hpp b/src/cave.hpp
new file mode 100644
index 00000000..ce1631a1
--- /dev/null
+++ b/src/cave.hpp
@@ -0,0 +1,57 @@
+#pragma once
+
+#include "h-basic.h"
+#include "cave_type_fwd.hpp"
+#include "object_type_fwd.hpp"
+
+int distance(int y1, int x1, int y2, int x2);
+bool_ los(int y1, int x1, int y2, int x2);
+bool_ cave_valid_bold(int y, int x);
+bool_ no_lite();
+void map_info_default(int y, int x, byte *ap, char *cp);
+void move_cursor_relative(int row, int col);
+void print_rel(char c, byte a, int y, int x);
+void note_spot(int y, int x);
+void lite_spot(int y, int x);
+void prt_map();
+void display_map(int *cy, int *cx);
+void do_cmd_view_map();
+errr vinfo_init();
+void forget_view();
+void update_view();
+void forget_mon_lite();
+void update_mon_lite();
+void update_flow();
+void map_area();
+void wiz_lite();
+void wiz_lite_extra();
+void wiz_dark();
+void cave_set_feat(int y, int x, int feat);
+void place_floor(int y, int x);
+void place_floor_convert_glass(int y, int x);
+void place_filler(int y, int x);
+void mmove2(int *y, int *x, int y1, int x1, int y2, int x2);
+bool_ projectable(int y1, int x1, int y2, int x2);
+void scatter(int *yp, int *xp, int y, int x, int d);
+void health_track(int m_idx);
+void monster_race_track(int r_idx, int ego);
+void object_track(object_type *o_ptr);
+void disturb();
+void disturb_on_state();
+void disturb_on_other();
+int is_quest(int level);
+int new_effect(int type, int dam, int time, int cy, int cx, int rad, s32b flags);
+bool cave_floor_bold(int y, int x);
+bool cave_floor_grid(cave_type const *c);
+bool cave_plain_floor_bold(int y, int x);
+bool cave_plain_floor_grid(cave_type const *c);
+bool cave_sight_bold(int y, int x);
+bool cave_sight_grid(cave_type const *c);
+bool cave_clean_bold(int y, int x);
+bool cave_empty_bold(int y, int x);
+bool cave_naked_bold(int y, int x);
+bool cave_naked_bold2(int y, int x);
+bool cave_perma_bold(int y, int x);
+bool cave_perma_grid(cave_type const *c);
+bool player_has_los_bold(int y, int x);
+bool player_can_see_bold(int y, int x);
diff --git a/src/cave_type.hpp b/src/cave_type.hpp
new file mode 100644
index 00000000..08e6002f
--- /dev/null
+++ b/src/cave_type.hpp
@@ -0,0 +1,63 @@
+#pragma once
+
+#include "h-basic.h"
+
+#include <cassert>
+#include <vector>
+
+/**
+ * A single "grid" in a Cave.
+ *
+ * Note that several aspects of the code restrict the actual cave
+ * to a max size of 256 by 256. In partcular, locations are often
+ * saved as bytes, limiting each coordinate to the 0-255 range.
+ *
+ * The "o_idx" and "m_idx" fields are very interesting. There are
+ * many places in the code where we need quick access to the actual
+ * monster or object(s) in a given cave grid. The easiest way to
+ * do this is to simply keep the index of the monster and object
+ * (if any) with the grid, but this takes 198*66*4 bytes of memory.
+ * Several other methods come to mind, which require only half this
+ * amound of memory, but they all seem rather complicated, and would
+ * probably add enough code that the savings would be lost. So for
+ * these reasons, we simply store an index into the "o_list" and
+ * "m_list" arrays, using "zero" when no monster/object is present.
+ *
+ * Note that "o_idx" is the index of the top object in a stack of
+ * objects, using the "next_o_idx" field of objects to create the
+ * singly linked list of objects. If "o_idx" is zero then there
+ * are no objects in the grid.
+ */
+struct cave_type
+{
+ u16b info = 0; /* Hack -- cave flags */
+
+ byte feat = 0; /* Hack -- feature type */
+
+ std::vector<s16b> o_idxs { }; /* Indexes of objects in this grid */
+
+ s16b m_idx = 0; /* Monster in this grid */
+
+ s16b special = 0; /* Special cave info */
+ s16b special2 = 0; /* Special cave info */
+
+ s16b inscription = 0; /* Inscription of the grid */
+
+ byte mana = 0; /* Magical energy of the grid */
+
+ byte mimic = 0; /* Feature to mimic */
+
+ byte cost = 0; /* Hack -- cost of flowing */
+ byte when = 0; /* Hack -- when cost was computed */
+
+ s16b effect = 0; /* The lasting effects */
+
+ /**
+ * @brief wipe the object's state
+ */
+ void wipe() {
+ /* Reset to defaults */
+ *this = cave_type();
+ }
+
+};
diff --git a/src/cave_type_fwd.hpp b/src/cave_type_fwd.hpp
new file mode 100644
index 00000000..f2569ea6
--- /dev/null
+++ b/src/cave_type_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct cave_type;
diff --git a/src/cli_comm.hpp b/src/cli_comm.hpp
new file mode 100644
index 00000000..6ae53edc
--- /dev/null
+++ b/src/cli_comm.hpp
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * A structure for CLI commands.
+ */
+struct cli_comm
+{
+ cptr comm; /* Extended name of the command. */
+ cptr descrip; /* Description of the command. */
+ s16b key; /* Key to convert command to. */
+};
diff --git a/src/cli_comm_fwd.hpp b/src/cli_comm_fwd.hpp
new file mode 100644
index 00000000..6d9b76a3
--- /dev/null
+++ b/src/cli_comm_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct cli_comm;
diff --git a/src/cmd1.c b/src/cmd1.cc
index 49c0d38f..13edf0ff 100644
--- a/src/cmd1.c
+++ b/src/cmd1.cc
@@ -1,7 +1,3 @@
-/* File: cmd1.c */
-
-/* Purpose: Movement commands (part 1) */
-
/*
* Copyright (c) 1989 James E. Wilson, Robert A. Koeneke
*
@@ -10,7 +6,50 @@
* included in all such copies.
*/
-#include "angband.h"
+#include "cmd1.hpp"
+
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "cmd4.hpp"
+#include "cmd5.hpp"
+#include "dungeon_info_type.hpp"
+#include "feature_flag.hpp"
+#include "feature_type.hpp"
+#include "files.hpp"
+#include "game.hpp"
+#include "gods.hpp"
+#include "hooks.hpp"
+#include "hook_move_in.hpp"
+#include "lua_bind.hpp"
+#include "melee1.hpp"
+#include "melee2.hpp"
+#include "mimic.hpp"
+#include "monster2.hpp"
+#include "monster3.hpp"
+#include "monster_race.hpp"
+#include "monster_race_flag.hpp"
+#include "monster_spell_flag.hpp"
+#include "monster_type.hpp"
+#include "object_flag.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "options.hpp"
+#include "player_race_flag.hpp"
+#include "player_type.hpp"
+#include "skills.hpp"
+#include "spells1.hpp"
+#include "spells2.hpp"
+#include "spells3.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "util.h"
+#include "variable.h"
+#include "variable.hpp"
+#include "wild.hpp"
+#include "xtra1.hpp"
+#include "xtra2.hpp"
+#include "z-rand.hpp"
+
#define MAX_VAMPIRIC_DRAIN 100
@@ -201,13 +240,10 @@ s16b tot_dam_aux(object_type *o_ptr, int tdam, monster_type *m_ptr,
{
int mult = 1;
- monster_race *r_ptr = race_inf(m_ptr);
-
- u32b f1, f2, f3, f4, f5, esp;
-
+ auto const r_ptr = m_ptr->race();
/* Extract the flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ auto const f = object_flags(o_ptr);
/* Some "weapons" and "ammo" do extra damage */
switch (o_ptr->tval)
@@ -223,150 +259,84 @@ s16b tot_dam_aux(object_type *o_ptr, int tdam, monster_type *m_ptr,
case TV_DIGGING:
{
/* Slay Animal */
- if ((f1 & (TR1_SLAY_ANIMAL)) && (r_ptr->flags3 & (RF3_ANIMAL)))
+ if ((f & TR_SLAY_ANIMAL) && (r_ptr->flags & RF_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 ((f & TR_SLAY_EVIL) && (r_ptr->flags & RF_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 ((f & TR_SLAY_UNDEAD) && (r_ptr->flags & RF_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 ((f & TR_SLAY_DEMON) && (r_ptr->flags & RF_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 ((f & TR_SLAY_ORC) && (r_ptr->flags & RF_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 ((f & TR_SLAY_TROLL) && (r_ptr->flags & RF_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 ((f & TR_SLAY_GIANT) && (r_ptr->flags & RF_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 ((f & TR_SLAY_DRAGON) && (r_ptr->flags & RF_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 ((f & TR_KILL_DRAGON) && (r_ptr->flags & RF_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 ((f & TR_KILL_UNDEAD) && (r_ptr->flags & RF_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 ((f & TR_KILL_DEMON) && (r_ptr->flags & RF_DEMON))
{
- if (m_ptr->ml)
- {
- r_ptr->r_flags3 |= (RF3_DEMON);
- }
-
if (mult < 5) mult = 5;
}
/* Brand (Acid) */
- if (f1 & (TR1_BRAND_ACID))
+ if (f & TR_BRAND_ACID)
{
- /* Notice immunity */
- if (r_ptr->flags3 & (RF3_IM_ACID))
+ if (r_ptr->flags & RF_IM_ACID)
{
- if (m_ptr->ml)
- {
- r_ptr->r_flags3 |= (RF3_IM_ACID);
- }
+ // No additional multiplier
}
-
- /* Notice susceptibility */
- else if (r_ptr->flags9 & (RF9_SUSCEP_ACID))
+ else if (r_ptr->flags & RF_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;
@@ -374,28 +344,16 @@ s16b tot_dam_aux(object_type *o_ptr, int tdam, monster_type *m_ptr,
}
/* Brand (Elec) */
- if (f1 & (TR1_BRAND_ELEC))
+ if (f & TR_BRAND_ELEC)
{
- /* Notice immunity */
- if (r_ptr->flags3 & (RF3_IM_ELEC))
+ if (r_ptr->flags & RF_IM_ELEC)
{
- if (m_ptr->ml)
- {
- r_ptr->r_flags3 |= (RF3_IM_ELEC);
- }
+ // No additional multiplier
}
-
- /* Notice susceptibility */
- else if (r_ptr->flags9 & (RF9_SUSCEP_ELEC))
+ else if (r_ptr->flags & RF_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;
@@ -403,28 +361,16 @@ s16b tot_dam_aux(object_type *o_ptr, int tdam, monster_type *m_ptr,
}
/* Brand (Fire) */
- if (f1 & (TR1_BRAND_FIRE))
+ if (f & TR_BRAND_FIRE)
{
- /* Notice immunity */
- if (r_ptr->flags3 & (RF3_IM_FIRE))
+ if (r_ptr->flags & RF_IM_FIRE)
{
- if (m_ptr->ml)
- {
- r_ptr->r_flags3 |= (RF3_IM_FIRE);
- }
+ // No additional multiplier
}
-
- /* Notice susceptibility */
- else if (r_ptr->flags3 & (RF3_SUSCEP_FIRE))
+ else if (r_ptr->flags & RF_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;
@@ -432,28 +378,16 @@ s16b tot_dam_aux(object_type *o_ptr, int tdam, monster_type *m_ptr,
}
/* Brand (Cold) */
- if (f1 & (TR1_BRAND_COLD))
+ if (f & TR_BRAND_COLD)
{
- /* Notice immunity */
- if (r_ptr->flags3 & (RF3_IM_COLD))
+ if (r_ptr->flags & RF_IM_COLD)
{
- if (m_ptr->ml)
- {
- r_ptr->r_flags3 |= (RF3_IM_COLD);
- }
+ // No additional multiplier
}
-
- /* Notice susceptibility */
- else if (r_ptr->flags3 & (RF3_SUSCEP_COLD))
+ else if (r_ptr->flags & RF_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;
@@ -461,29 +395,17 @@ s16b tot_dam_aux(object_type *o_ptr, int tdam, monster_type *m_ptr,
}
/* Brand (Poison) */
- if (f1 & (TR1_BRAND_POIS) || (p_ptr->tim_poison))
+ if ((f & TR_BRAND_POIS) || (p_ptr->tim_poison))
{
- /* Notice immunity */
- if (r_ptr->flags3 & (RF3_IM_POIS))
+ if (r_ptr->flags & RF_IM_POIS)
{
- if (m_ptr->ml)
- {
- r_ptr->r_flags3 |= (RF3_IM_POIS);
- }
+ // No additional damage
}
-
- /* Notice susceptibility */
- else if (r_ptr->flags9 & (RF9_SUSCEP_POIS))
+ else if (r_ptr->flags & RF_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;
@@ -492,18 +414,12 @@ s16b tot_dam_aux(object_type *o_ptr, int tdam, monster_type *m_ptr,
}
/* Wounding */
- if (f5 & (TR5_WOUNDING))
+ if (f & TR_WOUNDING)
{
- /* Notice immunity */
- if (r_ptr->flags8 & (RF8_NO_CUT))
+ if (r_ptr->flags & RF_NO_CUT)
{
- if (m_ptr->ml)
- {
- r_info[m_ptr->r_idx].r_flags8 |= (RF8_NO_CUT);
- }
+ // No additional damage
}
-
- /* Otherwise, take the damage */
else
{
if (magik(50)) *special |= SPEC_CUT;
@@ -520,103 +436,6 @@ s16b tot_dam_aux(object_type *o_ptr, int tdam, monster_type *m_ptr,
/*
- * 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, 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, 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, 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.
@@ -630,48 +449,17 @@ void carry(int pickup)
}
-/*
- * Handle player hitting a real trap
- */
-static void hit_trap(void)
+static void touch_zap_player(monster_type *m_ptr)
{
- bool_ ident = FALSE;
-
- cave_type *c_ptr;
-
-
- /* Disturb the player */
- disturb(0, 0);
+ auto r_ptr = m_ptr->race();
- /* 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 (r_ptr->flags & RF_AURA_FIRE)
{
if (!(p_ptr->immune_fire))
{
char aura_dam[80];
- aura_damage =
+ int aura_damage =
damroll(1 + (m_ptr->level / 26), 1 + (m_ptr->level / 17));
/* Hack -- Get the "died from" name */
@@ -684,19 +472,18 @@ void touch_zap_player(monster_type *m_ptr)
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 (r_ptr->flags & RF_AURA_ELEC)
{
if (!(p_ptr->immune_elec))
{
char aura_dam[80];
- aura_damage =
+ int aura_damage =
damroll(1 + (m_ptr->level / 26), 1 + (m_ptr->level / 17));
/* Hack -- Get the "died from" name */
@@ -707,7 +494,6 @@ void touch_zap_player(monster_type *m_ptr)
msg_print("You get zapped!");
take_hit(aura_damage, aura_dam);
- r_ptr->r_flags2 |= RF2_AURA_ELEC;
handle_stuff();
}
}
@@ -721,11 +507,9 @@ void touch_zap_player(monster_type *m_ptr)
static void carried_monster_attack(s16b m_idx, bool_ *fear, bool_ *mdeath,
int x, int y)
{
- monster_type *t_ptr = &m_list[m_idx];
+ auto const &r_info = game->edit_data.r_info;
- monster_race *r_ptr;
-
- monster_race *tr_ptr = race_inf(t_ptr);
+ monster_type *t_ptr = &m_list[m_idx];
int ap_cnt;
@@ -733,8 +517,6 @@ static void carried_monster_attack(s16b m_idx, bool_ *fear, bool_ *mdeath,
char t_name[80];
- cptr sym_name = symbiote_name(TRUE);
-
char temp[80];
bool_ blinked = FALSE, touched = FALSE;
@@ -743,17 +525,15 @@ static void carried_monster_attack(s16b m_idx, bool_ *fear, bool_ *mdeath,
byte x_saver = t_ptr->fx;
- object_type *o_ptr;
-
-
/* Get the carried monster */
- o_ptr = &p_ptr->inventory[INVEN_CARRY];
+ auto o_ptr = &p_ptr->inventory[INVEN_CARRY];
if (!o_ptr->k_idx) return;
- r_ptr = &r_info[o_ptr->pval];
+ /* Get monster race of the symbiote */
+ auto r_ptr = &r_info[o_ptr->pval];
/* Not allowed to attack */
- if (r_ptr->flags1 & RF1_NEVER_BLOW) return;
+ if (r_ptr->flags & RF_NEVER_BLOW) return;
/* Total armor */
ac = t_ptr->ac;
@@ -775,9 +555,6 @@ static void carried_monster_attack(s16b m_idx, bool_ *fear, bool_ *mdeath,
/* 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;
@@ -801,9 +578,6 @@ static void carried_monster_attack(s16b m_idx, bool_ *fear, bool_ *mdeath,
/* break; */
}
- /* Extract visibility (before blink) */
- visible = TRUE;
-
/* Extract the attack "power" */
power = get_attack_power(effect);
@@ -811,7 +585,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();
/* Describe the attack method */
switch (method)
@@ -984,15 +758,14 @@ static void carried_monster_attack(s16b m_idx, bool_ *fear, bool_ *mdeath,
/* Message */
if (act)
{
- strfmt(temp, act, t_name);
+ strnfmt(temp, sizeof(temp), act, t_name);
if (t_ptr->ml)
- msg_format("%s %s", sym_name, temp);
+ {
+ msg_format("%s %s", symbiote_name(true).c_str(), temp);
+ }
}
- /* Hack -- assume all attacks are obvious */
- obvious = TRUE;
-
/* Roll out the damage */
damage = damroll(d_dice, d_side);
@@ -1147,16 +920,15 @@ static void carried_monster_attack(s16b m_idx, bool_ *fear, bool_ *mdeath,
if (touched)
{
+ auto tr_ptr = t_ptr->race();
/* Aura fire */
- if ((tr_ptr->flags2 & RF2_AURA_FIRE) &&
- !(r_ptr->flags3 & RF3_IM_FIRE))
+ if ((tr_ptr->flags & RF_AURA_FIRE) &&
+ !(r_ptr->flags & RF_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),
@@ -1165,15 +937,13 @@ static void carried_monster_attack(s16b m_idx, bool_ *fear, bool_ *mdeath,
}
/* Aura elec */
- if ((tr_ptr->flags2 & (RF2_AURA_ELEC)) &&
- !(r_ptr->flags3 & (RF3_IM_ELEC)))
+ if ((tr_ptr->flags & RF_AURA_ELEC) &&
+ !(r_ptr->flags & RF_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),
@@ -1204,35 +974,20 @@ static void carried_monster_attack(s16b m_idx, bool_ *fear, bool_ *mdeath,
case RBM_CHARGE:
{
/* Disturb */
- disturb(1, 0);
+ disturb();
/* Message */
- msg_format("%s misses %s.", sym_name, t_name);
+ msg_format("%s misses %s.", symbiote_name(true).c_str(), 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));
+ msg_format("You and %s flee laughing!", symbiote_name(false).c_str());
teleport_player(MAX_SIGHT * 2 + 5);
}
@@ -1245,11 +1000,11 @@ static void carried_monster_attack(s16b m_idx, bool_ *fear, bool_ *mdeath,
static void incarnate_monster_attack(s16b m_idx, bool_ *fear, bool_ *mdeath,
int x, int y)
{
- monster_type *t_ptr = &m_list[m_idx];
+ auto const &r_info = game->edit_data.r_info;
- monster_race *r_ptr;
+ monster_type *t_ptr = &m_list[m_idx];
- monster_race *tr_ptr = race_inf(t_ptr);
+ auto tr_ptr = t_ptr->race();
int ap_cnt;
@@ -1268,10 +1023,10 @@ static void incarnate_monster_attack(s16b m_idx, bool_ *fear, bool_ *mdeath,
if (!p_ptr->body_monster) return;
- r_ptr = race_info_idx(p_ptr->body_monster, 0);
+ auto r_ptr = &r_info[p_ptr->body_monster];
/* Not allowed to attack */
- if (r_ptr->flags1 & RF1_NEVER_BLOW) return;
+ if (r_ptr->flags & RF_NEVER_BLOW) return;
/* Total armor */
ac = t_ptr->ac;
@@ -1294,9 +1049,6 @@ static void incarnate_monster_attack(s16b m_idx, bool_ *fear, bool_ *mdeath,
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;
@@ -1320,17 +1072,14 @@ static void incarnate_monster_attack(s16b m_idx, bool_ *fear, bool_ *mdeath,
/* break; */
}
- /* Extract visibility (before blink) */
- 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))
{
/* Always disturbing */
- disturb(1, 0);
+ disturb();
/* Describe the attack method */
switch (method)
@@ -1503,15 +1252,12 @@ static void incarnate_monster_attack(s16b m_idx, bool_ *fear, bool_ *mdeath,
/* Message */
if (act)
{
- strfmt(temp, act, t_name);
+ strnfmt(temp, sizeof(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;
@@ -1666,15 +1412,13 @@ static void incarnate_monster_attack(s16b m_idx, bool_ *fear, bool_ *mdeath,
if (touched)
{
/* Aura fire */
- if ((tr_ptr->flags2 & RF2_AURA_FIRE) &&
- !(r_ptr->flags3 & RF3_IM_FIRE))
+ if ((tr_ptr->flags & RF_AURA_FIRE) &&
+ !(r_ptr->flags & RF_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),
@@ -1683,15 +1427,13 @@ static void incarnate_monster_attack(s16b m_idx, bool_ *fear, bool_ *mdeath,
}
/* Aura elec */
- if ((tr_ptr->flags2 & (RF2_AURA_ELEC)) &&
- !(r_ptr->flags3 & (RF3_IM_ELEC)))
+ if ((tr_ptr->flags & RF_AURA_ELEC) &&
+ !(r_ptr->flags & RF_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),
@@ -1723,7 +1465,7 @@ static void incarnate_monster_attack(s16b m_idx, bool_ *fear, bool_ *mdeath,
case RBM_CHARGE:
{
/* Disturb */
- disturb(1, 0);
+ disturb();
/* Message */
msg_format("You miss %s.", t_name);
@@ -1732,21 +1474,6 @@ static void incarnate_monster_attack(s16b m_idx, bool_ *fear, bool_ *mdeath,
}
}
}
-
-
- /* 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 */
@@ -1813,33 +1540,29 @@ static void flavored_attack(int percent, char *output)
*/
void attack_special(monster_type *m_ptr, s32b special, int dam)
{
- char m_name[80];
-
- monster_race *r_ptr = race_inf(m_ptr);
-
+ auto const r_ptr = m_ptr->race();
/* Extract monster name (or "it") */
+ char m_name[80];
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 (r_ptr->flags & RF_NO_CUT)
{
- if (m_ptr->ml)
- {
- r_info[m_ptr->r_idx].r_flags8 |= (RF8_NO_CUT);
- }
+ // No damage
}
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 */
+ if (m_ptr->bleeding)
+ {
+ msg_format("%^s is bleeding more strongly.", m_name);
+ }
else
+ {
msg_format("%^s is bleeding.", m_name);
+ }
m_ptr->bleeding += dam * 2;
}
@@ -1848,36 +1571,33 @@ void attack_special(monster_type *m_ptr, s32b special, int dam)
/* Special - Poison monster */
if (special & SPEC_POIS)
{
- /* Poison the monster */
- if (r_ptr->flags3 & (RF3_IM_POIS))
+ if (r_ptr->flags & RF_IM_POIS)
{
- if (m_ptr->ml)
- {
- r_ptr->r_flags3 |= (RF3_IM_POIS);
- }
+ // No damage
}
- /* Notice susceptibility */
- else if (r_ptr->flags9 & (RF9_SUSCEP_POIS))
+ else if (r_ptr->flags & RF_SUSCEP_POIS)
{
- if (m_ptr->ml)
+ if (m_ptr->poisoned)
{
- r_ptr->r_flags9 |= (RF9_SUSCEP_POIS);
+ msg_format("%^s is more poisoned.", m_name);
}
- /* 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 */
+ if (m_ptr->poisoned)
+ {
+ msg_format("%^s is more poisoned.", m_name);
+ }
else
+ {
msg_format("%^s is poisoned.", m_name);
+ }
m_ptr->poisoned += dam;
}
@@ -1891,12 +1611,10 @@ void attack_special(monster_type *m_ptr, s32b special, int dam)
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];
+ martial_arts *blow_table = ma_blows;
+ int resist_stun = 0;
+ int max = MAX_MA;
bool_ desc = FALSE;
- bool_ done_crit;
int plev = p_ptr->lev;
if ((!p_ptr->body_monster) && (p_ptr->mimic_form == resolve_mimic_name("Bear")) &&
@@ -1912,17 +1630,16 @@ static void py_attack_hand(int *k, monster_type *m_ptr, s32b *special)
max = MAX_MA;
plev = get_skill(SKILL_HAND);
}
- ma_ptr = &blow_table[0];
- old_ptr = &blow_table[0];
+ martial_arts *ma_ptr = &blow_table[0];
+ martial_arts *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;
+ auto const r_ptr = m_ptr->race();
+ if (r_ptr->flags & RF_UNIQUE) resist_stun += 88;
+ if (r_ptr->flags & RF_NO_CONF) resist_stun += 44;
+ if (r_ptr->flags & RF_NO_SLEEP) resist_stun += 44;
+ if ((r_ptr->flags & RF_UNDEAD) ||
+ (r_ptr->flags & RF_NONLIVING)) resist_stun += 88;
if (plev)
{
@@ -1940,7 +1657,7 @@ static void py_attack_hand(int *k, monster_type *m_ptr, s32b *special)
{
old_ptr = ma_ptr;
- if (wizard && cheat_xtra)
+ if (wizard && options->cheat_xtra)
{
msg_print("Attack re-selected.");
}
@@ -1954,13 +1671,17 @@ static void py_attack_hand(int *k, monster_type *m_ptr, s32b *special)
*k = damroll(ma_ptr->dd, ma_ptr->ds);
+ /* Extract name */
+ char m_name[80];
+ monster_desc(m_name, m_ptr, 0);
+
+ /* Describe attack */
if (ma_ptr->effect & MA_KNEE)
{
- if (r_ptr->flags1 & RF1_MALE)
+ if (r_ptr->flags & RF_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);
@@ -1977,7 +1698,7 @@ static void py_attack_hand(int *k, monster_type *m_ptr, s32b *special)
if (ma_ptr->effect & MA_SLOW)
{
if (!
- ((r_ptr->flags1 & RF1_NEVER_MOVE) ||
+ ((r_ptr->flags & RF_NEVER_MOVE) ||
strchr("UjmeEv$,DdsbBFIJQSXclnw!=?", r_ptr->d_char)))
{
if (!desc) msg_format("You kick %s in the ankle.", m_name);
@@ -2007,6 +1728,7 @@ static void py_attack_hand(int *k, monster_type *m_ptr, s32b *special)
desc = TRUE;
}
+ bool_ done_crit;
*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))
@@ -2018,10 +1740,10 @@ static void py_attack_hand(int *k, monster_type *m_ptr, s32b *special)
if (((special_effect & MA_FULL_SLOW) || (special_effect & MA_SLOW)) &&
((*k + p_ptr->to_d) < m_ptr->hp))
{
- if (!(r_ptr->flags1 & RF1_UNIQUE) &&
+ if (!(r_ptr->flags & RF_UNIQUE) &&
(randint(plev) > m_ptr->level) && m_ptr->mspeed > 60)
{
- msg_format("%^s starts limping slower.", m_name);
+ msg_format("%^s starts limping.", m_name);
m_ptr->mspeed -= 10;
}
}
@@ -2044,27 +1766,28 @@ static void py_attack_hand(int *k, monster_type *m_ptr, s32b *special)
/*
* Apply nazgul effects
*/
-void do_nazgul(int *k, int *num, int num_blow, int weap, monster_race *r_ptr,
+static void do_nazgul(int *k, int *num, int num_blow, int weap, std::shared_ptr<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);
+ auto const f = object_flags(o_ptr);
/* It should be Slay Evil, Slay Undead, or *Slay Undead* */
- mundane = !(f1 & TR1_SLAY_EVIL) && !(f1 & TR1_SLAY_UNDEAD) &&
- !(f5 & TR5_KILL_UNDEAD);
+ bool_ const mundane =
+ !(f & TR_SLAY_EVIL) &&
+ !(f & TR_SLAY_UNDEAD) &&
+ !(f & TR_KILL_UNDEAD);
/* Some blades can resist shattering */
- if (f5 & TR5_RES_MORGUL)
+ if (f & TR_RES_MORGUL)
+ {
allow_shatter = FALSE;
+ }
/* Mega Hack -- Hitting Nazgul is REALY dangerous (ideas from Akhronath) */
- if (r_ptr->flags7 & RF7_NAZGUL)
+ if (r_ptr->flags & RF_NAZGUL)
{
if ((!o_ptr->name2) && (!artifact_p(o_ptr)) && allow_shatter)
{
@@ -2141,6 +1864,8 @@ void do_nazgul(int *k, int *num, int num_blow, int weap, monster_race *r_ptr,
*/
void py_attack(int y, int x, int max_blow)
{
+ auto const &r_info = game->edit_data.r_info;
+
int num = 0, k, bonus, chance;
s32b special = 0;
@@ -2149,12 +1874,6 @@ void py_attack(int y, int x, int max_blow)
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;
@@ -2177,15 +1896,12 @@ void py_attack(int y, int x, int max_blow)
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, 0);
+ disturb();
- if (r_info[p_ptr->body_monster].flags1 & RF1_NEVER_BLOW)
+ if (r_info[p_ptr->body_monster].flags & RF_NEVER_BLOW)
{
msg_print("You cannot attack in this form!");
return;
@@ -2209,15 +1925,9 @@ void py_attack(int y, int x, int max_blow)
/* Extract monster name (or "it") */
+ char m_name[80];
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);
@@ -2229,21 +1939,16 @@ void py_attack(int y, int x, int max_blow)
!(p_ptr->stun || p_ptr->confused || p_ptr->image ||
!(m_ptr->ml)))
{
- if (!(p_ptr->inventory[INVEN_WIELD].art_name))
+ // Only 'Stormbringer' can hit friendlies unless player forces attack.
+ if (p_ptr->inventory[INVEN_WIELD].artifact_name == "'Stormbringer'")
{
- msg_format("You stop to avoid hitting %s.", m_name);
- return;
+ msg_format("Your black blade greedily attacks %s!", m_name);
}
-
- if (!
- (streq
- (quark_str(p_ptr->inventory[INVEN_WIELD].art_name), "'Stormbringer'")))
+ else
{
msg_format("You stop to avoid hitting %s.", m_name);
return;
}
-
- msg_format("Your black blade greedily attacks %s!", m_name);
}
/* Break goi/manashield */
@@ -2295,15 +2000,18 @@ void py_attack(int y, int x, int max_blow)
num = 0;
/* Access the weapon */
- o_ptr = &p_ptr->inventory[INVEN_WIELD + weap];
+ object_type *o_ptr = &p_ptr->inventory[INVEN_WIELD + weap];
+
+ /* Get race info */
+ auto r_ptr = m_ptr->race();
/* 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);
+ auto const flags = object_flags(o_ptr);
- if (!(f4 & TR4_NEVER_BLOW))
+ if (!(flags & TR_NEVER_BLOW))
{
int num_blow = p_ptr->num_blow;
@@ -2317,14 +2025,11 @@ void py_attack(int y, int x, int max_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 ((flags & TR_CHAOTIC) && (rand_int(2) == 0))
{
if (randint(5) < 3)
{
@@ -2354,17 +2059,17 @@ void py_attack(int y, int x, int max_blow)
}
/* Vampiric drain */
- if ((f1 & TR1_VAMPIRIC) || (chaos_effect == 1))
+ if ((flags & TR_VAMPIRIC) || (chaos_effect == 1))
{
if (!
- ((r_ptr->flags3 & RF3_UNDEAD) ||
- (r_ptr->flags3 & RF3_NONLIVING)))
+ ((r_ptr->flags & RF_UNDEAD) ||
+ (r_ptr->flags & RF_NONLIVING)))
drain_result = m_ptr->hp;
else
drain_result = 0;
}
- if (f1 & TR1_VORPAL && (randint(6) == 1))
+ if ((flags & TR_VORPAL) && (randint(6) == 1))
vorpal_cut = TRUE;
else
vorpal_cut = FALSE;
@@ -2403,7 +2108,7 @@ void py_attack(int y, int x, int max_blow)
/* 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)
+ if (!(r_ptr->spells & SF_BR_SOUN) && !(r_ptr->spells & SF_BR_WALL) && k)
{
int tmp;
@@ -2437,7 +2142,7 @@ void py_attack(int y, int x, int max_blow)
while (randint(4) == 1);
}
- PRAY_GOD(GOD_TULKAS)
+ if (praying_to(GOD_TULKAS))
{
if (magik(wisdom_scale(130) - m_ptr->level) && (p_ptr->grace > 1000))
{
@@ -2464,9 +2169,9 @@ void py_attack(int y, int x, int max_blow)
}
/* Melkor can cast curse for you*/
- PRAY_GOD(GOD_MELKOR)
+ if (praying_to(GOD_MELKOR))
{
- int lv = exec_lua("return get_level(MELKOR_CURSE, 100)");
+ int lv = get_level_s(MELKOR_CURSE, 100);
if (lv >= 10)
{
@@ -2475,13 +2180,13 @@ 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);
}
}
}
/* May it clone the monster ? */
- if ((f4 & TR4_CLONE) && magik(30))
+ if ((flags & TR_CLONE) && magik(30))
{
msg_format("Oh no! Your weapon clones %^s!",
m_name);
@@ -2548,7 +2253,7 @@ void py_attack(int y, int x, int max_blow)
/* Hack -- High-level warriors can spread their attacks out
* among weaker foes.
*/
- if ((has_ability(AB_SPREAD_BLOWS)) && (num < num_blow) &&
+ if ((p_ptr->has_ability(AB_SPREAD_BLOWS)) && (num < num_blow) &&
(energy_use))
{
energy_use = energy_use * num / num_blow;
@@ -2582,7 +2287,7 @@ void py_attack(int y, int x, int max_blow)
{
drain_heal = damroll(4, (drain_result / 6));
- if (cheat_xtra)
+ if (options->cheat_xtra)
{
msg_format("Draining left: %d", drain_left);
}
@@ -2624,13 +2329,8 @@ void py_attack(int y, int x, int max_blow)
}
/* Confuse the monster */
- if (r_ptr->flags3 & (RF3_NO_CONF))
+ if (r_ptr->flags & RF_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)
@@ -2655,8 +2355,8 @@ void py_attack(int y, int x, int max_blow)
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) ||
+ if (!((r_ptr->flags & RF_UNIQUE) ||
+ (r_ptr->spells & SF_BR_CHAO) ||
(m_ptr->mflag & MFLAG_QUEST)))
{
/* Handle polymorph */
@@ -2672,7 +2372,7 @@ void py_attack(int y, int x, int max_blow)
monster_desc(m_name, m_ptr, 0);
/* Hack -- Get new race */
- r_ptr = race_inf(m_ptr);
+ r_ptr = m_ptr->race();
fear = FALSE;
}
@@ -2691,9 +2391,6 @@ void py_attack(int y, int x, int max_blow)
/* Player misses */
else
{
- /* Sound */
- sound(SOUND_MISS);
-
backstab = FALSE; /* Clumsy! */
/* Message */
@@ -2715,9 +2412,6 @@ void py_attack(int y, int x, int max_blow)
/* Hack -- delay fear messages */
if (fear && m_ptr->ml)
{
- /* Sound */
- sound(SOUND_FLEE);
-
/* Message */
msg_format("%^s flees in terror!", m_name);
}
@@ -2733,136 +2427,18 @@ void py_attack(int y, int x, int max_blow)
-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)
{
+ auto const &r_info = game->edit_data.r_info;
+ auto const &f_info = game->edit_data.f_info;
+
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)))
+ if (p_ptr->wraith_form || (race_flags_p(PR_SEMI_WRAITH)))
pass_wall = TRUE;
else
pass_wall = FALSE;
@@ -2898,32 +2474,135 @@ bool_ player_can_enter(byte feature)
{
if (p_ptr->fly ||
pass_wall ||
- (has_ability(AB_TREE_WALK)) ||
+ p_ptr->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)))
+ ((p_ptr->grace >= 9000) && praying_to(GOD_YAVANNA)))
return (TRUE);
}
- if ((p_ptr->climb) && (f_info[feature].flags1 & FF1_CAN_CLIMB))
+ if ((p_ptr->climb) && (f_info[feature].flags & FF_CAN_CLIMB))
return (TRUE);
if ((p_ptr->fly) &&
- ((f_info[feature].flags1 & FF1_CAN_FLY) ||
- (f_info[feature].flags1 & FF1_CAN_LEVITATE)))
+ ((f_info[feature].flags & FF_CAN_FLY) ||
+ (f_info[feature].flags & FF_CAN_LEVITATE)))
return (TRUE);
- else if (only_wall && (f_info[feature].flags1 & FF1_FLOOR))
+ else if (only_wall && (f_info[feature].flags & FF_FLOOR))
return (FALSE);
else if ((p_ptr->ffall) &&
- (f_info[feature].flags1 & FF1_CAN_LEVITATE))
+ (f_info[feature].flags & FF_CAN_LEVITATE))
return (TRUE);
else if ((pass_wall || only_wall) &&
- (f_info[feature].flags1 & FF1_CAN_PASS))
+ (f_info[feature].flags & FF_CAN_PASS))
return (TRUE);
- else if (f_info[feature].flags1 & FF1_NO_WALK)
+ else if (f_info[feature].flags & FF_NO_WALK)
+ return (FALSE);
+ else if ((f_info[feature].flags & FF_WEB) &&
+ ((!(r_info[p_ptr->body_monster].flags & RF_SPIDER)) && (p_ptr->mimic_form != resolve_mimic_name("Spider"))))
+ return (FALSE);
+
+ return (TRUE);
+}
+
+/*
+ * 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().
+ */
+
+static bool_ easy_open_door(int y, int x)
+{
+ auto const &r_info = game->edit_data.r_info;
+
+ int i, j;
+
+ cave_type *c_ptr = &cave[y][x];
+
+ auto r_ptr = &r_info[p_ptr->body_monster];
+
+
+ if ((p_ptr->body_monster != 0) && !(r_ptr->flags & RF_OPEN_DOOR))
+ {
+ msg_print("You cannot open doors.");
+
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"))))
+ }
+
+ /* 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 = 100;
+
+ /* 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.");
+
+ /* Open the door */
+ cave_set_feat(y, x, FEAT_OPEN);
+
+ /* Update some things */
+ p_ptr->update |= (PU_VIEW | PU_MONSTERS | PU_MON_LITE);
+
+ /* Experience */
+ gain_exp(1);
+ }
+
+ /* Failure */
+ else
+ {
+ /* Failure */
+ flush_on_failure();
+
+ /* Message */
+ msg_print("You failed to pick the lock.");
+ }
+ }
+ /* Closed door */
+ else
+ {
+ /* Open the door */
+ cave_set_feat(y, x, FEAT_OPEN);
+
+ /* Update some things */
+ p_ptr->update |= (PU_VIEW | PU_MONSTERS | PU_MON_LITE);
+ }
+
+ /* Result */
return (TRUE);
}
@@ -2936,43 +2615,43 @@ bool_ player_can_enter(byte feature)
* 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)
+void move_player_aux(int dir, int do_pickup, int run)
{
+ auto const &d_info = game->edit_data.d_info;
+ auto const &r_info = game->edit_data.r_info;
+ auto const &f_info = game->edit_data.f_info;
+
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;
+ auto r_ptr = &r_info[p_ptr->body_monster];
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))
+ else if ((r_ptr->flags & RF_RAND_25) && (r_ptr->flags & RF_RAND_50))
{
if (randint(100) < 75)
tmp = randint(9);
else
tmp = dir;
}
- else if (r_ptr->flags1 & RF1_RAND_50)
+ else if (r_ptr->flags & RF_RAND_50)
{
if (randint(100) < 50)
tmp = randint(9);
else
tmp = dir;
}
- else if (r_ptr->flags1 & RF1_RAND_25)
+ else if (r_ptr->flags & RF_RAND_25)
{
if (randint(100) < 25)
tmp = randint(9);
@@ -3096,26 +2775,35 @@ 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;
-
- /* Get the monster */
- m_ptr = &m_list[c_ptr->m_idx];
- mr_ptr = race_inf(m_ptr);
+ {
+ hook_move_in in = { y, x };
+ if (process_hooks_new(HOOK_MOVE, &in, NULL)) {
+ return; /* Prevent movement */
+ }
+ }
- if (p_ptr->inventory[INVEN_WIELD].art_name)
+ if (p_ptr->dripping_tread > 0)
{
- if (streq(quark_str(p_ptr->inventory[INVEN_WIELD].art_name), "'Stormbringer'"))
- stormbringer = TRUE;
+ 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];
+ auto const mr_ptr = m_ptr->race();
+
/* 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)) &&
+ !(p_ptr->confused || p_ptr->image || !(m_ptr->ml) || p_ptr->stun) &&
((player_can_enter(cave[y][x].feat))))
{
m_ptr->csleep = 0;
@@ -3129,13 +2817,16 @@ void move_player_aux(int dir, int do_pickup, int run, bool_ disarm)
/* Track a new monster */
if (m_ptr->ml) health_track(c_ptr->m_idx);
+ /* Is it Stormbringer? */
+ bool stormbringer = p_ptr->inventory[INVEN_WIELD].artifact_name == "'Stormbringer'";
+
/* 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))
+ (mr_ptr->flags & RF_PASS_WALL))
{
msg_format("You push past %s.", m_name);
m_ptr->fy = p_ptr->py;
@@ -3167,28 +2858,13 @@ void move_player_aux(int dir, int do_pickup, int run, bool_ disarm)
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, 0);
+ disturb();
if (p_ptr->prob_travel)
{
@@ -3217,13 +2893,12 @@ void move_player_aux(int dir, int do_pickup, int run, bool_ disarm)
/* Wall (or secret door) */
else
{
- int feat;
-
- if (c_ptr->mimic) feat = c_ptr->mimic;
- else
- feat = f_info[c_ptr->feat].mimic;
+ int const feat = c_ptr->mimic
+ ? c_ptr->mimic
+ : f_info[c_ptr->feat].mimic
+ ;
- msg_format("You feel %s.", f_text + f_info[feat].block);
+ msg_format("You feel %s.", f_info[feat].block);
c_ptr->info |= (CAVE_MARK);
lite_spot(y, x);
}
@@ -3235,110 +2910,36 @@ void move_player_aux(int dir, int do_pickup, int run, bool_ disarm)
/* Rubble */
if (c_ptr->feat == FEAT_RUBBLE)
{
- if (!easy_tunnel)
- {
- msg_print("There is rubble blocking your way.");
+ 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;
- }
+ 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...
+ */
}
/* 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;
- }
+ if (easy_open_door(y, x)) return;
}
/* 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);
+ int feat;
- if (!(p_ptr->confused || p_ptr->stun || p_ptr->image))
- energy_use = 0;
- }
+ if (c_ptr->mimic) feat = c_ptr->mimic;
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, 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, 0);
-
- /* but don't take a turn */
- energy_use = 0;
+ feat = f_info[c_ptr->feat].mimic;
- /* Tell player why */
- cmsg_print(TERM_VIOLET, "You are about to leave a trap detected zone.");
- /* Flush */
- /* msg_print(NULL); */
+ msg_format("There is %s.", f_info[feat].block);
- oktomove = FALSE;
+ if (!(p_ptr->confused || p_ptr->stun || p_ptr->image))
+ energy_use = 0;
+ }
}
}
@@ -3363,9 +2964,6 @@ void move_player_aux(int dir, int do_pickup, int run, bool_ disarm)
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);
@@ -3378,20 +2976,6 @@ void move_player_aux(int dir, int do_pickup, int run, bool_ disarm)
/* 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);
@@ -3402,34 +2986,22 @@ void move_player_aux(int dir, int do_pickup, int run, bool_ disarm)
if (!run) p_ptr->window |= (PW_OVERHEAD);
/* Some feature descs */
- if (f_info[cave[p_ptr->py][p_ptr->px].feat].text > 1)
+ if (f_info[cave[p_ptr->py][p_ptr->px].feat].text != DEFAULT_FEAT_TEXT)
{
/* 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);
+ msg_format("There is %s", d_info[c_ptr->special].text.c_str());
}
else
{
- msg_print(f_text + f_info[feat].text);
+ msg_print(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);
@@ -3437,7 +3009,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();
/* Hack -- Enter store */
command_new = '_';
@@ -3446,7 +3018,7 @@ void move_player_aux(int dir, int do_pickup, int run, bool_ disarm)
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 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);
@@ -3455,31 +3027,11 @@ void move_player_aux(int dir, int do_pickup, int run, bool_ disarm)
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, 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, 0);
+ disturb();
msg_format("There is an inscription here: %s",
inscription_info[c_ptr->inscription].text);
@@ -3503,9 +3055,9 @@ void move_player_aux(int dir, int do_pickup, int run, bool_ disarm)
}
}
-void move_player(int dir, int do_pickup, bool_ disarm)
+void move_player(int dir, int do_pickup)
{
- move_player_aux(dir, do_pickup, 0, disarm);
+ move_player_aux(dir, do_pickup, 0);
}
@@ -3514,13 +3066,7 @@ void move_player(int dir, int do_pickup, bool_ disarm)
*/
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);
-
+ auto const &f_info = game->edit_data.f_info;
/* Hack -- Handle special cases XXX XXX */
switch (c_ptr->feat)
@@ -3543,7 +3089,7 @@ static int see_obstacle_grid(cave_type *c_ptr)
/* "Safe" floor grids aren't obstacles */
- if (f_info[c_ptr->feat].flags1 & FF1_CAN_RUN) return (FALSE);
+ if (f_info[c_ptr->feat].flags & FF_CAN_RUN) return (FALSE);
/* Must be known to the player */
if (!(c_ptr->info & (CAVE_MARK))) return (FALSE);
@@ -3871,8 +3417,10 @@ static void run_init(int dir)
*
* Return TRUE if the running should be stopped
*/
-static bool_ run_test(void)
+static bool_ run_test()
{
+ auto const &f_info = game->edit_data.f_info;
+
int prev_dir, new_dir, check_dir = 0;
int row, col;
@@ -3881,9 +3429,6 @@ static bool_ run_test(void)
int option = 0, option2 = 0;
- cave_type *c_ptr;
-
-
/* Where we came from */
prev_dir = find_prevdir;
@@ -3895,9 +3440,6 @@ static bool_ run_test(void)
/* 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];
@@ -3906,7 +3448,7 @@ static bool_ run_test(void)
col = p_ptr->px + ddx[new_dir];
/* Access grid */
- c_ptr = &cave[row][col];
+ cave_type *c_ptr = &cave[row][col];
/* Visible monsters abort running */
@@ -3919,15 +3461,10 @@ static bool_ run_test(void)
}
/* Visible objects abort running */
- for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
+ for (auto const o_idx: c_ptr->o_idxs)
{
- object_type * o_ptr;
-
/* Acquire object */
- o_ptr = &o_list[this_o_idx];
-
- /* Acquire next object */
- next_o_idx = o_ptr->next_o_idx;
+ object_type * o_ptr = &o_list[o_idx];
/* Visible object */
if (o_ptr->marked) return (TRUE);
@@ -3973,7 +3510,7 @@ static bool_ run_test(void)
case FEAT_BROKEN:
{
/* Option -- ignore */
- if (find_ignore_doors) notice = FALSE;
+ if (options->find_ignore_doors) notice = FALSE;
/* Done */
break;
@@ -3999,7 +3536,7 @@ static bool_ run_test(void)
case FEAT_BETWEEN2:
{
/* Option -- ignore */
- if (find_ignore_stairs) notice = FALSE;
+ if (options->find_ignore_stairs) notice = FALSE;
/* Done */
break;
@@ -4007,14 +3544,11 @@ static bool_ run_test(void)
}
/* Check the "don't notice running" flag */
- if (f_info[c_ptr->feat].flags1 & FF1_DONT_NOTICE_RUNNING)
+ if (f_info[c_ptr->feat].flags & FF_DONT_NOTICE_RUNNING)
{
notice = FALSE;
}
- /* A detected trap is interesting */
- if (c_ptr->info & (CAVE_TRDT)) notice = TRUE;
-
/* Interesting feature */
if (notice) return (TRUE);
@@ -4022,9 +3556,6 @@ static bool_ run_test(void)
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))
{
@@ -4101,7 +3632,7 @@ static bool_ run_test(void)
col = p_ptr->px + ddx[new_dir];
/* Access grid */
- c_ptr = &cave[row][col];
+ cave_type *c_ptr = &cave[row][col];
/* Unknown grids or non-obstacle */
if (!see_obstacle_grid(c_ptr))
@@ -4133,7 +3664,7 @@ static bool_ run_test(void)
col = p_ptr->px + ddx[new_dir];
/* Access grid */
- c_ptr = &cave[row][col];
+ cave_type *c_ptr = &cave[row][col];
/* Unknown grid or non-obstacle */
if (!see_obstacle_grid(c_ptr))
@@ -4178,7 +3709,7 @@ static bool_ run_test(void)
}
/* Two options, examining corners */
- else if (find_examine && !find_cut)
+ else if (options->find_examine && !options->find_cut)
{
/* Primary option */
find_current = option;
@@ -4200,7 +3731,7 @@ static bool_ run_test(void)
{
/* Can not see anything ahead and in the direction we */
/* are turning, assume that it is a potential corner. */
- if (find_examine &&
+ if (options->find_examine &&
see_nothing(option, row, col) &&
see_nothing(option2, row, col))
{
@@ -4216,7 +3747,7 @@ static bool_ run_test(void)
}
/* This corner is seen to be enclosed; we cut the corner. */
- else if (find_cut)
+ else if (options->find_cut)
{
find_current = option2;
find_prevdir = option2;
@@ -4262,7 +3793,7 @@ void run_step(int dir)
msg_print("You cannot run in that direction.");
/* Disturb */
- disturb(0, 0);
+ disturb();
/* Done */
return;
@@ -4282,7 +3813,7 @@ void run_step(int dir)
if (run_test())
{
/* Disturb */
- disturb(0, 0);
+ disturb();
/* Done */
return;
@@ -4297,54 +3828,17 @@ void run_step(int dir)
/* Move the player, using the "pickup" flag */
- move_player_aux(find_current, always_pickup, 1, TRUE);
+ move_player_aux(find_current, options->always_pickup, 1);
}
/*
- * 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, 0);
-
- /* Hack -- Enter store */
- command_new = KTRL('V');
- }
-
- /* Discover/set off traps */
- else if (cave[y][x].t_idx != 0)
- {
- /* Disturb */
- disturb(0, 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)
+void do_cmd_pet()
{
+ auto const &r_info = game->edit_data.r_info;
+
int i = 0;
int num = 0;
@@ -4353,7 +3847,7 @@ void do_cmd_pet(void)
char power_desc[36][80];
- bool_ flag, redraw;
+ bool_ flag;
int ask;
@@ -4432,80 +3926,55 @@ void do_cmd_pet(void)
/* 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),
+ "(Command %c-%c, 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),
+ "(Command %c-%c, 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, "");
+ /* Save the screen */
+ character_icky = TRUE;
+ Term_save();
- /* 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++;
- }
+ /* Show the list */
+ {
+ byte y = 1, x = 0;
+ int ctr = 0;
+ char dummy[80];
- if (ctr < 17)
- {
- prt("", y + ctr, x);
- }
- else
- {
- prt("", y + 17, x);
- }
- }
+ strcpy(dummy, "");
- /* Hide the list */
- else
- {
- /* Hide list */
- redraw = FALSE;
+ prt("", y++, x);
- /* Restore the screen */
- Term_load();
- character_icky = FALSE;
- }
+ while (ctr < num)
+ {
+ strnfmt(dummy, 80, "%c) %s", I2A(ctr), power_desc[ctr]);
+ prt(dummy, y + ctr, x);
+ ctr++;
+ }
- /* Redo asking */
- continue;
+ if (ctr < 17)
+ {
+ prt("", y + ctr, x);
}
+ else
+ {
+ prt("", y + 17, x);
+ }
+ }
+ /* Get a command from the user */
+ while (!flag && get_com(out_val, &choice))
+ {
if (choice == '\r' && num == 1)
{
choice = 'a';
@@ -4553,11 +4022,8 @@ void do_cmd_pet(void)
}
/* Restore the screen */
- if (redraw)
- {
- Term_load();
- character_icky = FALSE;
- }
+ Term_load();
+ character_icky = FALSE;
/* Abort if needed */
if (!flag)
@@ -4633,13 +4099,11 @@ void do_cmd_pet(void)
/* 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];
+ auto 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! */
+ if ((!(r_ptr->flags & RF_NO_DEATH)) && ((m_ptr->status == MSTATUS_PET) || (m_ptr->status == MSTATUS_FRIEND))) /* Get rid of it! */
{
bool_ checked = FALSE;
char command;
@@ -4702,13 +4166,11 @@ void do_cmd_pet(void)
/* 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];
+ auto r_ptr = &r_info[m_ptr->r_idx];
- if ((!(r_ptr->flags7 & RF7_NO_DEATH)) && ((m_ptr->status == MSTATUS_COMPANION))) /* Get rid of it! */
+ if ((!(r_ptr->flags & RF_NO_DEATH)) && ((m_ptr->status == MSTATUS_COMPANION))) /* Get rid of it! */
{
bool_ delete_this = FALSE;
@@ -4788,35 +4250,31 @@ void do_cmd_pet(void)
/*
* Incarnate into a body
*/
-bool_ do_cmd_integrate_body()
+void 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;
+ return;
}
- /* 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;
+ int item;
+ if (!get_item(&item,
+ "Incarnate in which body? ",
+ "You have no corpse to incarnate in.",
+ (USE_FLOOR),
+ object_filter::TVal(TV_CORPSE)))
+ {
+ return;
+ }
- o_ptr = &o_list[0 - item];
+ object_type *o_ptr = &o_list[0 - item];
if (o_ptr->sval != SV_CORPSE_CORPSE)
{
msg_print("You must select a corpse.");
- return FALSE;
+ return;
}
p_ptr->body_monster = o_ptr->pval2;
@@ -4830,8 +4288,6 @@ bool_ do_cmd_integrate_body()
p_ptr->wraith_form = FALSE;
p_ptr->disembodied = FALSE;
do_cmd_redraw();
-
- return TRUE;
}
/*
@@ -4839,9 +4295,11 @@ bool_ do_cmd_integrate_body()
*/
bool_ do_cmd_leave_body(bool_ drop_body)
{
+ auto const &r_info = game->edit_data.r_info;
+
object_type *o_ptr, forge;
- monster_race *r_ptr = &r_info[p_ptr->body_monster];
+ auto r_ptr = &r_info[p_ptr->body_monster];
int i;
@@ -4878,7 +4336,7 @@ bool_ do_cmd_leave_body(bool_ drop_body)
o_ptr->ident |= IDENT_STOREB;
/* Unique corpses are unique */
- if (r_ptr->flags1 & RF1_UNIQUE)
+ if (r_ptr->flags & RF_UNIQUE)
{
o_ptr->name1 = 201;
}
@@ -4962,56 +4420,49 @@ bool_ execute_inscription(byte i, byte y, byte x)
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)
+ cave_type *c_ptr = &cave[ij][ii];
+
+ if (c_ptr->m_idx)
{
- m_ptr = &m_list[cave[ij][ii].m_idx];
- r_ptr = race_inf(m_ptr);
+ monster_type *m_ptr = &m_list[c_ptr->m_idx];
+ auto const r_ptr = m_ptr->race();
- if (r_ptr->flags7 & RF7_CAN_FLY)
+ if (r_ptr->flags & RF_CAN_FLY)
{
msg_print("The monster simply flies over the chasm.");
}
else
{
- if (!(r_ptr->flags1 & RF1_UNIQUE))
+ if (!(r_ptr->flags & RF_UNIQUE))
{
msg_print("The monster falls in the chasm!");
- delete_monster_idx(cave[ij][ii].m_idx);
+ delete_monster_idx(c_ptr->m_idx);
}
}
}
- if (cave[ij][ii].o_idx)
+ if (!c_ptr->o_idxs.empty())
{
- s16b this_o_idx, next_o_idx = 0;
-
- c_ptr = &cave[ij][ii];
+ /* Copy list of objects since we're going to be manipulating the list */
+ auto const object_idxs(c_ptr->o_idxs);
/* Scan all objects in the grid */
- for (this_o_idx = c_ptr->o_idx; this_o_idx;
- this_o_idx = next_o_idx)
+ for (auto const this_o_idx: object_idxs)
{
- object_type * o_ptr;
bool_ plural = FALSE;
char o_name[80];
/* Acquire object */
- o_ptr = &o_list[this_o_idx];
+ object_type * 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)
{
@@ -5079,13 +4530,14 @@ void do_cmd_engrave()
{
if (!strcmp(inscription_info[i].text, buf))
{
- if (inscription_info[i].know)
+ if (p_ptr->inscriptions[i])
{
- /* Save the inscription */
cave[p_ptr->py][p_ptr->px].inscription = i;
}
else
+ {
msg_print("You can't use this inscription for now.");
+ }
}
}
diff --git a/src/cmd1.hpp b/src/cmd1.hpp
new file mode 100644
index 00000000..19b40ebf
--- /dev/null
+++ b/src/cmd1.hpp
@@ -0,0 +1,25 @@
+#pragma once
+
+#include "h-basic.h"
+#include "monster_type_fwd.hpp"
+#include "object_type_fwd.hpp"
+
+void attack_special(monster_type *m_ptr, s32b special, int dam);
+bool_ test_hit_fire(int chance, int ac, int vis);
+bool_ test_hit_norm(int chance, int ac, int vis);
+s16b critical_shot(int weight, int plus, int dam, int skill);
+s16b critical_norm(int weight, int plus, int dam, int weapon_tval, bool_ *done_crit);
+s16b tot_dam_aux(object_type *o_ptr, int tdam, monster_type *m_ptr, s32b *special);
+void search();
+void carry(int pickup);
+void py_attack(int y, int x, int max_blow);
+bool_ player_can_enter(byte feature);
+void move_player(int dir, int do_pickup);
+void move_player_aux(int dir, int do_pickup, int run);
+void run_step(int dir);
+void do_cmd_pet();
+void do_cmd_integrate_body();
+bool_ do_cmd_leave_body(bool_ drop_body);
+bool_ execute_inscription(byte i, byte y, byte x);
+void do_cmd_engrave();
+void do_spin();
diff --git a/src/cmd2.c b/src/cmd2.cc
index 2d05c125..a348c221 100644
--- a/src/cmd2.c
+++ b/src/cmd2.cc
@@ -1,7 +1,3 @@
-/* File: cmd2.c */
-
-/* Purpose: Movement commands (part 2) */
-
/*
* Copyright (c) 1989 James E. Wilson, Robert A. Koeneke
*
@@ -10,9 +6,61 @@
* included in all such copies.
*/
-#include "angband.h"
-
-void do_cmd_immovable_special(void);
+#include "cmd2.hpp"
+
+#include "bldg.hpp"
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "cmd1.hpp"
+#include "dungeon_info_type.hpp"
+#include "dungeon_flag.hpp"
+#include "feature_flag.hpp"
+#include "feature_type.hpp"
+#include "files.hpp"
+#include "game.hpp"
+#include "gods.hpp"
+#include "hook_chat_in.hpp"
+#include "hook_enter_dungeon_in.hpp"
+#include "hook_give_in.hpp"
+#include "hook_stair_in.hpp"
+#include "hook_stair_out.hpp"
+#include "hooks.hpp"
+#include "levels.hpp"
+#include "monster2.hpp"
+#include "monster3.hpp"
+#include "monster_race.hpp"
+#include "monster_race_flag.hpp"
+#include "monster_type.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_flag.hpp"
+#include "object_kind.hpp"
+#include "options.hpp"
+#include "player_race_flag.hpp"
+#include "player_type.hpp"
+#include "skills.hpp"
+#include "spells1.hpp"
+#include "spells2.hpp"
+#include "spells3.hpp"
+#include "stats.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "util.h"
+#include "variable.h"
+#include "variable.hpp"
+#include "wilderness_map.hpp"
+#include "wilderness_type_info.hpp"
+#include "xtra1.hpp"
+#include "xtra2.hpp"
+#include "z-rand.hpp"
+
+#include <chrono>
+#include <thread>
+
+using std::this_thread::sleep_for;
+using std::chrono::milliseconds;
+
+void do_cmd_immovable_special();
/*
* Try to bash an altar
@@ -29,14 +77,16 @@ static bool_ do_cmd_bash_altar(int y, int x)
*/
static bool_ do_cmd_bash_fountain(int y, int x)
{
+ auto const &r_info = game->edit_data.r_info;
+
int bash, temp;
bool_ more = TRUE;
- monster_race *r_ptr = &r_info[p_ptr->body_monster];
+ auto r_ptr = &r_info[p_ptr->body_monster];
- if ((p_ptr->body_monster != 0) && !(r_ptr->flags2 & RF2_BASH_DOOR))
+ if ((p_ptr->body_monster != 0) && !(r_ptr->flags & RF_BASH_DOOR))
{
msg_print("You cannot do that.");
@@ -74,26 +124,65 @@ static bool_ do_cmd_bash_fountain(int y, int x)
return (more);
}
+/*
+ * Stair hooks
+ */
+static bool_ stair_hooks(stairs_direction direction)
+{
+ hook_stair_in in = { direction };
+ hook_stair_out out = { TRUE }; /* Allow by default */
+ process_hooks_new(HOOK_STAIR, &in, &out);
+ return (!out.allow);
+}
+
+/*
+ * Ask for confirmation before leaving level; based
+ * on whether the 'confirm_stairs' option is set.
+ */
+static bool ask_leave()
+{
+ if (options->confirm_stairs)
+ {
+ if (get_check("Really leave the level? "))
+ {
+ return true; // Leave
+ }
+ else
+ {
+ return false; // Don't leave
+ }
+ }
+ else
+ {
+ return true; // Leave
+ }
+}
+
/*
* Go up one level
*/
-void do_cmd_go_up(void)
+void do_cmd_go_up()
{
+ auto const &d_info = game->edit_data.d_info;
+
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];
+ auto d_ptr = &d_info[dungeon_type];
/* Player grid */
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))
@@ -102,15 +191,11 @@ void do_cmd_go_up(void)
{
go_up = TRUE;
}
- else if ((dungeon_flags2 & DF2_ASK_LEAVE))
+ else if (dungeon_flags & DF_ASK_LEAVE)
{
go_up = get_check("Leave this unique level forever? ");
}
- else if (confirm_stairs)
- {
- go_up = get_check("Really leave the level? ");
- }
- else
+ else if (ask_leave())
{
go_up = TRUE;
}
@@ -123,15 +208,11 @@ void do_cmd_go_up(void)
{
go_up = TRUE;
}
- else if ((dungeon_flags2 & DF2_ASK_LEAVE))
+ else if (dungeon_flags & DF_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
+ else if (ask_leave())
{
go_up_many = TRUE;
}
@@ -142,7 +223,7 @@ void do_cmd_go_up(void)
{
leaving_quest = p_ptr->inside_quest;
- if ((dungeon_flags2 & DF2_ASK_LEAVE) &&
+ if ((dungeon_flags & DF_ASK_LEAVE) &&
!get_check("Leave this unique level forever? "))
return;
@@ -156,12 +237,12 @@ void do_cmd_go_up(void)
}
/* Exits to previous area in flat terrains */
- else if (!(dungeon_flags1 & DF1_FLAT) &&
+ else if (!(dungeon_flags & DF_FLAT) &&
p_ptr->prob_travel && !p_ptr->inside_quest)
{
if (d_ptr->mindepth == dun_level) return;
- if (dungeon_flags2 & DF2_NO_EASY_MOVE)
+ if (dungeon_flags & DF_NO_EASY_MOVE)
{
msg_print("Some powerful force prevents your from teleporting.");
return;
@@ -169,12 +250,7 @@ void do_cmd_go_up(void)
prob_traveling = TRUE;
- if (confirm_stairs)
- {
- if (get_check("Really leave the level? "))
- go_up = TRUE;
- }
- else
+ if (ask_leave())
{
go_up = TRUE;
}
@@ -238,7 +314,7 @@ void do_cmd_go_up(void)
/*
* Returns TRUE if we are in the Between...
*/
-static bool_ between_effect(void)
+static bool_ between_effect()
{
byte bx, by;
@@ -282,19 +358,19 @@ static bool_ between_effect(void)
/*
* Go down one level
*/
-void do_cmd_go_down(void)
+void do_cmd_go_down()
{
+ auto const &d_info = game->edit_data.d_info;
+
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];
+ auto d_ptr = &d_info[dungeon_type];
/* MUST be actived now */
@@ -305,10 +381,8 @@ void do_cmd_go_down(void)
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))
+ if (dungeon_flags & DF_ASK_LEAVE)
{
prt("Leave this unique level forever (y/n) ? ", 0, 0);
flush();
@@ -318,7 +392,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)
@@ -333,12 +410,7 @@ void do_cmd_go_down(void)
}
else
{
- if (confirm_stairs)
- {
- if (get_check("Really leave the level? "))
- go_down_many = TRUE;
- }
- else
+ if (ask_leave())
{
go_down_many = TRUE;
}
@@ -362,12 +434,7 @@ void do_cmd_go_down(void)
}
else
{
- if (confirm_stairs)
- {
- if (get_check("Really leave the level? "))
- go_down = TRUE;
- }
- else
+ if (ask_leave())
{
go_down = TRUE;
}
@@ -383,31 +450,26 @@ void do_cmd_go_down(void)
return;
}
- else if (!(dungeon_flags1 & DF1_FLAT) &&
+ else if (!(dungeon_flags & DF_FLAT) &&
p_ptr->prob_travel && !p_ptr->inside_quest)
{
if (d_ptr->maxdepth == dun_level) return;
- if (dungeon_flags2 & DF2_NO_EASY_MOVE)
+ if (dungeon_flags & DF_NO_EASY_MOVE)
{
- msg_print("Some powerfull force prevents your from teleporting.");
+ msg_print("Some powerful force prevents your from teleporting.");
return;
}
prob_traveling = TRUE;
- if (confirm_stairs)
- {
- if (get_check("Really leave the level? "))
- go_down = TRUE;
- }
- else
+ if (ask_leave())
{
go_down = TRUE;
}
}
- else if (!(fall_trap))
+ else
{
msg_print("I see no down staircase here.");
return;
@@ -417,15 +479,10 @@ void do_cmd_go_down(void)
{
energy_use = 0;
- if (fall_trap)
- msg_print("You deliberately jump through the trap door.");
+ if (c_ptr->feat == FEAT_WAY_MORE)
+ msg_print("You enter the next area.");
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.");
- }
+ msg_print("You enter a maze of down staircases.");
autosave_checkpoint();
@@ -451,13 +508,16 @@ void do_cmd_go_down(void)
{
if (d_info[c_ptr->special].min_plev <= p_ptr->lev)
{
- dungeon_info_type *d_ptr = &d_info[c_ptr->special];
+ auto 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;
+ struct hook_enter_dungeon_in in = { c_ptr->special };
+ if (process_hooks_new(HOOK_ENTER_DUNGEON, &in, NULL))
+ {
+ dun_level = old_dun;
+ return;
+ }
}
/* Ok go in the new dungeon */
@@ -479,8 +539,7 @@ void do_cmd_go_down(void)
dun_level = d_ptr->mindepth;
}
- msg_format("You go into %s",
- d_text + d_info[dungeon_type].text);
+ msg_format("You go into %s", d_info[dungeon_type].text.c_str());
}
else
{
@@ -493,80 +552,9 @@ void do_cmd_go_down(void)
/* 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
*/
@@ -574,20 +562,14 @@ 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)
+ for (auto const this_o_idx: c_ptr->o_idxs)
{
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; */
@@ -613,6 +595,8 @@ static s16b chest_check(int y, int x)
*/
static void chest_death(int y, int x, s16b o_idx)
{
+ auto const &d_info = game->edit_data.d_info;
+
int number;
bool_ small;
@@ -682,41 +666,6 @@ static void chest_death(int y, int x, s16b o_idx)
/*
- * 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
@@ -725,6 +674,8 @@ static void chest_trap(int y, int x, s16b o_idx)
*/
static bool_ do_cmd_open_chest(int y, int x, s16b o_idx)
{
+ auto const &r_info = game->edit_data.r_info;
+
int i, j;
bool_ flag = TRUE;
@@ -733,10 +684,10 @@ static bool_ do_cmd_open_chest(int y, int x, s16b o_idx)
object_type *o_ptr = &o_list[o_idx];
- monster_race *r_ptr = &r_info[p_ptr->body_monster];
+ auto r_ptr = &r_info[p_ptr->body_monster];
- if ((p_ptr->body_monster != 0) && !(r_ptr->flags2 & RF2_OPEN_DOOR))
+ if ((p_ptr->body_monster != 0) && !(r_ptr->flags & RF_OPEN_DOOR))
{
msg_print("You cannot open chests.");
@@ -753,7 +704,7 @@ static bool_ do_cmd_open_chest(int y, int x, s16b o_idx)
flag = FALSE;
/* Get the "disarm" factor */
- i = p_ptr->skill_dis;
+ i = 100;
/* Penalize some conditions */
if (p_ptr->blind || no_lite()) i = i / 10;
@@ -779,7 +730,7 @@ static bool_ do_cmd_open_chest(int y, int x, s16b o_idx)
/* We may continue repeating */
more = TRUE;
- if (flush_failure) flush();
+ flush_on_failure();
msg_print("You failed to pick the lock.");
}
@@ -788,9 +739,6 @@ static bool_ do_cmd_open_chest(int y, int x, s16b o_idx)
/* 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);
}
@@ -827,16 +775,6 @@ static bool_ is_closed(cave_type *c_ptr)
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'
@@ -918,9 +856,6 @@ static int count_chests(int *y, int *x, bool_ trapped)
/* 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;
@@ -969,16 +904,18 @@ static int coords_to_dir(int y, int x)
*/
static bool_ do_cmd_open_aux(int y, int x, int dir)
{
+ auto const &r_info = game->edit_data.r_info;
+
int i, j;
cave_type *c_ptr;
bool_ more = FALSE;
- monster_race *r_ptr = &r_info[p_ptr->body_monster];
+ auto r_ptr = &r_info[p_ptr->body_monster];
- if ((p_ptr->body_monster != 0) && !(r_ptr->flags2 & RF2_OPEN_DOOR))
+ if ((p_ptr->body_monster != 0) && !(r_ptr->flags & RF_OPEN_DOOR))
{
msg_print("You cannot open doors.");
@@ -1002,7 +939,7 @@ static bool_ do_cmd_open_aux(int y, int x, int dir)
else if (c_ptr->feat >= FEAT_DOOR_HEAD + 0x01)
{
/* Disarm factor */
- i = p_ptr->skill_dis;
+ i = 100;
/* Penalize some conditions */
if (p_ptr->blind || no_lite()) i = i / 10;
@@ -1023,18 +960,12 @@ static bool_ do_cmd_open_aux(int y, int x, int dir)
/* 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);
}
@@ -1043,7 +974,7 @@ static bool_ do_cmd_open_aux(int y, int x, int dir)
else
{
/* Failure */
- if (flush_failure) flush();
+ flush_on_failure();
/* Message */
msg_print("You failed to pick the lock.");
@@ -1056,17 +987,11 @@ static bool_ do_cmd_open_aux(int y, int x, int dir)
/* 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 */
@@ -1080,8 +1005,10 @@ static bool_ do_cmd_open_aux(int y, int x, int dir)
*
* Unlocking a locked door/chest is worth one experience point.
*/
-void do_cmd_open(void)
+void do_cmd_open()
{
+ auto const &r_info = game->edit_data.r_info;
+
int y, x, dir;
s16b o_idx;
@@ -1090,18 +1017,17 @@ void do_cmd_open(void)
bool_ more = FALSE;
- monster_race *r_ptr = &r_info[p_ptr->body_monster];
+ auto r_ptr = &r_info[p_ptr->body_monster];
- if ((p_ptr->body_monster != 0) && !(r_ptr->flags2 & RF2_OPEN_DOOR))
+ if ((p_ptr->body_monster != 0) && !(r_ptr->flags & RF_OPEN_DOOR))
{
msg_print("You cannot open doors.");
return;
}
- /* Option: Pick a direction */
- if (easy_open)
+ /* Pick a direction if there's an obvious target */
{
int num_doors, num_chests;
@@ -1135,7 +1061,7 @@ void do_cmd_open(void)
command_rep = command_arg - 1;
/* Redraw the state */
- p_ptr->redraw |= (PR_STATE);
+ p_ptr->redraw |= (PR_FRAME);
/* Cancel the arg */
command_arg = 0;
@@ -1190,11 +1116,8 @@ void do_cmd_open(void)
}
}
- /* Process the appropriate hooks */
- process_hooks(HOOK_OPEN, "(d)", is_quest(dun_level));
-
/* Cancel repeat unless we may continue */
- if (!more) disturb(0, 0);
+ if (!more) disturb();
}
@@ -1210,14 +1133,16 @@ void do_cmd_open(void)
*/
static bool_ do_cmd_close_aux(int y, int x, int dir)
{
+ auto const &r_info = game->edit_data.r_info;
+
cave_type *c_ptr;
bool_ more = FALSE;
- monster_race *r_ptr = &r_info[p_ptr->body_monster];
+ auto r_ptr = &r_info[p_ptr->body_monster];
- if ((p_ptr->body_monster != 0) && !(r_ptr->flags2 & RF2_OPEN_DOOR))
+ if ((p_ptr->body_monster != 0) && !(r_ptr->flags & RF_OPEN_DOOR))
{
msg_print("You cannot close doors.");
@@ -1230,9 +1155,6 @@ static bool_ do_cmd_close_aux(int y, int x, int dir)
/* 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)
{
@@ -1248,9 +1170,6 @@ static bool_ do_cmd_close_aux(int y, int x, int dir)
/* Update some things */
p_ptr->update |= (PU_VIEW | PU_MONSTERS | PU_MON_LITE);
-
- /* Sound */
- sound(SOUND_SHUTDOOR);
}
/* Result */
@@ -1261,7 +1180,7 @@ static bool_ do_cmd_close_aux(int y, int x, int dir)
/*
* Close an open door.
*/
-void do_cmd_close(void)
+void do_cmd_close()
{
int y, x, dir;
@@ -1270,8 +1189,7 @@ void do_cmd_close(void)
bool_ more = FALSE;
- /* Option: Pick a direction */
- if (easy_open)
+ /* Pick a direction if there's an obvious choice */
{
int num_doors;
@@ -1302,7 +1220,7 @@ void do_cmd_close(void)
command_rep = command_arg - 1;
/* Redraw the state */
- p_ptr->redraw |= (PR_STATE);
+ p_ptr->redraw |= (PR_FRAME);
/* Cancel the arg */
command_arg = 0;
@@ -1347,7 +1265,7 @@ void do_cmd_close(void)
}
/* Cancel repeat unless we may continue */
- if (!more) disturb(0, 0);
+ if (!more) disturb();
}
@@ -1356,6 +1274,8 @@ void do_cmd_close(void)
*/
static bool_ do_cmd_tunnel_test(int y, int x)
{
+ auto const &f_info = game->edit_data.f_info;
+
/* Must have knowledge(execpt on "forget" levels) */
if (!(cave[y][x].info & (CAVE_MARK)))
{
@@ -1377,10 +1297,10 @@ static bool_ do_cmd_tunnel_test(int y, int x)
}
/* Must be tunnelable */
- if (!(f_info[cave[y][x].feat].flags1 & FF1_TUNNELABLE))
+ if (!(f_info[cave[y][x].feat].flags & FF_TUNNELABLE))
{
/* Message */
- msg_print(f_text + f_info[cave[y][x].feat].tunnel);
+ msg_print(f_info[cave[y][x].feat].tunnel);
/* Nope */
return (FALSE);
@@ -1434,12 +1354,15 @@ static bool_ twall(int y, int x, byte feat)
*
* Returns TRUE if repeated commands may continue
*/
-bool_ do_cmd_tunnel_aux(int y, int x, int dir)
+static bool_ do_cmd_tunnel_aux(int y, int x, int dir)
{
+ auto const &d_info = game->edit_data.d_info;
+ auto const &f_info = game->edit_data.f_info;
+
int skill_req = 0, skill_req_1pct = 0;
cave_type *c_ptr = &cave[y][x];
- feature_type *f_ptr = &f_info[c_ptr->feat];
+ auto f_ptr = &f_info[c_ptr->feat];
bool_ more = FALSE;
@@ -1465,13 +1388,10 @@ bool_ do_cmd_tunnel_aux(int y, int x, int dir)
/* Get grid */
c_ptr = &cave[y][x];
- /* Sound */
- sound(SOUND_DIG);
-
/* Titanium */
- if (f_ptr->flags1 & FF1_PERMANENT)
+ if (f_ptr->flags & FF_PERMANENT)
{
- msg_print(f_text + f_ptr->tunnel);
+ msg_print(f_ptr->tunnel);
}
else if ((c_ptr->feat == FEAT_TREES) || (c_ptr->feat == FEAT_DEAD_TREE))
@@ -1488,11 +1408,8 @@ bool_ do_cmd_tunnel_aux(int y, int x, int dir)
else
{
/* We may continue chopping */
- msg_print(f_text + f_ptr->tunnel);
+ msg_print(f_ptr->tunnel);
more = TRUE;
-
- /* Occasional Search XXX XXX */
- if (rand_int(100) < 25) search();
}
}
@@ -1513,7 +1430,7 @@ bool_ do_cmd_tunnel_aux(int y, int x, int dir)
else
{
/* We may continue tunelling */
- msg_print(f_text + f_ptr->tunnel);
+ msg_print(f_ptr->tunnel);
more = TRUE;
}
}
@@ -1593,7 +1510,7 @@ bool_ do_cmd_tunnel_aux(int y, int x, int dir)
else
{
/* Message, continue digging */
- msg_print(f_text + f_ptr->tunnel);
+ msg_print(f_ptr->tunnel);
more = TRUE;
}
}
@@ -1627,7 +1544,7 @@ bool_ do_cmd_tunnel_aux(int y, int x, int dir)
else
{
/* Message, keep digging */
- msg_print(f_text + f_ptr->tunnel);
+ msg_print(f_ptr->tunnel);
more = TRUE;
}
}
@@ -1643,9 +1560,6 @@ bool_ do_cmd_tunnel_aux(int y, int x, int dir)
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 */
@@ -1658,11 +1572,8 @@ bool_ do_cmd_tunnel_aux(int y, int x, int dir)
feat = c_ptr->feat;
/* We may continue tunelling */
- msg_print(f_text + f_info[feat].tunnel);
+ msg_print(f_info[feat].tunnel);
more = TRUE;
-
- /* Occasional Search XXX XXX */
- if (rand_int(100) < 25) search();
}
}
@@ -1681,7 +1592,7 @@ bool_ do_cmd_tunnel_aux(int y, int x, int dir)
else
{
/* We may continue tunelling */
- msg_print(f_text + f_ptr->tunnel);
+ msg_print(f_ptr->tunnel);
more = TRUE;
}
}
@@ -1720,7 +1631,7 @@ bool_ do_cmd_tunnel_aux(int y, int x, int dir)
* Digging is very difficult without a "digger" weapon, but can be
* accomplished by strong players using heavy weapons.
*/
-void do_cmd_tunnel(void)
+void do_cmd_tunnel()
{
int y, x, dir;
@@ -1738,7 +1649,7 @@ void do_cmd_tunnel(void)
command_rep = command_arg - 1;
/* Redraw the state */
- p_ptr->redraw |= (PR_STATE);
+ p_ptr->redraw |= (PR_FRAME);
/* Cancel the arg */
command_arg = 0;
@@ -1754,16 +1665,8 @@ void do_cmd_tunnel(void)
/* 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))
+ if (cave_floor_grid(c_ptr))
{
/* Message */
msg_print("You cannot tunnel through air.");
@@ -1791,423 +1694,9 @@ void do_cmd_tunnel(void)
}
/* Cancel repetition unless we can continue */
- if (!more) disturb(0, 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);
+ if (!more) disturb();
}
-
-/*
- * 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, 0);
-}
-
-
/*
* Perform the basic "bash" command
*
@@ -2219,16 +1708,18 @@ void do_cmd_disarm(void)
*/
static bool_ do_cmd_bash_aux(int y, int x, int dir)
{
+ auto const &r_info = game->edit_data.r_info;
+
int bash, temp;
cave_type *c_ptr;
bool_ more = FALSE;
- monster_race *r_ptr = &r_info[p_ptr->body_monster];
+ auto r_ptr = &r_info[p_ptr->body_monster];
- if ((p_ptr->body_monster != 0) && !(r_ptr->flags2 & RF2_BASH_DOOR))
+ if ((p_ptr->body_monster != 0) && !(r_ptr->flags & RF_BASH_DOOR))
{
msg_print("You cannot do that.");
@@ -2266,26 +1757,17 @@ static bool_ do_cmd_bash_aux(int y, int x, int dir)
/* 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);
+ move_player_aux(dir, options->always_pickup, 0);
/* Update some things */
p_ptr->update |= (PU_VIEW | PU_MON_LITE);
@@ -2309,7 +1791,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));
+ set_paralyzed(2 + rand_int(2));
}
/* Result */
@@ -2331,18 +1813,20 @@ static bool_ do_cmd_bash_aux(int y, int x, int dir)
*
* Creatures can also open or bash doors, see elsewhere.
*/
-void do_cmd_bash(void)
+void do_cmd_bash()
{
+ auto const &r_info = game->edit_data.r_info;
+
int y, x, dir;
cave_type *c_ptr;
bool_ more = FALSE;
- monster_race *r_ptr = &r_info[p_ptr->body_monster];
+ auto r_ptr = &r_info[p_ptr->body_monster];
- if ((p_ptr->body_monster != 0) && !(r_ptr->flags2 & RF2_BASH_DOOR))
+ if ((p_ptr->body_monster != 0) && !(r_ptr->flags & RF_BASH_DOOR))
{
msg_print("You cannot do that.");
@@ -2356,7 +1840,7 @@ void do_cmd_bash(void)
command_rep = command_arg - 1;
/* Redraw the state */
- p_ptr->redraw |= (PR_STATE);
+ p_ptr->redraw |= (PR_FRAME);
/* Cancel the arg */
command_arg = 0;
@@ -2413,7 +1897,7 @@ void do_cmd_bash(void)
}
/* Unless valid action taken, cancel bash */
- if (!more) disturb(0, 0);
+ if (!more) disturb();
}
@@ -2428,8 +1912,10 @@ void do_cmd_bash(void)
* This command must always take a turn, to prevent free detection
* of invisible monsters.
*/
-void do_cmd_alter(void)
+void do_cmd_alter()
{
+ auto const &f_info = game->edit_data.f_info;
+
int y, x, dir;
cave_type *c_ptr;
@@ -2444,7 +1930,7 @@ void do_cmd_alter(void)
command_rep = command_arg - 1;
/* Redraw the state */
- p_ptr->redraw |= (PR_STATE);
+ p_ptr->redraw |= (PR_FRAME);
/* Cancel the arg */
command_arg = 0;
@@ -2479,19 +1965,12 @@ void do_cmd_alter(void)
}
/* Tunnel through walls */
- else if (f_info[c_ptr->feat].flags1 & FF1_TUNNELABLE)
+ else if (f_info[c_ptr->feat].flags & FF_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
{
@@ -2501,7 +1980,7 @@ void do_cmd_alter(void)
}
/* Cancel repetition unless we can continue */
- if (!more) disturb(0, 0);
+ if (!more) disturb();
}
@@ -2545,7 +2024,7 @@ static bool_ get_spike(int *ip)
*
* This command may NOT be repeated
*/
-void do_cmd_spike(void)
+void do_cmd_spike()
{
int y, x, dir, item;
@@ -2612,8 +2091,10 @@ void do_cmd_spike(void)
}
-static void do_cmd_walk_jump(int pickup, bool_ disarm)
+static void do_cmd_walk_jump(int pickup)
{
+ auto const &wf_info = game->edit_data.wf_info;
+
int dir;
bool_ more = FALSE;
@@ -2626,7 +2107,7 @@ static void do_cmd_walk_jump(int pickup, bool_ disarm)
command_rep = command_arg - 1;
/* Redraw the state */
- p_ptr->redraw |= (PR_STATE);
+ p_ptr->redraw |= (PR_FRAME);
/* Cancel the arg */
command_arg = 0;
@@ -2639,7 +2120,7 @@ static void do_cmd_walk_jump(int pickup, bool_ disarm)
energy_use = 100;
/* Actually move the character */
- move_player(dir, pickup, disarm);
+ move_player(dir, pickup);
/* Allow more walking */
more = TRUE;
@@ -2649,8 +2130,9 @@ static void do_cmd_walk_jump(int pickup, bool_ disarm)
energy_use *= (p_ptr->wild_mode) ? ((MAX_HGT + MAX_WID) / 2) : 1;
/* Hack again -- Is there a special encounter ??? */
+ auto const &wilderness = game->wilderness;
if (p_ptr->wild_mode &&
- magik(wf_info[wild_map[p_ptr->py][p_ptr->px].feat].level - (p_ptr->lev * 2)))
+ magik(wf_info[wilderness(p_ptr->px, p_ptr->py).feat].level - (p_ptr->lev * 2)))
{
/* Go into large wilderness view */
p_ptr->wilderness_x = p_ptr->px;
@@ -2668,14 +2150,186 @@ static void do_cmd_walk_jump(int pickup, bool_ disarm)
}
/* Cancel repeat unless we may continue */
- if (!more) disturb(0, 0);
+ if (!more) disturb();
+}
+
+
+/*
+ * Try to ``walk'' using phase door.
+ */
+static 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_FRAME);
+
+ /* 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, options->always_pickup);
+ 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, options->always_pickup);
+ }
+
+ /* Walking semantics */
+ else
+ {
+ teleport_player_directed(10, dir);
+ }
+
+ /* Cancel repetition unless we can continue */
+ if (!more) disturb();
}
/*
* Support code for the "Walk" and "Jump" commands
*/
-void do_cmd_walk(int pickup, bool_ disarm)
+void do_cmd_walk(int pickup)
{
/* Move (usually pickup) */
@@ -2685,7 +2339,7 @@ void do_cmd_walk(int pickup, bool_ disarm)
}
else
{
- do_cmd_walk_jump(pickup, disarm);
+ do_cmd_walk_jump(pickup);
}
}
@@ -2718,7 +2372,7 @@ void do_cmd_run_run()
/*
* Start running.
*/
-void do_cmd_run(void)
+void do_cmd_run()
{
if (p_ptr->immovable)
{
@@ -2748,7 +2402,7 @@ void do_cmd_stay(int pickup)
command_rep = command_arg - 1;
/* Redraw the state */
- p_ptr->redraw |= (PR_STATE);
+ p_ptr->redraw |= (PR_FRAME);
/* Cancel the arg */
command_arg = 0;
@@ -2758,20 +2412,6 @@ void do_cmd_stay(int pickup)
/* 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);
@@ -2780,7 +2420,7 @@ void do_cmd_stay(int pickup)
if (c_ptr->feat == FEAT_SHOP)
{
/* Disturb */
- disturb(0, 0);
+ disturb();
/* Hack -- enter store */
command_new = '_';
@@ -2790,17 +2430,19 @@ void do_cmd_stay(int pickup)
/*
* Resting allows a player to safely restore his hp -RAK-
*/
-void do_cmd_rest(void)
+void do_cmd_rest()
{
+ auto const &f_info = game->edit_data.f_info;
+
/* 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();
+ flush_on_failure();
/* 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));
+ f_info[cave[p_ptr->py][p_ptr->px].feat].name));
/* Done */
return;
@@ -2810,7 +2452,7 @@ void do_cmd_rest(void)
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();
+ flush_on_failure();
/* Tell the player why */
msg_print("Resting is impossible while undead!");
@@ -2863,14 +2505,11 @@ void do_cmd_rest(void)
/* 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);
+ p_ptr->redraw |= (PR_FRAME);
/* Handle stuff */
handle_stuff();
@@ -3020,7 +2659,7 @@ int get_shooter_mult(object_type *o_ptr)
*
* Note that Bows of "Extra Shots" give an extra shot.
*/
-void do_cmd_fire(void)
+void do_cmd_fire()
{
int dir, item;
@@ -3052,9 +2691,7 @@ void do_cmd_fire(void)
char o_name[80];
- cptr q, s;
-
- int msec = delay_factor * delay_factor * delay_factor;
+ auto const msec = options->delay_factor_ms();
/* Get the "bow" (if any) */
@@ -3082,14 +2719,15 @@ void do_cmd_fire(void)
/* 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;
-
+ if (!get_item(&item,
+ "Your quiver is empty. Fire which item? ",
+ "You have nothing to fire.",
+ (USE_INVEN | USE_FLOOR),
+ object_filter::TVal(p_ptr->tval_ammo)))
+ {
+ return;
+ }
/* Access the item */
o_ptr = get_object(item);
@@ -3123,10 +2761,6 @@ void do_cmd_fire(void)
}
- /* Sound */
- sound(SOUND_SHOOT);
-
-
/* Describe the object */
object_desc(o_name, q_ptr, FALSE, 3);
@@ -3231,7 +2865,7 @@ void do_cmd_fire(void)
print_rel(missile_char, missile_attr, y, x);
move_cursor_relative(y, x);
Term_fresh();
- Term_xtra(TERM_XTRA_DELAY, msec);
+ sleep_for(milliseconds(msec));
lite_spot(y, x);
Term_fresh();
}
@@ -3240,7 +2874,7 @@ void do_cmd_fire(void)
else
{
/* Pause anyway, for consistancy */
- Term_xtra(TERM_XTRA_DELAY, msec);
+ sleep_for(milliseconds(msec));
}
@@ -3250,7 +2884,7 @@ void do_cmd_fire(void)
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);
+ auto const r_ptr = m_ptr->race();
/* Check the visibility */
visible = m_ptr->ml;
@@ -3267,9 +2901,9 @@ void do_cmd_fire(void)
cptr note_dies = " dies.";
/* Some monsters get "destroyed" */
- if ((r_ptr->flags3 & (RF3_DEMON)) ||
- (r_ptr->flags3 & (RF3_UNDEAD)) ||
- (r_ptr->flags2 & (RF2_STUPID)) ||
+ if ((r_ptr->flags & RF_DEMON) ||
+ (r_ptr->flags & RF_UNDEAD) ||
+ (r_ptr->flags & RF_STUPID) ||
(strchr("Evg", r_ptr->d_char)))
{
/* Special note at death */
@@ -3357,9 +2991,6 @@ void do_cmd_fire(void)
{
char m_name[80];
- /* Sound */
- sound(SOUND_FLEE);
-
/* Get the monster name (or "it") */
monster_desc(m_name, m_ptr, 0);
@@ -3459,9 +3090,11 @@ void do_cmd_fire(void)
* 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)
+void do_cmd_throw()
{
- int dir, item;
+ auto const &k_info = game->edit_data.k_info;
+
+ int dir;
s32b special = 0;
@@ -3480,8 +3113,6 @@ void do_cmd_throw(void)
object_type *q_ptr;
- object_type *o_ptr;
-
bool_ hit_body = FALSE;
bool_ hit_wall = FALSE;
@@ -3492,26 +3123,25 @@ void do_cmd_throw(void)
char o_name[80];
- int msec = delay_factor * delay_factor * delay_factor;
-
- cptr q, s;
-
- u32b f1, f2, f3, f4, f5, esp;
-
+ auto const msec = options->delay_factor_ms();
/* Get an item */
- q = "Throw which item? ";
- s = "You have nothing to throw.";
- if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return;
+ int item;
+ if (!get_item(&item,
+ "Throw which item? ",
+ "You have nothing to throw.",
+ (USE_INVEN | USE_FLOOR)))
+ {
+ return;
+ }
/* Access the item */
- o_ptr = get_object(item);
+ object_type *o_ptr = get_object(item);
-
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ auto const flags = object_flags(o_ptr);
/* Hack - Cannot throw away 'no drop' cursed items */
- if (cursed_p(o_ptr) && (f4 & TR4_CURSE_NO_DROP))
+ if (cursed_p(o_ptr) && (flags & TR_CURSE_NO_DROP))
{
/* Oops */
msg_print("Hmmm, you seem to be unable to throw it.");
@@ -3647,7 +3277,7 @@ void do_cmd_throw(void)
print_rel(missile_char, missile_attr, y, x);
move_cursor_relative(y, x);
Term_fresh();
- Term_xtra(TERM_XTRA_DELAY, msec);
+ sleep_for(milliseconds(msec));
lite_spot(y, x);
Term_fresh();
}
@@ -3656,7 +3286,7 @@ void do_cmd_throw(void)
else
{
/* Pause anyway, for consistancy */
- Term_xtra(TERM_XTRA_DELAY, msec);
+ sleep_for(milliseconds(msec));
}
@@ -3666,7 +3296,7 @@ void do_cmd_throw(void)
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);
+ auto r_ptr = m_ptr->race();
/* Check the visibility */
visible = m_ptr->ml;
@@ -3683,9 +3313,9 @@ void do_cmd_throw(void)
cptr note_dies = " dies.";
/* Some monsters get "destroyed" */
- if ((r_ptr->flags3 & (RF3_DEMON)) ||
- (r_ptr->flags3 & (RF3_UNDEAD)) ||
- (r_ptr->flags2 & (RF2_STUPID)) ||
+ if ((r_ptr->flags & RF_DEMON) ||
+ (r_ptr->flags & RF_UNDEAD) ||
+ (r_ptr->flags & RF_STUPID) ||
(strchr("Evg", r_ptr->d_char)))
{
/* Special note at death */
@@ -3769,9 +3399,6 @@ void do_cmd_throw(void)
{
char m_name[80];
- /* Sound */
- sound(SOUND_FLEE);
-
/* Get the monster name (or "it") */
monster_desc(m_name, m_ptr, 0);
@@ -3839,8 +3466,10 @@ void do_cmd_throw(void)
* 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)
+void do_cmd_boomerang()
{
+ auto const &k_info = game->edit_data.k_info;
+
int dir;
int j, y, x, ny, nx, ty, tx;
@@ -3867,7 +3496,7 @@ void do_cmd_boomerang(void)
s32b special = 0;
- int msec = delay_factor * delay_factor * delay_factor;
+ auto const msec = options->delay_factor_ms();
/* Get the "bow" (if any) */
@@ -3974,7 +3603,7 @@ void do_cmd_boomerang(void)
print_rel(missile_char, missile_attr, y, x);
move_cursor_relative(y, x);
Term_fresh();
- Term_xtra(TERM_XTRA_DELAY, msec);
+ sleep_for(milliseconds(msec));
lite_spot(y, x);
Term_fresh();
}
@@ -3983,7 +3612,7 @@ void do_cmd_boomerang(void)
else
{
/* Pause anyway, for consistancy */
- Term_xtra(TERM_XTRA_DELAY, msec);
+ sleep_for(milliseconds(msec));
}
@@ -3993,7 +3622,7 @@ void do_cmd_boomerang(void)
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);
+ auto const r_ptr = m_ptr->race();
/* Check the visibility */
visible = m_ptr->ml;
@@ -4010,9 +3639,9 @@ void do_cmd_boomerang(void)
cptr note_dies = " dies.";
/* Some monsters get "destroyed" */
- if ((r_ptr->flags3 & (RF3_DEMON)) ||
- (r_ptr->flags3 & (RF3_UNDEAD)) ||
- (r_ptr->flags2 & (RF2_STUPID)) ||
+ if ((r_ptr->flags & RF_DEMON) ||
+ (r_ptr->flags & RF_UNDEAD) ||
+ (r_ptr->flags & RF_STUPID) ||
(strchr("Evg", r_ptr->d_char)))
{
/* Special note at death */
@@ -4096,9 +3725,6 @@ void do_cmd_boomerang(void)
{
char m_name[80];
- /* Sound */
- sound(SOUND_FLEE);
-
/* Get the monster name (or "it") */
monster_desc(m_name, m_ptr, 0);
@@ -4111,8 +3737,7 @@ void do_cmd_boomerang(void)
j = (hit_body ? breakage_chance(o_ptr) : 0);
/* Break the boomerang */
- if (!(o_ptr->art_name || artifact_p(o_ptr)) &&
- (rand_int(100) < j))
+ if ((!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);
@@ -4150,7 +3775,7 @@ void do_cmd_boomerang(void)
print_rel(missile_char, missile_attr, y, x);
move_cursor_relative(y, x);
Term_fresh();
- Term_xtra(TERM_XTRA_DELAY, msec);
+ sleep_for(milliseconds(msec));
lite_spot(y, x);
Term_fresh();
}
@@ -4159,194 +3784,24 @@ void do_cmd_boomerang(void)
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;
+ sleep_for(milliseconds(msec));
}
}
-
- /* 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, 0);
}
static bool_ tport_vertically(bool_ how)
{
- /* arena or quest -KMW- */
- if ((p_ptr->inside_arena) || (p_ptr->inside_quest))
+ auto const &d_info = game->edit_data.d_info;
+
+ /* quest? */
+ if (p_ptr->inside_quest)
{
msg_print("There is no effect.");
return (FALSE);
}
- if (dungeon_flags2 & DF2_NO_EASY_MOVE)
+ if (dungeon_flags & DF_NO_EASY_MOVE)
{
msg_print("Some powerful force prevents you from teleporting.");
return FALSE;
@@ -4386,7 +3841,7 @@ static bool_ tport_vertically(bool_ how)
* Do a special ``movement'' action. Meant to be used for ``immovable''
* characters.
*/
-void do_cmd_immovable_special(void)
+void do_cmd_immovable_special()
{
int i, ii, ij, dir;
@@ -4447,8 +3902,8 @@ void do_cmd_immovable_special(void)
/* 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);
+ prt("(c) Go up one level", 6, 5);
+ prt("(d) Go down one level", 7, 5);
/* Prompt */
prt("Command: ", 9, 0);
@@ -4484,7 +3939,7 @@ void do_cmd_immovable_special(void)
if (!get_aim_dir(&dir)) return;
fetch(dir, p_ptr->lev * 15, FALSE);
- py_pickup_floor(always_pickup);
+ py_pickup_floor(options->always_pickup);
did_act = TRUE;
break;
@@ -4542,13 +3997,13 @@ void do_cmd_immovable_special(void)
if (lose_sp)
{
p_ptr->csp -= lose_sp;
- p_ptr->redraw |= (PR_MANA);
+ p_ptr->redraw |= (PR_FRAME);
}
if (lose_hp)
{
p_ptr->chp -= lose_hp;
- p_ptr->redraw |= (PR_HP);
+ p_ptr->redraw |= (PR_FRAME);
}
energy_use = 100;
@@ -4556,17 +4011,19 @@ void do_cmd_immovable_special(void)
}
/* Can we sacrifice it ? */
-static bool_ item_tester_hook_sacrifiable(object_type *o_ptr)
+static bool item_tester_hook_sacrificable(object_type const *o_ptr)
{
- GOD(GOD_MELKOR)
+ if (p_ptr->pgod == 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) && (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 */
@@ -4574,17 +4031,56 @@ static bool_ item_tester_hook_sacrifiable(object_type *o_ptr)
}
/*
+ * Is item eligible for sacrifice to Aule?
+ */
+static bool item_tester_hook_sacrifice_aule(object_type const *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;
+
+ if (!get_item(&item,
+ "Sacrifice which item? ",
+ "You have nothing to sacrifice.",
+ USE_INVEN,
+ item_tester_hook_sacrifice_aule))
+ {
+ 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)
+void do_cmd_sacrifice()
{
+ auto const &r_info = game->edit_data.r_info;
+
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);
+ show_god_info();
return;
}
else
@@ -4592,7 +4088,7 @@ void do_cmd_sacrifice(void)
int agod = on_what - FEAT_ALTAR_HEAD + 1;
/* Not worshipping a god ? ahhhh! */
- GOD(GOD_NONE)
+ if (p_ptr->pgod == GOD_NONE)
{
int i;
@@ -4610,7 +4106,7 @@ void do_cmd_sacrifice(void)
}
else if (p_ptr->pgod == agod)
{
- GOD(GOD_MELKOR)
+ if (p_ptr->pgod == 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? "))
@@ -4638,15 +4134,18 @@ void do_cmd_sacrifice(void)
}
else
{
+ /* Get an item */
int item;
- object_type *o_ptr;
-
- /* Restrict choices to food */
- item_tester_hook = item_tester_hook_sacrifiable;
+ if (!get_item(&item,
+ "Sacrifice which item? ",
+ "You have nothing to sacrifice.",
+ (USE_INVEN),
+ item_tester_hook_sacrificable))
+ {
+ return;
+ }
- /* Get an item */
- if (!get_item(&item, "Sacrifice which item? ", "You have nothing to sacrifice.", (USE_INVEN))) return;
- o_ptr = get_object(item);
+ object_type *o_ptr = get_object(item);
/* Piety for corpses is based on monster level */
if (o_ptr->tval == TV_CORPSE)
@@ -4657,7 +4156,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);
}
@@ -4666,10 +4165,12 @@ void do_cmd_sacrifice(void)
inc_stack_size(item, -1);
}
}
- else
+
+ if (p_ptr->pgod == GOD_AULE)
{
- process_hooks(HOOK_SACRIFICE_GOD, "()", "");
+ do_cmd_sacrifice_aule();
}
+
}
}
}
@@ -4680,148 +4181,114 @@ void do_cmd_sacrifice(void)
*
* Return a list of o_list[] indexes of items of the given monster
*/
-bool_ scan_monst(int *items, int *item_num, int m_idx)
+std::vector<s16b> scan_monst(int m_idx)
{
- int this_o_idx, next_o_idx;
-
- int num = 0;
-
+ constexpr std::size_t max_size = 23;
- (*item_num) = 0;
+ /* Create output vector. */
+ std::vector<s16b> objects;
+ objects.reserve(std::min(max_size, m_list[m_idx].hold_o_idxs.size()));
/* 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)
+ for (auto const this_o_idx: m_list[m_idx].hold_o_idxs)
{
- 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;
+ objects.push_back(this_o_idx);
+ if (objects.size() == max_size) break;
}
- /* Number of items */
- (*item_num) = num;
-
/* Result */
- return (num != 0);
+ return objects;
}
/*
* Display a list of the items that the given monster carries.
+ * Returns the list of objects.
*/
-byte show_monster_inven(int m_idx, int *monst_list)
+std::vector<s16b> show_monster_inven(int m_idx)
{
- 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;
+ int len = 79 - 50;
/* Maximum space allowed for descriptions */
- lim = 79 - 3;
+ int 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);
+ std::vector<s16b> objects = scan_monst(m_idx);
+ assert(objects.size() <= 23);
- /* Display the p_ptr->inventory */
- for (k = 0, i = 0; i < monst_num; i++)
+ /* Calculate width of object names */
+ for (std::size_t i = 0; i < objects.size(); i++)
{
- o_ptr = &o_list[monst_list[i]];
+ object_type *o_ptr = &o_list[objects.at(i)];
/* Describe the object */
+ char o_name[80];
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];
+ out_color[i] = tval_to_attr[o_ptr->tval & 0x7F];
/* Save the object description */
- strcpy(out_desc[k], o_name);
+ strcpy(out_desc[i], o_name);
/* Find the predicted "line length" */
- l = strlen(out_desc[k]) + 5;
+ int l = strlen(out_desc[i]) + 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;
-
- /* Advance to next "line" */
- k++;
}
/* Find the column to start in */
- col = (len > 76) ? 0 : (79 - len);
+ int col = (len > 76) ? 0 : (79 - len);
/* Output each entry */
- for (j = 0; j < k; j++)
+ std::size_t i = 0;
+ for (i = 0; i < objects.size(); i++)
{
- /* Get the index */
- i = monst_list[out_index[j]];
-
/* Get the item */
- o_ptr = &o_list[i];
+ object_type *o_ptr = &o_list[objects.at(i)];
/* Clear the line */
- prt("", j + 1, col ? col - 2 : col);
+ prt("", i + 1, col ? col - 2 : col);
/* Prepare an index --(-- */
- strnfmt(tmp_val, 80, "%c)", index_to_label(j));
+ char tmp_val[80];
+ strnfmt(tmp_val, 80, "%c)", index_to_label(i));
/* Clear the line with the (possibly indented) index */
- put_str(tmp_val, j + 1, col);
+ put_str(tmp_val, i + 1, col);
/* Display the entry itself */
- c_put_str(out_color[j], out_desc[j], j + 1, col + 3);
+ c_put_str(out_color[i], out_desc[i], i + 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);
- put_str(tmp_val, j + 1, 71);
+ put_str(tmp_val, i + 1, 71);
}
}
/* Make a "shadow" below the list (only if needed) */
- if (j && (j < 23)) prt("", j + 1, col ? col - 2 : col);
+ if (i && (i < 23))
+ {
+ prt("", i + 1, col ? col - 2 : col);
+ }
- return monst_num;
+ return objects;
}
@@ -4830,26 +4297,18 @@ byte show_monster_inven(int m_idx, int *monst_list)
*/
void do_cmd_steal()
{
- int x, y, dir = 0, item = -1, k = -1;
-
- cave_type *c_ptr;
-
- monster_type *m_ptr;
+ auto const &r_info = game->edit_data.r_info;
- object_type *o_ptr, forge;
-
- byte num = 0;
+ int dir = 0, item = -1, k = -1;
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];
+ int y = p_ptr->py + ddy[dir];
+ int x = p_ptr->px + ddx[dir];
+
+ cave_type const *c_ptr = &cave[y][x];
if (!(c_ptr->m_idx))
{
@@ -4857,17 +4316,17 @@ void do_cmd_steal()
return;
}
- m_ptr = &m_list[c_ptr->m_idx];
+ monster_type *m_ptr = &m_list[c_ptr->m_idx];
/* There were no non-gold items */
- if (!m_ptr->hold_o_idx)
+ if (m_ptr->hold_o_idxs.empty())
{
msg_print("That monster has no objects!");
return;
}
/* The monster is immune */
- if (r_info[m_ptr->r_idx].flags7 & (RF7_NO_THEFT))
+ if (r_info[m_ptr->r_idx].flags & RF_NO_THEFT)
{
msg_print("The monster is guarding the treasures.");
return;
@@ -4875,7 +4334,7 @@ void do_cmd_steal()
screen_save();
- num = show_monster_inven(c_ptr->m_idx, monst_list);
+ std::vector<s16b> objects = show_monster_inven(c_ptr->m_idx);
/* Repeat until done */
while (!done)
@@ -4885,7 +4344,7 @@ void do_cmd_steal()
/* Build the prompt */
strnfmt(tmp_val, 80, "Choose an item to steal (a-%c) or ESC:",
- 'a' - 1 + num);
+ 'a' - 1 + objects.size());
/* Show the prompt */
prt(tmp_val, 0, 0);
@@ -4912,7 +4371,7 @@ void do_cmd_steal()
which = tolower(which);
k = islower(which) ? A2I(which) : -1;
- if (k < 0 || k >= num)
+ if ((k < 0) || (static_cast<std::size_t>(k) >= objects.size()))
{
bell();
@@ -4920,7 +4379,7 @@ void do_cmd_steal()
}
/* Verify the item */
- if (ver && !verify("Try", 0 - monst_list[k]))
+ if (ver && !verify("Try", -objects[k]))
{
done = TRUE;
@@ -4928,7 +4387,7 @@ void do_cmd_steal()
}
/* Accept that choice */
- item = monst_list[k];
+ item = objects[k];
done = TRUE;
break;
@@ -4966,17 +4425,11 @@ void do_cmd_steal()
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];
- }
+ /* Remove from the monster's list of objects */
+ m_ptr->hold_o_idxs.erase(m_ptr->hold_o_idxs.begin() + k);
/* Rogues gain some xp */
- if (PRACE_FLAGS(PR1_EASE_STEAL))
+ if (race_flags_p(PR_EASE_STEAL))
{
s32b max_point;
@@ -4990,8 +4443,9 @@ void do_cmd_steal()
if (get_check("Phase door?")) teleport_player(10);
}
- /* Get the item */
- o_ptr = &forge;
+ /* Create the object we're going to copy into */
+ object_type forge;
+ object_type *o_ptr = &forge;
/* Special handling for gold */
if (o_list[item].tval == TV_GOLD)
@@ -5000,7 +4454,7 @@ void do_cmd_steal()
p_ptr->au += o_list[item].pval;
/* Redraw gold */
- p_ptr->redraw |= (PR_GOLD);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
@@ -5012,7 +4466,7 @@ void do_cmd_steal()
inven_carry(o_ptr, FALSE);
}
- /* Delete it */
+ /* Delete source item */
o_list[item].k_idx = 0;
}
@@ -5028,24 +4482,16 @@ void do_cmd_steal()
*/
void do_cmd_give()
{
- int dir, x, y;
-
- cave_type *c_ptr;
-
- cptr q, s;
-
- int item;
-
-
/* Get a "repeated" direction */
+ int dir;
if (!get_rep_dir(&dir)) return;
/* Get requested location */
- y = p_ptr->py + ddy[dir];
- x = p_ptr->px + ddx[dir];
+ int y = p_ptr->py + ddy[dir];
+ int x = p_ptr->px + ddx[dir];
/* Get requested grid */
- c_ptr = &cave[y][x];
+ cave_type *c_ptr = &cave[y][x];
/* No monster in the way */
if (c_ptr->m_idx == 0)
@@ -5055,12 +4501,18 @@ void do_cmd_give()
}
/* 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;
+ int item;
+ if (!get_item(&item,
+ "What item do you want to offer? ",
+ "You have nothing to offer.",
+ 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.");
}
@@ -5098,7 +4550,8 @@ void do_cmd_chat()
}
/* Process hook if there are any */
- if (!process_hooks(HOOK_CHAT, "(d)", c_ptr->m_idx))
+ struct hook_chat_in in = { c_ptr->m_idx };
+ if (!process_hooks_new(HOOK_CHAT, &in, NULL))
{
msg_print("The monster does not want to chat.");
}
diff --git a/src/cmd2.hpp b/src/cmd2.hpp
new file mode 100644
index 00000000..9641dc72
--- /dev/null
+++ b/src/cmd2.hpp
@@ -0,0 +1,32 @@
+#pragma once
+
+#include "h-basic.h"
+#include "object_type_fwd.hpp"
+#include <vector>
+
+std::vector<s16b> show_monster_inven(int m_idx);
+int breakage_chance(object_type *o_ptr);
+void do_cmd_go_up();
+void do_cmd_go_down();
+void do_cmd_search();
+void do_cmd_toggle_search();
+void do_cmd_open();
+void do_cmd_close();
+void do_cmd_chat();
+void do_cmd_give();
+void do_cmd_tunnel();
+void do_cmd_bash();
+void do_cmd_alter();
+void do_cmd_spike();
+void do_cmd_walk(int pickup);
+void do_cmd_stay(int pickup);
+void do_cmd_run();
+void do_cmd_rest();
+int get_shooter_mult(object_type *o_ptr);
+void do_cmd_fire();
+void do_cmd_throw();
+void do_cmd_boomerang();
+void do_cmd_immovable_special();
+void fetch(int dir, int wgt, bool_ require_los);
+void do_cmd_sacrifice();
+void do_cmd_steal();
diff --git a/src/cmd3.c b/src/cmd3.cc
index 02dbc1c4..cbf58820 100644
--- a/src/cmd3.c
+++ b/src/cmd3.cc
@@ -1,7 +1,3 @@
-/* File: cmd3.c */
-
-/* Purpose: Inventory commands */
-
/*
* Copyright (c) 1989 James E. Wilson, Robert A. Koeneke
*
@@ -9,14 +5,51 @@
* not for profit purposes provided that this copyright and statement are
* included in all such copies.
*/
-
-#include "angband.h"
-
+#include "cmd3.hpp"
+
+#include "artifact_type.hpp"
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "cli_comm.hpp"
+#include "files.hpp"
+#include "game.hpp"
+#include "gods.hpp"
+#include "hook_drop_in.hpp"
+#include "hook_wield_in.hpp"
+#include "hooks.hpp"
+#include "monster1.hpp"
+#include "monster_race.hpp"
+#include "monster_race_flag.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_flag.hpp"
+#include "object_kind.hpp"
+#include "object_type.hpp"
+#include "options.hpp"
+#include "player_type.hpp"
+#include "squeltch.hpp"
+#include "store.hpp"
+#include "store_type.hpp"
+#include "tables.hpp"
+#include "town_type.hpp"
+#include "util.hpp"
+#include "util.h"
+#include "variable.h"
+#include "variable.hpp"
+#include "xtra1.hpp"
+#include "xtra2.hpp"
+#include "z-rand.hpp"
+
+#include <cassert>
+#include <algorithm>
+#include <fmt/format.h>
+#include <memory>
+#include <utility>
/*
* Display p_ptr->inventory
*/
-void do_cmd_inven(void)
+void do_cmd_inven()
{
char out_val[160];
@@ -28,16 +61,10 @@ void do_cmd_inven(void)
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;
-
+ /* Show the inventory */
+ show_inven_full();
+ /* Show prompt */
{
s32b total_weight = calc_total_weight();
@@ -77,7 +104,7 @@ void do_cmd_inven(void)
/*
* Display equipment
*/
-void do_cmd_equip(void)
+void do_cmd_equip()
{
char out_val[160];
@@ -89,16 +116,10 @@ void do_cmd_equip(void)
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;
+ show_equip_full();
- /* Build a prompt */
+ /* Show prompt */
{
s32b total_weight = calc_total_weight();
@@ -139,30 +160,20 @@ void do_cmd_equip(void)
/*
* The "wearable" tester
*/
-static bool_ item_tester_hook_wear(object_type *o_ptr)
+static bool item_tester_hook_wear(object_type const *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)
+ if (object_flags(o_ptr) & TR_ULTIMATE)
{
- int i;
-
- for (i = INVEN_WIELD; i < INVEN_TOTAL; i++)
+ for (int 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 (object_flags(q_ptr) & TR_ULTIMATE) return (FALSE);
}
}
@@ -193,35 +204,34 @@ bool_ is_slot_ok(int slot)
/*
* Wield or wear a single item from the pack or floor
*/
-void do_cmd_wield(void)
+void do_cmd_wield()
{
+ auto const &a_info = game->edit_data.a_info;
+
int item, slot, num = 1;
object_type forge;
object_type *q_ptr;
- object_type *o_ptr, *i_ptr;
+ object_type *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;
+ if (!get_item(&item,
+ "Wear/Wield which item? ",
+ "You have nothing you can wear or wield.",
+ (USE_INVEN | USE_FLOOR),
+ item_tester_hook_wear))
+ {
+ return;
+ }
/* Get the item */
- o_ptr = get_object(item);
+ object_type *o_ptr = get_object(item);
/* Check the slot */
slot = wield_slot(o_ptr);
@@ -240,7 +250,7 @@ void do_cmd_wield(void)
return;
}
- if ((cursed_p(o_ptr)) && (wear_confirm)
+ if ((cursed_p(o_ptr)) && (options->wear_confirm)
&& (object_known_p(o_ptr) || (o_ptr->ident & (IDENT_SENSE))))
{
char dummy[512];
@@ -254,14 +264,20 @@ void do_cmd_wield(void)
}
/* Can we wield */
- if (process_hooks(HOOK_WIELD, "(d)", item)) return;
+ {
+ struct hook_wield_in in = { o_ptr };
+ if (process_hooks_new(HOOK_WIELD, &in, NULL))
+ {
+ return;
+ }
+ }
/* Extract the flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ auto const flags = object_flags(o_ptr);
/* Two handed weapons can't be wielded with a shield */
if ((is_slot_ok(slot - INVEN_WIELD + INVEN_ARM)) &&
- (f4 & TR4_MUST2H) &&
+ (flags & TR_MUST2H) &&
(p_ptr->inventory[slot - INVEN_WIELD + INVEN_ARM].k_idx != 0))
{
object_desc(o_name, o_ptr, FALSE, 0);
@@ -274,10 +290,10 @@ void do_cmd_wield(void)
i_ptr = &p_ptr->inventory[slot - INVEN_ARM + INVEN_WIELD];
/* Extract the flags */
- object_flags(i_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ auto const i_flags = object_flags(i_ptr);
/* Prevent shield from being put on if wielding 2H */
- if ((f4 & TR4_MUST2H) && (i_ptr->k_idx) &&
+ if ((i_flags & TR_MUST2H) && (i_ptr->k_idx) &&
(p_ptr->body_parts[slot - INVEN_WIELD] == INVEN_ARM))
{
object_desc(o_name, o_ptr, FALSE, 0);
@@ -286,7 +302,7 @@ void do_cmd_wield(void)
}
if ((p_ptr->body_parts[slot - INVEN_WIELD] == INVEN_ARM) &&
- (f4 & TR4_COULD2H))
+ (i_flags & TR_COULD2H))
{
if (!get_check("Are you sure you want to restrict your fighting? "))
{
@@ -295,13 +311,9 @@ void do_cmd_wield(void)
}
}
-
- /* 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))
+ (flags & TR_COULD2H))
{
if (!get_check("Are you sure you want to use this weapon with a shield?"))
{
@@ -309,19 +321,6 @@ void do_cmd_wield(void)
}
}
- /* 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;
@@ -348,7 +347,7 @@ void do_cmd_wield(void)
if (o_ptr->k_idx)
{
/* Take off existing item */
- (void)inven_takeoff(slot, 255, FALSE);
+ inven_takeoff(slot, 255, FALSE);
}
}
else
@@ -358,7 +357,7 @@ void do_cmd_wield(void)
if (!object_similar(o_ptr, q_ptr))
{
/* Take off existing item */
- (void)inven_takeoff(slot, 255, FALSE);
+ inven_takeoff(slot, 255, FALSE);
}
else
{
@@ -440,7 +439,7 @@ void do_cmd_wield(void)
p_ptr->update |= (PU_MANA | PU_SPELLS);
/* Redraw monster hitpoint */
- p_ptr->redraw |= (PR_MH);
+ p_ptr->redraw |= (PR_FRAME);
p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
}
@@ -450,25 +449,20 @@ void do_cmd_wield(void)
/*
* Take off an item
*/
-void do_cmd_takeoff(void)
+void do_cmd_takeoff()
{
- 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;
+ int item;
+ if (!get_item(&item,
+ "Take off which item? ",
+ "You are not wearing anything to take off.",
+ (USE_EQUIP)))
+ {
+ return;
+ }
/* Get the item */
- o_ptr = get_object(item);
-
- /* Can we take it off */
- if (process_hooks(HOOK_TAKEOFF, "(d)", item)) return;
+ object_type *o_ptr = get_object(item);
/* Item is cursed */
if (cursed_p(o_ptr) && (!wizard))
@@ -485,41 +479,37 @@ void do_cmd_takeoff(void)
energy_use = 50;
/* Take off the item */
- (void)inven_takeoff(item, 255, FALSE);
+ inven_takeoff(item, 255, FALSE);
/* Recalculate hitpoint */
p_ptr->update |= (PU_HP);
- p_ptr->redraw |= (PR_MH);
+ p_ptr->redraw |= (PR_FRAME);
}
/*
* Drop an item
*/
-void do_cmd_drop(void)
+void do_cmd_drop()
{
- 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;
+ int item;
+ if (!get_item(&item,
+ "Drop which item? ",
+ "You have nothing to drop.",
+ (USE_EQUIP | USE_INVEN)))
+ {
+ return;
+ }
/* Get the item */
- o_ptr = get_object(item);
-
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ object_type *o_ptr = get_object(item);
+ auto const flags = object_flags(o_ptr);
/* Can we drop */
- if (process_hooks(HOOK_DROP, "(d)", item)) return;
+ struct hook_drop_in in = { item };
+ if (process_hooks_new(HOOK_DROP, &in, NULL)) return;
/* Hack -- Cannot remove cursed items */
if (cursed_p(o_ptr))
@@ -534,7 +524,7 @@ void do_cmd_drop(void)
}
else
{
- if (f4 & TR4_CURSE_NO_DROP)
+ if (flags & TR_CURSE_NO_DROP)
{
/* Oops */
msg_print("Hmmm, you seem to be unable to drop it.");
@@ -545,8 +535,8 @@ void do_cmd_drop(void)
}
}
-
/* See how many items */
+ int amt = 1;
if (o_ptr->number > 1)
{
/* Get a quantity */
@@ -567,39 +557,37 @@ void do_cmd_drop(void)
/*
* Destroy an item
*/
-void do_cmd_destroy(void)
+void do_cmd_destroy()
{
- int item, amt = 1;
+ auto const &k_info = game->edit_data.k_info;
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;
+ int item;
+ if (!get_item(&item,
+ "Destroy which item? ",
+ "You have nothing to destroy.",
+ (USE_INVEN | USE_FLOOR | USE_AUTO)))
+ {
+ return;
+ }
/* Get the item */
- o_ptr = get_object(item);
-
+ object_type *o_ptr = get_object(item);
/* See how many items */
+ int amt = 1;
if (o_ptr->number > 1)
{
/* Get a quantity */
@@ -619,20 +607,16 @@ void do_cmd_destroy(void)
/* 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;
- }
+ /* 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))
+ auto const flags = object_flags(o_ptr);
+ if ((flags & TR_CURSE_NO_DROP) && cursed_p(o_ptr))
{
/* Oops */
msg_print("Hmmm, you seem to be unable to destroy it.");
@@ -643,7 +627,7 @@ void do_cmd_destroy(void)
/* Artifacts cannot be destroyed */
- if (artifact_p(o_ptr) || o_ptr->art_name)
+ if (artifact_p(o_ptr))
{
byte feel = SENSE_SPECIAL;
@@ -673,12 +657,11 @@ void do_cmd_destroy(void)
/* Message */
msg_format("You destroy %s.", o_name);
- sound(SOUND_DESTITEM);
/* Create an automatizer rule */
if (automatizer_create)
{
- automatizer_add_rule(o_ptr, TRUE);
+ automatizer_add_rule(o_ptr);
}
/*
@@ -692,8 +675,10 @@ void do_cmd_destroy(void)
}
/* Eru wont be happy */
- if (f3 & TR3_BLESSED)
+ if (flags & TR_BLESSED)
+ {
inc_piety(GOD_ERU, -10 * k_info[o_ptr->k_idx].level);
+ }
/* Eliminate the item */
inc_stack_size(item, -amt);
@@ -703,26 +688,23 @@ void do_cmd_destroy(void)
/*
* Observe an item which has been *identify*-ed
*/
-void do_cmd_observe(void)
+void do_cmd_observe()
{
- 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;
+ int item;
+ if (!get_item(&item,
+ "Examine which item? ",
+ "You have nothing to examine.",
+ (USE_EQUIP | USE_INVEN | USE_FLOOR)))
+ {
+ return;
+ }
/* Get the item */
- o_ptr = get_object(item);
+ object_type *o_ptr = get_object(item);
/* Description */
+ char o_name[80];
object_desc(o_name, o_ptr, TRUE, 3);
/* Describe */
@@ -738,25 +720,23 @@ void do_cmd_observe(void)
* Remove the inscription from an object
* XXX Mention item (when done)?
*/
-void do_cmd_uninscribe(void)
+void do_cmd_uninscribe()
{
- 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;
+ int item;
+ if (!get_item(&item,
+ "Un-inscribe which item? ",
+ "You have nothing to un-inscribe.",
+ (USE_EQUIP | USE_INVEN | USE_FLOOR)))
+ {
+ return;
+ }
/* Get the item */
- o_ptr = get_object(item);
+ object_type *o_ptr = get_object(item);
/* Nothing to remove */
- if (!o_ptr->note)
+ if (o_ptr->inscription.empty())
{
msg_print("That item had no inscription to remove.");
return;
@@ -766,7 +746,7 @@ void do_cmd_uninscribe(void)
msg_print("Inscription removed.");
/* Remove the incription */
- o_ptr->note = 0;
+ o_ptr->inscription.clear();
/* Combine the pack */
p_ptr->notice |= (PN_COMBINE);
@@ -779,49 +759,38 @@ void do_cmd_uninscribe(void)
/*
* Inscribe an object with a comment
*/
-void do_cmd_inscribe(void)
+void do_cmd_inscribe()
{
- 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;
+ int item;
+ if (!get_item(&item,
+ "Inscribe which item? ",
+ "You have nothing to inscribe.",
+ (USE_EQUIP | USE_INVEN | USE_FLOOR)))
+ {
+ return;
+ }
/* Get the item */
- o_ptr = get_object(item);
+ object_type *o_ptr = get_object(item);
/* Describe the activity */
+ char o_name[80];
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));
- }
+ /* Start with old inscription */
+ char out_val[80];
+ strcpy(out_val, o_ptr->inscription.c_str());
/* Get a new inscription (possibly empty) */
- if (get_string("Inscription: ", out_val, 80))
+ if (get_string("Inscription: ", out_val, sizeof(out_val)))
{
/* Save the inscription */
- o_ptr->note = quark_add(out_val);
+ o_ptr->inscription = out_val;
/* Combine the pack */
p_ptr->notice |= (PN_COMBINE);
@@ -836,49 +805,42 @@ void do_cmd_inscribe(void)
/*
* An "item_tester_hook" for refilling lanterns
*/
-static bool_ item_tester_refill_lantern(object_type *o_ptr)
+static object_filter_t const &item_tester_refill_lantern()
{
- /* 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);
+ using namespace object_filter;
+ static auto instance = Or(
+ TVal(TV_FLASK),
+ And(
+ TVal(TV_LITE),
+ SVal(SV_LITE_LANTERN)));
+ return instance;
}
/*
* Refill the players lamp (from the pack or floor)
*/
-static void do_cmd_refill_lamp(void)
+static void do_cmd_refill_lamp()
{
- 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;
+ int item;
+ if (!get_item(&item,
+ "Refill with which flask? ",
+ "You have no flasks of oil.",
+ (USE_INVEN | USE_FLOOR),
+ item_tester_refill_lantern()))
+ {
+ return;
+ }
/* Get the item */
- o_ptr = get_object(item);
+ object_type *o_ptr = get_object(item);
/* Take a partial turn */
energy_use = 50;
/* Access the lantern */
- j_ptr = &p_ptr->inventory[INVEN_LITE];
+ object_type *j_ptr = &p_ptr->inventory[INVEN_LITE];
/* Refuel */
if (o_ptr->tval == TV_FLASK)
@@ -907,47 +869,41 @@ static void do_cmd_refill_lamp(void)
/*
* An "item_tester_hook" for refilling torches
*/
-static bool_ item_tester_refill_torch(object_type *o_ptr)
+static object_filter_t const &item_tester_refill_torch()
{
- /* Torches are okay */
- if ((o_ptr->tval == TV_LITE) &&
- (o_ptr->sval == SV_LITE_TORCH)) return (TRUE);
-
- /* Assume not okay */
- return (FALSE);
+ using namespace object_filter;
+ static auto instance =
+ And(
+ TVal(TV_LITE),
+ SVal(SV_LITE_TORCH));
+ return instance;
}
/*
* Refuel the players torch (from the pack or floor)
*/
-static void do_cmd_refill_torch(void)
+static void do_cmd_refill_torch()
{
- 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;
+ int item;
+ if (!get_item(&item,
+ "Refuel with which torch? ",
+ "You have no extra torches.",
+ (USE_INVEN | USE_FLOOR),
+ item_tester_refill_torch()))
+ {
+ return;
+ }
/* Get the item */
- o_ptr = get_object(item);
+ object_type *o_ptr = get_object(item);
/* Take a partial turn */
energy_use = 50;
/* Access the primary torch */
- j_ptr = &p_ptr->inventory[INVEN_LITE];
+ object_type *j_ptr = &p_ptr->inventory[INVEN_LITE];
/* Refuel */
j_ptr->timeout += o_ptr->timeout + 5;
@@ -979,15 +935,10 @@ static void do_cmd_refill_torch(void)
/*
* Refill the players lamp, or restock his torches
*/
-void do_cmd_refill(void)
+void do_cmd_refill()
{
- object_type *o_ptr;
-
- u32b f1, f2, f3, f4, f5, esp;
-
-
/* Get the light */
- o_ptr = &p_ptr->inventory[INVEN_LITE];
+ auto o_ptr = &p_ptr->inventory[INVEN_LITE];
/* It is nothing */
if (o_ptr->tval != TV_LITE)
@@ -996,9 +947,9 @@ void do_cmd_refill(void)
return;
}
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ auto const flags = object_flags(o_ptr);
- if (f4 & TR4_FUEL_LITE)
+ if (flags & TR_FUEL_LITE)
{
/* It's a torch */
if (o_ptr->sval == SV_LITE_TORCH ||
@@ -1027,7 +978,7 @@ void do_cmd_refill(void)
/*
* Target command
*/
-void do_cmd_target(void)
+void do_cmd_target()
{
/* Target set */
if (target_set(TARGET_KILL))
@@ -1047,7 +998,7 @@ void do_cmd_target(void)
/*
* Look command
*/
-void do_cmd_look(void)
+void do_cmd_look()
{
/* Look around */
if (target_set(TARGET_LOOK))
@@ -1061,7 +1012,7 @@ void do_cmd_look(void)
/*
* Allow the player to examine other sectors on the map
*/
-void do_cmd_locate(void)
+void do_cmd_locate()
{
int dir, y1, x1, y2, x2;
int panel_hgt, panel_wid;
@@ -1269,113 +1220,72 @@ static cptr ident_info[] =
};
-
-/*
- * 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".
+/**
+ * Sort by monster experience.
*/
-static bool_ ang_sort_comp_hook(vptr u, vptr v, int a, int b)
+static bool compare_monster_experience(int w1, int w2)
{
- 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);
- }
-
+ auto const &r_info = game->edit_data.r_info;
- /* 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);
- }
+ /* 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;
- /* 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);
+ /* Punt to index */
+ return w1 < w2;
}
+/**
+ * Sort by monster level.
+ */
+static bool compare_monster_level(int w1, int w2)
+{
+ auto const &r_info = game->edit_data.r_info;
+
+ /* 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);
+}
/*
- * 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.
+ * Sort by player kills
*/
-static void ang_sort_swap_hook(vptr u, vptr v, int a, int b)
+static bool compare_player_kills(int w1, int w2)
{
- u16b *who = (u16b*)(u);
-
- u16b holder;
+ auto const &r_info = game->edit_data.r_info;
+ /* Extract player kills */
+ s16b z1 = r_info[w1].r_pkills;
+ s16b z2 = r_info[w2].r_pkills;
- /* XXX XXX */
- v = v ? v : 0;
+ /* Compare player kills */
+ if (z1 < z2) return true;
+ if (z1 > z2) return false;
- /* Swap */
- holder = who[a];
- who[a] = who[b];
- who[b] = holder;
+ /* Punt to monster level. */
+ return compare_monster_level(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];
+ auto const &r_info = game->edit_data.r_info;
+
+ auto r_ptr = &r_info[r_idx];
byte a1, a2;
@@ -1398,24 +1308,22 @@ static void roff_top(int r_idx)
Term_gotoxy(0, 0);
/* A title (use "The" for non-uniques) */
- if (!(r_ptr->flags1 & (RF1_UNIQUE)))
+ if (!(r_ptr->flags & RF_UNIQUE))
{
Term_addstr( -1, TERM_WHITE, "The ");
}
/* Dump the name */
- Term_addstr( -1, TERM_WHITE, (r_name + r_ptr->name));
+ Term_addstr( -1, TERM_WHITE, 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, "'):");
}
@@ -1433,9 +1341,9 @@ static void roff_top(int r_idx)
*
* Note that the player ghosts are ignored. XXX XXX XXX
*/
-void do_cmd_query_symbol(void)
+void do_cmd_query_symbol()
{
- int i, n, r_idx;
+ auto const &r_info = game->edit_data.r_info;
char sym, query;
@@ -1456,17 +1364,14 @@ void do_cmd_query_symbol(void)
bool_ recall = FALSE;
-
- u16b why = 0;
-
- u16b *who;
-
+ 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 */
+ std::size_t i;
for (i = 0; ident_info[i]; ++i)
{
if (sym == ident_info[i][0]) break;
@@ -1507,44 +1412,38 @@ void do_cmd_query_symbol(void)
/* 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++)
+ std::vector<std::size_t> who;
+ for (std::size_t i = 1; i < r_info.size(); i++)
{
- monster_race *r_ptr = &r_info[i];
-
- /* Nothing to recall */
- if (!cheat_know && !r_ptr->r_sights) continue;
+ auto r_ptr = &r_info[i];
/* Require non-unique monsters if needed */
- if (norm && (r_ptr->flags1 & (RF1_UNIQUE))) continue;
+ if (norm && (r_ptr->flags & RF_UNIQUE)) continue;
/* Require unique monsters if needed */
- if (uniq && !(r_ptr->flags1 & (RF1_UNIQUE))) continue;
+ if (uniq && !(r_ptr->flags & RF_UNIQUE)) continue;
/* Require monsters with the name requested if needed */
if (name)
{
char mon_name[80];
- strcpy(mon_name, r_name + r_ptr->name);
+ strcpy(mon_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;
+ if (all || (r_ptr->d_char == sym)) {
+ who.push_back(i);
+ }
}
/* Nothing to recall */
- if (!n)
+ if (who.empty())
{
- /* Free the "who" array */
- C_KILL(who, max_r_idx, u16b);
-
return;
}
@@ -1562,47 +1461,40 @@ void do_cmd_query_symbol(void)
/* Sort by kills (and level) */
if (query == 'k')
{
- why = 4;
+ sort_by = compare_player_kills;
query = 'y';
}
/* Sort by level */
if (query == 'p')
{
- why = 2;
+ sort_by = compare_monster_level;
query = 'y';
}
/* Catch "escape" */
if (query != 'y')
{
- /* Free the "who" array */
- C_KILL(who, max_r_idx, u16b);
-
return;
}
/* Sort if needed */
- if (why)
+ if (sort_by)
{
- /* 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);
+ std::sort(std::begin(who), std::end(who), sort_by);
}
/* Start at the end */
- i = n - 1;
+ i = who.size() - 1;
/* Scan the monster memory */
while (1)
{
/* Extract a race */
- r_idx = who[i];
+ auto r_idx = who[i];
/* Hack -- Auto-recall */
monster_race_track(r_idx, 0);
@@ -1627,7 +1519,7 @@ void do_cmd_query_symbol(void)
Term_save();
/* Recall on screen */
- screen_roff(who[i], 0, 0);
+ screen_roff(who[i], 0);
/* Hack -- Complete the prompt (again) */
Term_addstr( -1, TERM_WHITE, " [(r)ecall, ESC]");
@@ -1657,10 +1549,11 @@ void do_cmd_query_symbol(void)
/* Move to "prev" monster */
if (query == '-')
{
- if (++i == n)
+ i++;
+ assert(i >= 0);
+ if (static_cast<size_t>(i) == who.size())
{
i = 0;
- if (!expand_list) break;
}
}
@@ -1669,238 +1562,13 @@ void do_cmd_query_symbol(void)
{
if (i-- == 0)
{
- i = n - 1;
- if (!expand_list) break;
+ i = who.size() - 1;
}
}
}
/* 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);
}
@@ -1933,9 +1601,8 @@ bool_ do_cmd_sense_grid_mana()
/* Roll for usage */
if ((chance < USE_DEVICE) || (randint(chance) < USE_DEVICE))
{
- if (flush_failure) flush();
+ flush_on_failure();
msg_print("You failed to sense the grid's mana.");
- sound(SOUND_FAIL);
return FALSE;
}
@@ -1957,131 +1624,6 @@ bool_ do_cmd_sense_grid_mana()
/*
- * 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)
@@ -2136,16 +1678,19 @@ void cli_add(cptr active, cptr trigger, cptr descr)
}
if (*t == '\0') break;
}
- cli_ptr->comm = string_make(temp);
+ cli_ptr->comm = strdup(temp);
}
else
{
- cli_ptr->comm = string_make(trigger);
+ cli_ptr->comm = strdup(trigger);
}
/* First try copying everything across. */
cli_ptr->key = num;
- cli_ptr->descrip = string_make(descr);
+ cli_ptr->descrip = nullptr;
+ if (descr) {
+ cli_ptr->descrip = strdup(descr);
+ }
/* Take description for the previous record if appropriate. */
if ((cli_total > 0) && (old_ptr->key == cli_ptr->key) && (cli_ptr->descrip == 0))
@@ -2162,7 +1707,7 @@ void cli_add(cptr active, cptr trigger, cptr descr)
/*
* Get a string using CLI completion.
*/
-bool_ get_string_cli(cptr prompt, char *buf, int len)
+static bool_ get_string_cli(cptr prompt, char *buf, int len)
{
bool_ res;
@@ -2174,9 +1719,7 @@ bool_ get_string_cli(cptr prompt, char *buf, int len)
prt(prompt, 0, 0);
/* Ask the user for a string */
- askfor_aux_complete = TRUE;
- res = askfor_aux(buf, len);
- askfor_aux_complete = FALSE;
+ res = askfor_aux_with_completion(buf, len);
/* Clear prompt */
prt("", 0, 0);
@@ -2197,7 +1740,7 @@ bool_ get_string_cli(cptr prompt, char *buf, int len)
*
* See defines.h for a list of the codes used.
*/
-void do_cmd_cli(void)
+void do_cmd_cli()
{
char buff[80];
@@ -2230,33 +1773,23 @@ void do_cmd_cli(void)
*/
void do_cmd_cli_help()
{
- int i, j;
-
- FILE *fff;
-
- char file_name[1024];
-
-
- /* Temporary file */
- if (path_temp(file_name, 1024)) return;
+ fmt::MemoryWriter w;
+ for (int i = 0, j = -1; i < cli_total; i++)
+ {
+ if (j < i - 1)
+ {
+ w << "/";
+ }
- /* Open a new file */
- fff = my_fopen(file_name, "w");
+ w.write("[[[[[G{}]", cli_info[i].comm);
- 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);
+ w.write(" {}\n", cli_info[i].descrip);
j = i;
}
}
- /* Close the file */
- my_fclose(fff);
-
/* Enter "icky" mode */
character_icky = TRUE;
@@ -2264,16 +1797,13 @@ void do_cmd_cli_help()
Term_save();
/* Display the file contents */
- show_file(file_name, "Command line help", 0, 0);
+ show_string(w.c_str(), "Command line help");
/* Restore the screen */
Term_load();
/* Leave "icky" mode */
character_icky = FALSE;
-
- /* Remove the file */
- fd_kill(file_name);
}
@@ -2299,7 +1829,7 @@ void do_cmd_html_dump()
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_load_from(save);
Term_fresh();
return;
}
@@ -2310,14 +1840,14 @@ void do_cmd_html_dump()
if (!get_string("File: ", tmp_val, 80))
{
/* Now restore the screen to initial state */
- Term_load_from(save, TRUE);
+ Term_load_from(save);
Term_fresh();
return;
}
}
/* Now restore the screen to dump it */
- Term_load_from(save, TRUE);
+ Term_load_from(save);
if (html)
html_screenshot(tmp_val);
diff --git a/src/cmd3.hpp b/src/cmd3.hpp
new file mode 100644
index 00000000..97d3e22f
--- /dev/null
+++ b/src/cmd3.hpp
@@ -0,0 +1,23 @@
+#pragma once
+
+#include "h-basic.h"
+
+void do_cmd_html_dump();
+void cli_add(cptr active, cptr trigger, cptr descr);
+void do_cmd_cli();
+void do_cmd_cli_help();
+void do_cmd_inven();
+void do_cmd_equip();
+void do_cmd_wield();
+void do_cmd_takeoff();
+void do_cmd_drop();
+void do_cmd_destroy();
+void do_cmd_observe();
+void do_cmd_uninscribe();
+void do_cmd_inscribe();
+void do_cmd_refill();
+void do_cmd_target();
+void do_cmd_look();
+void do_cmd_locate();
+void do_cmd_query_symbol();
+bool_ do_cmd_sense_grid_mana();
diff --git a/src/cmd4.c b/src/cmd4.cc
index c4440428..a820da41 100644
--- a/src/cmd4.c
+++ b/src/cmd4.cc
@@ -1,7 +1,3 @@
-/* File: cmd4.c */
-
-/* Purpose: Interface commands */
-
/*
* Copyright (c) 1989 James E. Wilson, Robert A. Koeneke
*
@@ -9,9 +5,49 @@
* not for profit purposes provided that this copyright and statement are
* included in all such copies.
*/
-
-#include "angband.h"
-
+#include "cmd4.hpp"
+
+#include "artifact_type.hpp"
+#include "cave_type.hpp"
+#include "corrupt.hpp"
+#include "dungeon_flag.hpp"
+#include "dungeon_info_type.hpp"
+#include "feature_type.hpp"
+#include "files.hpp"
+#include "game.hpp"
+#include "hooks.hpp"
+#include "init1.hpp"
+#include "levels.hpp"
+#include "messages.hpp"
+#include "monster2.hpp"
+#include "monster_race.hpp"
+#include "monster_race_flag.hpp"
+#include "monster_type.hpp"
+#include "notes.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_flag.hpp"
+#include "object_kind.hpp"
+#include "options.hpp"
+#include "player_type.hpp"
+#include "skills.hpp"
+#include "squeltch.hpp"
+#include "tables.hpp"
+#include "town_type.hpp"
+#include "util.hpp"
+#include "util.h"
+#include "variable.h"
+#include "variable.hpp"
+#include "xtra1.hpp"
+#include "z-rand.hpp"
+
+#include <algorithm>
+#include <cassert>
+#include <fmt/format.h>
+#include <memory>
+#include <numeric>
+#include <string>
+#include <vector>
/*
* Hack -- redraw the screen
@@ -24,7 +60,7 @@
* 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)
+void do_cmd_redraw()
{
int j;
@@ -59,7 +95,7 @@ void do_cmd_redraw(void)
p_ptr->update |= (PU_MONSTERS);
/* Redraw everything */
- p_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP);
+ p_ptr->redraw |= (PR_WIPE | PR_FRAME | PR_MAP);
/* Window stuff */
p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER | PW_M_LIST);
@@ -95,7 +131,7 @@ void do_cmd_redraw(void)
/*
* Hack -- change name
*/
-void do_cmd_change_name(void)
+void do_cmd_change_name()
{
char c;
@@ -113,8 +149,8 @@ void do_cmd_change_name(void)
/* Forever */
while (1)
{
- /* keep mode below 7 */
- mode = (mode + 6) % 6;
+ /* keep mode below 5 */
+ mode = (mode + 5) % 5;
/* Display the player */
display_player(mode);
@@ -144,7 +180,7 @@ void do_cmd_change_name(void)
/* File dump */
else if (c == 'f')
{
- strnfmt(tmp, 160, "%s.txt", player_name);
+ strnfmt(tmp, 160, "%s.txt", game->player_name.c_str());
if (get_string("Filename(you can post it to http://angband.oook.cz/): ", tmp, 80))
{
if (tmp[0] && (tmp[0] != ' '))
@@ -169,11 +205,11 @@ void do_cmd_change_name(void)
/* Change tactic */
if (c == 't')
{
- (void)do_cmd_change_tactic( -1);
+ do_cmd_change_tactic( -1);
}
else if (c == 'T')
{
- (void)do_cmd_change_tactic(1);
+ do_cmd_change_tactic(1);
}
/* Change movement */
@@ -208,7 +244,7 @@ void do_cmd_change_name(void)
/* Redraw everything */
- p_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP);
+ p_ptr->redraw |= (PR_WIPE | PR_FRAME | PR_MAP);
handle_stuff();
}
@@ -217,12 +253,16 @@ void do_cmd_change_name(void)
/*
* Recall the most recent message
*/
-void do_cmd_message_one(void)
+void do_cmd_message_one()
{
- cptr msg = format("> %s", message_str(0));
+ auto const &messages = game->messages;
+
+ auto message = messages.at(0);
+
+ cptr msg = format("> %s", message.text_with_count().c_str());
/* Recall one message XXX XXX XXX */
- display_message(0, 0, strlen(msg), message_color(0), msg);
+ display_message(0, 0, strlen(msg), message.color, msg);
}
@@ -244,30 +284,21 @@ void do_cmd_message_one(void)
*
* Now taking advantages of big-screen. -pav-
*/
-void do_cmd_messages(void)
+void do_cmd_messages()
{
- int i, j, k, n;
- u32b q;
- int wid, hgt;
-
- char shower[80];
- char finder[80];
-
- /* Wipe finder */
- strcpy(finder, "");
-
- /* Wipe shower */
- strcpy(shower, "");
+ auto const &messages = game->messages;
+ /* String to highlight */
+ std::string shower;
/* Total messages */
- n = message_num();
+ const int n = messages.size();
/* Start on first message */
- i = 0;
+ int i = 0;
/* Start at leftmost edge */
- q = 0;
+ u32b q = 0;
/* Enter "icky" mode */
character_icky = TRUE;
@@ -282,35 +313,38 @@ void do_cmd_messages(void)
Term_clear();
/* Retrieve current screen size */
+ int wid;
+ int hgt;
Term_get_size(&wid, &hgt);
/* Dump up to 20 (or more in bigscreen) lines of messages */
+ int j;
for (j = 0; (j < (hgt - 4)) && (i + j < n); j++)
{
- cptr msg = message_str(i + j);
- byte color = message_color(i + j);
+ auto message = messages.at(i + j);
+ auto text = message.text_with_count();
+ auto color = message.color;
/* Apply horizontal scroll */
- msg = (strlen(msg) >= q) ? (msg + q) : "";
+ text = (text.size() >= q) ? text.substr(q) : "";
/* Dump the messages, bottom to top */
- display_message(0, (hgt - 3) - j, strlen(msg), color, msg);
+ display_message(0, (hgt - 3) - j, text.size(), color, text.c_str());
/* Hilite "shower" */
if (shower[0])
{
- cptr str = msg;
-
+ std::size_t pos = 0;
/* Display matches */
- while ((str = strstr(str, shower)) != NULL)
+ while ((pos = text.find(shower, pos)) != std::string::npos)
{
- int len = strlen(shower);
+ std::size_t len = shower.size();
/* Display the match */
- Term_putstr(str - msg, (hgt - 3) - j, len, TERM_YELLOW, shower);
+ Term_putstr(pos, (hgt - 3) - j, len, TERM_YELLOW, shower.c_str());
/* Advance */
- str += len;
+ pos += len;
}
}
}
@@ -323,7 +357,7 @@ void do_cmd_messages(void)
prt("[Press 'p' for older, 'n' for newer, ..., or ESCAPE]", hgt - 1, 0);
/* Get a command */
- k = inkey();
+ const auto k = inkey();
/* Exit on Escape */
if (k == ESCAPE) break;
@@ -358,7 +392,10 @@ void do_cmd_messages(void)
prt("Show: ", hgt - 1, 0);
/* Get a "shower" string, or continue */
- if (!askfor_aux(shower, 80)) continue;
+ if (!askfor_aux(&shower, 80))
+ {
+ continue;
+ }
/* Okay */
continue;
@@ -373,18 +410,22 @@ void do_cmd_messages(void)
prt("Find: ", hgt - 1, 0);
/* Get a "finder" string, or continue */
- if (!askfor_aux(finder, 80)) continue;
+ auto finder = shower;
+ if (!askfor_aux(&finder, 80))
+ {
+ continue;
+ }
/* Show it */
- strcpy(shower, finder);
+ shower = finder;
/* Scan messages */
for (z = i + 1; z < n; z++)
{
- cptr msg = message_str(z);
+ auto message = messages.at(z);
/* Search for it */
- if (strstr(msg, finder))
+ if (message.text_with_count().find(finder) != std::string::npos)
{
/* New location */
i = z;
@@ -448,63 +489,53 @@ void do_cmd_messages(void)
character_icky = FALSE;
}
+// File-local
+namespace {
+ /**
+ * Interaction mode for options
+ */
+ enum class interaction_mode_t {
+ READ_ONLY = 0,
+ READ_WRITE = 1
+ };
-/*
- * 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
+/**
+ * Interact with given vector of options.
*/
-static void do_cmd_options_cheat(cptr info)
+static void interact_with_options(std::vector<option_type> const &options, char const *info, interaction_mode_t interaction_mode)
{
- char ch;
-
- int i, k = 0, n = CHEAT_MAX;
-
- int dir;
-
- char buf[80];
-
+ size_t n = options.size();
/* Clear screen */
Term_clear();
/* Interact with the player */
+ size_t k = 0; /* Currently selected option index */
while (TRUE)
{
/* Prompt XXX XXX XXX */
+ char buf[80];
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++)
+ for (size_t i = 0; i < n; i++)
{
byte a = TERM_WHITE;
/* Color current option */
- if (i == k) a = TERM_L_BLUE;
+ 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);
+ options[i].o_desc,
+ (*options[i].o_var) ? "yes" : "no ",
+ options[i].o_text);
c_prt(a, buf, i + 2, 0);
}
@@ -512,15 +543,19 @@ static void do_cmd_options_cheat(cptr info)
move_cursor(k + 2, 50);
/* Get a key */
- ch = inkey();
+ int 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);
-
+ {
+ int dir = get_keymap_dir(ch);
+ if ((dir == 2) || (dir == 4) || (dir == 6) || (dir == 8))
+ {
+ ch = I2D(dir);
+ }
+ }
/* Analyze */
switch (ch)
@@ -533,8 +568,9 @@ static void do_cmd_options_cheat(cptr info)
case '-':
case '8':
{
+ /* Adding n pre-modulo ensures that we don't
+ wrap around to the wrong (post-modulo) index. */
k = (n + k - 1) % n;
-
break;
}
@@ -544,7 +580,6 @@ static void do_cmd_options_cheat(cptr info)
case '2':
{
k = (k + 1) % n;
-
break;
}
@@ -552,10 +587,12 @@ static void do_cmd_options_cheat(cptr info)
case 'Y':
case '6':
{
- noscore |= (cheat_info[k].o_page * 256 + cheat_info[k].o_bit);
- (*cheat_info[k].o_var) = TRUE;
+ if (interaction_mode == interaction_mode_t::READ_ONLY)
+ {
+ break;
+ }
+ *(options[k].o_var) = TRUE;
k = (k + 1) % n;
-
break;
}
@@ -563,9 +600,13 @@ static void do_cmd_options_cheat(cptr info)
case 'N':
case '4':
{
- (*cheat_info[k].o_var) = FALSE;
- k = (k + 1) % n;
+ if (interaction_mode == interaction_mode_t::READ_ONLY)
+ {
+ break;
+ }
+ *(options[k].o_var) = FALSE;
+ k = (k + 1) % n;
break;
}
@@ -577,14 +618,32 @@ static void do_cmd_options_cheat(cptr info)
}
}
}
+
+
}
-static option_type autosave_info[2] =
+
+/*
+ * Interact with some options for cheating
+ */
+static void do_cmd_options_cheat(cptr info)
{
- { &autosave_l, FALSE, 0, 6, "autosave_l", "Autosave when entering new levels" },
- { &autosave_t, FALSE, 0, 7, "autosave_t", "Timed autosave" },
-};
+ // Interact
+ interact_with_options(options->cheat_options, info, interaction_mode_t::READ_WRITE);
+
+ // If user toggled any of the options to TRUE, then we add those cheats
+ // to the player's "noscore" flags. Note that it doesn't matter what the
+ // previous value was -- we don't "unset" noscore flags anyway.
+ for (auto const &option: options->cheat_options)
+ {
+ if (*option.o_var)
+ {
+ noscore |= (option.o_page * 256 + option.o_bit);
+ }
+ }
+}
+
s16b toggle_frequency(s16b current)
{
@@ -609,7 +668,9 @@ static void do_cmd_options_autosave(cptr info)
{
char ch;
- int i, k = 0, n = 2;
+ int i, k = 0;
+
+ int n = options->autosave_options.size();
int dir;
@@ -636,15 +697,18 @@ static void do_cmd_options_autosave(cptr info)
/* Color current option */
if (i == k) a = TERM_L_BLUE;
+ /* Get the option */
+ auto const option = &options->autosave_options[i];
+
/* 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);
+ option->o_desc,
+ (*option->o_var) ? "yes" : "no ",
+ option->o_text);
c_prt(a, buf, i + 2, 0);
}
- prt(format("Timed autosave frequency: every %d turns", autosave_freq), 5, 0);
+ prt(format("Timed autosave frequency: every %d turns", options->autosave_freq), 5, 0);
/* Hilite current option */
@@ -690,8 +754,7 @@ static void do_cmd_options_autosave(cptr info)
case 'Y':
case '6':
{
-
- (*autosave_info[k].o_var) = TRUE;
+ (*options->autosave_options[k].o_var) = TRUE;
k = (k + 1) % n;
break;
@@ -701,7 +764,7 @@ static void do_cmd_options_autosave(cptr info)
case 'N':
case '4':
{
- (*autosave_info[k].o_var) = FALSE;
+ (*options->autosave_options[k].o_var) = FALSE;
k = (k + 1) % n;
break;
@@ -710,9 +773,9 @@ static void do_cmd_options_autosave(cptr info)
case 'f':
case 'F':
{
- autosave_freq = toggle_frequency(autosave_freq);
- prt(format("Timed autosave frequency: every %d turns",
- autosave_freq), 5, 0);
+ options->autosave_freq = toggle_frequency(options->autosave_freq);
+ prt(fmt::format("Timed autosave frequency: every {} turns",
+ options->autosave_freq), 5, 0);
break;
}
@@ -727,159 +790,35 @@ static void do_cmd_options_autosave(cptr info)
}
}
-/* 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;
- }
- }
- }
+ // Scrape together all the options from the relevant page.
+ std::vector<option_type> page_options;
+ page_options.reserve(options->standard_options.size());
+ std::copy_if(
+ std::begin(options->standard_options),
+ std::end(options->standard_options),
+ std::back_inserter(page_options),
+ [=](option_type const &option) -> bool {
+ return (option.o_page == page);
+ }
+ );
+
+ // Interact with the options
+ interaction_mode_t interaction_mode = read_only
+ ? interaction_mode_t::READ_ONLY
+ : interaction_mode_t::READ_WRITE;
+ interact_with_options(page_options, info, interaction_mode);
}
/*
* Modify the "window" options
*/
-static void do_cmd_options_win(void)
+static void do_cmd_options_win()
{
int i, j, d;
@@ -895,7 +834,7 @@ static void do_cmd_options_win(void)
/* Memorize old flags */
- for (j = 0; j < 8; j++)
+ for (j = 0; j < ANGBAND_TERM_MAX; j++)
{
/* Acquire current flags */
old_flag[j] = window_flag[j];
@@ -912,7 +851,7 @@ static void do_cmd_options_win(void)
prt("Window Flags (<dir>, t, y, n, ESC) ", 0, 0);
/* Display the windows */
- for (j = 0; j < 8; j++)
+ for (j = 0; j < ANGBAND_TERM_MAX; j++)
{
byte a = TERM_WHITE;
@@ -942,7 +881,7 @@ static void do_cmd_options_win(void)
Term_putstr(0, i + 5, -1, a, str);
/* Display the windows */
- for (j = 0; j < 8; j++)
+ for (j = 0; j < ANGBAND_TERM_MAX; j++)
{
byte a = TERM_WHITE;
@@ -979,7 +918,7 @@ static void do_cmd_options_win(void)
case 't':
{
/* Clear windows */
- for (j = 0; j < 8; j++)
+ for (j = 0; j < ANGBAND_TERM_MAX; j++)
{
window_flag[j] &= ~(1L << y);
}
@@ -1029,7 +968,7 @@ static void do_cmd_options_win(void)
}
/* Notice changes */
- for (j = 0; j < 8; j++)
+ for (j = 0; j < ANGBAND_TERM_MAX; j++)
{
term *old = Term;
@@ -1070,9 +1009,6 @@ static errr option_dump(cptr fname)
/* 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");
@@ -1087,25 +1023,25 @@ static errr option_dump(cptr fname)
fprintf(fff, "# Automatic option dump\n\n");
/* Dump options (skip cheat, adult, score) */
- for (i = 0; option_info[i].o_var != NULL; i++)
+ for (auto const &option: options->standard_options)
{
/* Require a real option */
- if (!option_info[i].o_text) continue;
+ if (!option.o_text) continue;
/* No birth options */
- if (option_info[i].o_page == 6) continue;
+ if (option.o_page == 6) continue;
/* Comment */
- fprintf(fff, "# Option '%s'\n", option_info[i].o_desc);
+ fprintf(fff, "# Option '%s'\n", option.o_desc);
/* Dump the option */
- if ((*option_info[i].o_var))
+ if (*option.o_var)
{
- fprintf(fff, "Y:%s\n", option_info[i].o_text);
+ fprintf(fff, "Y:%s\n", option.o_text);
}
else
{
- fprintf(fff, "X:%s\n", option_info[i].o_text);
+ fprintf(fff, "X:%s\n", option.o_text);
}
/* Skip a line */
@@ -1161,9 +1097,6 @@ static errr option_dump(cptr fname)
*/
static void do_cmd_pref_file_hack(int row)
{
- char ftmp[80];
-
-
/* Prompt */
prt("Command: Load a user pref file", row, 0);
@@ -1171,21 +1104,24 @@ static void do_cmd_pref_file_hack(int row)
prt("File: ", row + 2, 0);
/* Default filename */
- strnfmt(ftmp, 80, "%s.prf", player_base);
+ std::string ftmp = fmt::format("{}.prf", game->player_base);
/* Ask for a file (or cancel) */
- if (!askfor_aux(ftmp, 80)) return;
+ if (!askfor_aux(&ftmp, 80))
+ {
+ return;
+ }
/* Process the given filename */
- if (process_pref_file(ftmp))
+ if (process_pref_file(ftmp.c_str()))
{
/* Mention failure */
- msg_format("Failed to load '%s'!", ftmp);
+ msg_format("Failed to load '%s'!", ftmp.c_str());
}
else
{
/* Mention success */
- msg_format("Loaded '%s'.", ftmp);
+ msg_format("Loaded '%s'.", ftmp.c_str());
}
}
@@ -1196,7 +1132,7 @@ static void do_cmd_pref_file_hack(int row)
* 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)
+void do_cmd_options()
{
int k;
@@ -1266,8 +1202,6 @@ void do_cmd_options(void)
case 'u':
case 'U':
{
- char ftmp[80];
-
/* Prompt */
prt("Command: Append options to a file", 21, 0);
@@ -1275,13 +1209,13 @@ void do_cmd_options(void)
prt("File: ", 21, 0);
/* Default filename */
- strnfmt(ftmp, 80, "%s.prf", player_base);
+ auto ftmp = fmt::format("{}.prf", game->player_base);
/* Ask for a file */
- if (!askfor_aux(ftmp, 80)) continue;
+ if (!askfor_aux(&ftmp, 80)) continue;
/* Dump the options */
- if (option_dump(ftmp))
+ if (option_dump(ftmp.c_str()))
{
/* Failure */
msg_print("Failed!");
@@ -1390,14 +1324,26 @@ void do_cmd_options(void)
/* 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);
+ auto const msec = options->delay_factor_ms();
+
+ prt(fmt::format("Current base delay factor: {:d} ({:d} msec)",
+ options->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();
+ if (k == ESCAPE)
+ {
+ break;
+ }
+
+ if (isdigit(k))
+ {
+ options->delay_factor = D2I(k);
+ }
+ else
+ {
+ bell();
+ }
}
break;
@@ -1413,13 +1359,24 @@ void do_cmd_options(void)
/* Get a new value */
while (1)
{
- prt(format("Current hitpoint warning: %d0%%",
- hitpoint_warn), 22, 0);
+ prt(fmt::format("Current hitpoint warning: {:d}0%",
+ options->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();
+ if (k == ESCAPE)
+ {
+ break;
+ }
+
+ if (isdigit(k))
+ {
+ options->hitpoint_warn = D2I(k);
+ }
+ else
+ {
+ bell();
+ }
}
break;
@@ -1442,9 +1399,6 @@ void do_cmd_options(void)
/* Restore the screen */
screen_load();
-
- /* Set the ingame help */
- ingame_help(p_ptr->help.enabled);
}
@@ -1454,7 +1408,7 @@ void do_cmd_options(void)
*
* XXX XXX XXX Allow absolute file names?
*/
-void do_cmd_pref(void)
+void do_cmd_pref()
{
char buf[80];
@@ -1466,7 +1420,7 @@ void do_cmd_pref(void)
if (!get_string("Pref: ", buf, 80)) return;
/* Process that pref command */
- (void)process_pref_file_aux(buf);
+ process_pref_file_aux(buf);
}
@@ -1485,9 +1439,6 @@ static errr macro_dump(cptr fname)
/* 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");
@@ -1567,11 +1518,8 @@ static void do_cmd_macro_aux(char *buf, bool_ macro_screen)
/* Do not process macros */
inkey_base = TRUE;
- /* Do not wait for keys */
- inkey_scan = TRUE;
-
/* Attempt to read a key */
- i = inkey();
+ i = inkey_scan();
}
/* Terminate */
@@ -1644,9 +1592,6 @@ static errr keymap_dump(cptr fname)
/* 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");
@@ -1704,22 +1649,10 @@ static errr keymap_dump(cptr fname)
*
* Could use some helpful instructions on this page. XXX XXX XXX
*/
-void do_cmd_macros(void)
+void do_cmd_macros()
{
- 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);
+ int mode = get_keymap_mode();
/* Enter "icky" mode */
@@ -1732,6 +1665,8 @@ void do_cmd_macros(void)
/* Process requests until done */
while (1)
{
+ char buf[1024];
+
/* Clear screen */
Term_clear();
@@ -1765,7 +1700,7 @@ void do_cmd_macros(void)
prt("Command: ", 16, 0);
/* Get a command */
- i = inkey();
+ int i = inkey();
/* Leave */
if (i == ESCAPE) break;
@@ -1780,13 +1715,16 @@ void do_cmd_macros(void)
prt("File: ", 18, 0);
/* Default filename */
- strnfmt(tmp, 1024, "%s.prf", player_name);
+ auto tmp = fmt::format("{}.prf", game->player_name);
/* Ask for a file */
- if (!askfor_aux(tmp, 80)) continue;
+ if (!askfor_aux(&tmp, 80))
+ {
+ continue;
+ }
/* Process the given filename */
- if (0 != process_pref_file(tmp))
+ if (0 != process_pref_file(tmp.c_str()))
{
/* Prompt */
msg_print("Could not load file!");
@@ -1803,13 +1741,16 @@ void do_cmd_macros(void)
prt("File: ", 18, 0);
/* Default filename */
- strnfmt(tmp, 1024, "%s.prf", player_name);
+ auto tmp = fmt::format("{}.prf", game->player_name);
/* Ask for a file */
- if (!askfor_aux(tmp, 80)) continue;
+ if (!askfor_aux(&tmp, 80))
+ {
+ continue;
+ }
/* Dump the macros */
- (void)macro_dump(tmp);
+ macro_dump(tmp.c_str());
/* Prompt */
msg_print("Appended macros.");
@@ -1859,6 +1800,8 @@ void do_cmd_macros(void)
/* Create a macro */
else if (i == '4')
{
+ char tmp[1024];
+
/* Prompt */
prt("Command: Create a macro", 16, 0);
@@ -1920,13 +1863,16 @@ void do_cmd_macros(void)
prt("File: ", 18, 0);
/* Default filename */
- strnfmt(tmp, 1024, "%s.prf", player_name);
+ auto tmp = fmt::format("{}.prf", game->player_name);
/* Ask for a file */
- if (!askfor_aux(tmp, 80)) continue;
+ if (!askfor_aux(&tmp, 80))
+ {
+ continue;
+ }
/* Dump the macros */
- (void)keymap_dump(tmp);
+ keymap_dump(tmp.c_str());
/* Prompt */
msg_print("Appended keymaps.");
@@ -1976,6 +1922,8 @@ void do_cmd_macros(void)
/* Create a keymap */
else if (i == '8')
{
+ char tmp[1024];
+
/* Prompt */
prt("Command: Create a keymap", 16, 0);
@@ -2000,11 +1948,9 @@ void do_cmd_macros(void)
/* 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);
+ free(keymap_act[mode][(byte)(buf[0])]);
+ keymap_act[mode][(byte)(buf[0])] = strdup(macro__buf);
/* Prompt */
msg_print("Added a keymap.");
@@ -2023,10 +1969,8 @@ void do_cmd_macros(void)
/* Get a keymap trigger */
do_cmd_macro_aux_keymap(buf);
- /* Free old keymap */
- string_free(keymap_act[mode][(byte)(buf[0])]);
-
/* Make new keymap */
+ free(keymap_act[mode][(byte)(buf[0])]);
keymap_act[mode][(byte)(buf[0])] = NULL;
/* Prompt */
@@ -2036,6 +1980,8 @@ void do_cmd_macros(void)
/* Enter a new action */
else if (i == '0')
{
+ char tmp[1024];
+
/* Prompt */
prt("Command: Enter a new action", 16, 0);
@@ -2074,8 +2020,12 @@ void do_cmd_macros(void)
/*
* Interact with "visuals"
*/
-void do_cmd_visuals(void)
+void do_cmd_visuals()
{
+ auto &r_info = game->edit_data.r_info;
+ auto &f_info = game->edit_data.f_info;
+ auto &k_info = game->edit_data.k_info;
+
int i;
FILE *fff;
@@ -2085,10 +2035,6 @@ void do_cmd_visuals(void)
char buf[1024];
- /* File type is "TEXT" */
- FILE_TYPE(FILE_TYPE_TEXT);
-
-
/* Enter "icky" mode */
character_icky = TRUE;
@@ -2142,7 +2088,7 @@ void do_cmd_visuals(void)
if (!askfor_aux(tmp, 70)) continue;
/* Process the given filename */
- (void)process_pref_file(tmp);
+ process_pref_file(tmp);
}
/* Dump monster attr/chars */
@@ -2174,19 +2120,20 @@ void do_cmd_visuals(void)
fprintf(fff, "# Monster attr/char definitions\n\n");
/* Dump monsters */
- for (i = 0; i < max_r_idx; i++)
+ for (std::size_t i = 0; i < r_info.size(); i++)
{
- monster_race *r_ptr = &r_info[i];
+ auto 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));
+ fprintf(fff, "# %s\n", 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));
+ fprintf(fff, "R:%zu:0x%02X:0x%02X\n\n", i,
+ static_cast<unsigned int>(r_ptr->x_attr),
+ static_cast<unsigned int>(r_ptr->x_char));
}
/* All done */
@@ -2228,18 +2175,18 @@ void do_cmd_visuals(void)
fprintf(fff, "# Object attr/char definitions\n\n");
/* Dump objects */
- for (i = 0; i < max_k_idx; i++)
+ for (std::size_t k = 0; k < k_info.size(); k++)
{
- object_kind *k_ptr = &k_info[i];
+ object_kind *k_ptr = &k_info[k];
/* Skip non-entries */
if (!k_ptr->name) continue;
/* Dump a comment */
- fprintf(fff, "# %s\n", (k_name + k_ptr->name));
+ fprintf(fff, "# %s\n", k_ptr->name);
/* Dump the object attr/char info */
- fprintf(fff, "K:%d:0x%02X:0x%02X\n\n", i,
+ fprintf(fff, "K:%zu:0x%02X:0x%02X\n\n", k,
(byte)(k_ptr->x_attr), (byte)(k_ptr->x_char));
}
@@ -2282,18 +2229,18 @@ void do_cmd_visuals(void)
fprintf(fff, "# Feature attr/char definitions\n\n");
/* Dump features */
- for (i = 0; i < max_f_idx; i++)
+ for (std::size_t f_idx = 0; f_idx < f_info.size(); f_idx++)
{
- feature_type *f_ptr = &f_info[i];
+ auto f_ptr = &f_info[f_idx];
/* Skip non-entries */
if (!f_ptr->name) continue;
/* Dump a comment */
- fprintf(fff, "# %s\n", (f_name + f_ptr->name));
+ fprintf(fff, "# %s\n", f_ptr->name);
/* Dump the feature attr/char info */
- fprintf(fff, "F:%d:0x%02X:0x%02X\n\n", i,
+ fprintf(fff, "F:%zu:0x%02X:0x%02X\n\n", f_idx,
(byte)(f_ptr->x_attr), (byte)(f_ptr->x_char));
}
@@ -2318,7 +2265,7 @@ void do_cmd_visuals(void)
/* Hack -- query until done */
while (1)
{
- monster_race *r_ptr = &r_info[r];
+ auto r_ptr = &r_info[r];
byte da = (r_ptr->d_attr);
char dc = (r_ptr->d_char);
@@ -2328,33 +2275,19 @@ void do_cmd_visuals(void)
/* Label the object */
Term_putstr(5, 17, -1, TERM_WHITE,
format("Monster = %d, Name = %-40.40s",
- r, (r_name + r_ptr->name)));
+ r, 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,
@@ -2367,12 +2300,12 @@ void do_cmd_visuals(void)
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 = (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 == 'n') r = (r + r_info.size() + 1) % r_info.size();
+ if (i == 'N') r = (r + r_info.size() - 1) % r_info.size();
+ 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);
}
}
@@ -2389,41 +2322,27 @@ 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,
format("Object = %d, Name = %-40.40s",
- k, (k_name + k_ptr->name)));
+ k, 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,
@@ -2436,12 +2355,12 @@ void do_cmd_visuals(void)
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 = (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 == 'n') k = (k + k_info.size() + 1) % k_info.size();
+ if (i == 'N') k = (k + k_info.size() - 1) % k_info.size();
+ 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);
}
}
@@ -2456,43 +2375,29 @@ void do_cmd_visuals(void)
/* Hack -- query until done */
while (1)
{
- feature_type *f_ptr = &f_info[f];
+ auto 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,
format("Terrain = %d, Name = %-40.40s",
- f, (f_name + f_ptr->name)));
+ f, 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,
@@ -2505,12 +2410,12 @@ void do_cmd_visuals(void)
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 = (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 == 'n') f = (f + f_info.size() + 1) % f_info.size();
+ if (i == 'N') f = (f + f_info.size() - 1) % f_info.size();
+ 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;
@@ -2551,7 +2456,7 @@ void do_cmd_visuals(void)
/*
* Interact with "colors"
*/
-void do_cmd_colors(void)
+void do_cmd_colors()
{
int i;
@@ -2562,10 +2467,6 @@ void do_cmd_colors(void)
char buf[1024];
- /* File type is "TEXT" */
- FILE_TYPE(FILE_TYPE_TEXT);
-
-
/* Enter "icky" mode */
character_icky = TRUE;
@@ -2612,7 +2513,7 @@ void do_cmd_colors(void)
if (!askfor_aux(tmp, 70)) continue;
/* Process the given filename */
- (void)process_pref_file(tmp);
+ process_pref_file(tmp);
/* Mega-Hack -- react to changes */
Term_xtra(TERM_XTRA_REACT, 0);
@@ -2735,16 +2636,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);
@@ -2777,7 +2678,7 @@ void do_cmd_colors(void)
* Take notes. There are two ways this can happen, either in the message
* recall or a file.
*/
-void do_cmd_note(void)
+void do_cmd_note()
{
char buf[80];
@@ -2790,34 +2691,21 @@ 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, ' ');
}
/*
* Mention the current version
*/
-void do_cmd_version(void)
+void do_cmd_version()
{
- 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);
- call_lua("patchs_display", "()", "");
+ modules[game_module_idx].meta.author.name,
+ modules[game_module_idx].meta.author.email);
}
@@ -2845,30 +2733,32 @@ static cptr do_cmd_feeling_text[11] =
* 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)
+void do_cmd_feeling()
{
+ auto const &d_info = game->edit_data.d_info;
+
/* 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)
+ if (fate_flag && !(dungeon_flags & DF_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)))
+ if (process_hooks_new(HOOK_FEELING, NULL, NULL))
{
return;
}
/* No useful feeling in special levels */
- if (dungeon_flags2 & DF2_DESC)
+ if (dungeon_flags & DF_DESC)
{
char buf[1024];
- if ((get_dungeon_save(buf)) || (generate_special_feeling) || (dungeon_flags2 & DF2_DESC_ALWAYS))
+ if (get_dungeon_save(buf) || game->generate_special_feeling || (dungeon_flags & DF_DESC_ALWAYS))
{
if (!get_level_desc(buf)) msg_print("Someone forgot to describe this level!");
else msg_print(buf);
@@ -2888,7 +2778,7 @@ void do_cmd_feeling(void)
{
/* 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];
+ auto d_ptr = &d_info[dungeon_type];
/* Is it a town level ? */
for (i = 0; i < TOWN_DUNGEON; i++)
@@ -2915,7 +2805,7 @@ static char hack[17] = "dwsorgbuDWvyRGBU";
/*
* Hack -- load a screen dump from a file
*/
-void do_cmd_load_screen(void)
+void do_cmd_load_screen()
{
int i, y, x;
@@ -3003,7 +2893,7 @@ void do_cmd_load_screen(void)
for (x = 0; x < len; x++)
{
/* Get the attr/char */
- (void)(Term_what(x, y, &a, &c));
+ (Term_what(x, y, &a, &c));
/* Look up the attr */
for (i = 0; i < 16; i++)
@@ -3037,163 +2927,123 @@ void do_cmd_load_screen(void)
/*
- * Redefinable "save_screen" action
- */
-void (*screendump_aux)(void) = NULL;
-
-
-
-
-
-
-/*
* Hack -- save a screen dump to a file
*/
-void do_cmd_save_screen(void)
+void do_cmd_save_screen()
{
- /* 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 = ' ';
+ int y, x;
+ int wid, hgt;
- FILE *fff;
+ byte a = 0;
+ char c = ' ';
- char buf[1024];
+ 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);
+ /* Build the filename */
+ path_build(buf, 1024, ANGBAND_DIR_USER, "dump.txt");
- /* Append to the file */
- fff = my_fopen(buf, "w");
+ /* Append to the file */
+ fff = my_fopen(buf, "w");
- /* Oops */
- if (!fff) return;
+ /* Oops */
+ if (!fff) return;
- /* Retrieve the current screen size */
- Term_get_size(&wid, &hgt);
+ /* Retrieve the current screen size */
+ Term_get_size(&wid, &hgt);
- /* Enter "icky" mode */
- character_icky = TRUE;
+ /* Enter "icky" mode */
+ character_icky = TRUE;
- /* Save the screen */
- Term_save();
+ /* Save the screen */
+ Term_save();
- /* Dump the screen */
- for (y = 0; y < hgt; y++)
+ /* Dump the screen */
+ for (y = 0; y < hgt; y++)
+ {
+ /* Dump each row */
+ for (x = 0; x < wid; x++)
{
- /* Dump each row */
- for (x = 0; x < wid; x++)
- {
- /* Get the attr/char */
- (void)(Term_what(x, y, &a, &c));
+ /* Get the attr/char */
+ (Term_what(x, y, &a, &c));
- /* Dump it */
- buf[x] = c;
- }
+ /* Dump it */
+ buf[x] = c;
+ }
- /* Terminate */
- buf[x] = '\0';
+ /* Terminate */
+ buf[x] = '\0';
- /* End the row */
- fprintf(fff, "%s\n", buf);
- }
+ /* End the row */
+ fprintf(fff, "%s\n", buf);
+ }
- /* Skip a line */
- fprintf(fff, "\n");
+ /* Skip a line */
+ fprintf(fff, "\n");
- /* Dump the screen */
- for (y = 0; y < hgt; y++)
+ /* Dump the screen */
+ for (y = 0; y < hgt; y++)
+ {
+ /* Dump each row */
+ for (x = 0; x < wid; x++)
{
- /* Dump each row */
- for (x = 0; x < wid; x++)
- {
- /* Get the attr/char */
- (void)(Term_what(x, y, &a, &c));
+ /* Get the attr/char */
+ (Term_what(x, y, &a, &c));
- /* Dump it */
- buf[x] = hack[a & 0x0F];
- }
+ /* Dump it */
+ buf[x] = hack[a & 0x0F];
+ }
- /* Terminate */
- buf[x] = '\0';
+ /* Terminate */
+ buf[x] = '\0';
- /* End the row */
- fprintf(fff, "%s\n", buf);
- }
+ /* End the row */
+ fprintf(fff, "%s\n", buf);
+ }
- /* Skip a line */
- fprintf(fff, "\n");
+ /* Skip a line */
+ fprintf(fff, "\n");
- /* Close it */
- my_fclose(fff);
+ /* Close it */
+ my_fclose(fff);
- /* Message */
- msg_print("Screen dump saved.");
- msg_print(NULL);
+ /* Message */
+ msg_print("Screen dump saved.");
+ msg_print(NULL);
- /* Restore the screen */
- Term_load();
+ /* Restore the screen */
+ Term_load();
- /* Leave "icky" mode */
- character_icky = FALSE;
- }
+ /* Leave "icky" mode */
+ character_icky = FALSE;
}
/*
* Check the status of "artifacts"
*/
-void do_cmd_knowledge_artifacts(void)
+void do_cmd_knowledge_artifacts()
{
- int i, k, z, x, y;
-
- FILE *fff;
+ auto const &k_info = game->edit_data.k_info;
+ auto const &a_info = game->edit_data.a_info;
- char file_name[1024];
+ int i, z, x, y;
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++)
+ std::vector<bool_> okay(a_info.size(), FALSE);
+ for (std::size_t k = 0; k < a_info.size(); k++)
{
- artifact_type *a_ptr = &a_info[k];
-
- /* Default */
- okay[k] = FALSE;
+ auto a_ptr = &a_info[k];
/* Skip "empty" artifacts */
if (!a_ptr->name) continue;
@@ -3205,15 +3055,13 @@ void do_cmd_knowledge_artifacts(void)
okay[k] = TRUE;
}
- for (k = 0; k < max_k_idx; k++)
+ std::vector<bool_> okayk(k_info.size(), FALSE);
+ for (std::size_t k = 0; k < k_info.size(); k++)
{
- object_kind *k_ptr = &k_info[k];
-
- /* Default */
- okayk[k] = FALSE;
+ auto k_ptr = &k_info[k];
/* Skip "empty" artifacts */
- if (!(k_ptr->flags3 & TR3_NORM_ART)) continue;
+ if (!(k_ptr->flags & TR_NORM_ART)) continue;
/* Skip "uncreated" artifacts */
if (!k_ptr->artifact) continue;
@@ -3229,18 +3077,11 @@ void do_cmd_knowledge_artifacts(void)
{
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)
+ for (auto const this_o_idx: c_ptr->o_idxs)
{
- object_type * o_ptr;
-
/* Acquire object */
- o_ptr = &o_list[this_o_idx];
-
- /* Acquire next object */
- next_o_idx = o_ptr->next_o_idx;
+ object_type const * o_ptr = &o_list[this_o_idx];
/* Ignore random artifacts */
if (o_ptr->tval == TV_RANDART) continue;
@@ -3252,7 +3093,7 @@ void do_cmd_knowledge_artifacts(void)
if (object_known_p(o_ptr)) continue;
/* Note the artifact */
- if (k_info[o_ptr->k_idx].flags3 & TR3_NORM_ART)
+ if (k_info[o_ptr->k_idx].flags & TR_NORM_ART)
{
okayk[o_ptr->k_idx] = FALSE;
}
@@ -3267,21 +3108,14 @@ void do_cmd_knowledge_artifacts(void)
/* 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)
+ for (auto const this_o_idx: m_list[i].hold_o_idxs)
{
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;
@@ -3292,7 +3126,7 @@ void do_cmd_knowledge_artifacts(void)
if (object_known_p(o_ptr)) continue;
/* Note the artifact */
- if (k_info[o_ptr->k_idx].flags3 & TR3_NORM_ART)
+ if (k_info[o_ptr->k_idx].flags & TR_NORM_ART)
{
okayk[o_ptr->k_idx] = FALSE;
}
@@ -3321,7 +3155,7 @@ void do_cmd_knowledge_artifacts(void)
if (object_known_p(o_ptr)) continue;
/* Note the artifact */
- if (k_info[o_ptr->k_idx].flags3 & TR3_NORM_ART)
+ if (k_info[o_ptr->k_idx].flags & TR_NORM_ART)
{
okayk[o_ptr->k_idx] = FALSE;
}
@@ -3331,10 +3165,13 @@ void do_cmd_knowledge_artifacts(void)
}
}
+ /* Output buffer */
+ fmt::MemoryWriter w;
+
/* Scan the artifacts */
- for (k = 0; k < max_a_idx; k++)
+ for (std::size_t k = 0; k < a_info.size(); k++)
{
- artifact_type *a_ptr = &a_info[k];
+ auto a_ptr = &a_info[k];
/* List "dead" ones */
if (!okay[k]) continue;
@@ -3350,7 +3187,6 @@ void do_cmd_knowledge_artifacts(void)
{
object_type forge;
object_type *q_ptr;
- u32b f1, f2, f3, f4, f5, esp;
/* Get local object */
q_ptr = &forge;
@@ -3362,19 +3198,21 @@ void do_cmd_knowledge_artifacts(void)
q_ptr->name1 = k;
/* Spell in it ? no ! */
- object_flags(q_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
- if (f5 & TR5_SPELL_CONTAIN)
+ auto const flags = object_flags(q_ptr);
+ if (flags & TR_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);
+ w.write(" The {}\n", base_name);
}
- for (k = 0; k < max_k_idx; k++)
+ for (std::size_t k = 0; k < k_info.size(); k++)
{
/* List "dead" ones */
if (!okayk[k]) continue;
@@ -3399,211 +3237,90 @@ void do_cmd_knowledge_artifacts(void)
}
/* Hack -- Build the artifact name */
- fprintf(fff, " The %s\n", base_name);
+ w.write(" The {}\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_);
+ /* Display */
+ show_string(w.c_str(), "Artifacts Seen");
}
-/*
- * Check the status of traps
- */
-void do_cmd_knowledge_traps(void)
+static int monster_get_race_level(int r_idx)
{
- int k;
-
- FILE *fff;
-
- trap_type *t_ptr;
+ auto const &r_info = game->edit_data.r_info;
- 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);
+ /* Hack -- Morgoth is always last */
+ if (r_idx == 862) {
+ return 20000;
}
-
- /* 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);
+ /* Otherwise, we'll use the real level. */
+ return r_info[r_idx].level;
}
-
/*
* 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)
+static void do_cmd_knowledge_uniques()
{
- int i, j;
-
- monster_race *r_ptr = &r_info[r_idx];
-
- int level = r_ptr->level;
+ auto const &r_info = game->edit_data.r_info;
-
- /* 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--)
+ // Extract the unique race indexes.
+ std::vector<std::size_t> unique_r_idxs;
+ for (std::size_t k = 1; k < r_info.size(); k++)
{
- 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];
+ auto r_ptr = &r_info[k];
/* Only print Uniques */
- if (r_ptr->flags1 & (RF1_UNIQUE) &&
- !(r_ptr->flags7 & RF7_PET) &&
- !(r_ptr->flags7 & RF7_NEUTRAL))
+ if ((r_ptr->flags & RF_UNIQUE) &&
+ !(r_ptr->flags & RF_PET) &&
+ !(r_ptr->flags & RF_NEUTRAL))
{
- insert_sort_unique(sort_uniques, &num, k);
+ unique_r_idxs.push_back(k);
}
}
- /* Scan the monster races -- sorted */
- for (k = 0; k < num; k++)
+ // Sort races by level.
+ std::sort(std::begin(unique_r_idxs),
+ std::end(unique_r_idxs),
+ [](auto r_idx1, auto r_idx2) -> bool {
+ return monster_get_race_level(r_idx1) < monster_get_race_level(r_idx2);
+ });
+
+ // Scan the monster races
+ fmt::MemoryWriter w;
+ for (std::size_t r_idx : unique_r_idxs)
{
- monster_race *r_ptr = &r_info[sort_uniques[k]];
+ auto r_ptr = &r_info[r_idx];
/* Only print Uniques */
- if (r_ptr->flags1 & (RF1_UNIQUE))
+ if (r_ptr->flags & RF_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)
{
- /* 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));
- }
- }
+ w.write("[[[[[{}{}] [[[[[R{:<68} is dead]\n",
+ static_cast<char>(conv_color[r_ptr->d_attr]),
+ static_cast<char>(r_ptr->d_char),
+ r_ptr->name);
+ }
+ else
+ {
+ w.write("[[[[[{}{}] [[[[[w{:<68} is alive]\n",
+ static_cast<char>(conv_color[r_ptr->d_attr]),
+ static_cast<char>(r_ptr->d_char),
+ 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);
+ // Display
+ show_string(w.c_str(), "Known Uniques");
}
-void plural_aux(char *name)
+static void plural_aux(char *name)
{
int name_len = strlen(name);
@@ -3659,29 +3376,29 @@ void plural_aux(char *name)
}
/* Broken plurals are, well, broken */
- else if (name[name_len - 1] == 'y')
+ else if (name_len >= 1 && name[name_len - 1] == 'y')
{
strcpy(&name[name_len - 1], "ies");
}
- else if (streq(&name[name_len - 4], "ouse"))
+ else if (name_len >= 4 && streq(&name[name_len - 4], "ouse"))
{
strcpy(&name[name_len - 4], "ice");
}
- else if (streq(&name[name_len - 6], "kelman"))
+ else if (name_len >= 6 && streq(&name[name_len - 6], "kelman"))
{
strcpy(&name[name_len - 6], "kelmen");
}
- else if (streq(&name[name_len - 2], "ex"))
+ else if (name_len >= 2 && streq(&name[name_len - 2], "ex"))
{
strcpy(&name[name_len - 2], "ices");
}
- else if (streq(&name[name_len - 3], "olf"))
+ else if (name_len >= 3 && 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'))
+ else if ((name_len >= 2 && streq(&name[name_len - 2], "ch")) || (name_len >= 1 && name[name_len - 1] == 's'))
{
strcpy(&name[name_len], "es");
}
@@ -3695,38 +3412,19 @@ void plural_aux(char *name)
/*
* Display current pets
*/
-static void do_cmd_knowledge_pets(void)
+static void do_cmd_knowledge_pets()
{
- 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;
+ // Buffer
+ fmt::MemoryWriter w;
/* Process the monsters (backwards) */
- for (i = m_max - 1; i >= 1; i--)
+ for (int i = m_max - 1; i >= 1; i--)
{
/* Access the monster */
- m_ptr = &m_list[i];
+ monster_type *m_ptr = &m_list[i];
/* Ignore "dead" monsters */
if (!m_ptr->r_idx) continue;
@@ -3734,19 +3432,25 @@ static void do_cmd_knowledge_pets(void)
/* Calculate "upkeep" for friendly monsters */
if (m_ptr->status >= MSTATUS_PET)
{
- char pet_name[80];
- monster_race *r_ptr = race_inf(m_ptr);
+ auto const r_ptr = m_ptr->race();
t_friends++;
t_levels += m_ptr->level;
+
+ char pet_name[80];
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");
+
+ w.write("{}{} ({})\n",
+ (r_ptr->flags & RF_UNIQUE) ? "#####G" : "",
+ pet_name,
+ (m_ptr->status < MSTATUS_COMPANION) ? "pet" : "companion");
}
}
+ // Calculate upkeep
+ int show_upkeep = 0;
+ int upkeep_divider = p_ptr->has_ability(AB_PERFECT_CASTING) ? 15 : 20;
+
if (t_friends > 1 + (p_ptr->lev / (upkeep_divider)))
{
show_upkeep = (t_levels);
@@ -3755,105 +3459,78 @@ static void do_cmd_knowledge_pets(void)
else if (show_upkeep < 10) show_upkeep = 10;
}
+ // Summary
+ w.write("----------------------------------------------\n");
+ w.write(" Total: {} pet{}.\n", t_friends, (t_friends == 1 ? "" : "s"));
+ w.write(" Upkeep: {}% mana.\n", show_upkeep);
- 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);
+ // Display
+ show_string(w.c_str(), "Current Pets");
}
/*
* Total kill count
- *
- * Note that the player ghosts are ignored. XXX XXX XXX
*/
-static void do_cmd_knowledge_kill_count(void)
+static void do_cmd_knowledge_kill_count()
{
- int k;
-
- FILE *fff;
-
- char file_name[1024];
+ auto const &r_info = game->edit_data.r_info;
s32b Total = 0;
+ // Buffer
+ fmt::MemoryWriter w;
- /* Temporary file */
- if (path_temp(file_name, 1024)) return;
-
- /* Open a new file */
- fff = my_fopen(file_name, "w");
-
+ // Summary of monsters slain
{
- /* Monsters slain */
- int kk;
-
/* For all monsters */
- for (kk = 1; kk < max_r_idx; kk++)
+ for (auto const &r_ref: r_info)
{
- monster_race *r_ptr = &r_info[kk];
+ auto r_ptr = &r_ref;
- if (r_ptr->flags1 & (RF1_UNIQUE))
+ if (r_ptr->flags & RF_UNIQUE)
{
- bool_ dead = (r_ptr->max_num == 0);
-
- if (dead)
+ if (r_ptr->max_num == 0)
{
Total++;
}
}
else
{
- s16b This = r_ptr->r_pkills;
-
- if (This > 0)
- {
- Total += This;
- }
+ Total += std::max<s16b>(r_ptr->r_pkills, 0);
}
}
if (Total < 1)
{
- fprintf(fff, "You have defeated no enemies yet.\n\n");
+ w.write("You have defeated no enemies yet.\n\n");
}
else if (Total == 1)
{
- fprintf(fff, "You have defeated one enemy.\n\n");
+ w.write("You have defeated one enemy.\n\n");
}
else
{
- fprintf(fff, "You have defeated %ld enemies.\n\n", (long int) Total);
+ w.write("You have defeated {} enemies.\n\n", Total);
}
}
Total = 0;
/* Scan the monster races */
- for (k = 0; k < max_r_idx; k++)
+ for (auto const &r_ref: r_info)
{
- monster_race *r_ptr = &r_info[k];
+ auto r_ptr = &r_ref;
- if (r_ptr->flags1 & (RF1_UNIQUE))
+ if (r_ptr->flags & RF_UNIQUE)
{
bool_ dead = (r_ptr->max_num == 0);
if (dead)
{
/* Print a message */
- fprintf(fff, " %s\n",
- (r_name + r_ptr->name));
+ w.write(" {}\n", r_ptr->name);
Total++;
}
}
@@ -3865,21 +3542,21 @@ static void do_cmd_knowledge_kill_count(void)
{
if (This < 2)
{
- if (strstr(r_name + r_ptr->name, "coins"))
+ if (strstr(r_ptr->name, "coins"))
{
- fprintf(fff, " 1 pile of %s\n", (r_name + r_ptr->name));
+ w.write(" 1 pile of {}\n", r_ptr->name);
}
else
{
- fprintf(fff, " 1 %s\n", (r_name + r_ptr->name));
+ w.write(" 1 {}\n", r_ptr->name);
}
}
else
{
char to_plural[80];
- strcpy(to_plural, (r_name + r_ptr->name));
+ strcpy(to_plural, r_ptr->name);
plural_aux(to_plural);
- fprintf(fff, " %d %s\n", This, to_plural);
+ w.write(" {} {}\n", This, to_plural);
}
Total += This;
@@ -3887,147 +3564,100 @@ 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"));
-
- /* Close the file */
- my_fclose(fff);
+ w.write("----------------------------------------------\n");
+ w.write(" Total: {} creature{} killed.\n", Total, (Total == 1 ? "" : "s"));
/* Display the file contents */
- show_file(file_name, "Kill Count", 0, 0);
-
- /* Remove the file */
- fd_kill(file_name);
+ show_string(w.c_str(), "Kill Count");
}
/*
* Display known objects
*/
-static void do_cmd_knowledge_objects(void)
+static void do_cmd_knowledge_objects()
{
- int k;
-
- FILE *fff;
-
- char o_name[80];
-
- char file_name[1024];
+ auto const &k_info = game->edit_data.k_info;
-
- /* Temporary file */
- if (path_temp(file_name, 1024)) return;
-
- /* Open a new file */
- fff = my_fopen(file_name, "w");
+ fmt::MemoryWriter w;
/* Scan the object kinds */
- for (k = 1; k < max_k_idx; k++)
+ for (std::size_t k = 1; k < k_info.size(); k++)
{
- object_kind *k_ptr = &k_info[k];
+ auto k_ptr = &k_info[k];
/* Hack -- skip artifacts */
- if (k_ptr->flags3 & (TR3_INSTA_ART)) continue;
+ if (k_ptr->flags & (TR_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;
+ object_type *i_ptr = &object_type_body;
/* Create fake object */
object_prep(i_ptr, k);
/* Describe the object */
+ char o_name[80];
object_desc_store(o_name, i_ptr, FALSE, 0);
/* Print a message */
- fprintf(fff, " %s\n", o_name);
+ w.write(" {}\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);
+ // Display
+ show_string(w.c_str(), "Known Objects");
}
/*
* List recall depths
*/
-static void do_cmd_knowledge_dungeons(void)
+static void do_cmd_knowledge_dungeons()
{
- int y;
- char file_name[1024];
- FILE *fff;
-
- /* Temporary file */
- if (path_temp(file_name, 1024)) return;
+ auto const &d_info = game->edit_data.d_info;
- /* Open a new file */
- fff = my_fopen(file_name, "w");
-
- /* Oops */
- if (fff == NULL) return;
+ fmt::MemoryWriter w;
/* Scan all dungeons */
- for (y = 1; y < max_d_idx; y++)
+ for (std::size_t y = 1; y < d_info.size(); 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]));
+ w.write(" {}{}: Level {}\n",
+ (p_ptr->recall_dungeon == y) ? '*' : ' ',
+ d_info[y].name,
+ 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);
+ // Display
+ show_string(w.c_str(), "Recall Depths");
}
/*
* List known towns
*/
-void do_cmd_knowledge_towns(void)
+void do_cmd_knowledge_towns()
{
- int i, j;
- char file_name[1024];
- FILE *fff;
-
- /* Temporary file */
- if (path_temp(file_name, 1024)) return;
+ auto const &d_info = game->edit_data.d_info;
- /* Open a new file */
- fff = my_fopen(file_name, "w");
-
- /* Oops */
- if (fff == NULL) return;
+ fmt::MemoryWriter w;
/* Scan all dungeons */
- for (i = 0; i < max_d_idx; i++)
+ for (auto const &d_ref: d_info)
{
- dungeon_info_type *d_ptr = &d_info[i];
+ auto d_ptr = &d_ref;
/* Scan all dungeon town slots */
- for (j = 0; j < TOWN_DUNGEON; j++)
+ for (int j = 0; j < TOWN_DUNGEON; j++)
{
int town_idx = d_ptr->t_idx[j];
@@ -4038,136 +3668,51 @@ void do_cmd_knowledge_towns(void)
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]);
+ w.write(" {}: Level {}\n",
+ d_ptr->name,
+ 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);
+ show_string(w.c_str(), "Dungeon Towns");
}
/*
* 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);
-
- /* 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)
+static void do_cmd_knowledge_corruptions()
{
- 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)++;
+ show_string(dump_corruptions(true, false).c_str(), "Corruptions");
}
/*
* Print quest status of all active quests
*/
-static void do_cmd_knowledge_quests(void)
+static void do_cmd_knowledge_quests()
{
- FILE *fff;
-
- char file_name[1024];
-
- int *order;
-
- 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");
-
- C_MAKE(order, max_q_idx, int);
-
- for (i = 0; i < max_q_idx; i++)
- {
- insert_sort_quest(order, &num, i);
- }
-
- for (z = 0; z < max_q_idx; z++)
+ /* Figure out display order of quests */
+ int order[MAX_Q_IDX];
+ std::iota(order, order + MAX_Q_IDX, 0); // Start with order of definition
+ std::sort(order, order + MAX_Q_IDX, [](int qi, int qj) -> bool {
+ return (quest[qi].level < quest[qj].level);
+ });
+
+ /* Write */
+ fmt::MemoryWriter w;
+ for (int z = 0; z < MAX_Q_IDX; z++)
{
- i = order[z];
+ int const i = order[z];
- /* Dynamic quests */
- if (quest[i].dynamic_desc)
+ /* Dynamic descriptions */
+ if (quest[i].gen_desc != NULL)
{
- /* C type quests */
- if (quest[i].type == HOOK_TYPE_C)
+ auto s = quest[i].gen_desc();
+ if (!s.empty())
{
- if (!quest[i].gen_desc(fff))
- {
- continue;
- }
- }
- /* MUST be a lua quest */
- else
- {
- hook_file = fff;
- exec_lua(format("__quest_dynamic_desc[%d]()", i));
+ w.write("{}\n\n", s);
}
}
@@ -4177,70 +3722,42 @@ static void do_cmd_knowledge_quests(void)
if (quest[i].status == QUEST_STATUS_TAKEN)
{
/* Print the quest info */
- fprintf(fff, "#####y%s (Danger level: %d)\n",
+ w.write("#####y{} (Danger level: {})\n",
quest[i].name, quest[i].level);
- j = 0;
+ int j = 0;
while ((j < 10) && (quest[i].desc[j][0] != '\0'))
{
- fprintf(fff, "%s\n", quest[i].desc[j++]);
+ w.write("{}\n", quest[i].desc[j++]);
}
- fprintf(fff, "\n");
+ w.write("\n");
}
else if (quest[i].status == QUEST_STATUS_COMPLETED)
{
- fprintf(fff , "#####G%s Completed - Unrewarded\n", quest[i].name);
- fprintf(fff, "\n");
+ w.write("#####G{} Completed - Unrewarded\n", quest[i].name);
+ w.write("\n");
}
}
}
- C_FREE(order, max_q_idx, int);
-
- /* 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);
+ /* Display */
+ show_string(w.c_str(), "Quest status");
}
/*
* Print fate status
*/
-static void do_cmd_knowledge_fates(void)
+static void do_cmd_knowledge_fates()
{
- 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);
+ show_string(dump_fates().c_str(), "Fate status");
}
/*
* Print the note file
*/
-void do_cmd_knowledge_notes(void)
+void do_cmd_knowledge_notes()
{
/* Spawn */
show_notes_file();
@@ -4253,14 +3770,11 @@ void do_cmd_knowledge_notes(void)
/*
* Interact with "knowledge"
*/
-void do_cmd_knowledge(void)
+void do_cmd_knowledge()
{
int i;
- /* File type is "TEXT" */
- FILE_TYPE(FILE_TYPE_TEXT);
-
/* Enter "icky" mode */
character_icky = TRUE;
@@ -4286,12 +3800,11 @@ void do_cmd_knowledge(void)
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);
- if (take_notes) prt("(B) Display notes", 15, 5);
+ prt("(0) Display known dungeon towns", 13, 5);
+ prt("(A) Display notes", 14, 5);
/* Prompt */
- prt("Command: ", 17, 0);
+ prt("Command: ", 16, 0);
/* Prompt */
i = inkey();
@@ -4373,17 +3886,8 @@ void do_cmd_knowledge(void)
break;
}
- /* Traps */
- case '0':
- {
- do_cmd_knowledge_traps();
-
- break;
- }
-
/* Dungeon towns */
- case 'A':
- case 'a':
+ case '0':
{
do_cmd_knowledge_towns();
@@ -4391,11 +3895,10 @@ void do_cmd_knowledge(void)
}
/* Notes */
- case 'B':
- case 'b':
+ case 'A':
+ case 'a':
{
- if (take_notes) do_cmd_knowledge_notes();
- else bell();
+ do_cmd_knowledge_notes();
break;
}
@@ -4425,11 +3928,8 @@ void do_cmd_knowledge(void)
* Check on the status of an active quest -KMW-
* TODO: Spill out status when not a simple kill # monster.
*/
-void do_cmd_checkquest(void)
+void do_cmd_checkquest()
{
- /* File type is "TEXT" */
- FILE_TYPE(FILE_TYPE_TEXT);
-
/* Enter "icky" mode */
character_icky = TRUE;
@@ -4482,16 +3982,12 @@ void do_cmd_change_movement(int i)
*/
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;
@@ -4508,12 +4004,11 @@ void do_cmd_time()
/* 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);
+ /* Display day */
+ auto days = bst(DAY, turn) + 1;
+ auto days_str = get_day(days);
+ msg_format("This is the %s day of your adventure.",
+ days_str.c_str());
/* Message */
msg_format("The time is %d:%02d %s.",
@@ -4596,57 +4091,58 @@ void do_cmd_time()
* 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;
+
+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.");
- C_MAKE(macro_recorder_current, 1, char);
- macro_recorder_current[0] = '\0';
+ assert (macro_recorder_current == nullptr);
+ macro_recorder_current = new std::string();
}
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);
+ // 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()
{
- char *str, *macro;
- char buf[1024];
+ assert(macro_recorder_current != nullptr);
- /* Ok we remove the last key, because it is the key to stop recording */
- macro_recorder_current[strlen(macro_recorder_current) - 1] = '\0';
+ // Remove the last key, because it is the key to stop recording
+ macro_recorder_current->pop_back();
- /* Stop the recording */
- macro = macro_recorder_current;
- macro_recorder_current = NULL;
+ // 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);
+ macro_add(buf, macro.c_str());
/* 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);
+ std::unique_ptr<char[]> 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());
}
-
- /* Ok now rid of useless stuff */
- C_FREE(macro, strlen(macro) + 1, char);
}
void do_cmd_macro_recorder()
diff --git a/src/cmd4.hpp b/src/cmd4.hpp
new file mode 100644
index 00000000..39f1c16c
--- /dev/null
+++ b/src/cmd4.hpp
@@ -0,0 +1,28 @@
+#pragma once
+
+#include "h-basic.h"
+
+void macro_recorder_start();
+void macro_recorder_add(char c);
+void macro_recorder_stop();
+void do_cmd_macro_recorder();
+void do_cmd_redraw();
+void do_cmd_change_name();
+void do_cmd_message_one();
+void do_cmd_messages();
+void do_cmd_options();
+void do_cmd_pref();
+void do_cmd_macros();
+void do_cmd_visuals();
+void do_cmd_colors();
+void do_cmd_note();
+void do_cmd_version();
+void do_cmd_feeling();
+void do_cmd_load_screen();
+void do_cmd_save_screen();
+void do_cmd_knowledge();
+void do_cmd_checkquest();
+void do_cmd_change_tactic(int i);
+void do_cmd_change_movement(int i);
+void do_cmd_time();
+void do_cmd_options_aux(int page, cptr info, bool_ read_only);
diff --git a/src/cmd5.c b/src/cmd5.cc
index b415b166..a93759b0 100644
--- a/src/cmd5.c
+++ b/src/cmd5.cc
@@ -1,7 +1,3 @@
-/* File: cmd5.c */
-
-/* Purpose: Class commands */
-
/*
* Copyright (c) 1989 James E. Wilson, Robert A. Koeneke
*
@@ -10,61 +6,86 @@
* included in all such copies.
*/
-
-#include "angband.h"
-#include "lua/lua.h"
-#include "tolua.h"
-
-extern lua_State *L;
-
+#include "cmd5.hpp"
+
+#include "birth.hpp"
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "corrupt.hpp"
+#include "dungeon_flag.hpp"
+#include "game.hpp"
+#include "lua_bind.hpp"
+#include "monster2.hpp"
+#include "monster_race.hpp"
+#include "monster_race_flag.hpp"
+#include "monster_spell_flag.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_flag.hpp"
+#include "object_type.hpp"
+#include "player_class.hpp"
+#include "player_race.hpp"
+#include "player_race_mod.hpp"
+#include "player_type.hpp"
+#include "school_book.hpp"
+#include "skills.hpp"
+#include "spell_type.hpp"
+#include "spells1.hpp"
+#include "spells2.hpp"
+#include "spells4.hpp"
+#include "spells5.hpp"
+#include "stats.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "util.h"
+#include "variable.h"
+#include "variable.hpp"
+#include "wizard2.hpp"
+#include "xtra1.hpp"
+#include "xtra2.hpp"
+#include "z-rand.hpp"
+
+#include <boost/noncopyable.hpp>
+#include <boost/optional.hpp>
+#include <cassert>
/* Maximum number of tries for teleporting */
#define MAX_TRIES 300
-bool_ is_school_book(object_type *o_ptr)
+static object_filter_t const &is_school_book()
{
- 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;
- }
+ using namespace object_filter;
+ static auto instance = Or(
+ TVal(TV_BOOK),
+ TVal(TV_DAEMON_BOOK),
+ TVal(TV_INSTRUMENT));
+ return instance;
}
/* Does it contains a schooled spell ? */
-static bool_ hook_school_spellable(object_type *o_ptr)
+static object_filter_t const &hook_school_spellable()
{
- 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;
+ using namespace object_filter;
+ static auto has_pval2 =
+ [=](object_type const *o_ptr) -> bool {
+ return (o_ptr->pval2 != -1);
+ };
+ static auto instance = Or(
+ is_school_book(),
+ And(
+ HasFlags(TR_SPELL_CONTAIN),
+ has_pval2));
+ return instance;
}
-/* Is it a book */
-bool_ item_tester_hook_browsable(object_type *o_ptr)
+/* Is it a browsable for spells? */
+static object_filter_t const &item_tester_hook_browsable()
{
- if (hook_school_spellable(o_ptr)) return TRUE;
- if (o_ptr->tval >= TV_BOOK) return TRUE;
- return FALSE;
+ using namespace object_filter;
+ static auto instance = Or(
+ hook_school_spellable(),
+ TVal(TV_BOOK));
+ return instance;
}
/*
@@ -95,6 +116,106 @@ bool_ is_magestaff()
return (FALSE);
}
+
+static int print_book(s16b sval, s32b spell_idx, object_type *obj)
+{
+ int y = 2;
+ int i;
+
+ random_book_setup(sval, spell_idx);
+
+ school_book *school_book = school_books_at(sval);
+
+ /* Parse all spells */
+ i = 0;
+ for (auto spell_idx : school_book->spell_idxs)
+ {
+ byte color = TERM_L_DARK;
+ bool_ is_ok;
+ char label[8];
+
+ is_ok = is_ok_spell(spell_idx, obj->pval);
+ if (is_ok)
+ {
+ color = (get_mana(spell_idx) > get_power(spell_idx)) ? TERM_ORANGE : TERM_L_GREEN;
+ }
+
+ sprintf(label, "%c) ", 'a' + i);
+
+ y = print_spell(label, color, y, spell_idx);
+ i++;
+ }
+
+ prt(format(" %-20s%-16s Level Cost Fail Info", "Name", "School"), 1, 0);
+ return y;
+}
+
+
+
+static void browse_school_spell(int book, int spell_idx, object_type *o_ptr)
+{
+ int i;
+ int num = 0;
+ 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 */
+ print_book(book, spell_idx, o_ptr);
+
+ /* Get a spell from the user */
+ while (get_com(out_val, &choice))
+ {
+ /* Display a list of spells */
+ print_book(book, spell_idx, 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 */
+ auto where = print_book(book, spell_idx, o_ptr);
+ print_spell_desc(spell_x(book, spell_idx, i), where);
+ }
+
+
+ /* Restore the screen */
+ Term_load();
+ character_icky = FALSE;
+
+ /* Show choices */
+ window_stuff();
+}
+
+
/*
* Peruse the spells/prayers in a book
*
@@ -104,40 +225,40 @@ bool_ is_magestaff()
* and in the dark, primarily to allow browsing in stores.
*/
-extern void do_cmd_browse_aux(object_type *o_ptr)
+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);
+ auto const flags = object_flags(o_ptr);
- if (is_school_book(o_ptr))
+ 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)
+ }
+ else if ((flags & TR_SPELL_CONTAIN) && (o_ptr->pval2 != -1))
+ {
browse_school_spell(255, o_ptr->pval2, o_ptr);
+ }
}
-void do_cmd_browse(void)
+void do_cmd_browse()
{
- 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;
+ int item;
+ if (!get_item(&item,
+ "Browse which book? ",
+ "You have no books that you can read.",
+ (USE_INVEN | USE_EQUIP | USE_FLOOR),
+ item_tester_hook_browsable()))
+ {
+ return;
+ }
/* Get the item */
- o_ptr = get_object(item);
+ object_type *o_ptr = get_object(item);
do_cmd_browse_aux(o_ptr);
}
-void do_poly_wounds(void)
+static void do_poly_wounds()
{
/* Changed to always provide at least _some_ healing */
s16b wounds = p_ptr->cut;
@@ -165,8 +286,10 @@ void do_poly_wounds(void)
}
}
-void do_poly_self(void)
+void do_poly_self()
{
+ auto const &race_info = game->edit_data.race_info;
+
int power = p_ptr->lev;
int poly_power;
@@ -180,25 +303,6 @@ void do_poly_self(void)
/* 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;
@@ -210,14 +314,14 @@ void do_poly_self(void)
{
if ( rand_int(2) == 0)
{
- (void)dec_stat(tmp, randint(6) + 6, (rand_int(3) == 0));
+ 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);
+ dec_stat(A_CHR, randint(6), TRUE);
if (effect_msg[0])
{
@@ -236,7 +340,7 @@ void do_poly_self(void)
/* Polymorph into a less corrupted form */
power -= 10;
- lose_corruption(0);
+ lose_corruption();
}
/*
@@ -256,38 +360,38 @@ void do_poly_self(void)
/* Roll until an appropriate selection is made */
while (1)
{
- new_race = rand_int(max_rp_idx);
- expfact = race_info[new_race].r_exp;
+ new_race = rand_int(race_info.size());
+ expfact = race_info[new_race].ps.exp;
- if ((new_race != p_ptr->prace) && (expfact <= goalexpfact)) break;
+ 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);
+ (is_a_vowel(race_info[new_race].title[0]) ? "n" : ""),
+ race_info[new_race].title.c_str());
}
else
{
msg_format("You turn into a %s %s!", effect_msg,
- race_info[new_race].title);
+ race_info[new_race].title.c_str());
}
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();
-
+ p_ptr->expfact = rp_ptr->ps.exp + rmp_ptr->ps.exp + cp_ptr->ps.exp;
+ /* Level up if necessary */
check_experience();
p_ptr->max_plv = p_ptr->lev;
- p_ptr->redraw |= (PR_BASIC);
+ p_ptr->redraw |= (PR_FRAME);
p_ptr->update |= (PU_BONUS);
@@ -305,7 +409,7 @@ void do_poly_self(void)
msg_print("Your internal organs are rearranged!");
while (tmp < 6)
{
- (void)dec_stat(tmp, randint(6) + 6, (rand_int(3) == 0));
+ dec_stat(tmp, randint(6) + 6, (rand_int(3) == 0));
tmp++;
}
if (rand_int(6) == 0)
@@ -326,7 +430,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))
@@ -343,138 +447,24 @@ void do_poly_self(void)
}
}
-
-/*
- * 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)
+ if (!cave[p_ptr->py][p_ptr->px].o_idxs.empty())
{
msg_print("You can't fetch when you're already standing on something.");
return;
}
/* Use a target */
+ cave_type *c_ptr = nullptr;
if ((dir == 5) && target_okay())
{
- tx = target_col;
- ty = target_row;
+ int tx = target_col;
+ int ty = target_row;
if (distance(p_ptr->py, p_ptr->px, ty, tx) > MAX_RANGE)
{
@@ -484,7 +474,7 @@ void fetch(int dir, int wgt, bool_ require_los)
c_ptr = &cave[ty][tx];
- if (!c_ptr->o_idx)
+ if (c_ptr->o_idxs.empty())
{
msg_print("There is no object at this place.");
return;
@@ -499,8 +489,8 @@ void fetch(int dir, int wgt, bool_ require_los)
else
{
/* Use a direction */
- ty = p_ptr->py; /* Where to drop the item */
- tx = p_ptr->px;
+ int ty = p_ptr->py; /* Where to drop the item */
+ int tx = p_ptr->px;
while (1)
{
@@ -511,12 +501,17 @@ void fetch(int dir, int wgt, bool_ require_los)
if ((distance(p_ptr->py, p_ptr->px, ty, tx) > MAX_RANGE) ||
!cave_floor_bold(ty, tx)) return;
- if (c_ptr->o_idx) break;
+ if (!c_ptr->o_idxs.empty()) break;
}
}
- o_ptr = &o_list[c_ptr->o_idx];
+ assert(c_ptr != nullptr);
+ assert(!c_ptr->o_idxs.empty());
+
+ /* Pick object from the list */
+ auto o_idx = c_ptr->o_idxs.front();
+ object_type *o_ptr = &o_list[o_idx];
if (o_ptr->weight > wgt)
{
/* Too heavy to 'fetch' */
@@ -524,13 +519,16 @@ void fetch(int dir, int wgt, bool_ require_los)
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;
+ /* Move the object between the lists */
+ c_ptr->o_idxs.erase(c_ptr->o_idxs.begin()); // Remove
+ cave[p_ptr->py][p_ptr->px].o_idxs.push_back(o_idx); // Add
+
+ /* Update object's location */
o_ptr->iy = p_ptr->py;
o_ptr->ix = p_ptr->px;
+ /* Feedback */
+ char o_name[80];
object_desc(o_name, o_ptr, TRUE, 0);
msg_format("%^s flies through the air to your feet.", o_name);
@@ -540,477 +538,202 @@ void fetch(int dir, int wgt, bool_ require_los)
/*
- * Handle random effects of player shrieking
+ * Return the symbiote's name or description.
*/
-void shriek_effect()
+std::string symbiote_name(bool capitalize)
{
- 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);
+ auto const &r_info = game->edit_data.r_info;
- break;
- }
- case 3:
- case 7:
- {
- msg_print("The dungeon collapses!");
- earthquake(p_ptr->py, p_ptr->px, 5);
+ object_type *o_ptr = &p_ptr->inventory[INVEN_CARRY];
- 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");
+ std::string buf;
+ buf.reserve(32);
- break;
- }
+ // Fallback; shouldn't ever be necessary
+ if (!o_ptr->k_idx)
+ {
+ buf += "A non-existent symbiote";
}
-}
-
-
-/*
- * 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)
+ else
{
- 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);
+ auto r_ptr = &r_info[o_ptr->pval];
+ std::size_t i = 0;
- 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:
+ if (r_ptr->flags & RF_UNIQUE)
{
- /* Prevent destruction of quest levels and town */
- if (!is_quest(dun_level) && dun_level)
- earthquake(p_ptr->py, p_ptr->px, 5);
-
- break;
+ // Unique monster; no preceding "your" and ignore name
+ buf += r_ptr->name;
}
-
- case 27:
- case 28:
+ else if ((i = o_ptr->inscription.find("#named ")) != std::string::npos)
{
- break;
+ // We've named it; extract the name */
+ buf += o_ptr->inscription.substr(i);
}
-
- 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:
+ else
{
- summon_cyber();
-
- /* I don't think this is a fall through -- pelpel */
- break;
+ // No special cases; just return "Your <monster type>".
+ buf += "your ";
+ buf += r_ptr->name;
}
+ }
- default:
- {
- activate_ty_curse();
- }
+ // Capitalize?
+ if (capitalize)
+ {
+ buf[0] = toupper(buf[0]);
}
- return;
+ // Done
+ return buf;
}
/*
- * Hack -- Determine if the player is wearing an artefact ring
- * specified by art_type, that should be an index into a_info
+ * Find monster power
*/
-bool_ check_ring(int art_type)
+monster_power const *lookup_monster_power(std::size_t idx)
{
- 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)
+ for (auto const &p: monster_powers)
{
- /* Found the ring we were looking for */
- if (p_ptr->inventory[i].k_idx && (p_ptr->inventory[i].name1 == art_type))
+ if (p.monster_spell_index == idx)
{
- return (TRUE);
+ return &p;
}
-
- /* Next item */
- i++;
}
-
- /* Found nothing */
- return (FALSE);
+ return nullptr;
}
+
/*
- * Return the symbiote's name or description.
+ * Extract powers
*/
-cptr symbiote_name(bool_ capitalize)
+std::vector<monster_power const *> extract_monster_powers(monster_race const *r_ptr, bool great)
{
- object_type *o_ptr = &p_ptr->inventory[INVEN_CARRY];
- static char buf[80];
+ std::vector<monster_power const *> powers;
+ powers.reserve(MONSTER_POWERS_MAX);
- /* Make sure there actually is a symbiote there... */
- if (!o_ptr->k_idx)
+ for (std::size_t i = 0; i < monster_spell_flag_set::nbits; i++)
{
- 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
+ if (r_ptr->spells.bit(i))
{
- /* No special cases, just return "Your <monster type>". */
- strcpy(buf, "your ");
- strncpy(buf + 5, r_name + r_ptr->name, sizeof(buf) - 5);
+ if (auto power = lookup_monster_power(i))
+ {
+ if (power->great && (!great))
+ {
+ continue;
+ }
+ powers.push_back(power);
+ }
}
}
- /* Just in case... */
- buf[sizeof(buf) - 1] = '\0';
- if (capitalize) buf[0] = toupper(buf[0]);
- return buf;
+ return powers;
}
-/*
- * Use a power of the monster in symbiosis
+/**
+ * Calculate mana required for a given monster power.
*/
-int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost)
+static int calc_monster_spell_mana(monster_power const *mp_ptr)
{
- int power = -1;
-
- int num = 0, dir = 0 , i;
-
- int powers[96];
-
- bool_ flag, redraw;
-
- 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;
- }
- }
+ int mana = mp_ptr->mana / 10;
+ if (mana > p_ptr->msp) mana = p_ptr->msp;
+ if (!mana) mana = 1;
+ return mana;
+}
- /* 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;
- }
- }
+/**
+ * Choose a monster power
+ */
+static std::tuple<int, int> choose_monster_power(monster_race const *r_ptr, bool great, bool symbiosis)
+{
+ /* Extract available monster powers */
+ auto powers = extract_monster_powers(r_ptr, great);
+ int const num = powers.size(); // Avoid signed/unsigned warnings
if (!num)
{
msg_print("You have no powers you can use.");
- return (0);
+ return std::make_tuple(0, num);
}
- if (only_number) return (num);
-
- /* Nothing chosen yet */
- flag = FALSE;
-
- /* No redraw yet */
- redraw = FALSE;
-
/* Get the last label */
- label = (num <= 26) ? I2A(num - 1) : I2D(num - 1 - 26);
+ int 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 */
+ char out_val[160];
strnfmt(out_val, 78,
- "(Powers a-%c, *=List, ESC=exit) Use which power of your %s? ",
- label, (no_cost ? "symbiote" : "body"));
+ "(Powers a-%c, ESC=exit) Use which power of your %s? ",
+ label, (symbiosis ? "symbiote" : "body"));
+
+ /* Save the screen */
+ character_icky = TRUE;
+ Term_save();
/* Get a spell from the user */
- while (!flag && get_com(out_val, &choice))
+ monster_power const *power = nullptr;
+ bool_ flag = FALSE; // Nothing chosen yet
+ 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);
- /* Show list */
- redraw = TRUE;
-
- /* Save the screen */
- character_icky = TRUE;
- Term_save();
+ while (ctr < num)
+ {
+ monster_power const *mp_ptr = powers[ctr];
- prt ("", y++, x);
+ label = (ctr < 26) ? I2A(ctr) : I2D(ctr - 26);
- while (ctr < num)
+ byte color = TERM_L_GREEN;
+ if (!symbiosis)
{
- 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);
+ int mana = calc_monster_spell_mana(mp_ptr);
+ strnfmt(dummy, 80, " %c) %2d %s",
+ label, mana, mp_ptr->name);
+ // Gray out if player doesn't have enough mana to cast.
+ if (mana > p_ptr->csp) {
+ color = TERM_L_DARK;
}
-
- ctr++;
+ }
+ else
+ {
+ strnfmt(dummy, 80, " %c) %s",
+ label, mp_ptr->name);
}
if (ctr < 17)
{
- prt ("", y + ctr, x);
+ c_prt(color, dummy, y + ctr, x);
}
else
{
- prt ("", y + 17, x);
+ c_prt(color, 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;
+ char choice;
+ if (!get_com(out_val, &choice))
+ {
+ flag = FALSE;
+ break;
}
if (choice == '\r' && num == 1)
@@ -1018,6 +741,8 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
choice = 'a';
}
+ int i;
+ int ask;
if (isalpha(choice))
{
/* Note verify */
@@ -1044,16 +769,26 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
continue;
}
- /* Save the spell index */
+ /* Save the spell */
power = powers[i];
+ /* Make sure it's actually possible for the player to cast */
+ if (!symbiosis)
+ {
+ if (p_ptr->csp < calc_monster_spell_mana(power))
+ {
+ bell();
+ continue;
+ }
+ }
+
/* Verify it */
if (ask)
{
char tmp_val[160];
/* Prompt */
- strnfmt(tmp_val, 78, "Use %s? ", monster_powers[power].name);
+ strnfmt(tmp_val, 78, "Use %s? ", power->name);
/* Belay that order */
if (!get_check(tmp_val)) continue;
@@ -1064,62 +799,64 @@ 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)
+ if (!flag || (power == nullptr))
{
- energy_use = 0;
- return -1;
+ return std::make_tuple(-1, num);
}
- /* 'Powerful' monsters have wider radii */
- if (r_ptr->flags2 & RF2_POWERFUL)
- {
- rad = 1 + (p_ptr->lev / 15);
- }
- else
- {
- rad = 1 + (p_ptr->lev / 20);
- }
+ return std::make_tuple(power->monster_spell_index, num);
+}
+
+
+/*
+ * Apply the effect of a monster power
+ */
+static void apply_monster_power(monster_race const *r_ptr, std::size_t monster_spell_idx)
+{
+ assert(monster_spell_idx < monster_spell_flag_set::nbits);
+ /* Shorthand */
+ int const x = p_ptr->px;
+ int const y = p_ptr->py;
+ int const plev = p_ptr->lev;
+ int const rlev = ((r_ptr->level >= 1) ? r_ptr->level : 1);
+
+ /* 'Powerful' monsters have wider radii */
+ int rad = (r_ptr->flags & RF_POWERFUL)
+ ? 1 + (p_ptr->lev / 15)
+ : 1 + (p_ptr->lev / 20);
/* Analyse power */
- switch (power)
+ switch (monster_spell_idx)
{
- /**** RF4 (bit position) ****/
-
- /* SHRIEK */
- case 0:
+ case SF_SHRIEK_IDX:
{
aggravate_monsters( -1);
break;
}
- /* MULTIPLY */
- case 1:
+ case SF_MULTIPLY_IDX:
{
do_cmd_wiz_named_friendly(p_ptr->body_monster, FALSE);
break;
}
- /* S_ANIMAL */
- case 2:
+ case SF_S_ANIMAL_IDX:
{
summon_specific_friendly(y, x, rlev, SUMMON_ANIMAL, TRUE);
break;
}
- /* ROCKET */
- case 3:
+ case SF_ROCKET_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_ball(GF_ROCKET, dir, p_ptr->lev * 12, 1 + (p_ptr->lev / 20));
@@ -1127,9 +864,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* ARROW_1 */
- case 4:
+ case SF_ARROW_1_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_bolt(GF_ARROW, dir, damroll(1, 6));
@@ -1137,9 +874,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* ARROW_2 */
- case 5:
+ case SF_ARROW_2_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_bolt(GF_ARROW, dir, damroll(3, 6));
@@ -1147,9 +884,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* ARROW_3 */
- case 6:
+ case SF_ARROW_3_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_bolt(GF_ARROW, dir, damroll(5, 6));
@@ -1157,9 +894,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* ARROW_4 */
- case 7:
+ case SF_ARROW_4_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_bolt(GF_ARROW, dir, damroll(7, 6));
@@ -1167,9 +904,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BR_ACID */
- case 8:
+ case SF_BR_ACID_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_ball(GF_ACID, dir, p_ptr->lev * 5, rad);
@@ -1177,9 +914,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BR_ELEC */
- case 9:
+ case SF_BR_ELEC_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_ball(GF_ELEC, dir, p_ptr->lev * 5, rad);
@@ -1187,9 +924,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BR_FIRE */
- case 10:
+ case SF_BR_FIRE_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_ball(GF_FIRE, dir, p_ptr->lev * 5, rad);
@@ -1197,9 +934,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BR_COLD */
- case 11:
+ case SF_BR_COLD_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_ball(GF_COLD, dir, p_ptr->lev * 5, rad);
@@ -1207,9 +944,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BR_POIS */
- case 12:
+ case SF_BR_POIS_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_ball(GF_POIS, dir, p_ptr->lev * 5, rad);
@@ -1217,9 +954,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BR_NETH */
- case 13:
+ case SF_BR_NETH_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_ball(GF_NETHER, dir, p_ptr->lev * 5, rad);
@@ -1227,9 +964,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BR_LITE */
- case 14:
+ case SF_BR_LITE_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_ball(GF_LITE, dir, p_ptr->lev * 8, rad);
@@ -1237,9 +974,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BR_DARK */
- case 15:
+ case SF_BR_DARK_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_ball(GF_DARK, dir, p_ptr->lev * 8, rad);
@@ -1247,9 +984,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BR_CONF */
- case 16:
+ case SF_BR_CONF_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_ball(GF_CONFUSION, dir, p_ptr->lev * 8, rad);
@@ -1257,9 +994,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BR_SOUN */
- case 17:
+ case SF_BR_SOUN_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_ball(GF_SOUND, dir, p_ptr->lev * 8, rad);
@@ -1267,9 +1004,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BR_CHAO */
- case 18:
+ case SF_BR_CHAO_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_ball(GF_CHAOS, dir, p_ptr->lev * 7, rad);
@@ -1277,9 +1014,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BR_DISE */
- case 19:
+ case SF_BR_DISE_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_ball(GF_DISENCHANT, dir, p_ptr->lev * 7, rad);
@@ -1287,9 +1024,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BR_NEXU */
- case 20:
+ case SF_BR_NEXU_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_ball(GF_NEXUS, dir, p_ptr->lev * 5, rad);
@@ -1297,9 +1034,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BR_TIME */
- case 21:
+ case SF_BR_TIME_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_ball(GF_TIME, dir, p_ptr->lev * 3, rad);
@@ -1307,9 +1044,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BR_INER */
- case 22:
+ case SF_BR_INER_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_ball(GF_INERTIA, dir, p_ptr->lev * 4, rad);
@@ -1317,9 +1054,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BR_GRAV */
- case 23:
+ case SF_BR_GRAV_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_ball(GF_GRAVITY, dir, p_ptr->lev * 4, rad);
@@ -1327,9 +1064,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BR_SHAR */
- case 24:
+ case SF_BR_SHAR_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_ball(GF_SHARDS, dir, p_ptr->lev * 8, rad);
@@ -1337,9 +1074,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BR_PLAS */
- case 25:
+ case SF_BR_PLAS_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_ball(GF_PLASMA, dir, p_ptr->lev * 3, rad);
@@ -1347,9 +1084,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BR_WALL */
- case 26:
+ case SF_BR_WALL_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_ball(GF_FORCE, dir, p_ptr->lev * 4, rad);
@@ -1357,9 +1094,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BR_MANA */
- case 27:
+ case SF_BR_MANA_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_ball(GF_MANA, dir, p_ptr->lev * 5, rad);
@@ -1367,9 +1104,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BA_NUKE */
- case 28:
+ case SF_BA_NUKE_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_ball(GF_NUKE, dir, p_ptr->lev * 8, 1 + (p_ptr->lev / 20));
@@ -1377,9 +1114,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BR_NUKE */
- case 29:
+ case SF_BR_NUKE_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_ball(GF_NUKE, dir, p_ptr->lev * 8, 1 + (p_ptr->lev / 20));
@@ -1387,9 +1124,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BA_CHAO */
- case 30:
+ case SF_BA_CHAO_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_ball(GF_CHAOS, dir, p_ptr->lev * 4, 2);
@@ -1397,9 +1134,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BR_DISI */
- case 31:
+ case SF_BR_DISI_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_ball(GF_DISINTEGRATE, dir, p_ptr->lev * 5, 1 + (p_ptr->lev / 20));
@@ -1407,12 +1144,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
-
- /**** RF5 (bit position + 32) ****/
-
- /* BA_ACID */
- case 32:
+ case SF_BA_ACID_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_ball(GF_ACID, dir, randint(p_ptr->lev * 6) + 20, 2);
@@ -1420,9 +1154,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BA_ELEC */
- case 33:
+ case SF_BA_ELEC_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_ball(GF_ELEC, dir, randint(p_ptr->lev * 3) + 20, 2);
@@ -1430,9 +1164,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BA_FIRE */
- case 34:
+ case SF_BA_FIRE_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_ball(GF_FIRE, dir, randint(p_ptr->lev * 7) + 20, 2);
@@ -1440,9 +1174,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BA_COLD */
- case 35:
+ case SF_BA_COLD_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_ball(GF_COLD, dir, randint(p_ptr->lev * 3) + 20, 2);
@@ -1450,9 +1184,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BA_POIS */
- case 36:
+ case SF_BA_POIS_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_ball(GF_POIS, dir, damroll(12, 2), 2);
@@ -1460,9 +1194,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BA_NETH */
- case 37:
+ case SF_BA_NETH_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_ball(GF_NETHER, dir, randint(p_ptr->lev * 4) + 20, 2);
@@ -1470,9 +1204,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BA_WATE */
- case 38:
+ case SF_BA_WATE_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_ball(GF_WATER, dir, randint(p_ptr->lev * 4) + 20, 2);
@@ -1480,9 +1214,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BA_MANA */
- case 39:
+ case SF_BA_MANA_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_ball(GF_MANA, dir, randint(p_ptr->lev * 3) + 20, 2);
@@ -1490,9 +1224,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BA_DARK */
- case 40:
+ case SF_BA_DARK_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_ball(GF_DARK, dir, randint(p_ptr->lev * 3) + 20, 2);
@@ -1500,15 +1234,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* 41 DRAIN_MANA -- Not available */
-
- /* 42 MIND_BLAST -- Not available */
-
- /* 43 BRAIN_SMASH -- Not available */
-
- /* CAUSE_1 */
- case 44:
+ case SF_CAUSE_1_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_bolt(GF_MANA, dir, damroll(3, 8));
@@ -1516,9 +1244,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* CAUSE_2 */
- case 45:
+ case SF_CAUSE_2_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_bolt(GF_MANA, dir, damroll(8, 8));
@@ -1526,9 +1254,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* CAUSE_3 */
- case 46:
+ case SF_CAUSE_3_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_bolt(GF_MANA, dir, damroll(10, 15));
@@ -1536,9 +1264,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* CAUSE_4 */
- case 47:
+ case SF_CAUSE_4_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_bolt(GF_MANA, dir, damroll(15, 15));
@@ -1546,9 +1274,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BO_ACID */
- case 48:
+ case SF_BO_ACID_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_bolt(GF_ACID, dir, damroll(7, 8) + (p_ptr->lev / 3));
@@ -1556,9 +1284,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BO_ELEC */
- case 49:
+ case SF_BO_ELEC_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_bolt(GF_ELEC, dir, damroll(4, 8) + (p_ptr->lev / 3));
@@ -1566,9 +1294,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BO_FIRE */
- case 50:
+ case SF_BO_FIRE_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_bolt(GF_FIRE, dir, damroll(9, 8) + (p_ptr->lev / 3));
@@ -1576,9 +1304,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BO_COLD */
- case 51:
+ case SF_BO_COLD_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_bolt(GF_COLD, dir, damroll(6, 8) + (p_ptr->lev / 3));
@@ -1586,9 +1314,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BO_POIS */
- case 52:
+ case SF_BO_POIS_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_bolt(GF_POIS, dir, damroll(7, 8) + (p_ptr->lev / 3));
@@ -1596,9 +1324,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BO_NETH */
- case 53:
+ case SF_BO_NETH_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_bolt(GF_NETHER, dir, damroll(5, 5) + (p_ptr->lev / 3));
@@ -1606,9 +1334,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BO_WATE */
- case 54:
+ case SF_BO_WATE_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_bolt(GF_WATER, dir, damroll(10, 10) + (p_ptr->lev / 3));
@@ -1616,9 +1344,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BO_MANA */
- case 55:
+ case SF_BO_MANA_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_bolt(GF_MANA, dir, damroll(3, 8) + (p_ptr->lev / 3));
@@ -1626,9 +1354,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BO_PLAS */
- case 56:
+ case SF_BO_PLAS_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_bolt(GF_PLASMA, dir, damroll(8, 8) + (p_ptr->lev / 3));
@@ -1636,9 +1364,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BO_ICEE */
- case 57:
+ case SF_BO_ICEE_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_bolt(GF_ICE, dir, damroll(6, 6) + (p_ptr->lev / 3));
@@ -1646,9 +1374,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* MISSILE */
- case 58:
+ case SF_MISSILE_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_bolt(GF_MISSILE, dir, damroll(2, 6) + (p_ptr->lev / 3));
@@ -1656,9 +1384,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* SCARE */
- case 59:
+ case SF_SCARE_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fear_monster(dir, plev);
@@ -1666,9 +1394,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BLIND */
- case 60:
+ case SF_BLIND_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_bolt(GF_CONFUSION, dir, damroll(1, 8) + (p_ptr->lev / 3));
@@ -1676,9 +1404,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* CONF */
- case 61:
+ case SF_CONF_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_bolt(GF_CONFUSION, dir, damroll(7, 8) + (p_ptr->lev / 3));
@@ -1686,9 +1414,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* SLOW */
- case 62:
+ case SF_SLOW_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_bolt(GF_OLD_SLOW, dir, damroll(6, 8) + (p_ptr->lev / 3));
@@ -1696,9 +1424,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* HOLD */
- case 63:
+ case SF_HOLD_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_bolt(GF_OLD_SLEEP, dir, damroll(5, 8) + (p_ptr->lev / 3));
@@ -1706,27 +1434,23 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
-
- /**** RF6 (bit position + 64) ****/
-
- /* HASTE */
- case 64:
+ case SF_HASTE_IDX:
{
if (!p_ptr->fast)
{
- (void)set_fast(randint(20 + (plev) ) + plev, 10);
+ set_fast(randint(20 + (plev) ) + plev, 10);
}
else
{
- (void)set_fast(p_ptr->fast + randint(5), 10);
+ set_fast(p_ptr->fast + randint(5), 10);
}
break;
}
- /* HAND_DOOM */
- case 65:
+ case SF_HAND_DOOM_IDX:
{
+ int dir;
if (!get_aim_dir(&dir)) break;
fire_bolt(GF_MANA, dir, damroll(10, 8) + (p_ptr->lev));
@@ -1734,18 +1458,16 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* HEAL */
- case 66:
+ case SF_HEAL_IDX:
{
hp_player(damroll(8, 5));
break;
}
- /* S_ANIMALS */
- case 67:
+ case SF_S_ANIMALS_IDX:
{
- for (k = 0; k < 4; k++)
+ for (int k = 0; k < 4; k++)
{
summon_specific_friendly(y, x, rlev, SUMMON_ANIMAL, TRUE);
}
@@ -1753,10 +1475,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* BLINK */
- case 68:
+ case SF_BLINK_IDX:
{
- if (dungeon_flags2 & DF2_NO_TELEPORT)
+ if (dungeon_flags & DF_NO_TELEPORT)
{
msg_print("No teleport on special levels...");
break;
@@ -1767,10 +1488,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* TPORT */
- case 69:
+ case SF_TPORT_IDX:
{
- if (dungeon_flags2 & DF2_NO_TELEPORT)
+ if (dungeon_flags & DF_NO_TELEPORT)
{
msg_print("No teleport on special levels...");
break;
@@ -1781,12 +1501,11 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* TELE_TO */
- case 70:
+ case SF_TELE_TO_IDX:
{
int ii, ij;
- if (dungeon_flags2 & DF2_NO_TELEPORT)
+ if (dungeon_flags & DF_NO_TELEPORT)
{
msg_print("No teleport on special levels...");
break;
@@ -1799,8 +1518,8 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
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))
+ (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;
@@ -1811,26 +1530,25 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* TELE_AWAY */
- case 71:
+ case SF_TELE_AWAY_IDX:
{
- if (dungeon_flags2 & DF2_NO_TELEPORT)
+ if (dungeon_flags & DF_NO_TELEPORT)
{
msg_print("No teleport on special levels...");
break;
}
+ int dir;
if (!get_aim_dir(&dir)) break;
- (void)fire_beam(GF_AWAY_ALL, dir, plev);
+ fire_beam(GF_AWAY_ALL, dir, plev);
break;
}
- /* TELE_LEVEL */
- case 72:
+ case SF_TELE_LEVEL_IDX:
{
- if (dungeon_flags2 & DF2_NO_TELEPORT)
+ if (dungeon_flags & DF_NO_TELEPORT)
{
msg_print("No teleport on special levels...");
break;
@@ -1841,11 +1559,10 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* DARKNESS */
- case 73:
+ case SF_DARKNESS_IDX:
{
- (void)project( -1, 3, p_ptr->py, p_ptr->px, 0, GF_DARK_WEAK,
- PROJECT_GRID | PROJECT_KILL);
+ 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);
@@ -1853,34 +1570,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* TRAPS */
- case 74:
- {
- trap_creation();
-
- break;
- }
-
- /* 75 FORGET -- Not available */
-
- /* ANIM_DEAD -- Use the same code as the nether spell */
- case 76:
+ case SF_S_THUNDERLORD_IDX:
{
- 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++)
+ for (int k = 0; k < 1; k++)
{
summon_specific_friendly(y, x, rlev, SUMMON_THUNDERLORD, TRUE);
}
@@ -1888,13 +1580,12 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* S_KIN -- Summon Kin, because we code bugs :) */
- case 80:
+ case SF_S_KIN_IDX:
{
/* Big hack */
summon_kin_type = r_ptr->d_char;
- for (k = 0; k < 6; k++)
+ for (int k = 0; k < 6; k++)
{
summon_specific_friendly(y, x, rlev, SUMMON_KIN, TRUE);
}
@@ -1902,10 +1593,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* S_HI_DEMON */
- case 81:
+ case SF_S_HI_DEMON_IDX:
{
- for (k = 0; k < 1; k++)
+ for (int k = 0; k < 1; k++)
{
summon_specific_friendly(y, x, rlev, SUMMON_HI_DEMON, TRUE);
}
@@ -1913,10 +1603,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* S_MONSTER */
- case 82:
+ case SF_S_MONSTER_IDX:
{
- for (k = 0; k < 1; k++)
+ for (int k = 0; k < 1; k++)
{
summon_specific_friendly(y, x, rlev, 0, TRUE);
}
@@ -1924,10 +1613,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* S_MONSTERS */
- case 83:
+ case SF_S_MONSTERS_IDX:
{
- for (k = 0; k < 6; k++)
+ for (int k = 0; k < 6; k++)
{
summon_specific_friendly(y, x, rlev, 0, TRUE);
}
@@ -1935,10 +1623,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* S_ANT */
- case 84:
+ case SF_S_ANT_IDX:
{
- for (k = 0; k < 6; k++)
+ for (int k = 0; k < 6; k++)
{
summon_specific_friendly(y, x, rlev, SUMMON_ANT, TRUE);
}
@@ -1946,10 +1633,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* S_SPIDER */
- case 85:
+ case SF_S_SPIDER_IDX:
{
- for (k = 0; k < 6; k++)
+ for (int k = 0; k < 6; k++)
{
summon_specific_friendly(y, x, rlev, SUMMON_SPIDER, TRUE);
}
@@ -1957,10 +1643,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* S_HOUND */
- case 86:
+ case SF_S_HOUND_IDX:
{
- for (k = 0; k < 6; k++)
+ for (int k = 0; k < 6; k++)
{
summon_specific_friendly(y, x, rlev, SUMMON_HOUND, TRUE);
}
@@ -1968,10 +1653,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* S_HYDRA */
- case 87:
+ case SF_S_HYDRA_IDX:
{
- for (k = 0; k < 6; k++)
+ for (int k = 0; k < 6; k++)
{
summon_specific_friendly(y, x, rlev, SUMMON_HYDRA, TRUE);
}
@@ -1979,10 +1663,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* S_ANGEL */
- case 88:
+ case SF_S_ANGEL_IDX:
{
- for (k = 0; k < 1; k++)
+ for (int k = 0; k < 1; k++)
{
summon_specific_friendly(y, x, rlev, SUMMON_ANGEL, TRUE);
}
@@ -1990,10 +1673,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* S_DEMON */
- case 89:
+ case SF_S_DEMON_IDX:
{
- for (k = 0; k < 1; k++)
+ for (int k = 0; k < 1; k++)
{
summon_specific_friendly(y, x, rlev, SUMMON_DEMON, TRUE);
}
@@ -2001,10 +1683,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* S_UNDEAD */
- case 90:
+ case SF_S_UNDEAD_IDX:
{
- for (k = 0; k < 1; k++)
+ for (int k = 0; k < 1; k++)
{
summon_specific_friendly(y, x, rlev, SUMMON_UNDEAD, TRUE);
}
@@ -2012,10 +1693,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* S_DRAGON */
- case 91:
+ case SF_S_DRAGON_IDX:
{
- for (k = 0; k < 1; k++)
+ for (int k = 0; k < 1; k++)
{
summon_specific_friendly(y, x, rlev, SUMMON_DRAGON, TRUE);
}
@@ -2023,10 +1703,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* S_HI_UNDEAD */
- case 92:
+ case SF_S_HI_UNDEAD_IDX:
{
- for (k = 0; k < 8; k++)
+ for (int k = 0; k < 8; k++)
{
summon_specific_friendly(y, x, rlev, SUMMON_HI_UNDEAD_NO_UNIQUES, TRUE);
}
@@ -2034,10 +1713,9 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* S_HI_DRAGON */
- case 93:
+ case SF_S_HI_DRAGON_IDX:
{
- for (k = 0; k < 8; k++)
+ for (int k = 0; k < 8; k++)
{
summon_specific_friendly(y, x, rlev, SUMMON_HI_DRAGON_NO_UNIQUES, TRUE);
}
@@ -2045,41 +1723,46 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
break;
}
- /* S_WRAITH */
- case 94:
+ case SF_S_WRAITH_IDX:
{
- for (k = 0; k < 8; k++)
+ for (int 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;
+/*
+ * Use a monster power and call the given callback.
+ */
+static int use_monster_power_aux(monster_race const *r_ptr, bool great, bool symbiosis, std::function<void(monster_power const *power)> f)
+{
+ int power;
+ int num;
+ std::tie(power, num) = choose_monster_power(r_ptr, great, symbiosis);
+
+ // Early exit?
+ if (power == 0) {
+ // No powers available
+ return 0;
+ } else if (power < 0) {
+ // Canceled by user
+ energy_use = 0;
+ return -1;
+ }
- if (m > p_ptr->msp) m = p_ptr->msp;
- if (!m) m = 1;
+ // Apply the effect
+ apply_monster_power(r_ptr, power);
- p_ptr->csp -= m;
- }
- }
+ // Post-processing
+ f(&monster_powers[power]);
/* Redraw mana */
- p_ptr->redraw |= (PR_MANA);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
@@ -2087,6 +1770,38 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
return (num);
}
+/**
+ * Use a power of the monster in symbiosis
+ */
+int use_symbiotic_power(int r_idx, bool great)
+{
+ auto const &r_info = game->edit_data.r_info;
+
+ monster_race const *r_ptr = &r_info[r_idx];
+ return use_monster_power_aux(r_ptr, great, true, [](monster_power const *) {
+ // Don't need to do anything post-cast.
+ });
+}
+
+/**
+ * Use a power of a possessed body.
+ */
+void use_monster_power(int r_idx, bool great)
+{
+ auto const &r_info = game->edit_data.r_info;
+
+ monster_race const *r_ptr = &r_info[r_idx];
+ use_monster_power_aux(r_ptr, great, false, [r_ptr](monster_power const *power) {
+ // Sometimes give a free cast.
+ int chance = (power->mana + r_ptr->level);
+ int pchance = adj_str_wgt[p_ptr->stat_ind[A_WIS]] / 2 + get_skill(SKILL_POSSESSION);
+ if (rand_int(chance) >= pchance)
+ {
+ p_ptr->csp -= calc_monster_spell_mana(power);
+ }
+ });
+}
+
/*
* Schooled magic
*/
@@ -2095,107 +1810,129 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
* 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)
+static s32b hack_force_spell_pval = -1;
+
+boost::optional<int> get_item_hook_find_spell(object_filter_t const &)
{
- 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);
- if (spell == -1) return FALSE;
- for (i = 0; i < INVEN_TOTAL; i++)
+ {
+ return boost::none;
+ }
+
+ int const spell = find_spell(buf);
+ if (spell == -1)
+ {
+ return boost::none;
+ }
+
+ for (int 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;
+ /* Extract object flags */
+ auto const flags = object_flags(o_ptr);
- /* Is it a non-book? */
- if (!is_school_book(o_ptr))
+ /* Must we wield it to cast from it? */
+ if ((wield_slot(o_ptr) != -1) && (i < INVEN_WIELD) && (flags & TR_WIELD_CAST))
{
- u32b f1, f2, f3, f4, f5, esp;
-
- /* Extract object flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ continue;
+ }
- if ((f5 & TR5_SPELL_CONTAIN) && (o_ptr->pval2 == spell))
+ /* Is it a non-book? */
+ if (!is_school_book()(o_ptr))
+ {
+ /* Does it contain the appropriate spell? */
+ if ((flags & TR_SPELL_CONTAIN) && (o_ptr->pval2 == spell))
{
- *item = i;
hack_force_spell = spell;
- hack_force_spell_obj = o_ptr;
- return TRUE;
+ hack_force_spell_pval = o_ptr->pval;
+ return i;
}
}
/* 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;
- }
+ hack_force_spell_pval = o_ptr->pval;
+ return i;
}
}
- return FALSE;
+
+ return boost::none;
}
/*
+ * Is the spell castable?
+ */
+bool_ is_ok_spell(s32b spell_idx, s32b pval)
+{
+ spell_type *spell = spell_at(spell_idx);
+
+ // Calculate availability based on caster's skill level.
+ s32b level;
+ bool_ na;
+ get_level_school(spell, 50, 0, &level, &na);
+ if (na || (level == 0))
+ {
+ return FALSE;
+ }
+ // Are we permitted to cast based on item pval? Only music
+ // spells have non-zero minimum PVAL.
+ if (pval < spell_type_minimum_pval(spell))
+ {
+ return FALSE;
+ }
+ // OK, we're permitted to cast it.
+ 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;
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];
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;
+ hack_force_spell_pval = -1;
/* 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;
+ char buf2[40];
+ char buf3[40];
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;
+
+ if (!get_item(&item,
+ buf3,
+ buf2,
+ USE_INVEN | USE_EQUIP,
+ hook_school_spellable(),
+ get_item_hook_find_spell))
+ {
+ return -1;
+ }
/* Get the item */
o_ptr = get_object(item);
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ auto const f = object_flags(o_ptr);
/* If it can be wielded, it must */
- if ((wield_slot(o_ptr) != -1) && (item < INVEN_WIELD) && (f5 & TR5_WIELD_CAST))
+ if ((wield_slot(o_ptr) != -1) && (item < INVEN_WIELD) && (f & TR_WIELD_CAST))
{
msg_format("You cannot %s from that object; it must be wielded first.", do_what);
return -1;
@@ -2217,21 +1954,14 @@ s32b get_school_spell(cptr do_what, cptr check_fct, s16b force_book)
/* Nothing chosen yet */
flag = FALSE;
- /* No redraw yet */
- redraw = FALSE;
-
/* Show choices */
- if (show_choices)
- {
- /* Window stuff */
- window_stuff();
- }
+ window_stuff();
/* No spell to cast by default */
spell = -1;
/* Is it a random book, or something else ? */
- if (is_school_book(o_ptr))
+ if (is_school_book()(o_ptr))
{
sval = o_ptr->sval;
pval = o_ptr->pval;
@@ -2242,51 +1972,40 @@ s32b get_school_spell(cptr do_what, cptr check_fct, s16b force_book)
pval = o_ptr->pval2;
}
+ /* Save the screen */
+ character_icky = TRUE;
+ Term_save();
+
+ /* Go */
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? ",
+ 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();
+ char choice;
- /* Display a list of spells */
- call_lua("print_book", "(d,d,O)", "d", sval, pval, o_ptr, &where);
- }
-
- /* 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));
@@ -2306,38 +2025,19 @@ s32b get_school_spell(cptr do_what, cptr check_fct, 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 */
- 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));
+ where = print_book(sval, pval, o_ptr);
+ print_spell_desc(spell_x(sval, pval, i), where);
}
else
{
- s32b ok;
+ bool_ 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);
+ ok = is_ok_spell(spell, o_ptr->pval);
/* Require "okay" spells */
if (!ok)
@@ -2355,10 +2055,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_pval);
if (ok)
{
flag = TRUE;
@@ -2374,19 +2074,12 @@ s32b get_school_spell(cptr do_what, cptr check_fct, s16b force_book)
/* Restore the screen */
- if (redraw)
- {
- Term_load();
- character_icky = FALSE;
- }
+ Term_load();
+ character_icky = FALSE;
/* Show choices */
- if (show_choices)
- {
- /* Window stuff */
- window_stuff();
- }
+ window_stuff();
/* Abort if needed */
@@ -2415,97 +2108,21 @@ 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)
{
- exec_lua(format("cast_school_spell(%d, spell(%d))", spell, spell));
- }
-}
-
-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 */
- if (show_choices)
- {
- /* Window stuff */
- window_stuff();
- }
-
- num = exec_lua(format("return book_spells_num(%d)", 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 */
- call_lua("print_book", "(d,d,O)", "d", book, pval, o_ptr, &where);
-
- /* 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);
-
- /* 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 */
- 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));
- }
-
-
- /* Restore the screen */
- Term_load();
- character_icky = FALSE;
-
- /* Show choices */
- if (show_choices)
- {
- /* Window stuff */
- window_stuff();
+ lua_cast_school_spell(spell, FALSE);
}
}
/* Can it contains a schooled spell ? */
-static bool_ hook_school_can_spellable(object_type *o_ptr)
+static bool hook_school_can_spellable(object_type const *o_ptr)
{
- u32b f1, f2, f3, f4, f5, esp;
-
- /* Extract object flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ auto const f = object_flags(o_ptr);
- if ((f5 & TR5_SPELL_CONTAIN) && (o_ptr->pval2 == -1))
- return TRUE;
- return FALSE;
+ return ((f & TR_SPELL_CONTAIN) && (o_ptr->pval2 == -1));
}
/*
@@ -2513,50 +2130,26 @@ 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 (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);
+ if (!get_item(&item,
+ "Copy to which object? ",
+ "You have no object to copy to.",
+ (USE_INVEN | USE_EQUIP),
+ hook_school_can_spellable)) return;
+ object_type *o_ptr = get_object(item);
msg_print("You copy the spell!");
o_ptr->pval2 = spell;
inven_item_describe(item);
}
-
-/*
- * Finds a spell by name, optimized for speed
- */
-int find_spell(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/cmd5.hpp b/src/cmd5.hpp
new file mode 100644
index 00000000..d25efb73
--- /dev/null
+++ b/src/cmd5.hpp
@@ -0,0 +1,23 @@
+#pragma once
+
+#include "h-basic.h"
+#include "object_type_fwd.hpp"
+#include "monster_race_fwd.hpp"
+#include "monster_power_fwd.hpp"
+
+#include <string>
+#include <vector>
+
+bool_ is_magestaff();
+void do_cmd_browse_aux(object_type *o_ptr);
+void do_cmd_browse();
+void fetch(int dir, int wgt, bool_ require_los);
+void do_poly_self();
+std::string symbiote_name(bool capitalize);
+int use_symbiotic_power(int r_idx, bool great);
+void use_monster_power(int r_idx, bool great);
+bool_ is_ok_spell(s32b spell_idx, s32b pval);
+s32b get_school_spell(cptr do_what, s16b force_book);
+void do_cmd_copy_spell();
+void cast_school_spell();
+std::vector<monster_power const *> extract_monster_powers(monster_race const *r_ptr, bool great);
diff --git a/src/cmd6.c b/src/cmd6.cc
index db89c465..e36f0cb6 100644
--- a/src/cmd6.c
+++ b/src/cmd6.cc
@@ -1,7 +1,3 @@
-/* File: cmd6.c */
-
-/* Purpose: Object commands */
-
/*
* Copyright (c) 1989 James E. Wilson, Robert A. Koeneke
*
@@ -10,43 +6,98 @@
* included in all such copies.
*/
-#include "angband.h"
-
-
-/*
- * Forward declare
- */
-static bool_ activate_spell(object_type * o_ptr, byte choice);
-
+#include "cmd6.hpp"
+
+#include "artifact_type.hpp"
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "cmd1.hpp"
+#include "cmd7.hpp"
+#include "corrupt.hpp"
+#include "dungeon_flag.hpp"
+#include "dungeon_info_type.hpp"
+#include "ego_item_type.hpp"
+#include "files.hpp"
+#include "game.hpp"
+#include "hook_eat_in.hpp"
+#include "hook_eat_out.hpp"
+#include "hooks.hpp"
+#include "lua_bind.hpp"
+#include "mimic.hpp"
+#include "monster2.hpp"
+#include "monster_race.hpp"
+#include "monster_race_flag.hpp"
+#include "monster_spell_flag.hpp"
+#include "monster_type.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_flag.hpp"
+#include "object_kind.hpp"
+#include "object_type.hpp"
+#include "options.hpp"
+#include "player_race_flag.hpp"
+#include "player_type.hpp"
+#include "randart.hpp"
+#include "skills.hpp"
+#include "spell_type.hpp"
+#include "spells1.hpp"
+#include "spells2.hpp"
+#include "spells5.hpp"
+#include "stats.hpp"
+#include "store.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "variable.h"
+#include "variable.hpp"
+#include "wild.hpp"
+#include "wizard2.hpp"
+#include "xtra1.hpp"
+#include "xtra2.hpp"
+#include "z-rand.hpp"
+
+#include <boost/algorithm/string/predicate.hpp>
+#include <cassert>
+
+using boost::algorithm::iequals;
/*
* General function to find an item by its name
*/
-cptr get_item_hook_find_obj_what;
-bool_ get_item_hook_find_obj(int *item)
+static select_by_name_t select_object_by_name(std::string const &prompt)
{
- 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))
+ return [=](object_filter_t const &filter) -> boost::optional<int> {
+ // Ask for the name of the object we want to select
+ char buf[80] = "";
+ if (!get_string(prompt.c_str(), buf, 79))
{
- *item = i;
- return TRUE;
+ return boost::none;
}
- }
- return FALSE;
+ // Named objects must be in the inventory
+ for (size_t i = 0; i < INVEN_TOTAL; i++)
+ {
+ object_type *o_ptr = get_object(i);
+ // Must have an actual item in the slot
+ if (!o_ptr->k_idx)
+ {
+ continue;
+ }
+ // Must pass the filter
+ if (!filter(o_ptr))
+ {
+ continue;
+ }
+ // Check against the name of the object
+ // ignoring case.
+ char buf2[100];
+ object_desc(buf2, o_ptr, -1, 0);
+ if (iequals(buf, buf2))
+ {
+ return i;
+ }
+ }
+ // No match
+ return boost::none;
+ };
}
@@ -97,7 +148,9 @@ bool_ get_item_hook_find_obj(int *item)
*/
static void corpse_effect(object_type *o_ptr, bool_ cutting)
{
- monster_race *r_ptr = &r_info[o_ptr->pval2];
+ auto const &r_info = game->edit_data.r_info;
+
+ auto r_ptr = &r_info[o_ptr->pval2];
/* Assume no bad effects */
bool_ harmful = FALSE;
@@ -284,7 +337,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;
@@ -487,7 +540,7 @@ static void corpse_effect(object_type *o_ptr, bool_ cutting)
*/
/* Acid */
- if (r_ptr->flags4 & RF4_BR_ACID && brpow > 0)
+ if ((r_ptr->spells & SF_BR_ACID) && brpow > 0)
{
brdam = ((brpow / 3) > 1600 ? 1600 : (brpow / 3));
@@ -502,13 +555,13 @@ static void corpse_effect(object_type *o_ptr, bool_ cutting)
}
o_ptr->pval = 1;
}
- else if (r_ptr->flags4 & RF4_BR_ACID)
+ else if (r_ptr->spells & SF_BR_ACID)
{
set_oppose_acid(p_ptr->oppose_acid + rand_int(10) + 10);
}
/* Electricity */
- if (r_ptr->flags4 & RF4_BR_ELEC && brpow > 0)
+ if ((r_ptr->spells & SF_BR_ELEC) && brpow > 0)
{
brdam = ((brpow / 3) > 1600 ? 1600 : (brpow / 3));
@@ -524,13 +577,13 @@ static void corpse_effect(object_type *o_ptr, bool_ cutting)
o_ptr->weight = o_ptr->weight - brpow;
o_ptr->pval = o_ptr->weight;
}
- else if (r_ptr->flags4 & RF4_BR_ELEC)
+ else if (r_ptr->spells & SF_BR_ELEC)
{
set_oppose_elec(p_ptr->oppose_elec + rand_int(10) + 10);
}
/* Fire */
- if (r_ptr->flags4 & RF4_BR_FIRE && brpow > 0)
+ if ((r_ptr->spells & SF_BR_FIRE) && brpow > 0)
{
brdam = ((brpow / 3) > 1600 ? 1600 : (brpow / 3));
@@ -545,13 +598,13 @@ static void corpse_effect(object_type *o_ptr, bool_ cutting)
}
o_ptr->pval = 1;
}
- else if (r_ptr->flags4 & RF4_BR_FIRE)
+ else if (r_ptr->spells & SF_BR_FIRE)
{
set_oppose_fire(p_ptr->oppose_fire + rand_int(10) + 10);
}
/* Cold */
- if (r_ptr->flags4 & RF4_BR_COLD && brpow > 0)
+ if ((r_ptr->spells & SF_BR_COLD) && brpow > 0)
{
brdam = ((brpow / 3) > 1600 ? 1600 : (brpow / 3));
@@ -567,13 +620,13 @@ static void corpse_effect(object_type *o_ptr, bool_ cutting)
o_ptr->weight = o_ptr->weight - brpow;
o_ptr->pval = o_ptr->weight;
}
- else if (r_ptr->flags4 & RF4_BR_COLD)
+ else if (r_ptr->spells & SF_BR_COLD)
{
set_oppose_cold(p_ptr->oppose_cold + rand_int(10) + 10);
}
/* Poison */
- if (r_ptr->flags4 & RF4_BR_POIS && brpow > 0)
+ if ((r_ptr->spells & SF_BR_POIS) && brpow > 0)
{
brdam = ((brpow / 3) > 800 ? 800 : (brpow / 3));
@@ -585,7 +638,7 @@ static void corpse_effect(object_type *o_ptr, bool_ cutting)
if (!(p_ptr->resist_pois || p_ptr->oppose_pois))
{
- (void)set_poisoned(p_ptr->poisoned + rand_int(brdam) + 10);
+ set_poisoned(p_ptr->poisoned + rand_int(brdam) + 10);
}
/* Take damage */
@@ -596,7 +649,7 @@ static void corpse_effect(object_type *o_ptr, bool_ cutting)
}
/* Nether */
- if (r_ptr->flags4 & RF4_BR_NETH && brpow > 0)
+ if ((r_ptr->spells & SF_BR_NETH) && brpow > 0)
{
brdam = ((brpow / 6) > 550 ? 550 : (brpow / 6));
@@ -633,7 +686,7 @@ static void corpse_effect(object_type *o_ptr, bool_ cutting)
}
/* Confusion */
- if (r_ptr->flags4 & RF4_BR_CONF && brpow > 0)
+ if ((r_ptr->spells & SF_BR_CONF) && brpow > 0)
{
msg_print("A strange liquid splashes on you!");
@@ -646,7 +699,7 @@ static void corpse_effect(object_type *o_ptr, bool_ cutting)
}
/* Chaos */
- if (r_ptr->flags4 & RF4_BR_CHAO && brpow > 0)
+ if ((r_ptr->spells & SF_BR_CHAO) && brpow > 0)
{
brdam = ((brpow / 6) > 600 ? 600 : (brpow / 6));
@@ -660,12 +713,12 @@ static void corpse_effect(object_type *o_ptr, bool_ cutting)
if (!p_ptr->resist_conf)
{
- (void)set_confused(p_ptr->confused + rand_int(20) + 10);
+ set_confused(p_ptr->confused + rand_int(20) + 10);
}
if (!p_ptr->resist_chaos)
{
- (void)set_image(p_ptr->image + randint(10));
+ set_image(p_ptr->image + randint(10));
}
if (!p_ptr->resist_neth && !p_ptr->resist_chaos)
@@ -692,7 +745,7 @@ static void corpse_effect(object_type *o_ptr, bool_ cutting)
}
/* Disenchantment */
- if (r_ptr->flags4 & RF4_BR_DISE && brpow > 0)
+ if ((r_ptr->spells & SF_BR_DISE) && brpow > 0)
{
brdam = ((brpow / 6) > 500 ? 500 : (brpow / 6));
@@ -705,7 +758,7 @@ static void corpse_effect(object_type *o_ptr, bool_ cutting)
}
else
{
- (void)apply_disenchant(0);
+ apply_disenchant(0);
}
/* Take damage */
@@ -714,7 +767,7 @@ static void corpse_effect(object_type *o_ptr, bool_ cutting)
}
/* Plasma */
- if (r_ptr->flags4 & RF4_BR_PLAS && brpow > 0)
+ if ((r_ptr->spells & SF_BR_PLAS) && brpow > 0)
{
brdam = ((brpow / 6) > 150 ? 150 : (brpow / 6));
@@ -726,7 +779,7 @@ static void corpse_effect(object_type *o_ptr, bool_ cutting)
if (!p_ptr->resist_sound)
{
int k = (randint((brdam > 40) ? 35 : (brdam * 3 / 4 + 5)));
- (void)set_stun(p_ptr->stun + k);
+ set_stun(p_ptr->stun + k);
}
/* Take damage */
@@ -736,7 +789,7 @@ static void corpse_effect(object_type *o_ptr, bool_ cutting)
}
/* 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))
+ if (strchr("j", r_ptr->d_char) && (r_ptr->flags & RF_IM_ACID))
{
dam = damroll(8, 8);
@@ -758,7 +811,7 @@ static void corpse_effect(object_type *o_ptr, bool_ cutting)
* 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 (strchr("ijkmS,", r_ptr->d_char) && (r_ptr->flags & RF_IM_POIS))
{
if (!(p_ptr->resist_pois || p_ptr->oppose_pois))
{
@@ -773,82 +826,82 @@ static void corpse_effect(object_type *o_ptr, bool_ cutting)
*/
if (!harmful && !cutting && (o_ptr->sval != SV_CORPSE_MEAT))
{
- if (r_ptr->flags3 & RF3_IM_ACID)
+ if (r_ptr->flags & RF_IM_ACID)
{
set_oppose_acid(p_ptr->oppose_acid + rand_int(10) + 10);
}
- if (r_ptr->flags3 & RF3_IM_ELEC)
+ if (r_ptr->flags & RF_IM_ELEC)
{
set_oppose_elec(p_ptr->oppose_elec + rand_int(10) + 10);
}
- if (r_ptr->flags3 & RF3_IM_FIRE)
+ if (r_ptr->flags & RF_IM_FIRE)
{
set_oppose_fire(p_ptr->oppose_fire + rand_int(10) + 10);
}
- if (r_ptr->flags3 & RF3_IM_COLD)
+ if (r_ptr->flags & RF_IM_COLD)
{
set_oppose_cold(p_ptr->oppose_cold + rand_int(10) + 10);
}
- if (r_ptr->flags3 & RF3_IM_POIS)
+ if (r_ptr->flags & RF_IM_POIS)
{
set_oppose_pois(p_ptr->oppose_pois + rand_int(10) + 10);
}
- if (r_ptr->flags3 & RF3_RES_NETH)
+ if (r_ptr->flags & RF_RES_NETH)
{
set_protevil(p_ptr->protevil + rand_int(25) + 3 * r_ptr->level);
}
- if (r_ptr->flags3 & RF3_RES_PLAS)
+ if (r_ptr->flags & RF_RES_PLAS)
{
set_oppose_fire(p_ptr->oppose_fire + rand_int(20) + 20);
}
- if (r_ptr->flags2 & RF2_SHAPECHANGER)
+ if (r_ptr->flags & RF_SHAPECHANGER)
{
- /* DGDGDG (void)set_mimic(20 , rand_int(MIMIC_VALAR)); */
+ /* DGDGDG set_mimic(20 , rand_int(MIMIC_VALAR)); */
}
- if (r_ptr->flags3 & RF3_DEMON)
+ if (r_ptr->flags & RF_DEMON)
{
- /* DGDGDG (void)set_mimic(30 , MIMIC_DEMON); */
+ /* DGDGDG set_mimic(30 , MIMIC_DEMON); */
}
- if (r_ptr->flags3 & RF3_UNDEAD)
+ if (r_ptr->flags & RF_UNDEAD)
{
- /* DGDGDG (void)set_mimic(30 , MIMIC_VAMPIRE); */
+ /* DGDGDG set_mimic(30 , MIMIC_VAMPIRE); */
}
- if (r_ptr->flags3 & RF3_NO_FEAR)
+ if (r_ptr->flags & RF_NO_FEAR)
{
- (void)set_afraid(0);
+ set_afraid(0);
}
- if (r_ptr->flags3 & RF3_NO_STUN)
+ if (r_ptr->flags & RF_NO_STUN)
{
- (void)set_stun(0);
+ set_stun(0);
}
- if (r_ptr->flags3 & RF3_NO_CONF)
+ if (r_ptr->flags & RF_NO_CONF)
{
- (void)set_confused(0);
+ set_confused(0);
}
- if (r_ptr->flags6 & RF6_S_THUNDERLORD)
+ if (r_ptr->spells & SF_S_THUNDERLORD)
{
summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_THUNDERLORD, FALSE);
}
- if (r_ptr->flags6 & RF6_S_DEMON)
+ if (r_ptr->spells & SF_S_DEMON)
{
summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_DEMON, FALSE);
}
- if (r_ptr->flags6 & RF6_S_KIN)
+ if (r_ptr->spells & SF_S_KIN)
{
summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_KIN, FALSE);
}
- if (r_ptr->flags6 & RF6_S_HI_DEMON)
+ if (r_ptr->spells & SF_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)
+ if (r_ptr->spells & SF_S_MONSTER)
{
summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, 0, FALSE);
}
- if (r_ptr->flags6 & RF6_S_MONSTERS)
+ if (r_ptr->spells & SF_S_MONSTERS)
{
int k;
for (k = 0; k < 8; k++)
@@ -856,47 +909,47 @@ static void corpse_effect(object_type *o_ptr, bool_ cutting)
summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, 0, FALSE);
}
}
- if (r_ptr->flags6 & RF6_S_UNDEAD)
+ if (r_ptr->spells & SF_S_UNDEAD)
{
summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_UNDEAD, FALSE);
}
- if (r_ptr->flags6 & RF6_S_DRAGON)
+ if (r_ptr->spells & SF_S_DRAGON)
{
summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_DRAGON, FALSE);
}
- if (r_ptr->flags6 & RF6_S_ANT)
+ if (r_ptr->spells & SF_S_ANT)
{
summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_ANT, FALSE);
}
- if (r_ptr->flags6 & RF6_S_SPIDER)
+ if (r_ptr->spells & SF_S_SPIDER)
{
summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_SPIDER, FALSE);
}
- if (r_ptr->flags6 & RF6_S_HOUND)
+ if (r_ptr->spells & SF_S_HOUND)
{
summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_HOUND, FALSE);
}
- if (r_ptr->flags6 & RF6_S_HYDRA)
+ if (r_ptr->spells & SF_S_HYDRA)
{
summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_HYDRA, FALSE);
}
- if (r_ptr->flags6 & RF6_S_ANGEL)
+ if (r_ptr->spells & SF_S_ANGEL)
{
summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_ANGEL, FALSE);
}
- if (r_ptr->flags6 & RF6_S_HI_DRAGON)
+ if (r_ptr->spells & SF_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)
+ if (r_ptr->spells & SF_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)
+ if (r_ptr->spells & SF_S_WRAITH)
{
summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_WRAITH, FALSE);
}
- if (r_ptr->flags6 & RF6_S_UNIQUE)
+ if (r_ptr->spells & SF_S_UNIQUE)
{
summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_UNIQUE, FALSE);
}
@@ -907,51 +960,45 @@ static void corpse_effect(object_type *o_ptr, bool_ cutting)
/*
* Hook to determine if an object is eatable
*/
-static bool_ item_tester_hook_eatable(object_type *o_ptr)
+static object_filter_t const &item_tester_hook_eatable()
{
- /* Foods and, well, corpses are edible */
- if ((o_ptr->tval == TV_FOOD) || (o_ptr->tval == TV_CORPSE)) return (TRUE);
-
- /* Assume not */
- return (FALSE);
+ using namespace object_filter;
+ static auto instance =
+ Or(
+ TVal(TV_FOOD),
+ TVal(TV_CORPSE));
+ return instance;
}
/*
* Eat some food (from the pack or floor)
*/
-void do_cmd_eat_food(void)
+void do_cmd_eat_food()
{
- int item, ident, lev, fval = 0;
-
- object_type *o_ptr;
- object_type *q_ptr, forge;
+ auto const &r_info = game->edit_data.r_info;
+ auto const &k_info = game->edit_data.k_info;
- monster_race *r_ptr;
+ int ident, lev, fval = 0;
- cptr q, s;
+ object_type *q_ptr, forge;
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;
+ int item;
+ if (!get_item(&item,
+ "Eat which item? ",
+ "You have nothing to eat.",
+ (USE_INVEN | USE_FLOOR),
+ item_tester_hook_eatable(),
+ select_object_by_name("Food full name? ")))
+ {
+ return;
+ }
/* Get the item */
- o_ptr = get_object(item);
-
- /* Sound */
- sound(SOUND_EAT);
-
+ object_type *o_ptr = get_object(item);
/* Take a turn */
energy_use = 100;
@@ -963,9 +1010,11 @@ void do_cmd_eat_food(void)
lev = k_info[o_ptr->k_idx].level;
/* Scripted foods */
- if (process_hooks_ret(HOOK_EAT, "d", "(O)", o_ptr))
+ hook_eat_in in = { o_ptr };
+ hook_eat_out out = { FALSE };
+ if (process_hooks_new(HOOK_EAT, &in, &out))
{
- ident = process_hooks_return[0].num;
+ ident = out.ident;
}
/* (not quite) Normal foods */
else if (o_ptr->tval == TV_FOOD)
@@ -1052,7 +1101,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;
}
@@ -1064,7 +1113,7 @@ void do_cmd_eat_food(void)
case SV_FOOD_WEAKNESS:
{
take_hit(damroll(6, 6), "poisonous food");
- (void)do_dec_stat(A_STR, STAT_DEC_NORMAL);
+ do_dec_stat(A_STR, STAT_DEC_NORMAL);
ident = TRUE;
@@ -1074,7 +1123,7 @@ void do_cmd_eat_food(void)
case SV_FOOD_SICKNESS:
{
take_hit(damroll(6, 6), "poisonous food");
- (void)do_dec_stat(A_CON, STAT_DEC_NORMAL);
+ do_dec_stat(A_CON, STAT_DEC_NORMAL);
ident = TRUE;
@@ -1084,7 +1133,7 @@ void do_cmd_eat_food(void)
case SV_FOOD_STUPIDITY:
{
take_hit(damroll(8, 8), "poisonous food");
- (void)do_dec_stat(A_INT, STAT_DEC_NORMAL);
+ do_dec_stat(A_INT, STAT_DEC_NORMAL);
ident = TRUE;
@@ -1094,7 +1143,7 @@ void do_cmd_eat_food(void)
case SV_FOOD_NAIVETY:
{
take_hit(damroll(8, 8), "poisonous food");
- (void)do_dec_stat(A_WIS, STAT_DEC_NORMAL);
+ do_dec_stat(A_WIS, STAT_DEC_NORMAL);
ident = TRUE;
@@ -1104,7 +1153,7 @@ void do_cmd_eat_food(void)
case SV_FOOD_UNHEALTH:
{
take_hit(damroll(10, 10), "poisonous food");
- (void)do_dec_stat(A_CON, STAT_DEC_NORMAL);
+ do_dec_stat(A_CON, STAT_DEC_NORMAL);
ident = TRUE;
@@ -1114,7 +1163,7 @@ void do_cmd_eat_food(void)
case SV_FOOD_DISEASE:
{
take_hit(damroll(10, 10), "poisonous food");
- (void)do_dec_stat(A_STR, STAT_DEC_NORMAL);
+ do_dec_stat(A_STR, STAT_DEC_NORMAL);
ident = TRUE;
@@ -1246,7 +1295,7 @@ void do_cmd_eat_food(void)
/* 2% chance of getting the mold power */
if (magik(2))
{
- ADD_POWER(p_ptr->powers_mod, PWR_GROW_MOLD);
+ p_ptr->powers_mod[PWR_GROW_MOLD] = TRUE;
p_ptr->update |= PU_POWERS;
}
@@ -1258,8 +1307,8 @@ void do_cmd_eat_food(void)
case SV_FOOD_WAYBREAD:
{
msg_print("That tastes very good.");
- (void)set_poisoned(0);
- (void)hp_player(damroll(4, 8));
+ set_poisoned(0);
+ hp_player(damroll(4, 8));
set_food(PY_FOOD_MAX - 1);
ident = TRUE;
@@ -1280,7 +1329,7 @@ void do_cmd_eat_food(void)
object_aware(q_ptr);
object_known(q_ptr);
q_ptr->ident |= IDENT_STOREB;
- (void)inven_carry(q_ptr, FALSE);
+ inven_carry(q_ptr, FALSE);
break;
}
@@ -1289,9 +1338,9 @@ void do_cmd_eat_food(void)
{
msg_print("A fresh, clean essence rises, driving away wounds and poison.");
- (void)set_poisoned(0);
- (void)set_stun(0);
- (void)set_cut(0);
+ set_poisoned(0);
+ set_stun(0);
+ set_cut(0);
if (p_ptr->black_breath)
{
msg_print("The hold of the Black Breath on you is broken!");
@@ -1308,7 +1357,7 @@ void do_cmd_eat_food(void)
/* Corpses... */
else
{
- r_ptr = &r_info[o_ptr->pval2];
+ auto r_ptr = &r_info[o_ptr->pval2];
/* Analyse the corpse */
switch (o_ptr->sval)
@@ -1320,7 +1369,7 @@ void do_cmd_eat_food(void)
/* Not all is edible. Apologies if messy. */
/* Check weight -- they have to have some meat left */
- if (r_ptr->flags9 & RF9_DROP_SKELETON)
+ if (r_ptr->flags & RF_DROP_SKELETON)
{
if (o_ptr->weight <= (r_ptr->weight * 3) / 5)
{
@@ -1441,10 +1490,10 @@ void do_cmd_eat_food(void)
/* Food can feed the player, in a different ways */
/* Vampires */
- if ((PRACE_FLAG(PR1_VAMPIRE)) || (p_ptr->mimic_form == resolve_mimic_name("Vampire")))
+ if ((race_flags_p(PR_VAMPIRE)) || (p_ptr->mimic_form == resolve_mimic_name("Vampire")))
{
/* Reduced nutritional benefit */
- /* (void)set_food(p_ptr->food + (fval / 10)); -- No more */
+ /* set_food(p_ptr->food + (fval / 10)); -- No more */
msg_print("Mere victuals hold scant sustenance for a being such as yourself.");
/* Hungry */
@@ -1454,9 +1503,9 @@ void do_cmd_eat_food(void)
}
}
- else if (PRACE_FLAG(PR1_NO_FOOD))
+ else if (race_flags_p(PR_NO_FOOD))
{
- if (PRACE_FLAG(PR1_UNDEAD))
+ if (race_flags_p(PR_UNDEAD))
{
msg_print("The food of mortals is poor sustenance for you.");
}
@@ -1470,7 +1519,7 @@ void do_cmd_eat_food(void)
/* Those living in fresh */
else
{
- (void)set_food(p_ptr->food + fval);
+ set_food(p_ptr->food + fval);
}
@@ -1485,33 +1534,26 @@ void do_cmd_eat_food(void)
/*
* Cut a corpse up for convenient storage
*/
-void do_cmd_cut_corpse(void)
+void do_cmd_cut_corpse()
{
- int item, meat = 0, not_meat = 0;
-
- object_type *o_ptr;
-
- object_type *i_ptr;
+ auto const &r_info = game->edit_data.r_info;
- object_type object_type_body;
-
- monster_race *r_ptr;
-
- cptr q, s;
-
-
- /* Restrict choices to corpses */
- item_tester_tval = TV_CORPSE;
+ int item, meat = 0, not_meat = 0;
/* Get an item */
- q = "Hack up which corpse? ";
- s = "You have no corpses.";
- if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return;
+ if (!get_item(&item,
+ "Hack up which corpse? ",
+ "You have no corpses.",
+ (USE_INVEN | USE_FLOOR),
+ object_filter::TVal(TV_CORPSE)))
+ {
+ return;
+ }
/* Get the item */
- o_ptr = get_object(item);
+ object_type *o_ptr = get_object(item);
- r_ptr = &r_info[o_ptr->pval2];
+ auto r_ptr = &r_info[o_ptr->pval2];
if ((o_ptr->sval != SV_CORPSE_CORPSE) && (o_ptr->sval != SV_CORPSE_HEAD))
{
@@ -1523,7 +1565,7 @@ void do_cmd_cut_corpse(void)
{
case SV_CORPSE_CORPSE:
{
- if (r_ptr->flags9 & RF9_DROP_SKELETON)
+ if (r_ptr->flags & RF_DROP_SKELETON)
{
not_meat = (r_ptr->weight * 3) / 5;
}
@@ -1565,7 +1607,8 @@ void do_cmd_cut_corpse(void)
corpse_effect(o_ptr, TRUE);
/* Get local object */
- i_ptr = &object_type_body;
+ object_type object_type_body;
+ object_type *i_ptr = &object_type_body;
/* Make some meat */
object_prep(i_ptr, lookup_kind(TV_CORPSE, SV_CORPSE_MEAT));
@@ -1592,36 +1635,31 @@ void do_cmd_cut_corpse(void)
*
* Salt water works well.
*/
-void do_cmd_cure_meat(void)
+void do_cmd_cure_meat()
{
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;
+ if (!get_item(&item,
+ "Cure which meat? ",
+ "You have no meat to cure.",
+ (USE_INVEN | USE_FLOOR),
+ object_filter::And(item_tester_hook_eatable(), object_filter::TVal(TV_CORPSE))))
+ {
+ return;
+ }
/* Get the item */
- o_ptr = get_object(item);
-
- /* Restrict choices to potions */
- item_tester_tval = TV_POTION;
+ object_type *o_ptr = get_object(item);
/* 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;
+ if (!get_item(&item,
+ "Use which potion? ",
+ "You have no potions to use.",
+ (USE_INVEN | USE_FLOOR),
+ object_filter::TVal(TV_POTION))) return;
/* Get the item */
i_ptr = get_object(item);
@@ -1644,8 +1682,8 @@ void do_cmd_cure_meat(void)
/* Take a turn */
energy_use = 100;
- q = "You soak the meat.";
- s = "You soak the meat.";
+ cptr q = "You soak the meat.";
+ cptr s = "You soak the meat.";
switch (i_ptr->sval)
{
@@ -1707,8 +1745,14 @@ void do_cmd_cure_meat(void)
}
/* Message */
- if (object_known_p(i_ptr)) msg_print(q);
- else msg_print(s);
+ 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)) ||
@@ -1730,12 +1774,13 @@ void do_cmd_cure_meat(void)
/*
* Hook to determine if an object is quaffable
*/
-static bool_ item_tester_hook_quaffable(object_type *o_ptr)
+static object_filter_t const &item_tester_hook_quaffable()
{
- if ((o_ptr->tval == TV_POTION) || (o_ptr->tval == TV_POTION2)) return (TRUE);
-
- /* Assume not */
- return (FALSE);
+ using namespace object_filter;
+ static auto instance = Or(
+ TVal(TV_POTION),
+ TVal(TV_POTION2));
+ return instance;
}
@@ -1769,9 +1814,9 @@ static bool_ quaff_potion(int tval, int sval, int pval, int pval2)
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(p_ptr->paralyzed + 4);
+ set_food(PY_FOOD_STARVE - 1);
+ set_poisoned(0);
+ set_paralyzed(4);
ident = TRUE;
break;
@@ -1838,7 +1883,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;
}
@@ -1863,12 +1908,12 @@ static bool_ quaff_potion(int tval, int sval, int pval, int pval2)
{
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);
+ dec_stat(A_DEX, 25, TRUE);
+ dec_stat(A_WIS, 25, TRUE);
+ dec_stat(A_CON, 25, TRUE);
+ dec_stat(A_STR, 25, TRUE);
+ dec_stat(A_CHR, 25, TRUE);
+ dec_stat(A_INT, 25, TRUE);
ident = TRUE;
break;
@@ -1920,8 +1965,8 @@ static bool_ quaff_potion(int tval, int sval, int pval, int pval2)
{
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);
+ set_stun(p_ptr->stun + 75);
+ set_cut(p_ptr->cut + 5000);
ident = TRUE;
break;
@@ -1985,7 +2030,7 @@ static bool_ quaff_potion(int tval, int sval, int pval, int pval2)
}
else
{
- (void)set_fast(p_ptr->fast + 5, 10);
+ set_fast(p_ptr->fast + 5, 10);
}
break;
@@ -2089,18 +2134,18 @@ static bool_ quaff_potion(int tval, int sval, int pval, int pval2)
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);
+ set_poisoned(0);
+ set_blind(0);
+ set_confused(0);
+ set_image(0);
+ set_stun(0);
+ set_cut(0);
+ 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 (p_ptr->black_breath)
{
msg_print("The hold of the Black Breath on you is broken!");
@@ -2118,7 +2163,7 @@ static bool_ quaff_potion(int tval, int sval, int pval, int pval2)
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->redraw |= (PR_FRAME);
p_ptr->window |= (PW_PLAYER);
ident = TRUE;
}
@@ -2243,26 +2288,14 @@ static bool_ quaff_potion(int tval, int sval, int pval, int pval2)
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);
+ do_inc_stat(A_INT);
+ do_inc_stat(A_WIS);
+ detect_doors(DEFAULT_RADIUS);
+ detect_stairs(DEFAULT_RADIUS);
+ detect_treasure(DEFAULT_RADIUS);
+ detect_objects_gold(DEFAULT_RADIUS);
+ 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;
@@ -2272,10 +2305,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;
}
@@ -2284,11 +2315,11 @@ static bool_ quaff_potion(int tval, int sval, int pval, int pval2)
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);
+ set_oppose_acid(p_ptr->oppose_acid + randint(20) + 20);
+ set_oppose_elec(p_ptr->oppose_elec + randint(20) + 20);
+ set_oppose_fire(p_ptr->oppose_fire + randint(20) + 20);
+ set_oppose_cold(p_ptr->oppose_cold + randint(20) + 20);
+ set_oppose_pois(p_ptr->oppose_pois + randint(20) + 20);
ident = TRUE;
break;
@@ -2310,7 +2341,7 @@ static bool_ quaff_potion(int tval, int sval, int pval, int pval2)
case SV_POTION_INVULNERABILITY:
{
- (void)set_invuln(p_ptr->invuln + randint(7) + 7);
+ set_invuln(p_ptr->invuln + randint(7) + 7);
ident = TRUE;
break;
@@ -2335,8 +2366,19 @@ 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)
+ {
+ if (p_ptr->pgod == 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);
+ gain_random_corruption();
ident = TRUE;
break;
}
@@ -2378,14 +2420,12 @@ 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);
/* Redraw title */
- p_ptr->redraw |= (PR_TITLE);
+ p_ptr->redraw |= (PR_FRAME);
/* Recalculate bonuses */
p_ptr->update |= (PU_BONUS);
@@ -2438,35 +2478,26 @@ static bool_ quaff_potion(int tval, int sval, int pval, int pval2)
/*
* Quaff a potion (from the pack or the floor)
*/
-void do_cmd_quaff_potion(void)
+void do_cmd_quaff_potion()
{
- int item, ident, lev;
-
- object_type *o_ptr;
+ auto const &k_info = game->edit_data.k_info;
- 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;
+ int ident, lev;
/* 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;
+ int item;
+ if (!get_item(&item,
+ "Quaff which potion? ",
+ "You have no potions to quaff.",
+ (USE_INVEN | USE_FLOOR),
+ item_tester_hook_quaffable(),
+ select_object_by_name("Potion full name? ")))
+ {
+ return;
+ }
/* Get the item */
- o_ptr = get_object(item);
-
-
- /* Sound */
- sound(SOUND_QUAFF);
+ object_type *o_ptr = get_object(item);
/* Take a turn */
@@ -2478,13 +2509,15 @@ void do_cmd_quaff_potion(void)
/* Object level */
lev = k_info[o_ptr->k_idx].level;
- /* Analyze the potion */
- if (process_hooks_ret(HOOK_QUAFF, "d", "(O)", o_ptr))
+ /* Demon Breath corruption can spoil potions. */
+ if (player_has_corruption(CORRUPT_DEMON_BREATH) && magik(9))
{
- ident = process_hooks_return[0].num;
+ 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);
}
@@ -2501,28 +2534,12 @@ void do_cmd_quaff_potion(void)
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);
+ set_food(p_ptr->food + o_ptr->pval);
/* Destroy potion */
@@ -2531,92 +2548,15 @@ void do_cmd_quaff_potion(void)
/*
- * 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)
+static void do_cmd_fill_bottle()
{
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;
+ object_type *q_ptr, forge;
/* Is the fountain empty? */
/*
@@ -2642,14 +2582,17 @@ void do_cmd_fill_bottle(void)
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];
+ if (!get_item(&item,
+ "Fill which bottle? ",
+ "You have no bottles to fill.",
+ (USE_INVEN),
+ object_filter::TVal(TV_BOTTLE)))
+ {
+ return;
+ }
+
+ object_type *o_ptr = &p_ptr->inventory[item];
/* Find out how many the player wants */
if (o_ptr->number > 1)
@@ -2691,9 +2634,84 @@ void do_cmd_fill_bottle(void)
/*
+ * Drink from a fountain
+ */
+void do_cmd_drink_fountain()
+{
+ auto const &k_info = game->edit_data.k_info;
+
+ cave_type *c_ptr = &cave[p_ptr->py][p_ptr->px];
+
+ bool_ ident;
+
+ int tval, sval, pval = 0;
+
+ 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 (auto const &k_ref: k_info)
+ {
+ auto k_ptr = &k_ref;
+
+ 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;
+ }
+}
+
+
+/*
* Curse the players armor
*/
-bool_ curse_armor(void)
+bool_ curse_armor()
{
object_type *o_ptr;
@@ -2711,7 +2729,7 @@ bool_ curse_armor(void)
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))
+ if (artifact_p(o_ptr) && (rand_int(100) < 50))
{
/* Cool */
msg_format("A terrible black aura tries to surround your armour, "
@@ -2733,10 +2751,7 @@ bool_ curse_armor(void)
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;
+ o_ptr->art_flags = object_flag_set();
/* Curse it */
o_ptr->ident |= (IDENT_CURSED);
@@ -2758,7 +2773,7 @@ bool_ curse_armor(void)
/*
* Curse the players weapon
*/
-bool_ curse_weapon(void)
+bool_ curse_weapon()
{
object_type *o_ptr;
@@ -2776,7 +2791,7 @@ bool_ curse_weapon(void)
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))
+ if (artifact_p(o_ptr) && (rand_int(100) < 50))
{
/* Cool */
msg_format("A terrible black aura tries to surround your weapon, "
@@ -2798,10 +2813,7 @@ bool_ curse_weapon(void)
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;
+ o_ptr->art_flags = object_flag_set();
/* Curse it */
@@ -2825,12 +2837,14 @@ bool_ curse_weapon(void)
/*
* Hook to determine if an object is readable
*/
-static bool_ item_tester_hook_readable(object_type *o_ptr)
+static object_filter_t const &item_tester_hook_readable()
{
- if ((o_ptr->tval == TV_SCROLL) || (o_ptr->tval == TV_PARCHMENT)) return (TRUE);
-
- /* Assume not */
- return (FALSE);
+ using namespace object_filter;
+ static auto instance =
+ Or(
+ TVal(TV_SCROLL),
+ TVal(TV_PARCHMENT));
+ return instance;
}
@@ -2841,16 +2855,11 @@ static bool_ item_tester_hook_readable(object_type *o_ptr)
* 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)
+void do_cmd_read_scroll()
{
- int item, k, used_up, ident, lev;
-
- object_type *o_ptr;
-
- object_type *q_ptr, forge;
-
- cptr q, s;
-
+ auto const &d_info = game->edit_data.d_info;
+ auto const &k_info = game->edit_data.k_info;
+ auto &r_info = game->edit_data.r_info;
/* Check some conditions */
if (p_ptr->blind)
@@ -2871,41 +2880,42 @@ void do_cmd_read_scroll(void)
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;
+ int item;
+ if (!get_item(&item,
+ "Read which scroll? ",
+ "You have no scrolls to read.",
+ (USE_INVEN | USE_FLOOR),
+ item_tester_hook_readable(),
+ select_object_by_name("Scroll full name? ")))
+ {
+ return;
+ }
/* Get the item */
- o_ptr = get_object(item);
+ object_type *o_ptr = get_object(item);
/* Take a turn */
energy_use = 100;
/* Not identified yet */
- ident = FALSE;
+ int ident = FALSE;
/* Object level */
- lev = k_info[o_ptr->k_idx].level;
+ int lev = k_info[o_ptr->k_idx].level;
/* Assume the scroll will get used up */
- used_up = TRUE;
+ int used_up = TRUE;
- /* New scripts, can override the ingame code */
- if (process_hooks_ret(HOOK_READ, "dd", "(O)", o_ptr))
+ /* Corruption */
+ if (player_has_corruption(CORRUPT_BALROG_AURA) && magik(5))
{
- used_up = process_hooks_return[0].num;
- ident = process_hooks_return[1].num;
+ msg_print("Your demon aura burns the scroll before you read it!");
+ used_up = TRUE;
+ ident = FALSE;
}
- /* Traditional scrolls */
+
+ /* Scrolls */
else if (o_ptr->tval == TV_SCROLL)
{
/* Analyze the scroll */
@@ -2913,18 +2923,16 @@ void do_cmd_read_scroll(void)
{
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++)
+ for (auto &r_ref: r_info)
{
- monster_race *r_ptr = &r_info[k];
+ auto r_ptr = &r_ref;
- if (r_ptr->flags1 & RF1_UNIQUE &&
- !(r_ptr->flags9 & RF9_SPECIAL_GENE))
+ if (r_ptr->flags & RF_UNIQUE &&
+ !(r_ptr->flags & RF_SPECIAL_GENE))
{
r_ptr->max_num = 1;
}
@@ -2960,7 +2968,7 @@ void do_cmd_read_scroll(void)
}
msg_format("Recall reset to %s at level %d.",
- d_info[p_ptr->recall_dungeon].name + d_name,
+ d_info[p_ptr->recall_dungeon].name.c_str(),
max_dlv[p_ptr->recall_dungeon]);
ident = TRUE;
@@ -2972,7 +2980,6 @@ void do_cmd_read_scroll(void)
case SV_SCROLL_DIVINATION:
{
int i, count = 0;
- char buf[120];
while (count < 1000)
{
@@ -2984,8 +2991,7 @@ void do_cmd_read_scroll(void)
msg_print("A message appears on the scroll. It says:");
msg_print(NULL);
- fate_desc(buf, i);
- msg_format("%s", buf);
+ msg_format("%s", fate_desc(i).c_str());
msg_print(NULL);
msg_print("The scroll disappears in a puff of smoke!");
@@ -3003,7 +3009,7 @@ void do_cmd_read_scroll(void)
{
if (!(p_ptr->resist_blind) && !(p_ptr->resist_dark))
{
- (void)set_blind(p_ptr->blind + 3 + randint(5));
+ set_blind(p_ptr->blind + 3 + randint(5));
}
if (unlite_area(10, 3)) ident = TRUE;
@@ -3036,7 +3042,7 @@ void do_cmd_read_scroll(void)
case SV_SCROLL_SUMMON_MONSTER:
{
- for (k = 0; k < randint(3); k++)
+ for (int k = 0; k < randint(3); k++)
{
if (summon_specific(p_ptr->py, p_ptr->px, dun_level, 0))
{
@@ -3059,7 +3065,7 @@ void do_cmd_read_scroll(void)
case SV_SCROLL_SUMMON_UNDEAD:
{
- for (k = 0; k < randint(3); k++)
+ for (int k = 0; k < randint(3); k++)
{
if (summon_specific(p_ptr->py, p_ptr->px, dun_level, SUMMON_UNDEAD))
{
@@ -3070,13 +3076,6 @@ void do_cmd_read_scroll(void)
break;
}
- case SV_SCROLL_TRAP_CREATION:
- {
- if (trap_creation()) ident = TRUE;
-
- break;
- }
-
case SV_SCROLL_PHASE_DOOR:
{
teleport_player(10);
@@ -3097,7 +3096,7 @@ void do_cmd_read_scroll(void)
case SV_SCROLL_TELEPORT_LEVEL:
{
- (void)teleport_player_level();
+ teleport_player_level();
ident = TRUE;
@@ -3106,7 +3105,7 @@ void do_cmd_read_scroll(void)
case SV_SCROLL_WORD_OF_RECALL:
{
- if ((dungeon_flags2 & DF2_ASK_LEAVE) && !get_check("Leave this unique level forever? "))
+ if ((dungeon_flags & DF_ASK_LEAVE) && !get_check("Leave this unique level forever? "))
{
used_up = FALSE;
}
@@ -3151,9 +3150,11 @@ void do_cmd_read_scroll(void)
case SV_SCROLL_STAR_REMOVE_CURSE:
{
- remove_all_curse();
-
- ident = TRUE;
+ if (remove_all_curse())
+ {
+ msg_print("You feel as if someone is watching over you.");
+ ident = TRUE;
+ }
break;
}
@@ -3252,13 +3253,6 @@ void do_cmd_read_scroll(void)
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;
@@ -3316,8 +3310,11 @@ void do_cmd_read_scroll(void)
case SV_SCROLL_PROTECTION_FROM_EVIL:
{
- k = 3 * p_ptr->lev;
- if (set_protevil(p_ptr->protevil + randint(25) + k)) ident = TRUE;
+ int k = 3 * p_ptr->lev;
+ if (set_protevil(p_ptr->protevil + randint(25) + k))
+ {
+ ident = TRUE;
+ }
break;
}
@@ -3331,19 +3328,12 @@ void do_cmd_read_scroll(void)
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);
+ destroy_area(p_ptr->py, p_ptr->px, 15);
}
else
{
@@ -3364,7 +3354,7 @@ void do_cmd_read_scroll(void)
case SV_SCROLL_GENOCIDE:
{
- (void)genocide(TRUE);
+ genocide(TRUE);
ident = TRUE;
@@ -3373,7 +3363,7 @@ void do_cmd_read_scroll(void)
case SV_SCROLL_MASS_GENOCIDE:
{
- (void)mass_genocide(TRUE);
+ mass_genocide(TRUE);
ident = TRUE;
@@ -3509,6 +3499,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;
@@ -3549,17 +3547,18 @@ void do_cmd_read_scroll(void)
screen_save();
/* Get the filename */
- q = format("book-%d.txt", o_ptr->sval);
+ cptr q = format("book-%d.txt", o_ptr->sval);
/* Peruse the help file */
- (void)show_file(q, NULL, 0, 0);
+ show_file(q, NULL);
/* Load screen */
screen_load();
+ /* Inscriptions become known upon reading */
if (o_ptr->sval >= 100)
{
- inscription_info[o_ptr->sval - 100].know = TRUE;
+ p_ptr->inscriptions[o_ptr->sval - 100] = TRUE;
}
used_up = FALSE;
@@ -3587,25 +3586,8 @@ void do_cmd_read_scroll(void)
/* 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);
- }
- }
}
@@ -3615,13 +3597,56 @@ 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));
+ // Ensure that we're not assuming "reentrancy".
+ assert(get_level_use_stick < 0);
+ // Set up the casting mode
+ 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");
+ // Ensure that we're not assuming "reentrancy".
+ assert(get_level_use_stick > 0);
+ // Unset the casting mode
+ get_level_use_stick = -1;
+ get_level_max_stick = -1;
+}
+
+
+/*
+ * Activate a device
+ */
+static void activate_stick(object_type *o_ptr, bool_ *obvious, bool_ *use_charge)
+{
+ spell_type *spell = spell_at(o_ptr->pval2);
+ casting_result ret;
+
+ assert(obvious != NULL);
+ assert(use_charge != NULL);
+
+ set_stick_mode(o_ptr);
+ ret = spell_type_produce_effect(spell);
+ unset_stick_mode();
+
+ 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);
+ }
}
@@ -3632,17 +3657,9 @@ void unset_stick_mode()
*
* Hack -- staffs of identify can be "cancelled".
*/
-void do_cmd_use_staff(void)
+void do_cmd_use_staff()
{
- int item, ident, chance;
-
- s32b obvious, use_charge;
-
- object_type *o_ptr;
-
- u32b f1, f2, f3, f4, f5, esp;
-
- cptr q, s;
+ bool_ obvious, use_charge;
/* No magic */
if (p_ptr->antimagic)
@@ -3651,20 +3668,20 @@ void do_cmd_use_staff(void)
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;
+ int item;
+ if (!get_item(&item,
+ "Use which staff? ",
+ "You have no staff to use.",
+ (USE_INVEN | USE_FLOOR),
+ object_filter::TVal(TV_STAFF),
+ select_object_by_name("Staff full name? ")))
+ {
+ return;
+ }
/* Get the item */
- o_ptr = get_object(item);
+ object_type *o_ptr = get_object(item);
/* Mega-Hack -- refuse to use a pile from the ground */
if ((item < 0) && (o_ptr->number > 1))
@@ -3673,23 +3690,27 @@ void do_cmd_use_staff(void)
return;
}
- /* Enter device mode */
- set_stick_mode(o_ptr);
-
/* Take a turn */
energy_use = 100;
- /* Not identified yet */
- ident = FALSE;
+ /* Enter device mode */
+ set_stick_mode(o_ptr);
/* get the chance */
- chance = exec_lua(format("return spell_chance(%d)", o_ptr->pval2));
+ int chance;
+ {
+ auto spell = spell_at(o_ptr->pval2);
+ chance = spell_chance_device(spell);
+ }
+
+ /* Leave device mode */
+ unset_stick_mode();
/* Extract object flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ auto const flags = object_flags(o_ptr);
/* Is it simple to use ? */
- if (f4 & TR4_EASY_USE)
+ if (flags & TR_EASY_USE)
{
chance /= 3;
}
@@ -3703,34 +3724,23 @@ void do_cmd_use_staff(void)
/* Roll for usage */
if (magik(chance))
{
- if (flush_failure) flush();
+ flush_on_failure();
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();
+ flush_on_failure();
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 */
- call_lua("activate_stick", "(d)", "dd", o_ptr->pval2, &obvious, &use_charge);
+ activate_stick(o_ptr, &obvious, &use_charge);
/* Combine / Reorder the pack (later) */
p_ptr->notice |= (PN_COMBINE | PN_REORDER);
@@ -3746,9 +3756,6 @@ void do_cmd_use_staff(void)
/* Hack -- some uses are "free" */
if (!use_charge)
{
- /* Leave device mode */
- unset_stick_mode();
-
return;
}
@@ -3798,9 +3805,6 @@ void do_cmd_use_staff(void)
{
floor_item_charges(0 - item);
}
-
- /* Leave device mode */
- unset_stick_mode();
}
@@ -3824,18 +3828,9 @@ void do_cmd_use_staff(void)
* basic "bolt" rods, but the basic "ball" wands do the same damage
* as the basic "ball" rods.
*/
-void do_cmd_aim_wand(void)
+void do_cmd_aim_wand()
{
- s32b obvious, use_charge;
-
- int item, ident, chance, sval;
-
- object_type *o_ptr;
-
- cptr q, s;
-
- u32b f1, f2, f3, f4, f5, esp;
-
+ bool_ obvious, use_charge;
/* No magic */
if (p_ptr->antimagic)
@@ -3844,21 +3839,20 @@ void do_cmd_aim_wand(void)
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;
+ int item;
+ if (!get_item(&item,
+ "Aim which wand? ",
+ "You have no wand to aim.",
+ (USE_INVEN | USE_FLOOR),
+ object_filter::TVal(TV_WAND),
+ select_object_by_name("Wand full name? ")))
+ {
+ return;
+ }
/* Get the item */
- o_ptr = get_object(item);
-
+ object_type *o_ptr = get_object(item);
/* Mega-Hack -- refuse to aim a pile from the ground */
if ((item < 0) && (o_ptr->number > 1))
@@ -3870,20 +3864,24 @@ void do_cmd_aim_wand(void)
/* Take a turn */
energy_use = 100;
- /* Not identified yet */
- ident = FALSE;
-
/* Enter device mode */
set_stick_mode(o_ptr);
/* get the chance */
- chance = exec_lua(format("return spell_chance(%d)", o_ptr->pval2));
+ int chance;
+ {
+ auto spell = spell_at(o_ptr->pval2);
+ chance = spell_chance_device(spell);
+ }
+
+ /* Leave device mode */
+ unset_stick_mode();
/* Extract object flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ auto const flags = object_flags(o_ptr);
/* Is it simple to use ? */
- if (f4 & TR4_EASY_USE)
+ if (flags & TR_EASY_USE)
{
chance /= 3;
}
@@ -3891,37 +3889,22 @@ void do_cmd_aim_wand(void)
/* Roll for usage */
if (magik(chance))
{
- if (flush_failure) flush();
+ flush_on_failure();
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();
+ flush_on_failure();
msg_print("The wand has no charges left.");
o_ptr->ident |= (IDENT_EMPTY);
-
- /* Leave device mode */
- unset_stick_mode();
return;
}
-
- /* Sound */
- sound(SOUND_ZAP);
-
-
- /* XXX Hack -- Extract the "sval" effect */
- sval = o_ptr->sval;
-
/* Analyze the wand */
- call_lua("activate_stick", "(d)", "dd", o_ptr->pval2, &obvious, &use_charge);
+ activate_stick(o_ptr, &obvious, &use_charge);
/* Combine / Reorder the pack (later) */
p_ptr->notice |= (PN_COMBINE | PN_REORDER);
@@ -3932,9 +3915,6 @@ void do_cmd_aim_wand(void)
/* Hack -- some uses are "free" */
if (!use_charge)
{
- /* Leave device mode */
- unset_stick_mode();
-
return;
}
@@ -3962,9 +3942,6 @@ void do_cmd_aim_wand(void)
{
floor_item_charges(0 - item);
}
-
- /* Leave device mode */
- unset_stick_mode();
}
@@ -3985,25 +3962,24 @@ void do_cmd_aim_wand(void)
/*
* Hook to determine if an object is zapable
*/
-static bool_ item_tester_hook_zapable(object_type *o_ptr)
+static object_filter_t const &item_tester_hook_zapable()
{
- if ((o_ptr->tval == TV_ROD) || (o_ptr->tval == TV_ROD_MAIN)) return (TRUE);
-
- /* Assume not */
- return (FALSE);
+ using namespace object_filter;
+ static auto instance =
+ Or(
+ TVal(TV_ROD),
+ TVal(TV_ROD_MAIN));
+ return instance;
}
/*
* Hook to determine if an object is attachable
*/
-static bool_ item_tester_hook_attachable(object_type *o_ptr)
+static bool item_tester_hook_attachable(object_type const *o_ptr)
{
- if ((o_ptr->tval == TV_ROD_MAIN) &&
- (o_ptr->pval == SV_ROD_NOTHING)) return (TRUE);
-
- /* Assume not */
- return (FALSE);
+ return ((o_ptr->tval == TV_ROD_MAIN) &&
+ (o_ptr->pval == SV_ROD_NOTHING));
}
@@ -4012,16 +3988,6 @@ static bool_ item_tester_hook_attachable(object_type *o_ptr)
*/
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)
{
@@ -4029,24 +3995,26 @@ void zap_combine_rod_tip(object_type *q_ptr, int tip_item)
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;
+ int item;
+ if (!get_item(&item,
+ "Attach the rod tip with which rod? ",
+ "You have no rod to attach to.",
+ (USE_INVEN),
+ item_tester_hook_attachable))
+ {
+ return;
+ }
/* Get the item */
- o_ptr = get_object(item);
+ object_type *o_ptr = get_object(item);
/* Examine the rod */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ auto const flags = object_flags(o_ptr);
/* Calculate rod tip's mana cost */
- cost = q_ptr->pval;
-
- if (f4 & TR4_CHEAPNESS)
+ s32b cost = q_ptr->pval;
+ if (flags & TR_CHEAPNESS)
{
cost /= 2;
}
@@ -4072,22 +4040,16 @@ void zap_combine_rod_tip(object_type *q_ptr, int tip_item)
/*
* Zap a rod, or attack a rod tip to a rod
*/
-void do_cmd_zap_rod(void)
+void do_cmd_zap_rod()
{
+ auto const &k_info = game->edit_data.k_info;
+
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;
@@ -4099,21 +4061,19 @@ void do_cmd_zap_rod(void)
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;
+ if (!get_item(&item,
+ "Zap which rod? ",
+ "You have no rod to zap.",
+ (USE_INVEN | USE_FLOOR),
+ item_tester_hook_zapable(),
+ select_object_by_name("Rod full name? ")))
+ {
+ return;
+ }
/* Get the item */
- o_ptr = get_object(item);
+ object_type *o_ptr = get_object(item);
/* "Zapping" a Rod Tip on rod of nothing will attach it */
@@ -4143,7 +4103,6 @@ void do_cmd_zap_rod(void)
{
switch (o_ptr->pval)
{
- case SV_ROD_DETECT_TRAP:
case SV_ROD_HAVOC:
case SV_ROD_HOME:
{
@@ -4170,15 +4129,18 @@ void do_cmd_zap_rod(void)
energy_use = 100;
/* Examine the rod */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ auto const flags = object_flags(o_ptr);
- if (f4 & TR4_FAST_CAST) energy_use /= 2;
+ if (flags & TR_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)];
+ auto 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 */
@@ -4196,7 +4158,7 @@ void do_cmd_zap_rod(void)
}
/* Is it simple to use ? */
- if (f4 & TR4_EASY_USE)
+ if (flags & TR_EASY_USE)
{
chance *= 10;
}
@@ -4211,13 +4173,11 @@ void do_cmd_zap_rod(void)
if ((chance < USE_DEVICE) || (randint(chance) < USE_DEVICE))
{
/* Flush input if necessary */
- if (flush_failure) flush();
+ flush_on_failure();
/* Message */
msg_print("You failed to use the rod properly.");
- sound(SOUND_FAIL);
-
return;
}
@@ -4225,13 +4185,13 @@ void do_cmd_zap_rod(void)
cost = tip_ptr->pval;
/* "Cheapness" ego halven the cost */
- if (f4 & TR4_CHEAPNESS) cost = cost / 2;
+ if (flags & TR_CHEAPNESS) cost = cost / 2;
/* A single rod is still charging */
if (o_ptr->timeout < cost)
{
/* Flush input if necessary */
- if (flush_failure) flush();
+ flush_on_failure();
/* Message */
msg_print("The rod does not have enough mana yet.");
@@ -4242,9 +4202,6 @@ void do_cmd_zap_rod(void)
/* Increase the timeout by the rod kind's pval. */
o_ptr->timeout -= cost;
- /* Sound */
- sound(SOUND_ZAP);
-
/* Analyze the rod */
switch (o_ptr->pval)
{
@@ -4257,13 +4214,6 @@ void do_cmd_zap_rod(void)
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;
@@ -4283,7 +4233,7 @@ void do_cmd_zap_rod(void)
case SV_ROD_RECALL:
{
- if ((dungeon_flags2 & DF2_ASK_LEAVE) && !get_check("Leave this unique level forever? "))
+ if ((dungeon_flags & DF_ASK_LEAVE) && !get_check("Leave this unique level forever? "))
{
use_charge = FALSE;
}
@@ -4322,15 +4272,6 @@ void do_cmd_zap_rod(void)
break;
}
- case SV_ROD_PROBING:
- {
- probing();
-
- ident = TRUE;
-
- break;
- }
-
case SV_ROD_CURING:
{
if (set_blind(0)) ident = TRUE;
@@ -4373,7 +4314,7 @@ void do_cmd_zap_rod(void)
}
else
{
- (void)set_fast(p_ptr->fast + 5, 10);
+ set_fast(p_ptr->fast + 5, 10);
}
break;
@@ -4386,13 +4327,6 @@ void do_cmd_zap_rod(void)
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.");
@@ -4513,11 +4447,7 @@ void do_cmd_zap_rod(void)
}
default:
- {
- process_hooks(HOOK_ZAP, "(d,d)", o_ptr->tval, o_ptr->sval);
-
- break;
- }
+ break;
}
@@ -4552,26 +4482,16 @@ void do_cmd_zap_rod(void)
/*
* Hook to determine if an object is activable
*/
-static bool_ item_tester_hook_activate(object_type *o_ptr)
+static object_filter_t const &item_tester_hook_activate()
{
- 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);
+ using namespace object_filter;
+ static auto instance = And(
+ IsKnown(),
+ HasFlags(TR_ACTIVATE));
+ return instance;
}
-
/*
* Hack -- activate the ring of power
*/
@@ -4616,7 +4536,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...");
@@ -4668,7 +4588,7 @@ int ring_of_power()
/*
* Enchant some bolts
*/
-bool_ brand_bolts(void)
+bool_ brand_bolts()
{
int i;
@@ -4682,7 +4602,7 @@ bool_ brand_bolts(void)
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;
+ if (artifact_p(o_ptr) || ego_item_p(o_ptr)) continue;
/* Skip cursed/broken items */
if (cursed_p(o_ptr)) continue;
@@ -4707,7 +4627,7 @@ bool_ brand_bolts(void)
}
/* Flush */
- if (flush_failure) flush();
+ flush_on_failure();
/* Fail */
msg_print("The fiery enchantment failed.");
@@ -4718,6 +4638,153 @@ bool_ brand_bolts(void)
/*
+ * Eternal flame activation
+ */
+
+static int get_eternal_artifact_idx(object_type const *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 const *o_ptr)
+{
+ if ((o_ptr->name1 > 0) ||
+ (o_ptr->name2 > 0))
+ {
+ return FALSE;
+ }
+
+ return (get_eternal_artifact_idx(o_ptr) >= 0);
+}
+
+static bool activate_eternal_flame(int flame_item)
+{
+ int item;
+ int artifact_idx = -1;
+
+ if (!get_item(&item,
+ "Which object do you want to imbue?",
+ "You have no objects to imbue.",
+ USE_INVEN,
+ eternal_flame_item_tester_hook))
+ {
+ return false;
+ }
+
+ /* Get the artifact idx */
+ artifact_idx = get_eternal_artifact_idx(get_object(item));
+ assert(artifact_idx >= 0);
+
+ /* Forge the item */
+ object_type *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 true;
+}
+
+
+/**
+ * Farmer Maggot's sling activation.
+ */
+static bool activate_maggot()
+{
+ int dir;
+ if (!get_aim_dir(&dir))
+ {
+ return false;
+ }
+
+ fire_ball(GF_TURN_ALL, dir, 40, 2);
+ return true;
+}
+
+
+/**
+ * 'Radagast' (Theme)
+ */
+static void activate_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;
+}
+
+
+/**
+ * 'Valaroma' (Theme)
+ */
+static void activate_valaroma()
+{
+ int power = 5 * p_ptr->lev;
+ banish_evil(power);
+}
+
+
+/*
* 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
@@ -4727,36 +4794,32 @@ bool_ brand_bolts(void)
* 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)
+void do_cmd_activate()
{
- int item, lev, chance;
-
- char ch, spell_choice;
+ auto const &k_info = game->edit_data.k_info;
+ auto const &a_info = game->edit_data.a_info;
- object_type *o_ptr;
-
- u32b f1, f2, f3, f4, f5, esp;
-
- cptr q, s;
-
-
- /* Prepare the hook */
- item_tester_hook = item_tester_hook_activate;
+ int item, lev, chance;
/* 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;
+ if (!get_item(&item,
+ "Activate which item? ",
+ "You have nothing to activate.",
+ (USE_EQUIP | USE_INVEN),
+ item_tester_hook_activate()))
+ {
+ return;
+ }
/* Get the item */
- o_ptr = get_object(item);
+ object_type *o_ptr = get_object(item);
/* Extract object flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ auto const flags = object_flags(o_ptr);
/* Wearable items have to be worn */
- if (!(f5 & TR5_ACTIVATE_NO_WIELD))
+ if (!(flags & TR_ACTIVATE_NO_WIELD))
{
if (item < INVEN_WIELD)
{
@@ -4776,7 +4839,7 @@ void do_cmd_activate(void)
{
if (o_ptr->tval == TV_RANDART)
{
- lev = random_artifacts[o_ptr->sval].level;
+ lev = game->random_artifacts[o_ptr->sval].level;
}
else
{
@@ -4799,7 +4862,7 @@ void do_cmd_activate(void)
}
/* Is it simple to use ? */
- if (f4 & TR4_EASY_USE)
+ if (flags & TR_EASY_USE)
{
chance *= 10;
}
@@ -4813,24 +4876,16 @@ void do_cmd_activate(void)
/* Roll for usage */
if ((chance < USE_DEVICE) || (randint(chance) < USE_DEVICE))
{
- if (flush_failure) flush();
+ flush_on_failure();
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)
+ if (o_ptr->tval == TV_EGG)
{
msg_print("You resume the development of the egg.");
o_ptr->timeout = 0;
@@ -4854,15 +4909,6 @@ void do_cmd_activate(void)
/* 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 */
@@ -4875,61 +4921,6 @@ void do_cmd_activate(void)
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)
{
@@ -4964,10 +4955,12 @@ void do_cmd_activate(void)
msg_print("Oops. That object cannot be activated.");
}
-
-
const char *activation_aux(object_type * o_ptr, bool_ doit, int item)
{
+ auto const &k_info = game->edit_data.k_info;
+ auto const &a_info = game->edit_data.a_info;
+ auto const &e_info = game->edit_data.e_info;
+
int plev = get_skill(SKILL_DEVICE);
int i = 0, ii = 0, ij = 0, k, dir, dummy = 0;
@@ -4984,8 +4977,8 @@ const char *activation_aux(object_type * o_ptr, bool_ doit, int item)
if (!spell && o_ptr->name1)
spell = a_info[o_ptr->name1].activate;
- /* Random and Alchemist Artifacts */
- if (!spell && o_ptr->art_name)
+ /* Random Artifacts */
+ if (!spell && (!o_ptr->artifact_name.empty()))
spell = o_ptr->xtra2;
/* Ego Items */
@@ -5004,2728 +4997,2687 @@ const char *activation_aux(object_type * o_ptr, bool_ doit, int item)
if (!spell)
return "Unknown!";
- /* Negative means a unified spell index */
- if (spell < 0)
- {
- if (doit)
- {
- call_lua("activate_activation", "(d,d)", "", -spell, item);
- o_ptr->timeout = exec_lua(format("return get_activation_timeout(%d)", -spell));
- }
- else
- {
- return string_exec_lua(format("return get_activation_desc(%d)", -spell));
- }
- }
- else
+ /* Activations always have positive numbers */
+ assert(spell > 0);
+
+ /* Activate for attack */
+ switch (spell)
{
- /* Activate for attack */
- switch (spell)
+ case ACT_GILGALAD:
{
- case ACT_GILGALAD:
+ if (!doit) return "starlight (75) every 75+d75 turns";
+ for (k = 1; k < 10; k++)
{
- 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;
+ if (k - 5) fire_beam(GF_LITE, k, 75);
}
- 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(75) + 75;
- o_ptr->timeout = rand_int(50) + 20;
+ break;
+ }
- 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);
- 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(50) + 20;
- o_ptr->timeout = rand_int(200) + 200;
+ break;
+ }
- break;
- }
+ case ACT_SKULLCLEAVER:
+ {
+ if (!doit) return "destruction every 200+d200 turns";
+ destroy_area(p_ptr->py, p_ptr->px, 15);
- 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(200) + 200;
- o_ptr->timeout = rand_int(50) + 50;
+ break;
+ }
- 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);
- case ACT_FUNDIN:
- {
- if (!doit) return "dispel evil (x4) every 100+d100 turns";
- dispel_evil(p_ptr->lev * 4);
+ o_ptr->timeout = rand_int(50) + 50;
- o_ptr->timeout = rand_int(100) + 100;
+ break;
+ }
- break;
- }
+ case ACT_FUNDIN:
+ {
+ if (!doit) return "dispel evil (x4) every 100+d100 turns";
+ dispel_evil(p_ptr->lev * 4);
- 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(100) + 100;
- o_ptr->timeout = rand_int(7) + 7;
+ break;
+ }
- break;
- }
+ case ACT_EOL:
+ {
+ if (!doit) return "mana bolt (9d8) every 7+d7 turns";
+ if (!get_aim_dir(&dir)) break;
+ fire_bolt(GF_MANA, dir, damroll(9, 8));
- 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(7) + 7;
- o_ptr->timeout = rand_int(20) + 20;
+ break;
+ }
- 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));
- case ACT_NUMENOR:
- {
- /* Give full knowledge */
- /* Hack -- Maximal info */
- monster_race *r_ptr;
- cave_type *c_ptr;
- int x, y, m;
+ o_ptr->timeout = rand_int(20) + 20;
- if (!doit) return "analyze monster every 500+d200 turns";
+ break;
+ }
- if (!tgt_pt(&x, &y)) break;
+ case ACT_KNOWLEDGE:
+ {
+ if (!doit) return "whispers from beyond(sanity drain) every 100+d200 turns";
+ identify_fully();
+ take_sanity_hit(damroll(10, 7), "the sounds of the dead");
- c_ptr = &cave[y][x];
- if (!c_ptr->m_idx) break;
+ o_ptr->timeout = rand_int(200) + 100;
- r_ptr = &r_info[c_ptr->m_idx];
+ break;
+ }
- /* 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;
- }
- }
+ 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");
+ dec_stat(A_DEX, 25, STAT_DEC_PERMANENT);
+ dec_stat(A_WIS, 25, STAT_DEC_PERMANENT);
+ dec_stat(A_CON, 25, STAT_DEC_PERMANENT);
+ dec_stat(A_STR, 25, STAT_DEC_PERMANENT);
+ dec_stat(A_CHR, 25, STAT_DEC_PERMANENT);
+ dec_stat(A_INT, 25, STAT_DEC_PERMANENT);
- /* 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));
+ o_ptr->timeout = rand_int(10) + 10;
- /* 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;
+ break;
+ }
- /* Hack -- observe many spells */
- r_ptr->r_cast_inate = MAX_UCHAR;
- r_ptr->r_cast_spell = MAX_UCHAR;
+ case ACT_THRAIN:
+ {
+ if (!doit) return "detection every 30+d30 turns";
+ msg_print("The stone glows a deep green...");
+ detect_all(DEFAULT_RADIUS);
- /* 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(30) + 30;
- o_ptr->timeout = rand_int(200) + 500;
+ break;
+ }
- break;
- }
+ case ACT_BARAHIR:
+ {
+ if (!doit) return "dispel small life every 55+d55 turns";
+ msg_print("You exterminate small life.");
+ dispel_monsters(4);
- 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(55) + 55;
- o_ptr->timeout = rand_int(200) + 100;
+ break;
+ }
- 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)
+ {
+ set_fast(randint(75) + 75, 10);
}
-
- case ACT_UNDEATH:
+ else
{
- 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;
+ set_fast(p_ptr->fast + 5, 10);
}
- 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(150) + 150;
- o_ptr->timeout = rand_int(30) + 30;
+ break;
+ }
- 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);
- 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(100) + 200;
- o_ptr->timeout = rand_int(55) + 55;
+ break;
+ }
- 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);
- 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(200) + 100;
- o_ptr->timeout = rand_int(150) + 150;
+ break;
+ }
- 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!");
}
- 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(200) + 200;
- o_ptr->timeout = rand_int(100) + 200;
+ break;
+ }
- break;
- }
+ case ACT_POWER:
+ {
+ if (!doit) return "powerful things";
+ msg_print("The ring glows intensely black...");
- 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 = ring_of_power();
+
+ break;
+ }
- o_ptr->timeout = rand_int(200) + 100;
- 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;
- case ACT_VILYA:
+ if (p_ptr->has_ability(AB_PERFECT_CASTING))
{
- 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)
+ /* Sufficient mana */
+ if (20 <= p_ptr->csp)
{
- p_ptr->black_breath = FALSE;
- msg_print("The hold of the Black Breath on you is broken!");
+ /* Use some mana */
+ p_ptr->csp -= 20;
}
- o_ptr->timeout = rand_int(200) + 200;
+ /* Over-exert the player */
+ else
+ {
+ int oops = 20 - p_ptr->csp;
- break;
- }
+ /* No mana left */
+ p_ptr->csp = 0;
+ p_ptr->csp_frac = 0;
- case ACT_POWER:
- {
- if (!doit) return "powerful things";
- msg_print("The ring glows intensely black...");
+ /* Message */
+ msg_print("You are too weak to control the stone!");
- o_ptr->timeout = ring_of_power();
+ /* Hack -- Bypass free action */
+ set_paralyzed(randint(5 * oops + 1));
- break;
+ /* Confusing. */
+ set_confused(p_ptr->confused +
+ randint(5 * oops + 1));
+ }
+
+ /* Redraw mana */
+ p_ptr->redraw |= (PR_FRAME);
}
+ take_hit(damroll(1, 12), "perilous secrets");
- /* The Stone of Lore is perilous, for the sake of game balance. */
- case ACT_STONE_LORE:
+ /* Confusing. */
+ if (rand_int(5) == 0)
{
- 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;
+ set_confused(p_ptr->confused + randint(10));
+ }
- /* No mana left */
- p_ptr->csp = 0;
- p_ptr->csp_frac = 0;
+ /* Exercise a little care... */
+ if (rand_int(20) == 0)
+ {
+ take_hit(damroll(4, 10), "perilous secrets");
+ }
- /* Message */
- msg_print("You are too weak to control the stone!");
+ o_ptr->timeout = 1;
- /* Hack -- Bypass free action */
- (void)set_paralyzed(p_ptr->paralyzed +
- randint(5 * oops + 1));
+ break;
+ }
- /* Confusing. */
- (void)set_confused(p_ptr->confused +
- randint(5 * oops + 1));
- }
+ 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);
- /* Redraw mana */
- p_ptr->redraw |= (PR_MANA);
- }
+ o_ptr->timeout = 1000;
- take_hit(damroll(1, 12), "perilous secrets");
+ break;
+ }
- /* Confusing. */
- if (rand_int(5) == 0)
- {
- (void)set_confused(p_ptr->confused + randint(10));
- }
+ case ACT_BLADETURNER:
+ {
+ if (!doit) return "invulnerability (4+d8) every 800 turns";
+ set_invuln(p_ptr->invuln + randint(8) + 4);
- /* Exercise a little care... */
- if (rand_int(20) == 0)
- {
- take_hit(damroll(4, 10), "perilous secrets");
- }
+ o_ptr->timeout = 800;
- o_ptr->timeout = 1;
+ break;
+ }
- 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...");
+ set_afraid(0);
+ set_shero(p_ptr->shero + randint(50) + 50);
+ hp_player(30);
+ set_blessed(p_ptr->blessed + randint(50) + 50);
+ set_oppose_acid(p_ptr->oppose_acid + randint(50) + 50);
+ set_oppose_elec(p_ptr->oppose_elec + randint(50) + 50);
+ set_oppose_fire(p_ptr->oppose_fire + randint(50) + 50);
+ set_oppose_cold(p_ptr->oppose_cold + randint(50) + 50);
+ set_oppose_pois(p_ptr->oppose_pois + randint(50) + 50);
- 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 = 400;
- o_ptr->timeout = 1000;
+ break;
+ }
- break;
- }
+ case ACT_BELEGENNON:
+ {
+ if (!doit) return ("heal (777), curing and heroism every 300 turns");
+ msg_print("A heavenly choir sings...");
+ set_poisoned(0);
+ set_cut(0);
+ set_stun(0);
+ set_confused(0);
+ set_blind(0);
+ set_hero(p_ptr->hero + randint(25) + 25);
+ hp_player(777);
- case ACT_BLADETURNER:
- {
- if (!doit) return "invulnerability (4+d8) every 800 turns";
- set_invuln(p_ptr->invuln + randint(8) + 4);
+ o_ptr->timeout = 300;
- o_ptr->timeout = 800;
+ break;
+ }
- break;
- }
+ case ACT_GORLIM:
+ {
+ if (!doit) return "rays of fear in every direction";
+ turn_monsters(40 + p_ptr->lev);
- 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 = 3 * (p_ptr->lev + 10);
- o_ptr->timeout = 400;
+ break;
+ }
- break;
- }
+ case ACT_COLLUIN:
+ {
+ if (!doit) return "resistance (20+d20 turns) every 111 turns";
+ msg_print("Your cloak glows many colours...");
+ set_oppose_acid(p_ptr->oppose_acid + randint(20) + 20);
+ set_oppose_elec(p_ptr->oppose_elec + randint(20) + 20);
+ set_oppose_fire(p_ptr->oppose_fire + randint(20) + 20);
+ set_oppose_cold(p_ptr->oppose_cold + randint(20) + 20);
+ set_oppose_pois(p_ptr->oppose_pois + randint(20) + 20);
- 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 = 111;
- o_ptr->timeout = 300;
+ break;
+ }
- break;
- }
- case ACT_GORLIM:
- {
- if (!doit) return "rays of fear in every direction";
- turn_monsters(40 + p_ptr->lev);
+ 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 = 3 * (p_ptr->lev + 10);
+ o_ptr->timeout = rand_int(5) + 5;
- break;
- }
+ break;
+ }
- case ACT_COLLUIN:
+ case ACT_ANGUIREL:
+ {
+ if (!doit) return "a getaway every 35 turns";
+ switch (randint(13))
{
- 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;
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ {
+ teleport_player(10);
- break;
- }
+ break;
+ }
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ {
+ teleport_player(222);
- 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);
+ break;
+ }
- o_ptr->timeout = rand_int(5) + 5;
+ case 11:
+ case 12:
+ {
+ stair_creation();
- break;
- }
+ break;
+ }
- case ACT_ANGUIREL:
- {
- if (!doit) return "a getaway every 35 turns";
- switch (randint(13))
+ default:
{
- case 1:
- case 2:
- case 3:
- case 4:
- case 5:
+ if (get_check("Leave this level? "))
{
- teleport_player(10);
+ autosave_checkpoint();
- break;
+ /* Leaving */
+ p_ptr->leaving = TRUE;
}
- case 6:
- case 7:
- case 8:
- case 9:
- case 10:
- {
- teleport_player(222);
+ break;
+ }
+ }
- break;
- }
+ o_ptr->timeout = 35;
- case 11:
- case 12:
- {
- (void)stair_creation();
+ break;
+ }
- 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);
- default:
- {
- if (get_check("Leave this level? "))
- {
- autosave_checkpoint();
+ o_ptr->timeout = 500;
- /* Leaving */
- p_ptr->leaving = TRUE;
- }
+ break;
+ }
- 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.");
+ summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_DAWN, TRUE);
- o_ptr->timeout = 35;
+ o_ptr->timeout = 500 + randint(500);
- break;
- }
+ 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);
+ 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 = 500;
+ o_ptr->timeout = 100;
- break;
- }
+ 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);
+ 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 = 500 + randint(500);
+ o_ptr->timeout = 70;
- break;
- }
+ 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);
+ case ACT_CUBRAGOL:
+ {
+ if (!doit) return "fire branding of bolts every 999 turns";
+ msg_print("Your crossbow glows deep red...");
+ brand_bolts();
- o_ptr->timeout = 100;
+ o_ptr->timeout = 999;
- break;
- }
+ break;
+ }
- case ACT_TURMIL:
+ case ACT_ELESSAR:
+ {
+ if (!doit) return "heal and cure black breath every 200 turns";
+ if (p_ptr->black_breath)
{
- 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);
+ msg_print("The hold of the Black Breath on you is broken!");
+ }
+ p_ptr->black_breath = FALSE;
+ hp_player(100);
- o_ptr->timeout = 70;
+ o_ptr->timeout = 200;
- break;
- }
+ break;
+ }
- case ACT_CUBRAGOL:
+ 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)
{
- if (!doit) return "fire branding of bolts every 999 turns";
- msg_print("Your crossbow glows deep red...");
- (void)brand_bolts();
+ p_ptr->csp = p_ptr->msp;
+ p_ptr->csp_frac = 0;
+ msg_print("Your feel your head clear.");
+ p_ptr->redraw |= (PR_FRAME);
+ p_ptr->window |= (PW_PLAYER);
+ }
- o_ptr->timeout = 999;
+ o_ptr->timeout = 666;
- break;
- }
+ break;
+ }
- case ACT_ELESSAR:
+ case ACT_MARDA:
+ {
+ if (!doit) return "summon a thunderlord every 1000 turns";
+ if (randint(3) == 1)
{
- if (!doit) return "heal and cure black breath every 200 turns";
- if (p_ptr->black_breath)
+ if (summon_specific(p_ptr->py, p_ptr->px, ((plev * 3) / 2), SUMMON_THUNDERLORD))
{
- msg_print("The hold of the Black Breath on you is broken!");
+ msg_print("A Thunderlord comes from thin air!");
+ msg_print("'I will burn you!'");
}
- p_ptr->black_breath = FALSE;
- hp_player(100);
-
- o_ptr->timeout = 200;
-
- break;
}
-
- case ACT_GANDALF:
+ else
{
- if (!doit) return "restore mana every 666 turns";
- msg_print("Your mage staff glows deep blue...");
- if (p_ptr->csp < p_ptr->msp)
+ if (summon_specific_friendly(p_ptr->py, p_ptr->px, ((plev * 3) / 2),
+ SUMMON_THUNDERLORD, (plev == 50 ? TRUE : FALSE)))
{
- 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);
+ msg_print("A Thunderlord comes from thin air!");
+ msg_print("'I will help you in your difficult task.'");
}
-
- 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, (bool_)(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;
- o_ptr->timeout = 1000;
+ break;
+ }
- break;
- }
+ case ACT_PALANTIR:
+ {
+ if (!doit) return "clairvoyance every 100+d100 turns";
+ msg_print("The stone glows a deep green...");
+ wiz_lite_extra();
+ detect_doors(DEFAULT_RADIUS);
+ detect_stairs(DEFAULT_RADIUS);
- 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;
- o_ptr->timeout = rand_int(100) + 100;
+ break;
+ }
- break;
- }
+ case ACT_EREBOR:
+ {
+ if (!doit) return "open a secret passage every 75 turns";
+ msg_print("Your pick twists in your hands.");
- case ACT_EREBOR:
+ if (!get_aim_dir(&dir)) break;
+ if (passwall(dir, TRUE))
{
- if (!doit) return "open a secret passage every 75 turns";
- msg_print("Your pick twists in your hands.");
+ msg_print("A passage opens, and you step through.");
+ }
+ else
+ {
+ msg_print("There is no wall there!");
+ }
- 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;
- o_ptr->timeout = 75;
+ break;
+ }
- break;
- }
+ case ACT_DRUEDAIN:
+ {
+ if (!doit) return "detection every 99 turns";
+ msg_print("Your drum shows you the world.");
+ detect_all(DEFAULT_RADIUS);
- 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;
- o_ptr->timeout = 99;
+ break;
+ }
- 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);
- 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;
- o_ptr->timeout = 250;
+ break;
+ }
- 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);
- 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;
- o_ptr->timeout = 300;
+ break;
+ }
- 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);
}
- 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;
- o_ptr->timeout = 1000;
+ break;
+ }
- break;
+ case ACT_HURIN:
+ {
+ if (!doit) return "berserker and +10 to speed (50) every 100+d200 turns";
+ if (!p_ptr->fast)
+ {
+ set_fast(randint(50) + 50, 10);
}
-
- case ACT_HURIN:
+ else
{
- 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);
+ 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;
+ o_ptr->timeout = rand_int(200) + 100;
- break;
- }
+ 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);
+ 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);
+ o_ptr->timeout = 200 + rand_int(200);
- break;
- }
+ 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);
+ 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;
+ o_ptr->timeout = 100;
- break;
- }
+ break;
+ }
- case ACT_GROND:
- {
- if (!doit) return "alter reality every 100 turns";
- msg_print("Your hammer hits the floor...");
- alter_reality();
+ case ACT_GROND:
+ {
+ if (!doit) return "alter reality every 100 turns";
+ msg_print("Your hammer hits the floor...");
+ alter_reality();
- o_ptr->timeout = 100;
+ o_ptr->timeout = 100;
- break;
- }
+ break;
+ }
- case ACT_NATUREBANE:
- {
- if (!doit) return "dispel monsters (300) every 200+d200 turns";
- msg_print("Your axe glows blood red...");
- dispel_monsters(300);
+ 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);
+ o_ptr->timeout = 200 + randint(200);
- break;
- }
+ break;
+ }
- case ACT_NIGHT:
+ 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 (!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);
- }
+ if (drain_life(dir, 100)) hp_player(100);
+ }
- o_ptr->timeout = 250;
+ o_ptr->timeout = 250;
- break;
- }
+ 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);
+ case ACT_ORCHAST:
+ {
+ if (!doit) return "detect orcs every 10 turns";
+ msg_print("Your weapon glows brightly...");
+ detect_monsters_orcs(DEFAULT_RADIUS);
- o_ptr->timeout = 10;
+ o_ptr->timeout = 10;
- break;
- }
- case ACT_SUNLIGHT:
- {
- if (!doit) return "beam of sunlight every 10 turns";
+ 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);
+ if (!get_aim_dir(&dir)) break;
+ msg_print("A line of sunlight appears.");
+ lite_line(dir);
- o_ptr->timeout = 10;
+ o_ptr->timeout = 10;
- break;
- }
+ 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));
+ 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;
+ o_ptr->timeout = 2;
- break;
- }
+ 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);
+ 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;
+ o_ptr->timeout = rand_int(4) + 4;
- break;
- }
+ 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));
+ 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;
+ o_ptr->timeout = rand_int(6) + 6;
- break;
- }
+ 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));
+ 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;
+ o_ptr->timeout = rand_int(5) + 5;
- break;
- }
+ 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));
+ 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;
+ o_ptr->timeout = rand_int(7) + 7;
- break;
- }
+ 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));
+ 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;
+ o_ptr->timeout = rand_int(8) + 8;
- break;
- }
+ 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);
+ 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;
+ o_ptr->timeout = 400;
- break;
- }
+ 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);
+ 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;
+ o_ptr->timeout = 400;
- break;
- }
+ 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))
+ 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;
+ o_ptr->timeout = rand_int(100) + 100;
- break;
- }
+ 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);
+ 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;
+ o_ptr->timeout = 300;
- break;
- }
+ 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);
+ 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;
+ o_ptr->timeout = 500;
- break;
- }
+ 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);
+ 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;
+ o_ptr->timeout = 400;
- break;
- }
+ break;
+ }
- case ACT_VAMPIRE_1:
+ 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 (!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);
- }
+ if (drain_life(dir, 50))
+ hp_player(50);
+ }
- o_ptr->timeout = 400;
+ o_ptr->timeout = 400;
- break;
- }
+ 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);
+ 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;
+ o_ptr->timeout = rand_int(90) + 90;
- break;
- }
+ 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);
+ 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;
+ o_ptr->timeout = rand_int(225) + 225;
- break;
- }
+ 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);
+ 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;
+ o_ptr->timeout = rand_int(325) + 325;
- break;
- }
+ 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);
+ 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;
+ o_ptr->timeout = rand_int(425) + 425;
- break;
- }
+ 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";
+ 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];
+ 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];
+ /* 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);
- }
+ /* 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;
+ o_ptr->timeout = 250;
- break;
- }
+ break;
+ }
- case ACT_VAMPIRE_2:
+ 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 (!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);
- }
+ if (drain_life(dir, 100))
+ hp_player(100);
+ }
- o_ptr->timeout = 400;
+ o_ptr->timeout = 400;
- break;
- }
+ break;
+ }
- case ACT_CALL_CHAOS:
- {
- if (!doit) return "call chaos every 350 turns";
- msg_print("It glows in scintillating colours...");
- call_chaos();
+ 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;
+ o_ptr->timeout = 350;
- break;
- }
+ 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);
+ 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;
+ o_ptr->timeout = 400;
- break;
- }
+ 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);
+ 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;
+ o_ptr->timeout = rand_int(300) + 300;
- break;
- }
+ 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);
+ 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;
+ o_ptr->timeout = rand_int(300) + 300;
- break;
- }
+ 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);
+ 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;
+ o_ptr->timeout = 500;
- break;
- }
+ break;
+ }
- /* Activate for other offensive action */
+ /* 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);
+ 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;
+ o_ptr->timeout = 15;
- break;
- }
+ break;
+ }
- case ACT_SLEEP:
- {
- if (!doit) return "sleep nearby monsters every 55 turns";
- msg_print("It glows deep blue...");
- sleep_monsters_touch();
+ 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;
+ o_ptr->timeout = 55;
- break;
- }
+ break;
+ }
- case ACT_QUAKE:
+ 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)
{
- 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;
+ earthquake(p_ptr->py, p_ptr->px, 10);
+ o_ptr->timeout = 50;
}
- case ACT_TERROR:
- {
- if (!doit) return "terror every 3 * (level+10) turns";
- turn_monsters(40 + p_ptr->lev);
+ break;
+ }
- o_ptr->timeout = 3 * (p_ptr->lev + 10);
+ case ACT_TERROR:
+ {
+ if (!doit) return "terror every 3 * (level+10) turns";
+ turn_monsters(40 + p_ptr->lev);
- break;
- }
+ o_ptr->timeout = 3 * (p_ptr->lev + 10);
- 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);
+ break;
+ }
- o_ptr->timeout = 200;
+ case ACT_TELE_AWAY:
+ {
+ if (!doit) return "teleport away every 200 turns";
+ if (!get_aim_dir(&dir)) break;
+ fire_beam(GF_AWAY_ALL, dir, plev);
- break;
- }
+ o_ptr->timeout = 200;
+
+ break;
+ }
- case ACT_BANISH_EVIL:
+ case ACT_BANISH_EVIL:
+ {
+ if (!doit) return "banish evil every 250+d250 turns";
+ if (banish_evil(100))
{
- if (!doit) return "banish evil every 250+d250 turns";
- if (banish_evil(100))
- {
- msg_print("The power of the artifact banishes evil!");
- }
+ msg_print("The power of the artifact banishes evil!");
+ }
- o_ptr->timeout = 250 + randint(250);
+ o_ptr->timeout = 250 + randint(250);
- break;
- }
+ break;
+ }
- case ACT_GENOCIDE:
- {
- if (!doit) return "genocide every 500 turns";
- msg_print("It glows deep blue...");
- (void)genocide(TRUE);
+ case ACT_GENOCIDE:
+ {
+ if (!doit) return "genocide every 500 turns";
+ msg_print("It glows deep blue...");
+ genocide(TRUE);
- o_ptr->timeout = 500;
+ o_ptr->timeout = 500;
- break;
- }
+ 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);
+ case ACT_MASS_GENO:
+ {
+ if (!doit) return "mass genocide every 1000 turns";
+ msg_print("It lets out a long, shrill note...");
+ mass_genocide(TRUE);
- o_ptr->timeout = 1000;
+ o_ptr->timeout = 1000;
- break;
- }
+ break;
+ }
- /* Activate for summoning / charming */
+ /* 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);
+ case ACT_CHARM_ANIMAL:
+ {
+ if (!doit) return "charm animal every 300 turns";
+ if (!get_aim_dir(&dir)) break;
+ charm_animal(dir, plev);
- o_ptr->timeout = 300;
+ o_ptr->timeout = 300;
- break;
- }
+ 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);
+ case ACT_CHARM_UNDEAD:
+ {
+ if (!doit) return "enslave undead every 333 turns";
+ if (!get_aim_dir(&dir)) break;
+ control_one_undead(dir, plev);
- o_ptr->timeout = 333;
+ o_ptr->timeout = 333;
- break;
- }
+ break;
+ }
- case ACT_CHARM_OTHER:
- {
- if (!doit) return "charm monster every 400 turns";
- if (!get_aim_dir(&dir)) break;
- (void) charm_monster(dir, plev);
+ case ACT_CHARM_OTHER:
+ {
+ if (!doit) return "charm monster every 400 turns";
+ if (!get_aim_dir(&dir)) break;
+ charm_monster(dir, plev);
- o_ptr->timeout = 400;
+ o_ptr->timeout = 400;
- break;
- }
+ break;
+ }
- case ACT_CHARM_ANIMALS:
- {
- if (!doit) return "animal friendship every 500 turns";
- (void) charm_animals(plev * 2);
+ case ACT_CHARM_ANIMALS:
+ {
+ if (!doit) return "animal friendship every 500 turns";
+ charm_animals(plev * 2);
- o_ptr->timeout = 500;
+ o_ptr->timeout = 500;
- break;
- }
+ break;
+ }
- case ACT_CHARM_OTHERS:
- {
- if (!doit) return "mass charm every 750 turns";
- charm_monsters(plev * 2);
+ case ACT_CHARM_OTHERS:
+ {
+ if (!doit) return "mass charm every 750 turns";
+ charm_monsters(plev * 2);
- o_ptr->timeout = 750;
+ o_ptr->timeout = 750;
- break;
- }
+ 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);
+ case ACT_SUMMON_ANIMAL:
+ {
+ if (!doit) return "summon animal every 200+d300 turns";
+ summon_specific_friendly(p_ptr->py, p_ptr->px, plev, SUMMON_ANIMAL_RANGER, TRUE);
- o_ptr->timeout = 200 + randint(300);
+ o_ptr->timeout = 200 + randint(300);
- break;
- }
+ 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);
+ case ACT_SUMMON_PHANTOM:
+ {
+ if (!doit) return "summon phantasmal servant every 200+d200 turns";
+ msg_print("You summon a phantasmal servant.");
+ summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_PHANTOM, TRUE);
- o_ptr->timeout = 200 + randint(200);
+ o_ptr->timeout = 200 + randint(200);
- break;
- }
+ break;
+ }
- case ACT_SUMMON_ELEMENTAL:
+ case ACT_SUMMON_ELEMENTAL:
+ {
+ if (!doit) return "summon elemental every 750 turns";
+ if (randint(3) == 1)
{
- 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))
{
- 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!");
- }
+ msg_print("An elemental materialises...");
+ msg_print("You fail to control it!");
}
- else
+ }
+ else
+ {
+ if (summon_specific_friendly(p_ptr->py, p_ptr->px, ((plev * 3) / 2),
+ SUMMON_ELEMENTAL, (plev == 50 ? TRUE : FALSE)))
{
- if (summon_specific_friendly(p_ptr->py, p_ptr->px, ((plev * 3) / 2),
- SUMMON_ELEMENTAL, (bool_)(plev == 50 ? TRUE : FALSE)))
- {
- msg_print("An elemental materialises...");
- msg_print("It seems obedient to you.");
- }
+ msg_print("An elemental materialises...");
+ msg_print("It seems obedient to you.");
}
+ }
- o_ptr->timeout = 750;
+ o_ptr->timeout = 750;
- break;
- }
+ break;
+ }
- case ACT_SUMMON_DEMON:
+ case ACT_SUMMON_DEMON:
+ {
+ if (!doit) return "summon demon every 666+d333 turns";
+ if (randint(3) == 1)
{
- 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))
{
- 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!'");
- }
+ 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
+ }
+ else
+ {
+ if (summon_specific_friendly(p_ptr->py, p_ptr->px, ((plev * 3) / 2),
+ SUMMON_DEMON, (plev == 50 ? TRUE : FALSE)))
{
- if (summon_specific_friendly(p_ptr->py, p_ptr->px, ((plev * 3) / 2),
- SUMMON_DEMON, (bool_)(plev == 50 ? TRUE : FALSE)))
- {
- msg_print("The area fills with a stench of sulphur and brimstone.");
- msg_print("'What is thy bidding... Master?'");
- }
+ 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);
+ o_ptr->timeout = 666 + randint(333);
- break;
- }
+ break;
+ }
- case ACT_SUMMON_UNDEAD:
+ case ACT_SUMMON_UNDEAD:
+ {
+ if (!doit) return "summon undead every 666+d333 turns";
+ if (randint(3) == 1)
{
- 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)))
{
- 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!'");
- }
+ 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
+ }
+ 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)))
{
- 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)))
- {
- 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!");
- }
+ 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);
+ o_ptr->timeout = 666 + randint(333);
- break;
- }
+ break;
+ }
- /* Activate for healing */
+ /* 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);
+ case ACT_CURE_LW:
+ {
+ if (!doit) return format("cure light wounds every %d turns", (is_junkart ? 50 : 10));
+ set_afraid(0);
+ hp_player(30);
- o_ptr->timeout = 10;
+ o_ptr->timeout = 10;
- break;
- }
+ 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);
+ 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));
+ set_cut((p_ptr->cut / 2) - 50);
- o_ptr->timeout = rand_int(3) + 3;
+ o_ptr->timeout = rand_int(3) + 3;
- break;
- }
+ 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);
+ case ACT_CURE_POISON:
+ {
+ if (!doit) return "remove fear and cure poison every 5 turns";
+ msg_print("It glows deep blue...");
+ set_afraid(0);
+ set_poisoned(0);
- o_ptr->timeout = 5;
+ o_ptr->timeout = 5;
- break;
- }
+ break;
+ }
- case ACT_REST_LIFE:
- {
- if (!doit) return "restore life levels every 450 turns";
- msg_print("It glows a deep red...");
- restore_level();
+ 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;
+ o_ptr->timeout = 450;
- break;
- }
+ 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();
+ 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...");
+ do_res_stat(A_STR, TRUE);
+ do_res_stat(A_INT, TRUE);
+ do_res_stat(A_WIS, TRUE);
+ do_res_stat(A_DEX, TRUE);
+ do_res_stat(A_CON, TRUE);
+ do_res_stat(A_CHR, TRUE);
+ restore_level();
- o_ptr->timeout = 750;
+ o_ptr->timeout = 750;
- break;
- }
+ 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);
+ 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...");
+ hp_player(700);
+ set_cut(0);
- o_ptr->timeout = 250;
+ o_ptr->timeout = 250;
- break;
- }
+ 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);
+ 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...");
+ hp_player(1000);
+ set_cut(0);
- o_ptr->timeout = 888;
+ o_ptr->timeout = 888;
- break;
- }
+ 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);
+ case ACT_ESP:
+ {
+ if (!doit) return "temporary ESP (dur 25+d30) every 200 turns";
+ set_tim_esp(p_ptr->tim_esp + randint(30) + 25);
- o_ptr->timeout = 200;
+ o_ptr->timeout = 200;
- break;
- }
+ 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);
+ case ACT_BERSERK:
+ {
+ if (!doit) return "heroism and berserk (dur 50+d50) every 100+d100 turns";
+ set_shero(p_ptr->shero + randint(50) + 50);
+ set_blessed(p_ptr->blessed + randint(50) + 50);
- o_ptr->timeout = 100 + randint(100);
+ o_ptr->timeout = 100 + randint(100);
- break;
- }
+ 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);
+ 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;
+ set_protevil(p_ptr->protevil + randint(25) + k);
- o_ptr->timeout = rand_int(225) + 225;
+ o_ptr->timeout = rand_int(225) + 225;
- break;
- }
+ 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);
+ case ACT_RESIST_ALL:
+ {
+ if (!doit) return "resist elements (dur 40+d40) every 200 turns";
+ msg_print("It glows many colours...");
+ set_oppose_acid(p_ptr->oppose_acid + randint(40) + 40);
+ set_oppose_elec(p_ptr->oppose_elec + randint(40) + 40);
+ set_oppose_fire(p_ptr->oppose_fire + randint(40) + 40);
+ set_oppose_cold(p_ptr->oppose_cold + randint(40) + 40);
+ set_oppose_pois(p_ptr->oppose_pois + randint(40) + 40);
- o_ptr->timeout = 200;
+ o_ptr->timeout = 200;
- break;
- }
+ break;
+ }
- case ACT_SPEED:
+ case ACT_SPEED:
+ {
+ if (!doit) return "speed (dur 20+d20) every 250 turns";
+ msg_print("It glows bright green...");
+ if (!p_ptr->fast)
{
- 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);
- }
+ set_fast(randint(20) + 20, 10);
+ }
+ else
+ {
+ set_fast(p_ptr->fast + 5, 10);
+ }
- o_ptr->timeout = 250;
+ o_ptr->timeout = 250;
- break;
- }
+ break;
+ }
- case ACT_XTRA_SPEED:
+ case ACT_XTRA_SPEED:
+ {
+ if (!doit) return "speed (dur 75+d75) every 200+d200 turns";
+ msg_print("It glows brightly...");
+ if (!p_ptr->fast)
{
- 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);
- }
+ set_fast(randint(75) + 75, 10);
+ }
+ else
+ {
+ set_fast(p_ptr->fast + 5, 10);
+ }
- o_ptr->timeout = rand_int(200) + 200;
+ o_ptr->timeout = rand_int(200) + 200;
- break;
- }
+ 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));
+ 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;
+ o_ptr->timeout = 1000;
- break;
- }
+ break;
+ }
- case ACT_INVULN:
- {
- if (!doit) return "invulnerability (dur 8+d8) every 1000 turns";
- (void)set_invuln(p_ptr->invuln + randint(8) + 8);
+ case ACT_INVULN:
+ {
+ if (!doit) return "invulnerability (dur 8+d8) every 1000 turns";
+ set_invuln(p_ptr->invuln + randint(8) + 8);
- o_ptr->timeout = 1000;
+ o_ptr->timeout = 1000;
- break;
- }
+ break;
+ }
- /* Activate for general purpose effect (detection etc.) */
+ /* 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);
+ 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;
+ o_ptr->timeout = rand_int(10) + 10;
- break;
- }
+ 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);
+ 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;
+ o_ptr->timeout = rand_int(50) + 50;
- break;
- }
+ 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);
+ 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;
+ o_ptr->timeout = rand_int(55) + 55;
- break;
- }
+ 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();
+ case ACT_DETECT_XTRA:
+ {
+ if (!doit) return "detection and identify true every 1000 turns";
+ msg_print("It glows brightly...");
+ detect_all(DEFAULT_RADIUS);
+ identify_fully();
- o_ptr->timeout = 1000;
+ o_ptr->timeout = 1000;
- break;
- }
+ break;
+ }
- case ACT_ID_FULL:
- {
- if (!doit) return "identify true every 750 turns";
- msg_print("It glows yellow...");
- identify_fully();
+ case ACT_ID_FULL:
+ {
+ if (!doit) return "identify true every 750 turns";
+ msg_print("It glows yellow...");
+ identify_fully();
- o_ptr->timeout = 750;
+ o_ptr->timeout = 750;
- break;
- }
+ break;
+ }
- case ACT_ID_PLAIN:
- {
- if (!doit) return "identify spell every 10 turns";
- if (!ident_spell()) break;
+ case ACT_ID_PLAIN:
+ {
+ if (!doit) return "identify spell every 10 turns";
+ if (!ident_spell()) break;
- o_ptr->timeout = 10;
+ o_ptr->timeout = 10;
- break;
- }
+ break;
+ }
- case ACT_RUNE_EXPLO:
- {
- if (!doit) return "explosive rune every 200 turns";
- msg_print("It glows bright red...");
- explosive_rune();
+ case ACT_RUNE_EXPLO:
+ {
+ if (!doit) return "explosive rune every 200 turns";
+ msg_print("It glows bright red...");
+ explosive_rune();
- o_ptr->timeout = 200;
+ o_ptr->timeout = 200;
- break;
- }
+ break;
+ }
- case ACT_RUNE_PROT:
- {
- if (!doit) return "rune of protection every 400 turns";
- msg_print("It glows light blue...");
- warding_glyph();
+ 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;
+ o_ptr->timeout = 400;
- break;
- }
+ break;
+ }
- case ACT_SATIATE:
- {
- if (!doit) return "satisfy hunger every 200 turns";
- (void)set_food(PY_FOOD_MAX - 1);
+ case ACT_SATIATE:
+ {
+ if (!doit) return "satisfy hunger every 200 turns";
+ set_food(PY_FOOD_MAX - 1);
- o_ptr->timeout = 200;
+ o_ptr->timeout = 200;
- break;
- }
+ break;
+ }
- case ACT_DEST_DOOR:
- {
- if (!doit) return "destroy doors and traps every 10 turns";
- msg_print("It glows bright red...");
- destroy_doors_touch();
+ 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;
+ o_ptr->timeout = 10;
- break;
- }
+ 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);
+ 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;
+ o_ptr->timeout = 5;
- break;
- }
+ break;
+ }
- case ACT_RECHARGE:
- {
- if (!doit) return "recharging every 70 turns";
- recharge(60);
+ case ACT_RECHARGE:
+ {
+ if (!doit) return "recharging every 70 turns";
+ recharge(60);
- o_ptr->timeout = 70;
+ o_ptr->timeout = 70;
- break;
- }
+ break;
+ }
- case ACT_ALCHEMY:
- {
- if (!doit) return "alchemy every 500 turns";
- msg_print("It glows bright yellow...");
- (void) alchemy();
+ case ACT_ALCHEMY:
+ {
+ if (!doit) return "alchemy every 500 turns";
+ msg_print("It glows bright yellow...");
+ alchemy();
+
+ o_ptr->timeout = 500;
- o_ptr->timeout = 500;
+ break;
+ }
+ case ACT_DIM_DOOR:
+ {
+ if (!doit) return "dimension door every 100 turns";
+ if (dungeon_flags & DF_NO_TELEPORT)
+ {
+ msg_print("Not on special levels!");
break;
}
- case ACT_DIM_DOOR:
+ 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)))
{
- if (!doit) return "dimension door every 100 turns";
- if (dungeon_flags2 & DF2_NO_TELEPORT)
- {
- msg_print("Not on special levels!");
- break;
- }
+ msg_print("You fail to exit the void correctly!");
+ p_ptr->energy -= 100;
+ get_pos_player(10, &ij, &ii);
+ }
- msg_print("You open a Void Jumpgate. Choose a destination.");
- if (!tgt_pt(&ii, &ij)) break;
+ 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);
- p_ptr->energy -= 60 - plev;
+ o_ptr->timeout = 100;
- 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);
- }
+ break;
+ }
- 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);
+ 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 = 100;
+ o_ptr->timeout = 45;
- break;
- }
+ break;
+ }
- case ACT_TELEPORT:
+ case ACT_RECALL:
+ {
+ if (!(dungeon_flags & DF_ASK_LEAVE) || ((dungeon_flags & DF_ASK_LEAVE) && !get_check("Leave this unique level forever? ")))
{
- if (!doit) return format("teleport (range 100) every %d turns", (is_junkart? 100 : 45));
- msg_print("It twists space around you...");
- teleport_player(100);
+ if (!doit) return "word of recall every 200 turns";
+ msg_print("It glows soft white...");
+ recall_player(20,15);
- o_ptr->timeout = 45;
-
- break;
+ o_ptr->timeout = 200;
}
- 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);
+ break;
+ }
- o_ptr->timeout = 200;
- }
+ case ACT_DEATH:
+ {
+ if (!doit) return "death";
+ take_hit(5000, "activating a death spell");
- break;
- }
+ /* Timeout is set before return */
- case ACT_DEATH:
- {
- if (!doit) return "death";
- take_hit(5000, "activating a death spell");
+ break;
+ }
- /* Timeout is set before return */
+ case ACT_RUINATION:
+ {
+ if (!doit) return "Ruination";
+ msg_print("Your nerves and muscles feel weak and lifeless!");
- break;
- }
+ take_hit(damroll(10, 10), "activating Ruination");
+ dec_stat(A_DEX, 25, TRUE);
+ dec_stat(A_WIS, 25, TRUE);
+ dec_stat(A_CON, 25, TRUE);
+ dec_stat(A_STR, 25, TRUE);
+ dec_stat(A_CHR, 25, TRUE);
+ dec_stat(A_INT, 25, TRUE);
- case ACT_RUINATION:
- {
- if (!doit) return "Ruination";
- msg_print("Your nerves and muscles feel weak and lifeless!");
+ /* Timeout is set before return */
- 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);
+ break;
+ }
- /* Timeout is set before return */
+ case ACT_DESTRUC:
+ {
+ if (!doit) return "Destruction every 100 turns";
+ earthquake(p_ptr->py, p_ptr->px, 12);
- break;
- }
+ /* Timeout is set before return */
- case ACT_DESTRUC:
- {
- if (!doit) return "Destruction every 100 turns";
- earthquake(p_ptr->py, p_ptr->px, 12);
+ break;
+ }
- /* Timeout is set before return */
+ case ACT_UNINT:
+ {
+ if (!doit) return "decreasing Intelligence";
+ dec_stat(A_INT, 25, FALSE);
- break;
- }
+ /* Timeout is set before return */
- case ACT_UNINT:
- {
- if (!doit) return "decreasing Intelligence";
- (void)dec_stat(A_INT, 25, FALSE);
+ break;
+ }
- /* Timeout is set before return */
+ case ACT_UNSTR:
+ {
+ if (!doit) return "decreasing Strength";
+ dec_stat(A_STR, 25, FALSE);
- break;
- }
+ /* Timeout is set before return */
- case ACT_UNSTR:
- {
- if (!doit) return "decreasing Strength";
- (void)dec_stat(A_STR, 25, FALSE);
+ break;
+ }
- /* Timeout is set before return */
+ case ACT_UNCON:
+ {
+ if (!doit) return "decreasing Constitution";
+ dec_stat(A_CON, 25, FALSE);
- break;
- }
+ /* Timeout is set before return */
- case ACT_UNCON:
- {
- if (!doit) return "decreasing Constitution";
- (void)dec_stat(A_CON, 25, FALSE);
+ break;
+ }
- /* Timeout is set before return */
+ case ACT_UNCHR:
+ {
+ if (!doit) return "decreasing Charisma";
+ dec_stat(A_CHR, 25, FALSE);
- break;
- }
+ /* Timeout is set before return */
- case ACT_UNCHR:
- {
- if (!doit) return "decreasing Charisma";
- (void)dec_stat(A_CHR, 25, FALSE);
+ break;
+ }
- /* Timeout is set before return */
+ case ACT_UNDEX:
+ {
+ if (!doit) return "decreasing Dexterity";
+ dec_stat(A_DEX, 25, FALSE);
- break;
- }
+ /* Timeout is set before return */
- case ACT_UNDEX:
- {
- if (!doit) return "decreasing Dexterity";
- (void)dec_stat(A_DEX, 25, FALSE);
+ break;
+ }
- /* Timeout is set before return */
+ case ACT_UNWIS:
+ {
+ if (!doit) return "decreasing Wisdom";
+ dec_stat(A_WIS, 25, FALSE);
- break;
- }
+ /* Timeout is set before return */
- case ACT_UNWIS:
- {
- if (!doit) return "decreasing Wisdom";
- (void)dec_stat(A_WIS, 25, FALSE);
+ break;
+ }
- /* Timeout is set before return */
+ case ACT_STATLOSS:
+ {
+ if (!doit) return "stat loss";
+ dec_stat(A_STR, 15, FALSE);
+ dec_stat(A_INT, 15, FALSE);
+ dec_stat(A_WIS, 15, FALSE);
+ dec_stat(A_DEX, 15, FALSE);
+ dec_stat(A_CON, 15, FALSE);
+ dec_stat(A_CHR, 15, FALSE);
- break;
- }
+ /* Timeout is set before return */
- 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);
+ break;
+ }
- /* Timeout is set before return */
+ case ACT_HISTATLOSS:
+ {
+ if (!doit) return "high stat loss";
+ dec_stat(A_STR, 25, FALSE);
+ dec_stat(A_INT, 25, FALSE);
+ dec_stat(A_WIS, 25, FALSE);
+ dec_stat(A_DEX, 25, FALSE);
+ dec_stat(A_CON, 25, FALSE);
+ dec_stat(A_CHR, 25, FALSE);
- break;
- }
+ /* Timeout is set before return */
- 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);
+ break;
+ }
- /* Timeout is set before return */
+ case ACT_EXPLOSS:
+ {
+ if (!doit) return "experience loss";
+ lose_exp(p_ptr->exp / 20);
- break;
- }
+ /* Timeout is set before return */
- case ACT_EXPLOSS:
- {
- if (!doit) return "experience loss";
- lose_exp(p_ptr->exp / 20);
+ break;
+ }
- /* Timeout is set before return */
+ case ACT_HIEXPLOSS:
+ {
+ if (!doit) return "high experience loss";
+ lose_exp(p_ptr->exp / 10);
- break;
- }
+ /* Timeout is set before return */
- case ACT_HIEXPLOSS:
- {
- if (!doit) return "high experience loss";
- lose_exp(p_ptr->exp / 10);
+ break;
+ }
- /* Timeout is set before return */
+ case ACT_SUMMON_MONST:
+ {
+ if (!doit) return "summon monster";
+ summon_specific(p_ptr->py, p_ptr->px, max_dlv[dungeon_type], 0);
- break;
- }
+ /* Timeout is set before return */
- case ACT_SUMMON_MONST:
- {
- if (!doit) return "summon monster";
- summon_specific(p_ptr->py, p_ptr->px, max_dlv[dungeon_type], 0);
+ break;
+ }
- /* Timeout is set before return */
+ case ACT_PARALYZE:
+ {
+ if (!doit) return "paralyze";
+ set_paralyzed(20 + randint(10));
- break;
- }
+ /* Timeout is set before return */
- case ACT_PARALYZE:
- {
- if (!doit) return "paralyze";
- set_paralyzed(p_ptr->paralyzed + 20 + randint(10));
+ break;
+ }
- /* Timeout is set before return */
+ case ACT_HALLU:
+ {
+ if (!doit) return "hallucination every 10 turns";
+ set_image(p_ptr->image + 20 + randint(10));
- break;
- }
+ /* Timeout is set before return */
- case ACT_HALLU:
- {
- if (!doit) return "hallucination every 10 turns";
- set_image(p_ptr->image + 20 + randint(10));
+ break;
+ }
- /* Timeout is set before return */
+ case ACT_POISON:
+ {
+ if (!doit) return "poison";
+ set_poisoned(p_ptr->poisoned + 20 + randint(10));
- break;
- }
+ /* Timeout is set before return */
- case ACT_POISON:
- {
- if (!doit) return "poison";
- set_poisoned(p_ptr->poisoned + 20 + randint(10));
+ break;
+ }
- /* Timeout is set before return */
+ case ACT_HUNGER:
+ {
+ if (!doit) return "create hunger";
+ set_food(PY_FOOD_WEAK);
- break;
- }
+ /* Timeout is set before return */
- case ACT_HUNGER:
- {
- if (!doit) return "create hunger";
- (void)set_food(PY_FOOD_WEAK);
+ break;
+ }
- /* Timeout is set before return */
+ case ACT_STUN:
+ {
+ if (!doit) return "stun";
+ set_stun(p_ptr->stun + 20 + randint(10));
- break;
- }
+ /* Timeout is set before return */
- case ACT_STUN:
- {
- if (!doit) return "stun";
- set_stun(p_ptr->stun + 20 + randint(10));
+ break;
+ }
- /* Timeout is set before return */
+ case ACT_CUTS:
+ {
+ if (!doit) return "cuts";
+ set_cut(p_ptr->cut + 20 + randint(10));
- break;
- }
+ /* Timeout is set before return */
- case ACT_CUTS:
- {
- if (!doit) return "cuts";
- set_cut(p_ptr->cut + 20 + randint(10));
+ break;
+ }
- /* Timeout is set before return */
+ case ACT_PARANO:
+ {
+ if (!doit) return "confusion";
+ set_confused(p_ptr->confused + 30 + randint(10));
- break;
- }
+ /* Timeout is set before return */
- case ACT_PARANO:
- {
- if (!doit) return "confusion";
- set_confused(p_ptr->confused + 30 + randint(10));
+ break;
+ }
- /* Timeout is set before return */
+ case ACT_CONFUSION:
+ {
+ if (!doit) return "confusion";
+ set_confused(p_ptr->confused + 20 + randint(10));
- break;
- }
+ /* Timeout is set before return */
- case ACT_CONFUSION:
- {
- if (!doit) return "confusion";
- set_confused(p_ptr->confused + 20 + randint(10));
+ break;
+ }
- /* Timeout is set before return */
+ case ACT_BLIND:
+ {
+ if (!doit) return "blindness";
+ set_blind(p_ptr->blind + 20 + randint(10));
- break;
- }
+ /* Timeout is set before return */
- case ACT_BLIND:
- {
- if (!doit) return "blindness";
- set_blind(p_ptr->blind + 20 + randint(10));
+ break;
+ }
- /* Timeout is set before return */
+ 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);
- break;
- }
+ /* Timeout is set before return */
+ /*FINDME*/
- 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);
+ break;
+ }
- /* Timeout is set before return */
- /*FINDME*/
+ case ACT_CURE_PARA:
+ {
+ if (!doit) return "cure confusion every 500 turns";
+ set_confused(0);
- break;
- }
+ /* Timeout is set before return */
- case ACT_CURE_PARA:
- {
- if (!doit) return "cure confusion every 500 turns";
- set_confused(0);
+ break;
+ }
- /* Timeout is set before return */
+ case ACT_CURE_HALLU:
+ {
+ if (!doit) return "cure hallucination every 100 turns";
+ set_image(0);
- break;
- }
+ /* Timeout is set before return */
- case ACT_CURE_HALLU:
- {
- if (!doit) return "cure hallucination every 100 turns";
- set_image(0);
+ break;
+ }
- /* Timeout is set before return */
+ case ACT_CURE_POIS:
+ {
+ if (!doit) return "cure poison every 100 turns";
+ set_poisoned(0);
- break;
- }
+ /* Timeout is set before return */
- case ACT_CURE_POIS:
- {
- if (!doit) return "cure poison every 100 turns";
- set_poisoned(0);
+ break;
+ }
- /* Timeout is set before return */
+ case ACT_CURE_HUNGER:
+ {
+ if (!doit) return "satisfy hunger every 100 turns";
+ set_food(PY_FOOD_MAX - 1);
- break;
- }
+ /* Timeout is set before return */
- case ACT_CURE_HUNGER:
- {
- if (!doit) return "satisfy hunger every 100 turns";
- (void)set_food(PY_FOOD_MAX - 1);
+ break;
+ }
- /* Timeout is set before return */
+ case ACT_CURE_STUN:
+ {
+ if (!doit) return "cure stun every 100 turns";
+ set_stun(0);
- break;
- }
+ /* Timeout is set before return */
- case ACT_CURE_STUN:
- {
- if (!doit) return "cure stun every 100 turns";
- set_stun(0);
+ break;
+ }
- /* Timeout is set before return */
+ case ACT_CURE_CUTS:
+ {
+ if (!doit) return "cure cuts every 100 turns";
+ set_cut(0);
- break;
- }
+ /* Timeout is set before return */
- case ACT_CURE_CUTS:
- {
- if (!doit) return "cure cuts every 100 turns";
- set_cut(0);
+ break;
+ }
- /* Timeout is set before return */
+ case ACT_CURE_FEAR:
+ {
+ if (!doit) return "cure fear every 100 turns";
+ set_afraid(0);
- break;
- }
+ /* Timeout is set before return */
- case ACT_CURE_FEAR:
- {
- if (!doit) return "cure fear every 100 turns";
- set_afraid(0);
+ break;
+ }
- /* Timeout is set before return */
+ case ACT_CURE_CONF:
+ {
+ if (!doit) return "cure confusion every 100 turns";
+ set_confused(0);
- break;
- }
+ /* Timeout is set before return */
- case ACT_CURE_CONF:
- {
- if (!doit) return "cure confusion every 100 turns";
- set_confused(0);
+ break;
+ }
- /* Timeout is set before return */
+ case ACT_CURE_BLIND:
+ {
+ if (!doit) return "cure blindness every 100 turns";
+ set_blind(0);
- break;
- }
+ /* Timeout is set before return */
- case ACT_CURE_BLIND:
- {
- if (!doit) return "cure blindness every 100 turns";
- set_blind(0);
+ break;
+ }
- /* Timeout is set before return */
+ 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);
- break;
- }
+ /* Timeout is set before return */
- 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);
+ break;
+ }
- /* Timeout is set before return */
+ case ACT_DARKNESS:
+ {
+ if (!doit) return "darkness";
+ unlite_area(damroll(2, 10), 10);
- break;
- }
+ /* Timeout is set before return */
- case ACT_DARKNESS:
- {
- if (!doit) return "darkness";
- unlite_area(damroll(2, 10), 10);
+ break;
+ }
- /* Timeout is set before return */
+ case ACT_LEV_TELE:
+ {
+ if (!doit) return "teleport level every 50 turns";
+ teleport_player_level();
- break;
- }
+ /* Timeout is set before return */
- case ACT_LEV_TELE:
- {
- if (!doit) return "teleport level every 50 turns";
- teleport_player_level();
+ break;
+ }
- /* Timeout is set before return */
+ case ACT_ACQUIREMENT:
+ {
+ if (!doit) return "acquirement every 3000 turns";
+ acquirement(p_ptr->py, p_ptr->px, 1, FALSE, FALSE);
- break;
- }
+ /* Timeout is set before return */
- case ACT_ACQUIREMENT:
- {
- if (!doit) return "acquirement every 3000 turns";
- acquirement(p_ptr->py, p_ptr->px, 1, FALSE, FALSE);
+ break;
+ }
- /* Timeout is set before return */
+ case ACT_WEIRD:
+ {
+ if (!doit) return "something weird every 5 turns";
+ /* It doesn't do anything */
- break;
- }
+ /* Timeout is set before return */
- case ACT_WEIRD:
- {
- if (!doit) return "something weird every 5 turns";
- /* It doesn't do anything */
+ break;
+ }
- /* Timeout is set before return */
+ case ACT_AGGRAVATE:
+ {
+ if (!doit) return "aggravate";
+ aggravate_monsters(1);
- break;
- }
+ /* Timeout is set before return */
- case ACT_AGGRAVATE:
- {
- if (!doit) return "aggravate";
- aggravate_monsters(1);
+ break;
+ }
- /* Timeout is set before return */
+ case ACT_MUT:
+ {
+ if (!doit) return "gain corruption every 10 turns";
+ gain_random_corruption();
+ /* Timeout is set before return */
- break;
- }
+ break;
+ }
- case ACT_MUT:
- {
- if (!doit) return "gain corruption every 10 turns";
- gain_random_corruption(0);
- /* Timeout is set before return */
+ case ACT_CURE_INSANITY:
+ {
+ if (!doit) return "cure insanity every 200 turns";
+ heal_insanity(damroll(10, 10));
- break;
- }
+ /* Timeout is set before return */
- case ACT_CURE_INSANITY:
- {
- if (!doit) return "cure insanity every 200 turns";
- heal_insanity(damroll(10, 10));
+ break;
+ }
- /* Timeout is set before return */
+ case ACT_CURE_MUT:
+ {
+ msg_print("Ahah, you wish.");
+ /* Timeout is set before return */
- break;
- }
+ break;
+ }
- case ACT_CURE_MUT:
- {
- msg_print("Ahah, you wish.");
- /* Timeout is set before return */
+ case ACT_LIGHT_ABSORBTION:
+ {
+ int y, x, light = 0, dir;
+ cave_type *c_ptr;
- break;
- }
+ if (!doit) return "light absorption every 80 turns";
- case ACT_LIGHT_ABSORBTION:
+ for (y = p_ptr->py - 6; y <= p_ptr->py + 6; y++)
{
- int y, x, light = 0, dir;
- cave_type *c_ptr;
+ for (x = p_ptr->px - 6; x <= p_ptr->px + 6; x++)
+ {
+ if (!in_bounds(y, x)) continue;
+
+ c_ptr = &cave[y][x];
- if (!doit) return "light absorption every 80 turns";
+ if (distance(y, x, p_ptr->py, p_ptr->px) > 6) continue;
- 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 (c_ptr->info & CAVE_GLOW)
{
- if (!in_bounds(y, x)) continue;
+ light++;
- c_ptr = &cave[y][x];
+ /* No longer in the array */
+ c_ptr->info &= ~(CAVE_TEMP);
- if (distance(y, x, p_ptr->py, p_ptr->px) > 6) continue;
+ /* Darken the grid */
+ c_ptr->info &= ~(CAVE_GLOW);
- if (c_ptr->info & CAVE_GLOW)
+ /* Hack -- Forget "boring" grids */
+ if (cave_plain_floor_grid(c_ptr))
{
- 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);
+ /* 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);
+ 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));
+ 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 */
+ /* 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);
+ 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;
+ o_ptr->timeout = 100;
- /* Window stuff */
- p_ptr->window |= (PW_INVEN | PW_EQUIP);
+ /* 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);
+ 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;
+ o_ptr->timeout = 100;
- /* Window stuff */
- p_ptr->window |= (PW_INVEN | PW_EQUIP);
+ /* 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);
+ 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;
+ o_ptr->timeout = 100;
- /* Window stuff */
- p_ptr->window |= (PW_INVEN | PW_EQUIP);
+ /* 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);
+ 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;
+ o_ptr->timeout = 100;
- /* Window stuff */
- p_ptr->window |= (PW_INVEN | PW_EQUIP);
+ /* Window stuff */
+ p_ptr->window |= (PW_INVEN | PW_EQUIP);
- break;
- }
+ break;
+ }
- case ACT_SPIN:
- {
- if (!doit) return "spinning around every 50+d25 turns";
- do_spin();
+ case ACT_SPIN:
+ {
+ if (!doit) return "spinning around every 50+d25 turns";
+ do_spin();
- o_ptr->timeout = 50 + randint(25);
+ o_ptr->timeout = 50 + randint(25);
- /* Window stuff */
- p_ptr->window |= (PW_INVEN | PW_EQUIP);
+ /* 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);
+ /* Done */
+ break;
+ }
+ case ACT_NOLDOR:
+ {
+ if (!doit) return "detect treasure every 10+d20 turns";
+ detect_treasure(DEFAULT_RADIUS);
- o_ptr->timeout = 10 + randint(20);
+ o_ptr->timeout = 10 + randint(20);
- /* Window stuff */
- p_ptr->window |= (PW_INVEN | PW_EQUIP);
+ /* Window stuff */
+ p_ptr->window |= (PW_INVEN | PW_EQUIP);
- /* Done */
- break;
+ /* Done */
+ break;
+ }
+ case ACT_SPECTRAL:
+ {
+ if (!doit) return "wraith-form every 50+d50 turns";
+ if (!p_ptr->wraith_form)
+ {
+ set_shadow(20 + randint(20));
}
- case ACT_SPECTRAL:
+ else
{
- 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));
- }
+ set_shadow(p_ptr->tim_wraith + randint(20));
+ }
- o_ptr->timeout = 50 + randint(50);
+ o_ptr->timeout = 50 + randint(50);
- /* Window stuff */
- p_ptr->window |= PW_INVEN | PW_EQUIP;
+ /* Window stuff */
+ p_ptr->window |= PW_INVEN | PW_EQUIP;
- /* Done */
- break;
+ /* 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!");
}
- case ACT_JUMP:
+ if (get_check("This will destroy the ring. Do you wish to continue? "))
{
- if (!doit) return "phasing every 10+d10 turns";
- teleport_player(10);
- o_ptr->timeout = 10 + randint(10);
+ msg_print("The ring explodes into a space distortion.");
+ teleport_player(200);
- /* Window stuff */
- p_ptr->window |= (PW_INVEN | PW_EQUIP);
+ /* It explodes, doesn't it ? */
+ take_hit(damroll(2, 10), "an exploding ring");
- /* Done */
- break;
+ inc_stack_size_ex(item, -255, OPTIMIZE, NO_DESCRIBE);
}
- 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);
+ 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;
- /* It explodes, doesn't it ? */
- take_hit(damroll(2, 10), "an exploding ring");
+ msg_print("You breathe venom...");
+ fire_ball(GF_POIS, dir, 100, 2);
- inc_stack_size_ex(item, -255, OPTIMIZE, NO_DESCRIBE);
- }
+ o_ptr->timeout = rand_int(60) + 40;
- 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;
+ /* Window stuff */
+ p_ptr->window |= PW_INVEN | PW_EQUIP;
- msg_print("You breathe venom...");
- fire_ball(GF_POIS, dir, 100, 2);
+ /* 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;
- o_ptr->timeout = rand_int(60) + 40;
+ fire_ball(GF_COLD, dir, 50, 2);
+ set_oppose_cold(p_ptr->oppose_cold + randint(20) + 20);
- /* Window stuff */
- p_ptr->window |= PW_INVEN | PW_EQUIP;
+ o_ptr->timeout = rand_int(50) + 50;
- /* 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;
+ break;
+ }
- fire_ball(GF_COLD, dir, 50, 2);
- (void)set_oppose_cold(p_ptr->oppose_cold + randint(20) + 20);
+ 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;
- o_ptr->timeout = rand_int(50) + 50;
+ fire_ball(GF_FIRE, dir, 50, 2);
+ set_oppose_fire(p_ptr->oppose_fire + randint(20) + 20);
- break;
- }
+ o_ptr->timeout = rand_int(50) + 50;
- 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;
+ 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_FIRE, dir, 50, 2);
- (void)set_oppose_fire(p_ptr->oppose_fire + randint(20) + 20);
+ fire_ball(GF_ACID, dir, 50, 2);
+ set_oppose_acid(p_ptr->oppose_acid + randint(20) + 20);
- o_ptr->timeout = rand_int(50) + 50;
+ 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;
+ break;
+ }
- fire_ball(GF_ACID, dir, 50, 2);
- (void)set_oppose_acid(p_ptr->oppose_acid + randint(20) + 20);
+ 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;
- o_ptr->timeout = rand_int(50) + 50;
+ fire_ball(GF_ELEC, dir, 50, 2);
+ set_oppose_elec(p_ptr->oppose_elec + randint(20) + 20);
- break;
- }
+ o_ptr->timeout = rand_int(50) + 50;
- 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;
+ break;
+ }
- fire_ball(GF_ELEC, dir, 50, 2);
- (void)set_oppose_elec(p_ptr->oppose_elec + randint(20) + 20);
+ 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(50) + 50;
+ o_ptr->timeout = rand_int(90) + 90;
- break;
- }
+ 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);
+ 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;
+ o_ptr->timeout = rand_int(90) + 90;
- break;
- }
+ 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);
+ 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;
+ o_ptr->timeout = rand_int(90) + 90;
- break;
- }
+ 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);
+ 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;
+ o_ptr->timeout = rand_int(90) + 90;
- break;
- }
+ 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);
+ 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;
+ o_ptr->timeout = rand_int(90) + 90;
- break;
- }
+ 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);
+ 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(90) + 90;
+ o_ptr->timeout = rand_int(60) + 60;
- break;
- }
+ 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);
+ 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(60) + 60;
+ o_ptr->timeout = rand_int(90) + 90;
- break;
- }
+ 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);
+ 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;
+ o_ptr->timeout = rand_int(90) + 90;
- break;
- }
+ 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);
+ 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) + 90;
+ o_ptr->timeout = rand_int(90) + 60;
- break;
- }
+ 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);
+ 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;
+ o_ptr->timeout = rand_int(90) + 60;
- break;
- }
+ 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);
+ 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;
+ o_ptr->timeout = rand_int(90) + 60;
- break;
- }
+ 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);
+ 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;
+ o_ptr->timeout = rand_int(90) + 60;
- break;
- }
+ 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);
- 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;
- 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);
- 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 = randint(50) + 50;
- o_ptr->timeout = rand_int(90) + 60;
+ break;
+ }
+ case ACT_MUSIC:
+ /* Should be handled specially by caller, so if we get here something's wrong. */
+ abort();
+ case ACT_ETERNAL_FLAME:
+ {
+ if (!doit) return "imbuing an object with the eternal fire";
- break;
- }
- case ACT_GROW_MOLD:
+ if (!activate_eternal_flame(item))
{
- 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;
+ // Eternal Flame object was NOT destroyed, so let's
+ // set the timeout.
+ o_ptr->timeout = 0;
}
- case ACT_MUSIC:
- /*
- fall through to unknown, as music should be
- handled by calling procedure.
- */
+ break;
+ }
+ case ACT_MAGGOT:
+ {
+ if (!doit) return "terrify every 10+d50 turns";
- default:
+ if (activate_maggot())
{
- msg_format("Unknown activation effect: %d.", spell);
- if ( !doit ) return "Unknown Activation";
- return NULL;
+ o_ptr->timeout = 10 + randint(50);
}
+ break;
}
- }
+ case ACT_LEBOHAUM:
+ {
+ if (!doit) return "sing a cheerful song every turn";
- /* 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;
+ 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 NULL;
-}
+ o_ptr->timeout = 3;
+
+ break;
+ }
+ case ACT_DURANDIL:
+ {
+ if (!doit) return "sing a cheerful song every turn";
+ 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!'");
-static bool_ activate_spell(object_type * o_ptr, byte choice)
-{
- int mana = 0, gf = 0, mod = 0;
+ o_ptr->timeout = 3;
- rune_spell s_ptr;
+ break;
+ }
+ case ACT_RADAGAST:
+ {
+ if (!doit) return "purity and health every 15000 turns";
+ activate_radagast();
+ o_ptr->timeout = 15000;
- 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;
- }
+ break;
+ }
+ case ACT_VALAROMA:
+ {
+ if (!doit) return "banish evil (level x5) every 250 turns";
- s_ptr.type = gf;
- s_ptr.rune2 = 1 << mod;
- s_ptr.mana = mana;
+ activate_valaroma();
+ o_ptr->timeout = 250;
- /* Execute */
- rune_exec(&s_ptr, 0);
+ break;
+ }
+ default:
+ {
+ msg_format("Unknown activation effect: %d.", spell);
+ if ( !doit ) return "Unknown Activation";
+ return NULL;
+ }
+ }
- if (choice == 1) o_ptr->timeout = mana * 5;
- if (choice == 2) o_ptr->xtra2 = mana * 5;
+ /* 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 (TRUE);
+ return NULL;
}
diff --git a/src/cmd6.hpp b/src/cmd6.hpp
new file mode 100644
index 00000000..076a9abb
--- /dev/null
+++ b/src/cmd6.hpp
@@ -0,0 +1,18 @@
+#pragma once
+
+#include "h-basic.h"
+#include "object_type_fwd.hpp"
+
+void set_stick_mode(object_type *o_ptr);
+void unset_stick_mode();
+void do_cmd_eat_food();
+void do_cmd_quaff_potion();
+void do_cmd_read_scroll();
+void do_cmd_aim_wand();
+void do_cmd_use_staff();
+void do_cmd_zap_rod();
+const char *activation_aux(object_type *o_ptr, bool_ desc, int item);
+void do_cmd_activate();
+void do_cmd_cut_corpse();
+void do_cmd_cure_meat();
+void do_cmd_drink_fountain();
diff --git a/src/cmd7.c b/src/cmd7.c
deleted file mode 100644
index aca14dcd..00000000
--- a/src/cmd7.c
+++ /dev/null
@@ -1,7652 +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"
-
-
-/*
- * 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;
- }
-}
-
-
-/*
- * 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.
- */
-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 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;
-
-
- /* 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;
-
- /* No redraw yet */
- redraw = 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, *=List, 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();
-
- /* 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));
-
- /* 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;
- continue;
- }
-
- /* Stop the loop */
- flag = TRUE;
- }
-
- /* Restore the screen */
- if (redraw)
- {
- 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(p_ptr->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;
-
- call_lua("get_mimic_info", "(d,s)", "d", mimic, "level", &chance);
- 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(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(p_ptr->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 %ld)",
- (items < 26) ? I2A(items) : ('0' + items - 26),
- al_name + a_select_flags[i].desc,
- (long int) 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(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];
-
- 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, bool_ quick)
-{
- 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, * to list, 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)
- {
- print_spell_batch(batch, mut_max);
- }
-
- while (1)
- {
- /* Get a command */
- which = inkey();
-
- /* Abort */
- if (which == ESCAPE)
- {
- /* No selection */
- ret = NULL;
-
- /* Leave the command loop */
- break;
-
- }
-
- /* List */
- if (which == '*' || which == '?' || which == ' ')
- {
- /* Print power list */
- print_spell_batch(batch, mut_max);
-
- /* Wait for next command */
- continue;
- }
-
- /* 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
- */
-random_spell* select_spell(bool_ quick)
-{
- 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)
- {
- ret = NULL;
-
- break;
- }
-
- if (which == '\r')
- {
- if (batch_max == 0)
- {
- ret = select_spell_from_batch(0, quick);
-
- break;
- }
-
- continue;
- }
-
- which = tolower(which);
- if (isalpha(which) && (A2I(which) <= batch_max))
- {
- ret = select_spell_from_batch(A2I(which), quick);
-
- break;
- }
- else
- {
- bell();
- }
- }
-
- /* Restore the screen */
- Term_load();
-
- /* 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(FALSE);
-
- 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];
- char *ammo_name;
- 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(p_ptr->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, bool_ quick,
- int *s_idx)
-{
- char tmp[160];
-
- char out_val[30];
-
- char which;
-
- int mut_max = 10;
-
- rune_spell* ret;
-
-
- character_icky = TRUE;
- Term_save();
-
- 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);
-
- if (quick)
- {
- print_runespell_batch(batch, mut_max);
- }
-
- while (1)
- {
- which = inkey();
-
- 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();
- }
- }
- }
-
- Term_load();
- character_icky = FALSE;
-
- return (ret);
-}
-
-
-/*
- * Pick a random spell from a menu
- */
-
-rune_spell* select_runespell(bool_ quick, 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, quick, 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), quick, 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(FALSE, &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(FALSE, &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(p_ptr->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..ec13c908
--- /dev/null
+++ b/src/cmd7.cc
@@ -0,0 +1,3314 @@
+/*
+ * 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 "cmd7.hpp"
+
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "cmd1.hpp"
+#include "cmd5.hpp"
+#include "cmd6.hpp"
+#include "dungeon_flag.hpp"
+#include "ego_item_type.hpp"
+#include "files.hpp"
+#include "game.hpp"
+#include "hooks.hpp"
+#include "mimic.hpp"
+#include "monster2.hpp"
+#include "monster_race.hpp"
+#include "monster_race_flag.hpp"
+#include "monster_type.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_flag.hpp"
+#include "object_kind.hpp"
+#include "options.hpp"
+#include "player_type.hpp"
+#include "skills.hpp"
+#include "spells1.hpp"
+#include "spells2.hpp"
+#include "stats.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "util.h"
+#include "variable.h"
+#include "variable.hpp"
+#include "xtra1.hpp"
+#include "xtra2.hpp"
+#include "z-rand.hpp"
+
+#include <fmt/format.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)
+{
+ auto const &k_info = game->edit_data.k_info;
+
+ 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()
+{
+ 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)
+ {
+ flush_on_failure();
+
+ msg_format("You failed to concentrate hard enough!");
+
+ 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
+ {
+ /* 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);
+ }
+ 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_flags & DF_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
+ {
+ 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 */
+ set_fast(b, plev / 5);
+ }
+ else
+ {
+ 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 */
+ 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 */
+ dec_stat(A_WIS, 15 + randint(10), perm);
+ }
+ }
+
+ /* Redraw mana */
+ p_ptr->redraw |= (PR_FRAME);
+
+ /* 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()
+{
+ auto const &k_info = game->edit_data.k_info;
+
+ 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_FRAME);
+
+ /* Recalculate bonuses */
+ p_ptr->update |= (PU_BONUS);
+}
+
+static bool mimic_forbid_travel(void *, void *, void *)
+{
+ 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()
+{
+ 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_new(HOOK_FORBID_TRAVEL, mimic_forbid_travel, "mimic_forbid_travel", NULL);
+ 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)
+ {
+ flush_on_failure();
+
+ msg_format("You failed to concentrate hard enough!");
+
+ 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
+ {
+ /* 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 */
+ 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 */
+ dec_stat(A_DEX, 15 + randint(10), perm);
+ }
+ }
+
+ /* Redraw mana */
+ p_ptr->redraw |= (PR_FRAME);
+
+ /* Window stuff */
+ p_ptr->window |= (PW_PLAYER);
+}
+
+
+/*
+ * do_cmd_cast calls this function if the player's class
+ * is 'beastmaster'.
+ */
+void do_cmd_beastmaster()
+{
+ 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);
+}
+
+
+/*
+ * Command to ask favors from your god.
+ */
+void do_cmd_pray()
+{
+ 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_WIPE | PR_FRAME | PR_MAP;
+ energy_use = 100;
+ }
+}
+
+
+/*
+ * Return percentage chance of spell failure.
+ */
+int spell_chance_random(random_spell const *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)
+{
+ auto const &random_spells = p_ptr->random_spells;
+
+ prt(format(" %-30s Lev Fail Mana Damage ", "Name"), 1, 20);
+
+ int i;
+ for (i = 0; i < max; i++)
+ {
+ auto rspell = &random_spells[batch * 10 + i];
+
+ std::string buff;
+ std::string name = name_spell(rspell);
+
+ if (rspell->untried)
+ {
+ buff = fmt::format(" {:c}) {:<30} (Spell untried) ",
+ (char) I2A(i), name);
+
+ }
+ else
+ {
+ buff = fmt::format(" {:c}) {:<30} {:>3d} {:>4d}% {:>3d} {:>3d}d{:d} ",
+ (char) I2A(i), 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(std::size_t batch)
+{
+ auto &random_spells = p_ptr->random_spells;
+
+ char tmp[160];
+ char which;
+ random_spell* ret = nullptr;
+
+ /* Enter "icky" mode */
+ character_icky = TRUE;
+
+ /* Save the screen */
+ Term_save();
+
+ int const mut_max = (random_spells.size() < (batch + 1) * 10)
+ ? random_spells.size() - batch * 10
+ : 10;
+
+ strnfmt(tmp, 160, "(a-%c) Select a power: ",
+ I2A(mut_max - 1));
+
+ 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;
+ }
+
+ 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()
+{
+ auto const &random_spells = p_ptr->random_spells;
+
+ char tmp[160];
+ char which;
+
+ 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 (random_spells.empty())
+ {
+ msg_print("There are no spells you can cast.");
+ return NULL;
+ }
+
+ /* How many spells in the last batch? */
+ int batch_max = (random_spells.size() - 1) / 10;
+
+ /* 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()
+{
+ 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 */
+ flush_on_failure();
+
+ /* 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!");
+ }
+
+ /* 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_FRAME);
+
+ 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_FRAME);
+}
+
+
+/*
+ * 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
+ {
+ flush_on_failure();
+ msg_print("The enchantment failed.");
+ }
+}
+
+
+/*
+ * From Kamband by Ivan Tkatchev
+ */
+void summon_monster(int sumtype)
+{
+ /* Take a turn */
+ energy_use = 100;
+
+ 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()
+{
+ auto const &r_info = game->edit_data.r_info;
+
+ 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)
+ {
+ if (p_ptr->disembodied)
+ {
+ msg_print("You don't currently own a body to use.");
+ return;
+ }
+
+ /* Do we have access to all the powers ? */
+ bool use_great = (get_skill_scale(SKILL_POSSESSION, 100) >= r_info[p_ptr->body_monster].level);
+
+ /* Select power */
+ use_monster_power(p_ptr->body_monster, use_great);
+ assert(p_ptr->csp >= 0); // Sanity check
+ }
+ 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 object_filter_t const &item_tester_hook_convertible()
+{
+ using namespace object_filter;
+ static auto instance =
+ Or(
+ TVal(TV_JUNK),
+ TVal(TV_SKELETON));
+ return instance;
+}
+
+
+/*
+ * do_cmd_cast calls this function if the player's class
+ * is 'archer'.
+ */
+void do_cmd_archer()
+{
+ 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;
+
+ inven_carry(q_ptr, FALSE);
+
+ msg_print("You make some ammo.");
+
+ 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;
+
+ /* Get an item */
+ if (!get_item(&item,
+ "Convert which item? ",
+ "You have no item to convert.",
+ (USE_INVEN | USE_FLOOR),
+ item_tester_hook_convertible())) 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);
+
+ inven_carry(q_ptr, FALSE);
+ }
+
+ /**********Create bolts*********/
+ else if (ext == 3)
+ {
+ int item;
+
+ /* Get an item */
+ if (!get_item(&item,
+ "Convert which item? ",
+ "You have no item to convert.",
+ (USE_INVEN | USE_FLOOR),
+ item_tester_hook_convertible())) 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);
+
+ inven_carry(q_ptr, FALSE);
+ }
+}
+
+/*
+ * Control whether shots are allowed to pierce
+ */
+void do_cmd_set_piercing()
+{
+ 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()
+{
+ 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)
+ {
+ flush_on_failure();
+ msg_format("You failed to concentrate hard enough!");
+
+ 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_FRAME);
+
+ /* 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
+ {
+ /* 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_flags |= TR_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);
+ 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_FRAME);
+
+ /* 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 */
+ 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 */
+ dec_stat(A_CON, 15 + randint(10), perm);
+ }
+ }
+
+ /* Redraw mana */
+ p_ptr->redraw |= (PR_FRAME);
+
+ /* Window stuff */
+ p_ptr->window |= (PW_PLAYER);
+}
+
+/*
+ * 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);
+}
+
+
+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]estroy Doors", &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;
+ }
+
+ /* Destroy Doors */
+ case 2:
+ {
+ s16b skill = get_skill(SKILL_ANTIMAGIC);
+
+ if (skill < 25)
+ {
+ msg_print("You cannot use your door destruction abilities yet.");
+ break;
+ }
+
+ destroy_doors_touch();
+
+ break;
+ }
+ }
+}
+
+/*
+ * Hook to determine if an object is totemable
+ */
+static object_filter_t const &item_tester_hook_totemable()
+{
+ using namespace object_filter;
+ static auto instance = And(
+ TVal(TV_CORPSE),
+ Or(
+ SVal(SV_CORPSE_CORPSE),
+ SVal(SV_CORPSE_SKELETON)));
+ return instance;
+}
+
+
+/*
+ * Summoners
+ */
+void do_cmd_summoner_extract()
+{
+ auto const &r_info = game->edit_data.r_info;
+
+ object_type forge, *q_ptr;
+
+ /* 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;
+ }
+
+ /* Get an item */
+ int item;
+ if (!get_item(&item,
+ "Use which corpse? ",
+ "You have no corpse to use.",
+ (USE_INVEN | USE_FLOOR),
+ item_tester_hook_totemable()))
+ {
+ return;
+ }
+
+ /* Get the item */
+ object_type *o_ptr = get_object(item);
+
+ bool_ partial;
+ if (r_info[o_ptr->pval2].flags & RF_UNIQUE)
+ {
+ partial = FALSE;
+ }
+ else
+ {
+ partial = get_check("Do you want to create a partial totem?");
+ }
+
+ int 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;
+ 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)
+{
+ auto const &r_info = game->edit_data.r_info;
+
+ int i, status, x = 1, y = 1, rx, ry = 0, chance;
+
+ bool_ used;
+
+ auto r_ptr = &r_info[r_idx];
+
+
+ /* Uniques are less likely to be nice */
+ if (r_ptr->flags & RF_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;
+
+ monster_type *m_ptr;
+
+
+ /* Which Totem? */
+ q = "Summon from which Totem?";
+ s = "There are no totems to summon from!";
+ if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR), object_filter::TVal(TV_TOTEM))) return;
+
+ /* Access the item */
+ object_type *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()
+{
+ 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;
+ }
+ }
+}
+
+
+/*
+ * Dodge Chance Feedback.
+ */
+void use_ability_blade()
+{
+ 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()
+{
+ 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)
+ {
+ flush_on_failure();
+ msg_format("You failed to concentrate hard enough!");
+ }
+ else
+ {
+ /* spell code */
+ switch (n)
+ {
+ case 0:
+ {
+ int dir, x, y;
+ cave_type *c_ptr;
+ monster_type *m_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];
+ auto const r_ptr = m_ptr->race();
+
+ if (!(r_ptr->flags & RF_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->flags & RF_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;
+
+ /* Get an item */
+ if (!get_item(&item,
+ "Awaken which monster? ",
+ "You have no monster to awaken.",
+ (USE_FLOOR),
+ object_filter::TVal(TV_HYPNOS)))
+ {
+ return;
+ }
+
+ object_type *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;
+
+ /* Window stuff */
+ p_ptr->window |= (PW_PLAYER);
+
+ /* Display the monster hitpoints */
+ p_ptr->redraw |= (PR_FRAME);
+
+ 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))
+ 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).c_str());
+
+ /* Display the monster hitpoints */
+ p_ptr->redraw |= (PR_FRAME);
+
+ 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))
+ 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;
+ if (!tgt_pt(&x, &y)) return;
+
+ cave_type *c_ptr = &cave[y][x];
+
+ if (!c_ptr->m_idx) break;
+
+ monster_type *m_ptr = &m_list[c_ptr->m_idx];
+ use_symbiotic_power(m_ptr->r_idx, 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 */
+ 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 */
+ dec_stat(A_CHR, 15 + randint(10), perm);
+ }
+ }
+
+ /* Redraw mana */
+ p_ptr->redraw |= (PR_FRAME);
+
+ /* 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;
+
+ 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;
+
+ 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
+ */
+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.hpp b/src/cmd7.hpp
new file mode 100644
index 00000000..b9d518b2
--- /dev/null
+++ b/src/cmd7.hpp
@@ -0,0 +1,25 @@
+#pragma once
+
+#include "h-basic.h"
+#include "object_type_fwd.hpp"
+
+void do_cmd_pray();
+void do_cmd_create_boulder();
+void necro_info(char *p, int power);
+void mindcraft_info(char *p, int power);
+void symbiotic_info(char *p, int power);
+void mimic_info(char *p, int power);
+void do_cmd_summoner();
+void do_cmd_mindcraft();
+void do_cmd_mimic();
+void use_ability_blade();
+void do_cmd_beastmaster();
+void do_cmd_powermage();
+void do_cmd_possessor();
+void do_cmd_archer();
+void do_cmd_set_piercing();
+void do_cmd_necromancer();
+void do_cmd_unbeliever();
+void do_cmd_symbiotic();
+s32b sroot(s32b n);
+int clamp_failure_chance(int chance, int minfail);
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/config.h b/src/config.h
index 7c1cf1d7..290ec624 100644
--- a/src/config.h
+++ b/src/config.h
@@ -30,24 +30,13 @@
* OPTION: See the Makefile(s), where several options may be declared.
*
* Some popular options include "USE_GCU" (allow use with Unix "curses"),
- * "USE_X11" (allow basic use with Unix X11) and "USE_XAW" (allow use with
- * Unix X11 plus the Athena Widget set).
+ * and "USE_X11" (allow basic use with Unix X11).
*
* The old "USE_NCU" option has been replaced with "USE_GCU".
*
* Several other such options are available for non-unix machines,
* such as "MACINTOSH", "WINDOWS".
- *
- * You may also need to specify the "system", using defines such as
- * "SOLARIS" (for Solaris), etc, see "h-config.h" for more info.
- */
-
-
-/*
- * 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 */
/*
@@ -67,90 +56,11 @@
/*
- * OPTION: Use "blocking getch() calls" in "main-gcu.c".
- * Hack -- Note that this option will NOT work on many BSD machines
- * Currently used whenever available, if you get a warning about
- * "nodelay()" undefined, then make sure to undefine this.
- */
-#if defined(SYS_V)
-# define USE_GETCH
-#endif
-
-
-/*
- * OPTION: Use the "curs_set()" call in "main-gcu.c".
- * Hack -- This option will not work on most BSD machines
- */
-#ifdef SYS_V
-# define USE_CURS_SET
-#endif
-
-
-/*
* OPTION: Include "ncurses.h" instead of "curses.h" in "main-gcu.c"
*/
/* #define USE_NCURSES */
-/*
- * OPTION: for multi-user machines running the game setuid to some other
- * user (like 'games') this SAFE_SETUID option allows the program to drop
- * its privileges when saving files that allow for user specified pathnames.
- * This lets the game be installed system wide without major security
- * concerns. There should not be any side effects on any machines.
- *
- * This will handle "gids" correctly once the permissions are set right.
- */
-#define SAFE_SETUID
-
-
-/*
- * This flag enables the "POSIX" methods for "SAFE_SETUID".
- */
-#if defined(_POSIX_SAVED_IDS) && !(defined(SUNOS) && !defined(SOLARIS)) && !defined(__APPLE__)
-# define SAFE_SETUID_POSIX
-#endif
-
-
-/*
- * OPTION: Allow characteres to be "auto-rolled"
- */
-#define ALLOW_AUTOROLLER
-
-
-/*
- * OPTION: Allow monsters to "flee" when hit hard
- */
-#define ALLOW_FEAR
-
-/*
- * OPTION: Allow monsters to "flee" from strong players
- */
-#define ALLOW_TERROR
-
-
-/*
- * OPTION: Handle signals
- */
-#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 */
-
-
/*
* OPTION: Maximum flow depth
@@ -159,50 +69,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.
- */
-#define USE_SOUND
-
-/*
- * OPTION: Allow the use of "graphics" in various places
- */
-#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.
@@ -233,29 +99,7 @@
/*
* Where to put the user's files.
*/
-#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
-
-/*
- * 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
/*
@@ -279,33 +123,6 @@
-/* ToME options: */
-
-/* Should the player know his / her starting life rate? */
-/* #define SHOW_LIFE_RATE */
-
-/* Allow hordes of 'similar' monsters */
-#define MONSTER_HORDES
-
-/* Wizard mode testing options: */
-
-/* For testing the vaults */
-/* # define FORCE_V_IDX 20 */
-
-/* Testing upkeep */
-/* # define TRACK_FRIENDS */
-
-/*
- * 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
- */
-/* #define ALLOW_QUITTING */
-
/*
* Allow makefiles to override the default file mode
*/
diff --git a/src/corrupt.cc b/src/corrupt.cc
new file mode 100644
index 00000000..bd3ae5f0
--- /dev/null
+++ b/src/corrupt.cc
@@ -0,0 +1,998 @@
+#include "corrupt.hpp"
+
+#include "game.hpp"
+#include "init1.hpp"
+#include "object_flag.hpp"
+#include "player_race.hpp"
+#include "player_race_flag.hpp"
+#include "player_race_mod.hpp"
+#include "player_type.hpp"
+#include "stats.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+#include "xtra1.hpp"
+#include "xtra2.hpp"
+#include "z-rand.hpp"
+
+#include <cassert>
+#include <fmt/format.h>
+
+/**
+ * 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 */
+ s16b power; /* index of granted power if >= 0, ignored otherwise */
+};
+
+/**
+ * Vampire corruption helpers
+ */
+
+static void subrace_add_power(player_race_mod *rmp_ptr, int power)
+{
+ rmp_ptr->ps.powers.push_back(power);
+}
+
+static void player_gain_vampire_teeth()
+{
+ auto &race_mod_info = game->edit_data.race_mod_info;
+
+ 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->flags = rmp_ptr->flags
+ | PR_VAMPIRE
+ | PR_UNDEAD
+ | PR_NO_SUBRACE_CHANGE;
+}
+
+static void player_gain_vampire_strength()
+{
+ auto &race_mod_info = game->edit_data.race_mod_info;
+
+ player_race_mod *rmp_ptr = &race_mod_info[SUBRACE_SAVE];
+
+ rmp_ptr->ps.mhp += +1;
+ rmp_ptr->ps.exp += +100;
+
+ rmp_ptr->ps.adj[A_STR] += +3;
+ rmp_ptr->ps.adj[A_INT] += +2;
+ rmp_ptr->ps.adj[A_WIS] += -3;
+ rmp_ptr->ps.adj[A_DEX] += -2;
+ rmp_ptr->ps.adj[A_CON] += +1;
+ rmp_ptr->ps.adj[A_CHR] += -4;
+
+ /* be reborn! */
+ do_rebirth();
+ cmsg_print(TERM_L_DARK, "You feel death slipping inside.");
+}
+
+static void player_gain_vampire()
+{
+ auto &race_mod_info = game->edit_data.race_mod_info;
+
+ player_race_mod *rmp_ptr = &race_mod_info[SUBRACE_SAVE];
+
+ if (rmp_ptr->title == "Vampire")
+ {
+ rmp_ptr->place = FALSE;
+ }
+ else
+ {
+ rmp_ptr->title = fmt::format("Vampire {}", rmp_ptr->title);
+ }
+
+ /* Bonus/and .. not bonus :) */
+ rmp_ptr->flags |= PR_HURT_LITE;
+ rmp_ptr->lflags[1].oflags |=
+ ( TR_RES_POIS
+ | TR_RES_NETHER
+ | TR_RES_COLD
+ | TR_RES_DARK
+ | TR_HOLD_LIFE
+ | TR_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)
+{
+ 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 (rp_ptr->title == "Troll")
+ {
+ allowed = FALSE;
+ }
+ }
+
+ /* Theme module adds additional restrictions for Maiar */
+
+ if (game_module_idx == MODULE_THEME)
+ {
+ if (rp_ptr->title == "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 (race_flags_p(PR_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_FRAME;
+ 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
+ */
+std::string dump_corruptions(bool color, bool header)
+{
+ fmt::MemoryWriter w;
+
+ for (int i = 0; i < CORRUPTIONS_MAX; i++)
+ {
+ corruption_type const *c_ptr = &corruptions[i];
+
+ if (header)
+ {
+ w.write("\nCorruption list:\n\n");
+ header = false;
+ }
+
+ if (p_ptr->corruptions[i])
+ {
+ byte c = c_ptr->color;
+
+ if (color)
+ {
+ w.write("#####{}{}:\n", static_cast<char>(conv_color[c]), c_ptr->name);
+ }
+ else
+ {
+ w.write("{}:\n", c_ptr->name);
+ }
+
+ w.write("{}\n\n", c_ptr->desc);
+ }
+ }
+
+ return w.str();
+}
+
+/*
+ * 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.hpp b/src/corrupt.hpp
new file mode 100644
index 00000000..77a7496e
--- /dev/null
+++ b/src/corrupt.hpp
@@ -0,0 +1,49 @@
+#include "h-basic.h"
+
+#include <string>
+
+void gain_random_corruption();
+std::string dump_corruptions(bool color, bool header);
+void lose_corruption();
+bool_ player_has_corruption(int corruption_idx);
+void player_gain_corruption(int corruption_idx);
+s16b get_corruption_power(int corruption_idx);
+
+/*
+ * 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
diff --git a/src/defines.h b/src/defines.h
index 850bbc7a..4a2ad0e0 100644
--- a/src/defines.h
+++ b/src/defines.h
@@ -41,16 +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
-
-/*
- * This value is not currently used
- */
-#define VERSION_EXTRA 0
+#define SAVEFILE_VERSION 105
/*
* Maximum amount of Angband windows.
@@ -121,87 +114,24 @@
*/
#define DEFAULT_RADIUS 25
-
-#define CHANCE_TRAP_JAMMED_DOOR 2500
-#define CHANCE_TRAP_SECRET_DOOR 1500
-#define CHANCE_TRAP_LOCKED_DOOR 1000
-#define CHANCE_TRAP_DOOR 500 /* in 10000 */
-#define CHANCE_TRAP_FLOOR 4 /* in 10000 chance of placing a trap */
-
-#define MAX_BOUNTIES 24
-
#define MAX_SPELLS 100
#define MAX_RUNES 100
/*
- * Arena constants
+ * Total number of monster powers
*/
-#define MAX_ARENA_MONS 29 /* -KMW- */
+#define MONSTER_POWERS_MAX 96
/*
* 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)
- */
-#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
@@ -223,6 +153,7 @@
/* Mimicry */
#define MAX_MIMIC_POWERS 5
+#define MIMIC_FORMS_MAX 14
/* Symbiosis */
#define MAX_SYMBIOTIC_POWERS 9
@@ -234,19 +165,6 @@
/*
- * Size of memory reserved for initialization of some arrays
- */
-#define FAKE_NAME_SIZE 40 * 1024L
-#define FAKE_TEXT_SIZE 120 * 1024L
-
-
-/*
- * Maximum number of high scores in the high score file
- */
-#define MAX_HISCORES 100
-
-
-/*
* Maximum dungeon level. The player can never reach this level
* in the dungeon, and this value is used for various calculations
* involving object and monster creation. It must be at least 100.
@@ -304,30 +222,6 @@
#define MACRO_MAX 256
/*
- * OPTION: Maximum number of "quarks" (see "io.c")
- * Default: assume at most 512 different inscriptions are used
- */
-#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)
*/
#define MAX_UCHAR 255
@@ -342,7 +236,6 @@
* Store constants
*/
#define STORE_INVEN_MAX 255 /* Max number of discrete objs in inven */
-#define STORE_CHOICES 56 /* Number of items to choose stock from */
#define STORE_OBJ_LEVEL 5 /* Magic Level for normal stores */
#define STORE_TURNOVER 9 /* Normal shop turnover, per day */
#define STORE_MIN_KEEP 6 /* Min slots to "always" keep full */
@@ -358,8 +251,6 @@
#define HOUR (DAY / 24) /* Number of turns per hour */
#define MINUTE (HOUR / 60) /* Number of turns per minute */
#define DAY_START (HOUR * 6) /* Sunrise */
-#define START_YEAR 2890 /* Bilbo birthday year */
-#define START_DAY (DAY * (42 + 127)) /* Bilbo birthday */
#define BREAK_GLYPH 550 /* Rune of protection resistance */
#define BREAK_MINOR_GLYPH 99 /* For explosive runes */
@@ -418,7 +309,6 @@
#define NASTY_MON 50 /* 1/chance of inflated monster level */
-
/*
* Refueling constants
*/
@@ -460,7 +350,6 @@
#define SUBRACE_SAVE 9 /* Ugly hack, should be in foo-info, the subrace saved to the savefile */
#define PY_MAX_EXP 99999999L /* Maximum exp */
#define PY_MAX_GOLD 999999999L /* Maximum gold */
-#define PY_MAX_LEVEL 50 /* Maximum level */
/*
* Player "food" crucial values
@@ -482,131 +371,19 @@
#define PY_REGEN_MNBASE 524 /* Min amount mana regen*2^16 */
/*
- * Maximum number of "normal" pack slots, and the index of the "overflow"
- * slot, which can hold an item, but only temporarily, since it causes the
- * pack to "overflow", dropping the "last" item onto the ground. Since this
- * value is used as an actual slot, it must be less than "INVEN_WIELD" (below).
- * Note that "INVEN_PACK" is probably hard-coded by its use in savefiles, and
- * by the fact that the screen can only show 23 items plus a one-line prompt.
- */
-#define INVEN_PACK 23
-
-/*
- * Body parts
- */
-#define BODY_WEAPON 0
-#define BODY_TORSO 1
-#define BODY_ARMS 2
-#define BODY_FINGER 3
-#define BODY_HEAD 4
-#define BODY_LEGS 5
-#define BODY_MAX 6
-
-/*
- * Indexes used for various "equipment" slots (hard-coded by savefiles, etc).
- */
-#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 */
-
-/*
- * Total number of inventory slots (hard-coded).
- */
-#define INVEN_TOTAL 52
-#define INVEN_EQ (INVEN_TOTAL - INVEN_WIELD)
-
-/*
* A "stack" of items is limited to less than 100 items (hard-coded).
*/
#define MAX_STACK_SIZE 100
-
-/*
- * Indexes of the various "stats" (hard-coded by savefiles, etc).
- */
-#define A_STR 0
-#define A_INT 1
-#define A_WIS 2
-#define A_DEX 3
-#define A_CON 4
-#define A_CHR 5
-
-/*
- * Player sex constants (hard-coded by save-files, arrays, etc)
- */
-#define SEX_FEMALE 0
-#define SEX_MALE 1
-#define SEX_NEUTER 2
-
-
-/* Race flags */
-#define PR1_EXPERIMENTAL 0x00000001L /* Is still under developemnt */
-/* XXX */
-#define PR1_RESIST_BLACK_BREATH 0x00000004L /* Resist black breath */
-#define PR1_NO_STUN 0x00000008L /* Never stunned */
-#define PR1_XTRA_MIGHT_BOW 0x00000010L /* Xtra might with bows */
-#define PR1_XTRA_MIGHT_XBOW 0x00000020L /* Xtra might with xbows */
-#define PR1_XTRA_MIGHT_SLING 0x00000040L /* Xtra might with slings */
-#define PR1_AC_LEVEL 0x00000080L /* More AC with levels */
-#define PR1_HURT_LITE 0x00000100L /* Hurt by light */
-#define PR1_VAMPIRE 0x00000200L /* Vampire */
-#define PR1_UNDEAD 0x00000400L /* Undead */
-#define PR1_NO_CUT 0x00000800L /* no cuts */
-#define PR1_CORRUPT 0x00001000L /* hack-- corrupted */
-#define PR1_NO_FOOD 0x00002000L /* little gain from food */
-#define PR1_NO_GOD 0x00004000L /* cannot worship */
-/* XXX */
-#define PR1_ELF 0x00010000L /* Is an elf */
-#define PR1_SEMI_WRAITH 0x00020000L /* Takes damage when going in walls */
-#define PR1_NO_SUBRACE_CHANGE 0x00040000L /* Impossible to change subrace */
-/* XXX */
-#define PR1_ANTIMAGIC 0x00100000L /* antimagic ... hack */
-#define PR1_MOLD_FRIEND 0x00200000L /* Not attacked by molds wielded */
-#define PR1_GOD_FRIEND 0x00400000L /* Better grace */
-/* XXX */
-#define PR1_INNATE_SPELLS 0x01000000L /* KNown all spells, only need books */
-/* XXX */
-/* XXX */
-#define PR1_EASE_STEAL 0x08000000L /* Gain xp by stealing */
-/* XXX */
-/* XXX */
-/* XXX */
-/* XXX */
-
-/* XXX */
-#define PR2_ASTRAL 0x00000002L /* Is it an astral being coming from th halls of mandos ? */
-/* XXX */
-
-#define PRACE_FLAG2(f) ((rp_ptr->flags2 | rmp_ptr->flags2 | cp_ptr->flags2 | spp_ptr->flags2) & (f))
-#define PRACE_FLAG(f) ((rp_ptr->flags1 | rmp_ptr->flags1 | cp_ptr->flags1 | spp_ptr->flags1) & (f))
-#define PRACE_FLAGS(f) PRACE_FLAG(f)
-
-/* XXX */
#define MKEY_MINDCRAFT 2
#define MKEY_ANTIMAGIC 3
-#define MKEY_BLADE 4
-#define MKEY_ALCHEMY 5
#define MKEY_MIMIC 6
#define MKEY_NECRO 7
#define MKEY_POWER_MAGE 8
-#define MKEY_RUNE 9
#define MKEY_FORGING 10
#define MKEY_INCARNATION 11
-#define MKEY_TELEKINESIS 12
#define MKEY_SUMMON 13
-#define MKEY_TRAP 14
#define MKEY_STEAL 15
#define MKEY_DODGE 16
#define MKEY_SCHOOL 17
@@ -616,6 +393,9 @@
#define MKEY_BOULDER 21
#define MKEY_COMPANION 22
#define MKEY_PIERCING 23
+#define MKEY_DEATH_TOUCH 100
+#define MKEY_GEOMANCY 101
+#define MKEY_REACH_ATTACK 102
/*** Screen Locations ***/
@@ -668,45 +448,6 @@
#define ROW_MH 19
#define COL_MH 0 /* "MH xxxxx/xxxxx" */
-#define ROW_INFO (Term->hgt - 4)
-#define COL_INFO 0 /* "xxxxxxxxxxxx" */
-
-#define ROW_CUT (Term->hgt - 3)
-#define COL_CUT 0 /* <cut> */
-
-#define ROW_STUN (Term->hgt - 2)
-#define COL_STUN 0 /* <stun> */
-
-#define ROW_HUNGRY (Term->hgt - 1)
-#define COL_HUNGRY 0 /* "Weak" / "Hungry" / "Full" / "Gorged" */
-
-#define ROW_BLIND (Term->hgt - 1)
-#define COL_BLIND 7 /* "Blind" */
-
-#define ROW_CONFUSED (Term->hgt - 1)
-#define COL_CONFUSED 13 /* "Conf" */
-
-#define ROW_AFRAID (Term->hgt - 1)
-#define COL_AFRAID 18 /* "Afraid" */
-
-#define ROW_POISONED (Term->hgt - 1)
-#define COL_POISONED 25 /* "Poison" */
-
-#define ROW_DTRAP (Term->hgt - 1)
-#define COL_DTRAP 32 /* "DTrap" */
-
-#define ROW_STATE (Term->hgt - 1)
-#define COL_STATE 38 /* <state> */
-
-#define ROW_SPEED (Term->hgt - 1)
-#define COL_SPEED 49 /* "Slow (-NN)" or "Fast (+NN)" */
-
-#define ROW_STUDY (Term->hgt - 1)
-#define COL_STUDY 60 /* "Study" */
-
-#define ROW_DEPTH (Term->hgt - 1)
-#define COL_DEPTH (Term->wid - 14) /* "Lev NNN" / "NNNN ft" */
-
/*** Terrain Feature Indexes (see "lib/edit/f_info.txt") ***/
@@ -738,9 +479,6 @@
/* Feature 0x10 -- web */
-/* Traps */
-#define FEAT_TRAP 0x11
-
/* Features 0x12 - 0x1F -- unused */
/* Doors */
@@ -788,9 +526,6 @@
/* Permanent walls for quests */
#define FEAT_QUEST1 0x4B
-#define FEAT_QUEST2 0x4C
-#define FEAT_QUEST3 0x4D
-#define FEAT_QUEST4 0x4E
/* Features 0x4F - 0x53 -- unused */
@@ -827,7 +562,6 @@
#define FEAT_MARKER 0xAC /* 172 */
/* Feature 0xAD -- Underground Tunnel */
#define FEAT_TAINTED_WATER 0xAE /* 174 */
-#define FEAT_MON_TRAP 0xAF /* 175 */
#define FEAT_BETWEEN2 0xB0 /* 176 */
#define FEAT_LAVA_WALL 0xB1 /* 177 */
#define FEAT_GREAT_FIRE 0xB2 /* 178 */
@@ -862,7 +596,17 @@
/* Features 0xCF - 0xFF -- unused */
-#define MAX_BETWEEN_EXITS 2
+#define MAX_BETWEEN_EXITS 3
+
+/*
+ * Maximum number of school spells
+ */
+#define SCHOOL_SPELLS_MAX 200
+
+/*
+ * Maximum number of spell schools
+ */
+#define SCHOOLS_MAX 50
/*
* Number of effects
@@ -880,228 +624,15 @@
#define EFF_DIR8 0x00000200 /* Directed effect */
#define EFF_DIR9 0x00000400 /* Directed effect */
-/*
- * Wilderness terrains
- */
-#define TERRAIN_EDGE 0 /* Edge of the World */
-#define TERRAIN_TOWN 1 /* Town */
-#define TERRAIN_DEEP_WATER 2 /* Deep water */
-#define TERRAIN_SHALLOW_WATER 3 /* Shallow water */
-#define TERRAIN_SWAMP 4 /* Swamp */
-#define TERRAIN_DIRT 5 /* Dirt */
-#define TERRAIN_GRASS 6 /* Grass */
-#define TERRAIN_TREES 7 /* Trees */
-#define TERRAIN_DESERT 8 /* Desert */
-#define TERRAIN_SHALLOW_LAVA 9 /* Shallow lava */
-#define TERRAIN_DEEP_LAVA 10 /* Deep lava */
-#define TERRAIN_MOUNTAIN 11 /* Mountain */
-
-#define MAX_WILD_TERRAIN 18
-
/*** Artifact indexes (see "lib/edit/a_info.txt") ***/
-
-/* Lites */
-#define ART_GALADRIEL 1
-#define ART_ELENDIL 2
-#define ART_THRAIN 3
-#define ART_PALANTIR 202
-#define ART_UNDEATH 200
-#define ART_STONE_LORE 15
-#define ART_PALANTIR_ITHIL 208
-
-/* Amulets */
-#define ART_CARLAMMAS 4
-#define ART_INGWE 5
-#define ART_DWARVES 6
#define ART_ANCHOR 14
-#define ART_ELESSAR 206
-#define ART_EVENSTAR 207
-
-/* Rings */
-#define ART_FLAR 7
-#define ART_BARAHIR 8
-#define ART_TULKAS 9
-#define ART_NARYA 10
-#define ART_NENYA 11
-#define ART_VILYA 12
#define ART_POWER 13
-/* 14 used by the anchor of space-time */
-/* 15 used by the stone of lore */
-
-/* Dragon Scale */
-#define ART_RAZORBACK 16
-#define ART_BLADETURNER 17
-#define ART_MEDIATOR 166
-
-/* Hard Armour */
-#define ART_HIMRING 167
-#define ART_SOULKEEPER 19
-#define ART_ISILDUR 20
-#define ART_ROHIRRIM 21
-#define ART_BELEGENNON 22
-#define ART_CELEBORN 23
-#define ART_ARVEDUI 24
-#define ART_CASPANION 25
-
-/* Thunderlord flying suit */
-#define ART_MARDA 26
-#define ART_TRON 27
-
-/* Soft Armour */
-#define ART_THALKETTOTH 28
-
-/* Shields */
-#define ART_THORIN 30
-#define ART_CELEGORM 31
-#define ART_ANARION 32
-#define ART_GILGALAD 169
-#define ART_HARADRIM 176
-
-/* Helms and Crowns */
#define ART_MORGOTH 34
-#define ART_BERUTHIEL 35
-#define ART_THRANDUIL 36
-#define ART_THENGEL 37
-#define ART_HAMMERHAND 38
-#define ART_DOR 39
-#define ART_HOLHENNETH 40
-#define ART_GORLIM 41
-#define ART_GONDOR 42
-#define ART_KNOWLEDGE 160
-#define ART_NUMENOR 43
-#define ART_CELEBRIMBOR 170
-
-/* Cloaks */
-#define ART_COLLUIN 44
-#define ART_HOLCOLLETH 45
-#define ART_THINGOL 46
-#define ART_THORONGIL 47
-#define ART_COLANNON 48
-#define ART_LUTHIEN 49
-#define ART_TUOR 50
-
-/* Gloves */
-#define ART_CAMBELEG 52
-#define ART_CAMMITHRIM 53
-#define ART_PAURHACH 54
-#define ART_PAURNIMMEN 55
-#define ART_PAURAEGEN 56
-#define ART_PAURNEN 57
-#define ART_CAMLOST 58
-#define ART_FINGOLFIN 59
-#define ART_EOL 178
-
-/* Boots */
-#define ART_FEANOR 60
-#define ART_DAL 61
-#define ART_THROR 62
-
-/* Swords */
#define ART_NARSIL 164
-#define ART_MAEDHROS 64
-#define ART_ANGRIST 65
-#define ART_NARTHANC 66
-#define ART_NIMTHANC 67
-#define ART_DETHANC 68
-#define ART_RILIA 69
-#define ART_BELANGIL 70
-#define ART_CALRIS 71
-#define ART_ARUNRUTH 72
#define ART_GLAMDRING 73
-#define ART_AEGLIN 74
-#define ART_ORCRIST 75
-#define ART_GURTHANG 76
-#define ART_ZARCUTHRA 77
-#define ART_MORMEGIL 78
-#define ART_GONDRICAM 79
-#define ART_CRISDURIAN 80
-#define ART_AGLARANG 81
-#define ART_RINGIL 82
#define ART_ANDURIL 83
-#define ART_ANGUIREL 84
-#define ART_ELVAGIL 85
-#define ART_FORASGIL 86
-#define ART_CARETH 87
-#define ART_STING 88
-#define ART_HARADEKKET 89
-#define ART_GILETTAR 90
-#define ART_DOOMCALLER 91
-#define ART_VORPAL_BLADE 92
-#define ART_ERU 147
-
-/* Polearms */
-#define ART_THEODEN 93
-#define ART_PAIN 94
-#define ART_OSONDIR 95
-#define ART_TIL 96
-#define ART_AEGLOS 97
-#define ART_OROME 98
-#define ART_NIMLOTH 99
-#define ART_EORLINGAS 100
-#define ART_DURIN 101
-#define ART_EONWE 102
-#define ART_BALLI 103
-#define ART_LOTHARANG 104
-#define ART_MUNDWINE 105
-#define ART_BARUKKHELED 106
-#define ART_WRATH 107
-#define ART_ULMO 108
-#define ART_AVAVIR 109
-#define ART_FUNDIN 175
-
-/* The sword of the Dawn */
-#define ART_DAWN 110
-
-/* Hafted */
-#define ART_MELKOR 18
-#define ART_HURIN 33
#define ART_GROND 111
-#define ART_TOTILA 112
-#define ART_THUNDERFIST 113
-#define ART_BLOODSPIKE 114
-#define ART_FIRESTAR 115
-#define ART_TARATOL 116
-#define ART_AULE 117
-#define ART_NAR 118
-#define ART_ERIRIL 119
-#define ART_OLORIN 120
-#define ART_DEATHWREAKER 121
-#define ART_TURMIL 122
-#define ART_GOTHMOG 123
-#define ART_AXE_GOTHMOG 145
-#define ART_SKULLCLEAVER 177
-
-#define ART_NAIN 174
-
-/* Bows */
-#define ART_BELTHRONDING 124
-#define ART_BARD 125
-#define ART_CUBRAGOL 126
-#define ART_UMBAR 171
-
-/* Mage Staffs */
-#define ART_GANDALF 127
-
-/* Boomerangs */
-#define ART_BEOR 128
-#define ART_GLIMDRIR 129
-
-/* Musical Instrument */
-#define ART_MAGLOR 137
-#define ART_SKY 138
-#define ART_DAERON 139
-#define ART_DRUEDAIN 141
-#define ART_ROHAN 142
-#define ART_HELM 143
-#define ART_BOROMIR 144
-
-/* Diggers */
-#define ART_EREBOR 140
-
-#define ART_ORCHAST 156
-#define ART_NIGHT 157
-#define ART_NATUREBANE 158
/* Spell for various object */
#define SPELL_ID_PLAIN 1
@@ -1122,7 +653,6 @@
#define EGO_MANA 1
#define EGO_POWER 2
#define EGO_MANA_POWER 3
-#define EGO_MSTAFF_SPELL 4
#define EGO_BRAND_POIS 77
#define EGO_BRAND_ELEC 74
#define EGO_BRAND_FIRE 75
@@ -1205,7 +735,6 @@
#define ACT_FUNDIN 30
#define ACT_EOL 31
#define ACT_UMBAR 32
-#define ACT_NUMENOR 33
#define ACT_KNOWLEDGE 34
#define ACT_UNDEATH 35
#define ACT_THRAIN 36
@@ -1251,10 +780,6 @@
#define ACT_GANDALF 76
#define ACT_MARDA 77
#define ACT_PALANTIR 78
-/*
- 79
- 80
-*/
#define ACT_CURE_LW 81
#define ACT_CURE_MW 82
#define ACT_CURE_POISON 83
@@ -1262,9 +787,6 @@
#define ACT_REST_ALL 85
#define ACT_CURE_700 86
#define ACT_CURE_1000 87
-/*
- 88
-*/
#define ACT_EREBOR 89
#define ACT_DRUEDAIN 90
#define ACT_ESP 91
@@ -1375,9 +897,14 @@
#define ACT_BR_BALANCE 194
#define ACT_BR_LIGHT 195
#define ACT_BR_POWER 196
-#define ACT_GROW_MOLD 197
-#define ACT_MUSIC 200
-/* 170 -> unused */
+#define ACT_GROW_MOLD 197
+#define ACT_MUSIC 200
+#define ACT_ETERNAL_FLAME 201
+#define ACT_MAGGOT 202
+#define ACT_LEBOHAUM 203
+#define ACT_DURANDIL 204
+#define ACT_RADAGAST 205 /* Theme */
+#define ACT_VALAROMA 206 /* Theme */
/*** Object "tval" and "sval" codes ***/
@@ -1398,8 +925,6 @@
#define TV_SKELETON 1 /* Skeletons ('s') */
#define TV_BOTTLE 2 /* Empty bottles ('!') */
-/* XXX */
-#define TV_BATERIE 4 /* For the Alchemists */
#define TV_SPIKE 5 /* Spikes ('~') */
#define TV_MSTAFF 6 /* Mage Staffs */
#define TV_CHEST 7 /* Chests ('~') */
@@ -1432,7 +957,6 @@
#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
@@ -1446,8 +970,6 @@
#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
@@ -1462,7 +984,6 @@
/* 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
@@ -1477,14 +998,6 @@
#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 /* 1d8 */
@@ -1687,10 +1200,8 @@
/* 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
@@ -1741,7 +1252,6 @@
#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
@@ -1843,14 +1353,11 @@
#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
@@ -1865,7 +1372,6 @@
#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
@@ -1891,7 +1397,6 @@
#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
@@ -1912,7 +1417,6 @@
#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
@@ -1923,7 +1427,6 @@
#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
@@ -1938,6 +1441,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
@@ -1954,7 +1458,6 @@
#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
@@ -1994,11 +1497,9 @@
#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
@@ -2050,27 +1551,6 @@
#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
-#define MAX_BATERIE_SVAL 18
-
/* The "sval" codes for TV_CORPSE */
#define SV_CORPSE_CORPSE 1
#define SV_CORPSE_SKELETON 2
@@ -2103,13 +1583,6 @@
*/
#define SV_BOOK_MAX_GOOD 49
-/* flags for operation in get_random_trap in object3.c */
-
-#define TRAP_EXISTS 0x00000001L
-#define TRAP_FOUND 0x00000002L
-#define TRAP_NOTFOUND 0x00000004L
-#define TRAP_IDENTIFIED 0x00000008L
-
/*** General flag values ***/
@@ -2124,11 +1597,9 @@
#define CAVE_VIEW 0x0020 /* view flag */
#define CAVE_TEMP 0x0040 /* temp flag */
#define CAVE_WALL 0x0080 /* wall flag */
-#define CAVE_TRDT 0x0100 /* trap detected */
#define CAVE_IDNT 0x0200 /* grid identified (fountains) */
#define CAVE_SPEC 0x0400 /* special mark(quests) */
#define CAVE_FREE 0x0800 /* no random generation on it */
-#define CAVE_DETECT 0x1000 /* Traps detected here */
#define CAVE_PLIT 0x2000 /* Player lit grid */
#define CAVE_MLIT 0x4000 /* Monster lit grid */
@@ -2211,7 +1682,6 @@
#define SM_OPP_POIS 0x00100000
#define SM_OPP_XXX1 0x00200000
#define SM_CLONED 0x00400000
-#define SM_NOTE_TRAP 0x00800000
#define SM_IMM_ACID 0x01000000
#define SM_IMM_ELEC 0x02000000
#define SM_IMM_FIRE 0x04000000
@@ -2238,7 +1708,6 @@
#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 USE_AUTO 0x10 /* Allow creation of automatizer rule */
/*
* Bit flags for the "p_ptr->notice" variable
@@ -2259,279 +1728,39 @@
#define PU_MANA 0x00000020L /* Calculate csp and msp */
#define PU_SPELLS 0x00000040L /* Calculate spells */
#define PU_POWERS 0x00000080L /* Calculate powers */
-/* xxx (many) */
#define PU_UN_VIEW 0x00010000L /* Forget view */
-/* xxx (many) */
#define PU_VIEW 0x00100000L /* Update view */
#define PU_MON_LITE 0x00200000L /* Update monster light */
-/* xxx */
#define PU_MONSTERS 0x01000000L /* Update monsters */
#define PU_DISTANCE 0x02000000L /* Update distances */
-/* xxx */
#define PU_FLOW 0x10000000L /* Update flow */
-/* xxx (many) */
/*
* Bit flags for the "p_ptr->redraw" variable
*/
-#define PR_MISC 0x00000001L /* Display Race/Class */
-#define PR_TITLE 0x00000002L /* Display Title */
-#define PR_LEV 0x00000004L /* Display Level */
-#define PR_EXP 0x00000008L /* Display Experience */
-#define PR_STATS 0x00000010L /* Display Stats */
-#define PR_ARMOR 0x00000020L /* Display Armor */
-#define PR_HP 0x00000040L /* Display Hitpoints */
-#define PR_MANA 0x00000080L /* Display Mana */
-#define PR_GOLD 0x00000100L /* Display Gold */
-#define PR_DEPTH 0x00000200L /* Display Depth */
-/****/
-#define PR_HEALTH 0x00000800L /* Display Health Bar */
-#define PR_CUT 0x00001000L /* Display Extra (Cut) */
-#define PR_STUN 0x00002000L /* Display Extra (Stun) */
-#define PR_HUNGER 0x00004000L /* Display Extra (Hunger) */
-#define PR_PIETY 0x00008000L /* Display Piety */
-#define PR_BLIND 0x00010000L /* Display Extra (Blind) */
-#define PR_CONFUSED 0x00020000L /* Display Extra (Confused) */
-#define PR_AFRAID 0x00040000L /* Display Extra (Afraid) */
-#define PR_POISONED 0x00080000L /* Display Extra (Poisoned) */
-#define PR_STATE 0x00100000L /* Display Extra (State) */
-#define PR_SPEED 0x00200000L /* Display Extra (Speed) */
-#define PR_STUDY 0x00400000L /* Display Extra (Study) */
-#define PR_SANITY 0x00800000L /* Display Sanity */
-#define PR_EXTRA 0x01000000L /* Display Extra Info */
-#define PR_BASIC 0x02000000L /* Display Basic Info */
+#define PR_FRAME 0x02000000L /* Display Basic Info */
#define PR_MAP 0x04000000L /* Display Map */
#define PR_WIPE 0x08000000L /* Hack -- Total Redraw */
-#define PR_MH 0x10000000L /* Display Monster hitpoints */
-#define PR_DTRAP 0x20000000L /* Display Extra (DTrap) */
-/* xxx */
-/* xxx */
/*
* Bit flags for the "p_ptr->window" variable (etc)
*/
#define PW_INVEN 0x00000001L /* Display inven/equip */
#define PW_EQUIP 0x00000002L /* Display equip/inven */
-/* xxx */
#define PW_PLAYER 0x00000008L /* Display character */
#define PW_M_LIST 0x00000010L /* Show monster list */
-/* xxx */
#define PW_MESSAGE 0x00000040L /* Display messages */
#define PW_OVERHEAD 0x00000080L /* Display overhead view */
#define PW_MONSTER 0x00000100L /* Display monster recall */
#define PW_OBJECT 0x00000200L /* Display object recall */
-/* xxx */
-#define PW_SNAPSHOT 0x00000800L /* Display snap-shot */
-/* xxx */
-/* xxx */
-#define PW_BORG_1 0x00004000L /* Display borg messages */
-#define PW_BORG_2 0x00008000L /* Display borg status */
-
-/* jk */
-#define FTRAP_CHEST 0x000000001 /* may appear on chests */
-#define FTRAP_DOOR 0x000000002 /* may appear on doors/floors */
-#define FTRAP_FLOOR 0x000000004 /* may appear on floor */
-#define FTRAP_CHANGE 0x000000008 /* Color changing */
-#define FTRAP_XXX5 0x000000010
-#define FTRAP_XXX6 0x000000020
-#define FTRAP_XXX7 0x000000040
-#define FTRAP_XXX8 0x000000080
-#define FTRAP_XXX9 0x000000100
-#define FTRAP_XXX10 0x000000200
-#define FTRAP_XXX11 0x000000400
-#define FTRAP_XXX12 0x000000800
-#define FTRAP_XXX13 0x000001000
-#define FTRAP_XXX14 0x000002000
-#define FTRAP_XXX15 0x000004000
-#define FTRAP_XXX16 0x000008000
-#define FTRAP_LEVEL1 0x000010000 /* low level ball/bolt trap */
-#define FTRAP_LEVEL2 0x000020000 /* medium level ball/bolt trap */
-#define FTRAP_LEVEL3 0x000040000 /* high level ball/bolt trap */
-#define FTRAP_LEVEL4 0x000080000 /* oops level ball/bolt trap */
-#define FTRAP_XXX21 0x000100000
-#define FTRAP_XXX22 0x000200000
-#define FTRAP_XXX23 0x000400000
-#define FTRAP_XXX24 0x000800000
-#define FTRAP_XXX25 0x001000000
-#define FTRAP_XXX26 0x002000000
-#define FTRAP_XXX27 0x004000000
-#define FTRAP_XXX28 0x008000000
-#define FTRAP_XXX29 0x010000000
-#define FTRAP_XXX30 0x020000000
-#define FTRAP_XXX31 0x040000000
-#define FTRAP_XXX32 0x080000000
/* jk */
#define STAT_DEC_TEMPORARY 1
#define STAT_DEC_NORMAL 2
#define STAT_DEC_PERMANENT 3
-/* jk - which trap is which number */
-#define TRAP_OF_WEAKNESS_I 1
-#define TRAP_OF_WEAKNESS_II 2
-#define TRAP_OF_WEAKNESS_III 3
-#define TRAP_OF_INTELLIGENCE_I 4
-#define TRAP_OF_INTELLIGENCE_II 5
-#define TRAP_OF_INTELLIGENCE_III 6
-#define TRAP_OF_WISDOM_I 7
-#define TRAP_OF_WISDOM_II 8
-#define TRAP_OF_WISDOM_III 9
-#define TRAP_OF_FUMBLING_I 10
-#define TRAP_OF_FUMBLING_II 11
-#define TRAP_OF_FUMBLING_III 12
-#define TRAP_OF_WASTING_I 13
-#define TRAP_OF_WASTING_II 14
-#define TRAP_OF_WASTING_III 15
-#define TRAP_OF_BEAUTY_I 16
-#define TRAP_OF_BEAUTY_II 17
-#define TRAP_OF_BEAUTY_III 18
-
-#define TRAP_OF_CURSE_WEAPON 20
-#define TRAP_OF_CURSE_ARMOR 21
-#define TRAP_OF_EARTHQUAKE 22
-#define TRAP_OF_POISON_NEEDLE 23
-#define TRAP_OF_SUMMON_MONSTER 24
-#define TRAP_OF_SUMMON_UNDEAD 25
-#define TRAP_OF_SUMMON_GREATER_UNDEAD 26
-#define TRAP_OF_TELEPORT 27
-#define TRAP_OF_PARALYZING 28
-#define TRAP_OF_EXPLOSIVE_DEVICE 29
-#define TRAP_OF_TELEPORT_AWAY 30
-#define TRAP_OF_LOSE_MEMORY 31
-#define TRAP_OF_BITTER_REGRET 32
-#define TRAP_OF_BOWEL_CRAMPS 33
-#define TRAP_OF_BLINDNESS_CONFUSION 34
-#define TRAP_OF_AGGRAVATION 35
-#define TRAP_OF_MULTIPLICATION 36
-#define TRAP_OF_STEAL_ITEM 37
-#define TRAP_OF_SUMMON_FAST_QUYLTHULGS 38
-#define TRAP_OF_SINKING 39
-#define TRAP_OF_MANA_DRAIN 40
-#define TRAP_OF_MISSING_MONEY 41
-#define TRAP_OF_NO_RETURN 42
-#define TRAP_OF_SILENT_SWITCHING 43
-#define TRAP_OF_WALLS 44
-#define TRAP_OF_CALLING_OUT 45
-#define TRAP_OF_SLIDING 46
-#define TRAP_OF_CHARGES_DRAIN 47
-#define TRAP_OF_STAIR_MOVEMENT 48
-#define TRAP_OF_NEW 49
-#define TRAP_OF_SCATTER_ITEMS 50
-#define TRAP_OF_DECAY 51
-#define TRAP_OF_WASTING_WANDS 52
-#define TRAP_OF_FILLING 53
-#define TRAP_OF_DRAIN_SPEED 54
-
-#define TRAP_OF_ELEC_BOLT 60
-#define TRAP_OF_POIS_BOLT 61
-#define TRAP_OF_ACID_BOLT 62
-#define TRAP_OF_COLD_BOLT 63
-#define TRAP_OF_FIRE_BOLT 64
-#define TRAP_OF_PLASMA_BOLT 65
-#define TRAP_OF_WATER_BOLT 66
-#define TRAP_OF_LITE_BOLT 67
-#define TRAP_OF_DARK_BOLT 68
-#define TRAP_OF_SHARDS_BOLT 69
-#define TRAP_OF_SOUND_BOLT 70
-#define TRAP_OF_CONFUSION_BOLT 71
-#define TRAP_OF_FORCE_BOLT 72
-#define TRAP_OF_INERTIA_BOLT 73
-#define TRAP_OF_MANA_BOLT 74
-#define TRAP_OF_ICE_BOLT 75
-#define TRAP_OF_CHAOS_BOLT 76
-#define TRAP_OF_NETHER_BOLT 77
-#define TRAP_OF_DISENCHANT_BOLT 78
-#define TRAP_OF_NEXUS_BOLT 79
-#define TRAP_OF_TIME_BOLT 80
-#define TRAP_OF_GRAVITY_BOLT 81
-
-#define TRAP_OF_ELEC_BALL 82
-#define TRAP_OF_POIS_BALL 83
-#define TRAP_OF_ACID_BALL 84
-#define TRAP_OF_COLD_BALL 85
-#define TRAP_OF_FIRE_BALL 86
-#define TRAP_OF_PLASMA_BALL 87
-#define TRAP_OF_WATER_BALL 88
-#define TRAP_OF_LITE_BALL 89
-#define TRAP_OF_DARK_BALL 90
-#define TRAP_OF_SHARDS_BALL 91
-#define TRAP_OF_SOUND_BALL 92
-#define TRAP_OF_CONFUSION_BALL 93
-#define TRAP_OF_FORCE_BALL 94
-#define TRAP_OF_INERTIA_BALL 95
-#define TRAP_OF_MANA_BALL 96
-#define TRAP_OF_ICE_BALL 97
-#define TRAP_OF_CHAOS_BALL 98
-#define TRAP_OF_NETHER_BALL 99
-#define TRAP_OF_DISENCHANT_BALL 100
-#define TRAP_OF_NEXUS_BALL 101
-#define TRAP_OF_TIME_BALL 102
-#define TRAP_OF_GRAVITY_BALL 103
-
-#define TRAP_OF_ARROW_I 110
-#define TRAP_OF_ARROW_II 111
-#define TRAP_OF_ARROW_III 112
-#define TRAP_OF_ARROW_IV 113
-#define TRAP_OF_POISON_ARROW_I 114
-#define TRAP_OF_POISON_ARROW_II 115
-#define TRAP_OF_POISON_ARROW_III 116
-#define TRAP_OF_POISON_ARROW_IV 117
-#define TRAP_OF_DAGGER_I 118
-#define TRAP_OF_DAGGER_II 119
-#define TRAP_OF_POISON_DAGGER_I 120
-#define TRAP_OF_POISON_DAGGER_II 121
-#define TRAP_OF_ARROWS_I 122
-#define TRAP_OF_ARROWS_II 123
-#define TRAP_OF_ARROWS_III 124
-#define TRAP_OF_ARROWS_IV 125
-#define TRAP_OF_POISON_ARROWS_I 126
-#define TRAP_OF_POISON_ARROWS_II 127
-#define TRAP_OF_POISON_ARROWS_III 128
-#define TRAP_OF_POISON_ARROWS_IV 129
-#define TRAP_OF_DAGGERS_I 130
-#define TRAP_OF_DAGGERS_II 131
-#define TRAP_OF_POISON_DAGGERS_I 132
-#define TRAP_OF_POISON_DAGGERS_II 133
-
-#define TRAP_OF_DROP_ITEMS 140
-#define TRAP_OF_DROP_ALL_ITEMS 141
-#define TRAP_OF_DROP_EVERYTHING 142
-
-/* -SC- */
-#define TRAP_OF_FEMINITY 150
-#define TRAP_OF_MASCULINITY 151
-#define TRAP_OF_NEUTRALITY 152
-#define TRAP_OF_AGING 153
-#define TRAP_OF_GROWING 154
-#define TRAP_OF_SHRINKING 155
-#define TRAP_OF_ELDRITCH_HORROR 156
-/* XXX */
-#define TRAP_OF_DIVINE_ANGER 158
-#define TRAP_OF_DIVINE_WRATH 159
-#define TRAP_OF_HALLUCINATION 160
-
-#define TRAP_OF_ROCKET 161
-#define TRAP_OF_NUKE_BOLT 162
-#define TRAP_OF_DEATH_RAY 163
-#define TRAP_OF_HOLY_FIRE 164
-#define TRAP_OF_HELL_FIRE 165
-#define TRAP_OF_PSI_BOLT 166
-#define TRAP_OF_PSI_DRAIN 167
-#define TRAP_OF_NUKE_BALL 168
-#define TRAP_OF_PSI_BALL 169
-
-/* DG */
-#define TRAP_OF_ACQUIREMENT 170
-
-/* Runescrye */
-#define TRAP_G_ELEC_BOLT 171
-#define TRAP_G_POIS_BOLT 172
-#define TRAP_G_ACID_BOLT 173
-#define TRAP_G_COLD_BOLT 174
-#define TRAP_G_FIRE_BOLT 175
-
/*** General index values ***/
@@ -2575,7 +1804,6 @@
#define SUMMON_SHADOWS 55
#define SUMMON_GHOST 56
#define SUMMON_QUYLTHULG 57
-#define SUMMON_LUA 58
/*
@@ -2613,10 +1841,8 @@
#define GF_GRAVITY 35
#define GF_KILL_WALL 40
#define GF_KILL_DOOR 41
-#define GF_KILL_TRAP 42
#define GF_MAKE_WALL 45
#define GF_MAKE_DOOR 46
-#define GF_MAKE_TRAP 47
#define GF_OLD_CLONE 51
#define GF_OLD_POLY 52
#define GF_OLD_HEAL 53
@@ -2655,7 +1881,6 @@
#define GF_JAM_DOOR 88
#define GF_DOMINATION 89
#define GF_DISP_GOOD 90
-#define GF_IDENTIFY 91
#define GF_RAISE 92
#define GF_STAR_IDENTIFY 93
#define GF_DESTRUCTION 94
@@ -2674,11 +1899,15 @@
#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
*/
+#define DRS_NONE 0
#define DRS_ACID 1
#define DRS_ELEC 2
#define DRS_FIRE 3
@@ -2720,9 +1949,6 @@
/* High resist */
#define EGO_XTRA_POWER 2
-/* Special ability */
-#define EGO_XTRA_ABILITY 3
-
/*** Object flag values ***/
@@ -2730,7 +1956,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 !!!! */
@@ -2757,348 +1982,14 @@
MFLAG_PARTIAL | MFLAG_CONTROL | MFLAG_NO_DROP \
)
-
-/*
- * As of 2.7.8, the "object flags" are valid for all objects, and as
- * of 2.7.9, these flags are not actually stored with the object.
- *
- * Note that "flags1" contains all flags dependant on "pval" (including
- * stat bonuses, but NOT stat sustainers), plus all "extra attack damage"
- * flags (SLAY_XXX and BRAND_XXX).
- *
- * Note that "flags2" contains all "resistances" (including "Stat Sustainers",
- * actual immunities, and resistances). Note that "Hold Life" is really an
- * "immunity" to ExpLoss, and "Free Action" is "immunity to paralysis".
- *
- * Note that "flags3" contains everything else -- including the three "CURSED"
- * flags, and the "BLESSED" flag, several "item display" parameters, some new
- * flags for powerful Bows, and flags which affect the player in a "general"
- * way (LITE, TELEPATHY, SEE_INVIS, SLOW_DIGEST, REGEN, FEATHER), including
- * all the "general" curses (TELEPORT, AGGRAVATE, EXP_DRAIN). It also has
- * four new flags called "ITEM_IGNORE_XXX" which lets an item specify that
- * it can not be affected by various forms of destruction. This is NOT as
- * powerful as actually granting resistance/immunity to the wearer.
- */
-
-#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 TRAP2_AUTOMATIC_5 0x00000001L /* Trap automatically rearms itself, 1 in 5 failure */
-#define TRAP2_AUTOMATIC_99 0x00000002L /* Trap automatically rearms itself */
-#define TRAP2_KILL_GHOST 0x00000004L /* Trap also affects PASS_WALL creatures */
-#define TRAP2_TELEPORT_TO 0x00000008L /* After everything else, teleport to player */
-#define TRAP2_ONLY_DRAGON 0x00000010L /* Affect only dragons & other AFFECTed creatures */
-#define TRAP2_ONLY_DEMON 0x00000020L /* Affect only demons & other AFFECTed creatures */
-#define TRAP2_ONLY_ANIMAL 0x00000100L /* Affect only animals & other AFFECTed creatures */
-#define TRAP2_ONLY_UNDEAD 0x00000200L /* Affect only undead & others */
-#define TRAP2_ONLY_EVIL 0x00000400L /* Affect only evil creatures &c. */
-
-#define TRAP2_ONLY_MASK (TRAP2_ONLY_DRAGON | TRAP2_ONLY_DEMON | TRAP2_ONLY_ANIMAL | \
- TRAP2_ONLY_UNDEAD | TRAP2_ONLY_EVIL )
-
-#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) */
-
-/* ESP defines */
-#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
-
-/* Number of group of flags to choose from */
-#define MAX_FLAG_GROUP 12
#define NEW_GROUP_CHANCE 40 /* Chance to get a new group */
-/*
- * Hack masks for "pval-dependant" flags.
- */
-#define TR1_PVAL_MASK \
- (TR1_STR | TR1_INT | TR1_WIS | TR1_DEX | \
- TR1_CON | TR1_CHR | \
- TR1_STEALTH | TR1_SEARCH | TR1_INFRA | TR1_TUNNEL | \
- TR1_SPEED | TR1_BLOWS | TR1_SPELL)
-
-#define TR5_PVAL_MASK \
- (TR5_CRIT | TR5_LUCK)
-
-
-/*** Ego flags ***/
-#define ETR4_SUSTAIN 0x00000001L /* Ego-Item gives a Random Sustain */
-#define ETR4_OLD_RESIST 0x00000002L /* The old "extra power" random high resist */
-#define ETR4_ABILITY 0x00000004L /* Ego-Item has a random Sustain */
-#define ETR4_R_ELEM 0x00000008L /* Item resists Acid/Fire/Cold/Elec or Poison */
-#define ETR4_R_LOW 0x00000010L /* Item has a random low resist */
-#define ETR4_R_HIGH 0x00000020L /* Item has a random high resist */
-#define ETR4_R_ANY 0x00000040L /* Item has one additional resist */
-#define ETR4_R_DRAGON 0x00000080L /* Item gets "Dragon" Resist */
-#define ETR4_SLAY_WEAP 0x00000100L /* Special 'Slaying' bonus */
-#define ETR4_DAM_DIE 0x00000200L /* Item has an additional dam die */
-#define ETR4_DAM_SIZE 0x00000400L /* Item has greater damage dice */
-#define ETR4_PVAL_M1 0x00000800L /* Item has +1 to pval */
-#define ETR4_PVAL_M2 0x00001000L /* Item has +(up to 2) to pval */
-#define ETR4_PVAL_M3 0x00002000L /* Item has +(up to 3) to pval */
-#define ETR4_PVAL_M5 0x00004000L /* Item has +(up to 5) to pval */
-#define ETR4_AC_M1 0x00008000L /* Item has +1 to AC */
-#define ETR4_AC_M2 0x00010000L /* Item has +(up to 2) to AC */
-#define ETR4_AC_M3 0x00020000L /* Item has +(up to 3) to AC */
-#define ETR4_AC_M5 0x00040000L /* Item has +(up to 5) to AC */
-#define ETR4_TH_M1 0x00080000L /* Item has +1 to hit */
-#define ETR4_TH_M2 0x00100000L /* Item has +(up to 2) to hit */
-#define ETR4_TH_M3 0x00200000L /* Item has +(up to 3) to hit */
-#define ETR4_TH_M5 0x00400000L /* Item has +(up to 5) to hit */
-#define ETR4_TD_M1 0x00800000L /* Item has +1 to dam */
-#define ETR4_TD_M2 0x01000000L /* Item has +(up to 2) to dam */
-#define ETR4_TD_M3 0x02000000L /* Item has +(up to 3) to dam */
-#define ETR4_TD_M5 0x04000000L /* Item has +(up to 5) to dam */
-#define ETR4_R_P_ABILITY 0x08000000L /* Item has a random pval-affected ability */
-#define ETR4_R_STAT 0x10000000L /* Item affects a random stat */
-#define ETR4_R_STAT_SUST 0x20000000L /* Item affects a random stat & sustains it */
-#define ETR4_R_IMMUNITY 0x40000000L /* Item gives a random immunity */
-#define ETR4_LIMIT_BLOWS 0x80000000L /* switch the "limit blows" feature */
-
-/*** Features flags -- DG ***/
-#define FF1_NO_WALK 0x00000001L
-#define FF1_NO_VISION 0x00000002L
-#define FF1_CAN_LEVITATE 0x00000004L
-#define FF1_CAN_PASS 0x00000008L
-#define FF1_FLOOR 0x00000010L
-#define FF1_WALL 0x00000020L
-#define FF1_PERMANENT 0x00000040L
-#define FF1_CAN_FLY 0x00000080L
-#define FF1_REMEMBER 0x00000100L
-#define FF1_NOTICE 0x00000200L
-#define FF1_DONT_NOTICE_RUNNING 0x00000400L
-#define FF1_CAN_RUN 0x00000800L
-#define FF1_DOOR 0x00001000L
-#define FF1_SUPPORT_LIGHT 0x00002000L
-#define FF1_CAN_CLIMB 0x00004000L
-#define FF1_TUNNELABLE 0x00008000L
-#define FF1_WEB 0x00010000L
-#define FF1_ATTR_MULTI 0x00020000L
-#define FF1_SUPPORT_GROWTH 0x00040000L
-
-/*** Dungeon type flags -- DG ***/
-#define DF1_PRINCIPAL 0x00000001L /* Is a principal dungeon */
-#define DF1_MAZE 0x00000002L /* Is a maze-type dungeon */
-#define DF1_SMALLEST 0x00000004L /* Creates VERY small levels like The Maze */
-#define DF1_SMALL 0x00000008L /* Creates small levels like Dol Goldor */
-#define DF1_BIG 0x00000010L /* Creates big levels like Moria, and Angband dungeons */
-#define DF1_NO_DOORS 0x00000020L /* No doors on rooms, like Barrowdowns, Old Forest etc) */
-#define DF1_WATER_RIVER 0x00000040L /* Allow a single water streamer on a level */
-#define DF1_LAVA_RIVER 0x00000080L /* Allow a single lava streamer on a level */
-#define DF1_WATER_RIVERS 0x00000100L /* Allow multiple water streamers on a level */
-#define DF1_LAVA_RIVERS 0x00000200L /* Allow multiple lava streamers on a level */
-#define DF1_CAVE 0x00000400L /* Allow rooms */
-#define DF1_CAVERN 0x00000800L /* Allow cavern rooms */
-#define DF1_NO_UP 0x00001000L /* Disallow up stairs */
-#define DF1_HOT 0x00002000L /* Corpses on ground and in pack decay quicker through heat */
-#define DF1_COLD 0x00004000L /* Corpses on ground and in pack decay quicker through cold */
-#define DF1_FORCE_DOWN 0x00008000L /* No up stairs generated */
-#define DF1_FORGET 0x00010000L /* Features are forgotten, like the Maze and Illusory Castle */
-#define DF1_NO_DESTROY 0x00020000L /* No destroyed levels in dungeon */
-#define DF1_SAND_VEIN 0x00040000L /* Like in the sandworm lair */
-#define DF1_CIRCULAR_ROOMS 0x00080000L /* Allow circular rooms */
-#define DF1_EMPTY 0x00100000L /* Allow arena levels */
-#define DF1_DAMAGE_FEAT 0x00200000L
-#define DF1_FLAT 0x00400000L /* Creates paths to next areas at edge of level, like Barrowdowns */
-#define DF1_TOWER 0x00800000L /* You start at bottom and go up rather than the reverse */
-#define DF1_RANDOM_TOWNS 0x01000000L /* Allow random towns */
-#define DF1_DOUBLE 0x02000000L /* Creates double-walled dungeon like Helcaraxe and Erebor */
-#define DF1_LIFE_LEVEL 0x04000000L /* Creates dungeon level on modified 'game of life' algorithm */
-#define DF1_EVOLVE 0x08000000L /* Evolving, pulsing levels like Heart of the Earth */
-#define DF1_ADJUST_LEVEL_1 0x10000000L /* Minimum monster level will be equal to dungeon level */
-#define DF1_ADJUST_LEVEL_2 0x20000000L /* Minimum monster level will be double the dungeon level */
-#define DF1_NO_RECALL 0x40000000L /* No recall allowed */
-#define DF1_NO_STREAMERS 0x80000000L /* No streamers */
-
-#define DF2_ADJUST_LEVEL_1_2 0x00000001L /* Minimum monster level will be half the dungeon level */
-#define DF2_NO_SHAFT 0x00000002L /* No shafts */
-#define DF2_ADJUST_LEVEL_PLAYER 0x00000004L /* Uses player level*2 instead of dungeon level for other ADJUST_LEVEL flags */
-#define DF2_NO_TELEPORT 0x00000008L
-#define DF2_ASK_LEAVE 0x00000010L
-#define DF2_NO_STAIR 0x00000020L
-#define DF2_SPECIAL 0x00000040L
-#define DF2_NO_NEW_MONSTER 0x00000080L
-#define DF2_DESC 0x00000100L
-#define DF2_NO_GENO 0x00000200L
-#define DF2_NO_BREATH 0x00000400L /* Oups, cannot breath here */
-#define DF2_WATER_BREATH 0x00000800L /* Oups, cannot breath here, need water breathing */
-#define DF2_ELVEN 0x00001000L /* Try to create elven monster ego */
-#define DF2_DWARVEN 0x00002000L /* Try to create dwarven monster ego */
-#define DF2_NO_EASY_MOVE 0x00004000L /* Forbid stuff like teleport level, probability travel, ... */
-#define DF2_NO_RECALL_OUT 0x00008000L /* Cannot recall out of the place */
-#define DF2_DESC_ALWAYS 0x00010000L /* Always shows the desc */
-
/*** Town flags ***/
#define TOWN_REAL 0x01 /* Town is really present */
#define TOWN_KNOWN 0x02 /* Town is found by the player */
-/*** Monster blow constants ***/
-
-#define MODIFY_AUX(o, n) ((o) = modify_aux((o), (n) >> 2, (n) & 3))
-#define MODIFY(o, n, min) MODIFY_AUX(o, n); (o) = ((o) < (min))?(min):(o)
-
/*
* New monster blow methods
*/
@@ -3172,343 +2063,6 @@
/*** Monster flag values (hard-coded) ***/
#define MONSTER_LEVEL_MAX 150
-#define MONSTER_EXP(level) ((((level) > MONSTER_LEVEL_MAX)?MONSTER_LEVEL_MAX:(level)) * (((level) > MONSTER_LEVEL_MAX)?MONSTER_LEVEL_MAX:(level)) * (((level) > MONSTER_LEVEL_MAX)?MONSTER_LEVEL_MAX:(level)) * 6)
-
-/*
- * New monster race bit flags
- */
-#define RF1_UNIQUE 0x00000001 /* Unique Monster */
-#define RF1_QUESTOR 0x00000002 /* Quest Monster */
-#define RF1_MALE 0x00000004 /* Male gender */
-#define RF1_FEMALE 0x00000008 /* Female gender */
-#define RF1_CHAR_CLEAR 0x00000010 /* Absorbs symbol */
-#define RF1_CHAR_MULTI 0x00000020 /* Changes symbol */
-#define RF1_ATTR_CLEAR 0x00000040 /* Absorbs color */
-#define RF1_ATTR_MULTI 0x00000080 /* Changes color */
-#define RF1_FORCE_DEPTH 0x00000100 /* Start at "correct" depth */
-#define RF1_FORCE_MAXHP 0x00000200 /* Start with max hitpoints */
-#define RF1_FORCE_SLEEP 0x00000400 /* Start out sleeping */
-#define RF1_FORCE_EXTRA 0x00000800 /* Start out something */
-#define RF1_FRIEND 0x00001000 /* Arrive with a friend */
-#define RF1_FRIENDS 0x00002000 /* Arrive with some friends */
-#define RF1_ESCORT 0x00004000 /* Arrive with an escort */
-#define RF1_ESCORTS 0x00008000 /* Arrive with some escorts */
-#define RF1_NEVER_BLOW 0x00010000 /* Never make physical blow */
-#define RF1_NEVER_MOVE 0x00020000 /* Never make physical move */
-#define RF1_RAND_25 0x00040000 /* Moves randomly (25%) */
-#define RF1_RAND_50 0x00080000 /* Moves randomly (50%) */
-#define RF1_ONLY_GOLD 0x00100000 /* Drop only gold */
-#define RF1_ONLY_ITEM 0x00200000 /* Drop only items */
-#define RF1_DROP_60 0x00400000 /* Drop an item/gold (60%) */
-#define RF1_DROP_90 0x00800000 /* Drop an item/gold (90%) */
-#define RF1_DROP_1D2 0x01000000 /* Drop 1d2 items/gold */
-#define RF1_DROP_2D2 0x02000000 /* Drop 2d2 items/gold */
-#define RF1_DROP_3D2 0x04000000 /* Drop 3d2 items/gold */
-#define RF1_DROP_4D2 0x08000000 /* Drop 4d2 items/gold */
-#define RF1_DROP_GOOD 0x10000000 /* Drop good items */
-#define RF1_DROP_GREAT 0x20000000 /* Drop great items */
-#define RF1_DROP_USEFUL 0x40000000 /* Drop "useful" items */
-#define RF1_DROP_CHOSEN 0x80000000 /* Drop "chosen" items */
-
-/*
- * New monster race bit flags
- */
-#define RF2_STUPID 0x00000001 /* Monster is stupid */
-#define RF2_SMART 0x00000002 /* Monster is smart */
-#define RF2_CAN_SPEAK 0x00000004 /* TY: can speak */
-#define RF2_REFLECTING 0x00000008 /* Reflects bolts */
-#define RF2_INVISIBLE 0x00000010 /* Monster avoids vision */
-#define RF2_COLD_BLOOD 0x00000020 /* Monster avoids infra */
-#define RF2_EMPTY_MIND 0x00000040 /* Monster avoids telepathy */
-#define RF2_WEIRD_MIND 0x00000080 /* Monster avoids telepathy? */
-#define RF2_DEATH_ORB 0x00000100 /* Death Orb */
-#define RF2_REGENERATE 0x00000200 /* Monster regenerates */
-#define RF2_SHAPECHANGER 0x00000400 /* TY: shapechanger */
-#define RF2_ATTR_ANY 0x00000800 /* TY: Attr_any */
-#define RF2_POWERFUL 0x00001000 /* Monster has strong breath */
-#define RF2_ELDRITCH_HORROR 0x00002000 /* Sanity-blasting horror */
-#define RF2_AURA_FIRE 0x00004000 /* Burns in melee */
-#define RF2_AURA_ELEC 0x00008000 /* Shocks in melee */
-#define RF2_OPEN_DOOR 0x00010000 /* Monster can open doors */
-#define RF2_BASH_DOOR 0x00020000 /* Monster can bash doors */
-#define RF2_PASS_WALL 0x00040000 /* Monster can pass walls */
-#define RF2_KILL_WALL 0x00080000 /* Monster can destroy walls */
-#define RF2_MOVE_BODY 0x00100000 /* Monster can move monsters */
-#define RF2_KILL_BODY 0x00200000 /* Monster can kill monsters */
-#define RF2_TAKE_ITEM 0x00400000 /* Monster can pick up items */
-#define RF2_KILL_ITEM 0x00800000 /* Monster can crush items */
-#define RF2_BRAIN_1 0x01000000
-#define RF2_BRAIN_2 0x02000000
-#define RF2_BRAIN_3 0x04000000
-#define RF2_BRAIN_4 0x08000000
-#define RF2_BRAIN_5 0x10000000
-#define RF2_BRAIN_6 0x20000000
-#define RF2_BRAIN_7 0x40000000
-#define RF2_BRAIN_8 0x80000000
-
-/*
- * New monster race bit flags
- */
-#define RF3_ORC 0x00000001 /* Orc */
-#define RF3_TROLL 0x00000002 /* Troll */
-#define RF3_GIANT 0x00000004 /* Giant */
-#define RF3_DRAGON 0x00000008 /* Dragon */
-#define RF3_DEMON 0x00000010 /* Demon */
-#define RF3_UNDEAD 0x00000020 /* Undead */
-#define RF3_EVIL 0x00000040 /* Evil */
-#define RF3_ANIMAL 0x00000080 /* Animal */
-#define RF3_THUNDERLORD 0x00000100 /* DG: Thunderlord */
-#define RF3_GOOD 0x00000200 /* Good */
-#define RF3_AURA_COLD 0x00000400 /* Freezes in melee */
-#define RF3_NONLIVING 0x00000800 /* TY: Non-Living (?) */
-#define RF3_HURT_LITE 0x00001000 /* Hurt by lite */
-#define RF3_HURT_ROCK 0x00002000 /* Hurt by rock remover */
-#define RF3_SUSCEP_FIRE 0x00004000 /* Hurt badly by fire */
-#define RF3_SUSCEP_COLD 0x00008000 /* Hurt badly by cold */
-#define RF3_IM_ACID 0x00010000 /* Resist acid a lot */
-#define RF3_IM_ELEC 0x00020000 /* Resist elec a lot */
-#define RF3_IM_FIRE 0x00040000 /* Resist fire a lot */
-#define RF3_IM_COLD 0x00080000 /* Resist cold a lot */
-#define RF3_IM_POIS 0x00100000 /* Resist poison a lot */
-#define RF3_RES_TELE 0x00200000 /* Resist teleportation */
-#define RF3_RES_NETH 0x00400000 /* Resist nether a lot */
-#define RF3_RES_WATE 0x00800000 /* Resist water */
-#define RF3_RES_PLAS 0x01000000 /* Resist plasma */
-#define RF3_RES_NEXU 0x02000000 /* Resist nexus */
-#define RF3_RES_DISE 0x04000000 /* Resist disenchantment */
-#define RF3_UNIQUE_4 0x08000000 /* Is a "Nazgul" unique */
-#define RF3_NO_FEAR 0x10000000 /* Cannot be scared */
-#define RF3_NO_STUN 0x20000000 /* Cannot be stunned */
-#define RF3_NO_CONF 0x40000000 /* Cannot be confused */
-#define RF3_NO_SLEEP 0x80000000 /* Cannot be slept */
-
-/*
- * New monster race bit flags
- */
-#define RF4_SHRIEK 0x00000001 /* Shriek for help */
-#define RF4_MULTIPLY 0x00000002 /* Monster reproduces */
-#define RF4_S_ANIMAL 0x00000004 /* Summon animals */
-#define RF4_ROCKET 0x00000008 /* TY: Rocket */
-#define RF4_ARROW_1 0x00000010 /* Fire an arrow (light) */
-#define RF4_ARROW_2 0x00000020 /* Fire an arrow (heavy) */
-#define RF4_ARROW_3 0x00000040 /* Fire missiles (light) */
-#define RF4_ARROW_4 0x00000080 /* Fire missiles (heavy) */
-#define RF4_BR_ACID 0x00000100 /* Breathe Acid */
-#define RF4_BR_ELEC 0x00000200 /* Breathe Elec */
-#define RF4_BR_FIRE 0x00000400 /* Breathe Fire */
-#define RF4_BR_COLD 0x00000800 /* Breathe Cold */
-#define RF4_BR_POIS 0x00001000 /* Breathe Poison */
-#define RF4_BR_NETH 0x00002000 /* Breathe Nether */
-#define RF4_BR_LITE 0x00004000 /* Breathe Lite */
-#define RF4_BR_DARK 0x00008000 /* Breathe Dark */
-#define RF4_BR_CONF 0x00010000 /* Breathe Confusion */
-#define RF4_BR_SOUN 0x00020000 /* Breathe Sound */
-#define RF4_BR_CHAO 0x00040000 /* Breathe Chaos */
-#define RF4_BR_DISE 0x00080000 /* Breathe Disenchant */
-#define RF4_BR_NEXU 0x00100000 /* Breathe Nexus */
-#define RF4_BR_TIME 0x00200000 /* Breathe Time */
-#define RF4_BR_INER 0x00400000 /* Breathe Inertia */
-#define RF4_BR_GRAV 0x00800000 /* Breathe Gravity */
-#define RF4_BR_SHAR 0x01000000 /* Breathe Shards */
-#define RF4_BR_PLAS 0x02000000 /* Breathe Plasma */
-#define RF4_BR_WALL 0x04000000 /* Breathe Force */
-#define RF4_BR_MANA 0x08000000 /* Breathe Mana */
-#define RF4_BA_NUKE 0x10000000 /* TY: Nuke Ball */
-#define RF4_BR_NUKE 0x20000000 /* TY: Toxic Breath */
-#define RF4_BA_CHAO 0x40000000 /* Chaos Ball */
-#define RF4_BR_DISI 0x80000000 /* Breathe Disintegration */
-
-/*
- * New monster race bit flags
- */
-#define RF5_BA_ACID 0x00000001 /* Acid Ball */
-#define RF5_BA_ELEC 0x00000002 /* Elec Ball */
-#define RF5_BA_FIRE 0x00000004 /* Fire Ball */
-#define RF5_BA_COLD 0x00000008 /* Cold Ball */
-#define RF5_BA_POIS 0x00000010 /* Poison Ball */
-#define RF5_BA_NETH 0x00000020 /* Nether Ball */
-#define RF5_BA_WATE 0x00000040 /* Water Ball */
-#define RF5_BA_MANA 0x00000080 /* Mana Storm */
-#define RF5_BA_DARK 0x00000100 /* Darkness Storm */
-#define RF5_DRAIN_MANA 0x00000200 /* Drain Mana */
-#define RF5_MIND_BLAST 0x00000400 /* Blast Mind */
-#define RF5_BRAIN_SMASH 0x00000800 /* Smash Brain */
-#define RF5_CAUSE_1 0x00001000 /* Cause Light Wound */
-#define RF5_CAUSE_2 0x00002000 /* Cause Serious Wound */
-#define RF5_CAUSE_3 0x00004000 /* Cause Critical Wound */
-#define RF5_CAUSE_4 0x00008000 /* Cause Mortal Wound */
-#define RF5_BO_ACID 0x00010000 /* Acid Bolt */
-#define RF5_BO_ELEC 0x00020000 /* Elec Bolt (unused) */
-#define RF5_BO_FIRE 0x00040000 /* Fire Bolt */
-#define RF5_BO_COLD 0x00080000 /* Cold Bolt */
-#define RF5_BO_POIS 0x00100000 /* Poison Bolt (unused) */
-#define RF5_BO_NETH 0x00200000 /* Nether Bolt */
-#define RF5_BO_WATE 0x00400000 /* Water Bolt */
-#define RF5_BO_MANA 0x00800000 /* Mana Bolt */
-#define RF5_BO_PLAS 0x01000000 /* Plasma Bolt */
-#define RF5_BO_ICEE 0x02000000 /* Ice Bolt */
-#define RF5_MISSILE 0x04000000 /* Magic Missile */
-#define RF5_SCARE 0x08000000 /* Frighten Player */
-#define RF5_BLIND 0x10000000 /* Blind Player */
-#define RF5_CONF 0x20000000 /* Confuse Player */
-#define RF5_SLOW 0x40000000 /* Slow Player */
-#define RF5_HOLD 0x80000000 /* Paralyze Player */
-
-/*
- * New monster race bit flags
- */
-#define RF6_HASTE 0x00000001 /* Speed self */
-#define RF6_HAND_DOOM 0x00000002 /* Hand of Doom */
-#define RF6_HEAL 0x00000004 /* Heal self */
-#define RF6_S_ANIMALS 0x00000008 /* Summon animals */
-#define RF6_BLINK 0x00000010 /* Teleport Short */
-#define RF6_TPORT 0x00000020 /* Teleport Long */
-#define RF6_TELE_TO 0x00000040 /* Move player to monster */
-#define RF6_TELE_AWAY 0x00000080 /* Move player far away */
-#define RF6_TELE_LEVEL 0x00000100 /* Move player vertically */
-#define RF6_DARKNESS 0x00000200 /* Create Darkness */
-#define RF6_TRAPS 0x00000400 /* Create Traps */
-#define RF6_FORGET 0x00000800 /* Cause amnesia */
-#define RF6_RAISE_DEAD 0x00001000 /* Raise Dead */
-#define RF6_S_BUG 0x00002000 /* Summon Software bug */
-#define RF6_S_RNG 0x00004000 /* Summon RNG */
-#define RF6_S_THUNDERLORD 0x00008000 /* Summon Thunderlords */
-#define RF6_S_KIN 0x00010000 /* Summon "kin" */
-#define RF6_S_HI_DEMON 0x00020000 /* Summon greater demons! */
-#define RF6_S_MONSTER 0x00040000 /* Summon Monster */
-#define RF6_S_MONSTERS 0x00080000 /* Summon Monsters */
-#define RF6_S_ANT 0x00100000 /* Summon Ants */
-#define RF6_S_SPIDER 0x00200000 /* Summon Spiders */
-#define RF6_S_HOUND 0x00400000 /* Summon Hounds */
-#define RF6_S_HYDRA 0x00800000 /* Summon Hydras */
-#define RF6_S_ANGEL 0x01000000 /* Summon Angel */
-#define RF6_S_DEMON 0x02000000 /* Summon Demon */
-#define RF6_S_UNDEAD 0x04000000 /* Summon Undead */
-#define RF6_S_DRAGON 0x08000000 /* Summon Dragon */
-#define RF6_S_HI_UNDEAD 0x10000000 /* Summon Greater Undead */
-#define RF6_S_HI_DRAGON 0x20000000 /* Summon Ancient Dragon */
-#define RF6_S_WRAITH 0x40000000 /* Summon Unique Wraith */
-#define RF6_S_UNIQUE 0x80000000 /* Summon Unique Monster */
-
-/*
- * New monster race bit flags
- */
-#define RF7_AQUATIC 0x00000001 /* Aquatic monster */
-#define RF7_CAN_SWIM 0x00000002 /* Monster can swim */
-#define RF7_CAN_FLY 0x00000004 /* Monster can fly */
-#define RF7_FRIENDLY 0x00000008 /* Monster is friendly */
-#define RF7_PET 0x00000010 /* Monster is a pet */
-#define RF7_MORTAL 0x00000020 /* Monster is a mortal being */
-#define RF7_SPIDER 0x00000040 /* Monster is a spider (can pass webs) */
-#define RF7_NAZGUL 0x00000080 /* Monster is a Nazgul */
-#define RF7_DG_CURSE 0x00000100 /* If killed the monster grant a DG Curse to the player */
-#define RF7_POSSESSOR 0x00000200 /* Is it a dreaded possessor monster ? */
-#define RF7_NO_DEATH 0x00000400 /* Cannot be killed */
-#define RF7_NO_TARGET 0x00000800 /* Cannot be targeted */
-#define RF7_AI_ANNOY 0x00001000 /* Try to tease the player */
-#define RF7_AI_SPECIAL 0x00002000 /* For quests */
-#define RF7_NEUTRAL 0x00004000 /* Monster is neutral */
-#define RF7_DROP_ART 0x00008000 /* Monster drop one art */
-#define RF7_DROP_RANDART 0x00010000 /* Monster drop one randart */
-#define RF7_AI_PLAYER 0x00020000 /* Controlled by the player */
-#define RF7_NO_THEFT 0x00040000 /* Monster is immune to theft */
-#define RF7_SPIRIT 0x00080000 /* This is a Spirit, coming from the Void */
-#define RF7_IM_MELEE 0x00100000 /* IM melee */
-
-
-/*
- * Monster race flags
- */
-#define RF8_DUNGEON 0x00000001
-#define RF8_WILD_TOWN 0x00000002
-#define RF8_XXX8X02 0x00000004
-#define RF8_WILD_SHORE 0x00000008
-#define RF8_WILD_OCEAN 0x00000010
-#define RF8_WILD_WASTE 0x00000020
-#define RF8_WILD_WOOD 0x00000040
-#define RF8_WILD_VOLCANO 0x00000080
-#define RF8_XXX8X08 0x00000100
-#define RF8_WILD_MOUNTAIN 0x00000200
-#define RF8_WILD_GRASS 0x00000400
-#define RF8_NO_CUT 0x00000800
-#define RF8_CTHANGBAND 0x00001000 /* Not used in ToME */
-/* XXX */
-#define RF8_ZANGBAND 0x00004000 /* Not used in ToME */
-#define RF8_JOKEANGBAND 0x00008000
-#define RF8_ANGBAND 0x00010000
-
-#define RF8_WILD_TOO 0x80000000
-
-
-/*
- * Monster race flags
- */
-#define RF9_DROP_CORPSE 0x00000001
-#define RF9_DROP_SKELETON 0x00000002
-#define RF9_HAS_LITE 0x00000004 /* Carries a lite */
-#define RF9_MIMIC 0x00000008 /* *REALLY* looks like an object ... only nastier */
-#define RF9_HAS_EGG 0x00000010 /* Can be monster's eggs */
-#define RF9_IMPRESED 0x00000020 /* The monster can follow you on each level until he dies */
-#define RF9_SUSCEP_ACID 0x00000040 /* Susceptible to acid */
-#define RF9_SUSCEP_ELEC 0x00000080 /* Susceptible to lightning */
-#define RF9_SUSCEP_POIS 0x00000100 /* Susceptible to poison */
-#define RF9_KILL_TREES 0x00000200 /* Monster can eat trees */
-#define RF9_WYRM_PROTECT 0x00000400 /* The monster is protected by great wyrms of power: They'll be summoned if it's killed */
-#define RF9_DOPPLEGANGER 0x00000800 /* The monster looks like you */
-#define RF9_ONLY_DEPTH 0x00001000 /* The monster can only be generated at the GIVEN depth */
-#define RF9_SPECIAL_GENE 0x00002000 /* The monster can only be generated in special conditions like quests, special dungeons, ... */
-#define RF9_NEVER_GENE 0x00004000 /* The monster cannot be normaly generated */
-
-
-/*
- * Hack -- choose "intelligent" spells when desperate
- */
-
-#define RF4_INT_MASK \
- (RF4_S_ANIMAL)
-
-#define RF5_INT_MASK \
- (RF5_HOLD | RF5_SLOW | RF5_CONF | RF5_BLIND | RF5_SCARE)
-
-#define RF6_INT_MASK \
- (RF6_BLINK | RF6_TPORT | RF6_TELE_LEVEL | RF6_TELE_AWAY | \
- RF6_HEAL | RF6_HASTE | RF6_TRAPS | \
- RF6_S_KIN | RF6_S_HI_DEMON | RF6_S_MONSTER | RF6_S_MONSTERS | \
- RF6_S_ANT | RF6_S_SPIDER | RF6_S_HOUND | RF6_S_HYDRA | \
- RF6_S_ANGEL | RF6_S_DRAGON | RF6_S_UNDEAD | RF6_S_DEMON | \
- RF6_S_HI_DRAGON | RF6_S_HI_UNDEAD | RF6_S_WRAITH | RF6_S_UNIQUE | \
- RF6_S_THUNDERLORD | RF6_S_BUG | RF6_S_RNG | RF6_S_ANIMALS)
-
-
-/*
- * Hack -- "bolt" spells that may hurt fellow monsters
- */
-#define RF4_BOLT_MASK \
- (RF4_ARROW_1 | RF4_ARROW_2 | RF4_ARROW_3 | RF4_ARROW_4)
-
-#define RF5_BOLT_MASK \
- (RF5_BO_ACID | RF5_BO_ELEC | RF5_BO_FIRE | RF5_BO_COLD | \
- RF5_BO_POIS | RF5_BO_NETH | RF5_BO_WATE | RF5_BO_MANA | \
- RF5_BO_PLAS | RF5_BO_ICEE | RF5_MISSILE)
-
-#define RF6_BOLT_MASK \
- 0L
-
-
-/* Hack -- summon spells */
-
-#define RF4_SUMMON_MASK \
- (RF4_S_ANIMAL)
-
-#define RF5_SUMMON_MASK \
- 0L
-
-#define RF6_SUMMON_MASK \
- (RF6_S_KIN | RF6_S_HI_DEMON | RF6_S_MONSTER | RF6_S_MONSTERS | RF6_S_ANT | \
- RF6_S_SPIDER | RF6_S_HOUND | RF6_S_HYDRA | RF6_S_ANGEL | RF6_S_DEMON | \
- RF6_S_UNDEAD | RF6_S_DRAGON | RF6_S_HI_UNDEAD | RF6_S_HI_DRAGON | \
- RF6_S_WRAITH | RF6_S_UNIQUE | RF6_S_THUNDERLORD | RF6_S_BUG | RF6_S_RNG | \
- RF6_S_ANIMALS)
/*** Macro Definitions ***/
@@ -3520,459 +2074,6 @@
#define term_screen (angband_term[0])
-/*
- * Determine if a given inventory item is "aware"
- */
-#define object_aware_p(T) \
- (k_info[(T)->k_idx].aware)
-
-/*
- * Determine if a given inventory item is "tried"
- */
-#define object_tried_p(T) \
- (k_info[(T)->k_idx].tried)
-
-
-/*
- * Determine if a given inventory item is "known"
- * Test One -- Check for special "known" tag
- * Test Two -- Check for "Easy Know" + "Aware"
- */
-#define object_known_p(T) \
- (((T)->ident & (IDENT_KNOWN)) || \
- (k_info[(T)->k_idx].easy_know && k_info[(T)->k_idx].aware))
-
-
-/*
- * Return the "attr" for a given item.
- * Use "flavor" if available.
- * Default to user definitions.
- */
-#define object_attr(T) \
- (((T)->tval == TV_RANDART) ? \
- random_artifacts[(T)->sval].attr : \
- (k_info[(T)->k_idx].flavor) ? \
- misc_to_attr[k_info[(T)->k_idx].flavor] : \
- k_info[(T)->k_idx].x_attr)
-
-#define object_attr_default(T) \
- (((T)->tval == TV_RANDART) ? \
- random_artifacts[(T)->sval].attr : \
- (k_info[(T)->k_idx].flavor) ? \
- misc_to_attr[k_info[(T)->k_idx].flavor] : \
- k_info[(T)->k_idx].d_attr)
-
-/*
- * Return the "char" for a given item.
- * Use "flavor" if available.
- * Default to user definitions.
- */
-#define object_char(T) \
- ((k_info[(T)->k_idx].flavor) ? \
- misc_to_char[k_info[(T)->k_idx].flavor] : \
- k_info[(T)->k_idx].x_char)
-
-#define object_char_default(T) \
- ((k_info[(T)->k_idx].flavor) ? \
- misc_to_char[k_info[(T)->k_idx].flavor] : \
- k_info[(T)->k_idx].d_char)
-
-
-
-/*
- * Artifacts use the "name1" field
- */
-#define artifact_p(T) \
- ( \
- ((T)->tval == TV_RANDART || \
- ((T)->name1 ? TRUE : FALSE) || \
- ((T)->art_name ? TRUE : FALSE) || \
- ((k_info[(T)->k_idx].flags3 & TR3_NORM_ART)? TRUE : FALSE)) \
- )
-
-/*
- * Ego-Items use the "name2" field
- */
-#define ego_item_p(T) \
- ((T)->name2 || (T)->name2b ? TRUE : FALSE)
-
-/*
- * Ego-Items use the "name2" field
- */
-#define is_ego_p(T, e) \
- (((T)->name2 == (e)) || ((T)->name2b == (e)))
-
-
-
-/*
- * Cursed items.
- */
-#define cursed_p(T) \
- ((T)->ident & (IDENT_CURSED))
-
-
-/*
- * Convert an "attr"/"char" pair into a "pict" (P)
- */
-#define PICT(A,C) \
- ((((u16b)(A)) << 8) | ((byte)(C)))
-
-/*
- * Convert a "pict" (P) into an "attr" (A)
- */
-#define PICT_A(P) \
- ((byte)((P) >> 8))
-
-/*
- * Convert a "pict" (P) into an "char" (C)
- */
-#define PICT_C(P) \
- ((char)((byte)(P)))
-
-
-/*
- * Convert a "location" (Y,X) into a "grid" (G)
- */
-#define GRID(Y,X) \
- (256 * (Y) + (X))
-
-/*
- * Convert a "grid" (G) into a "location" (Y)
- */
-#define GRID_Y(G) \
- ((int)((G) / 256U))
-
-/*
- * Convert a "grid" (G) into a "location" (X)
- */
-#define GRID_X(G) \
- ((int)((G) % 256U))
-
-
-/*
- * Determines if a map location is fully inside the outer walls
- */
-#define in_bounds(Y,X) \
- (((Y) > 0) && ((X) > 0) && ((Y) < cur_hgt-1) && ((X) < cur_wid-1))
-
-/*
- * Determines if a map location is on or inside the outer walls
- */
-#define in_bounds2(Y,X) \
- (((Y) >= 0) && ((X) >= 0) && ((Y) < cur_hgt) && ((X) < cur_wid))
-
-
-/*
- * Determines if a map location is currently "on screen" -RAK-
- * Note that "panel_contains(Y,X)" always implies "in_bounds2(Y,X)".
- */
-#define panel_contains(Y,X) \
- (((Y) >= panel_row_min) && ((Y) <= panel_row_max) && \
- ((X) >= panel_col_min) && ((X) <= panel_col_max))
-
-
-
-/*
- * Determine if a "legal" grid is a "floor" grid
- *
- * Line 1 -- forbid doors, rubble, seams, walls
- *
- * Note that the terrain features are split by a one bit test
- * into those features which block line of sight and those that
- * do not, allowing an extremely fast single bit check below.
- *
- * Add in the fact that some new terrain (water & lava) do NOT block sight
- * -KMW-
- */
-#define cave_floor_bold(Y,X) \
- ((f_info[cave[Y][X].feat].flags1 & FF1_FLOOR) && \
- (cave[Y][X].feat != FEAT_MON_TRAP))
-
-
-/*
- * Determine if a "legal" grid is floor without the REMEMBER flag set
- * Sometimes called "boring" grid
- */
-#define cave_plain_floor_bold(Y,X) \
- ((f_info[cave[Y][X].feat].flags1 & FF1_FLOOR) && \
- !(f_info[cave[Y][X].feat].flags1 & FF1_REMEMBER))
-
-
-/*
- * Determine if a "legal" grid isn't a "blocking line of sight" grid
- *
- * Line 1 -- forbid doors, rubble, seams, walls
- *
- * Note that the terrain features are split by a one bit test
- * into those features which block line of sight and those that
- * do not, allowing an extremely fast single bit check below.
- *
- * Add in the fact that some new terrain (water & lava) do NOT block sight
- * -KMW-
- */
-#define cave_sight_bold(Y,X) \
- (!(f_info[cave[Y][X].feat].flags1 & FF1_NO_VISION))
-
-
-/*
- * Determine if a "legal" grid is a "clean" floor grid
- *
- * Line 1 -- forbid non-floors
- * Line 2 -- forbid deep water -KMW-
- * Line 3 -- forbid deep lava -KMW-
- * Line 4 -- forbid normal objects
- */
-#define cave_clean_bold(Y,X) \
- ((f_info[cave[Y][X].feat].flags1 & FF1_FLOOR) && \
- (cave[Y][X].feat != FEAT_MON_TRAP) && \
- (cave[Y][X].o_idx == 0) && \
- !(f_info[cave[Y][X].feat].flags1 & FF1_PERMANENT))
-
-
-/*
- * Determine if a "legal" grid is an "empty" floor grid
- *
- * Line 1 -- forbid doors, rubble, seams, walls
- * Line 2 -- forbid normal monsters
- * Line 3 -- forbid the player
- */
-#define cave_empty_bold(Y,X) \
- (cave_floor_bold(Y,X) && \
- !(cave[Y][X].m_idx) && \
- !(((Y) == p_ptr->py) && ((X) == p_ptr->px)))
-
-
-/*
- * Determine if a "legal" grid is an "naked" floor grid
- *
- * Line 1 -- forbid non-floors, non-shallow water & lava -KMW-
- * Line 2 -- forbid normal objects
- * Line 3 -- forbid player/monsters
- */
-#define cave_naked_bold(Y,X) \
- ((f_info[cave[Y][X].feat].flags1 & FF1_FLOOR) && \
- (cave[Y][X].feat != FEAT_MON_TRAP) && \
- !(f_info[cave[Y][X].feat].flags1 & FF1_PERMANENT) && \
- (cave[Y][X].o_idx == 0) && \
- (cave[Y][X].m_idx == 0))
-
-#define cave_naked_bold2(Y,X) \
- ((f_info[cave[Y][X].feat].flags1 & FF1_FLOOR) && \
- (cave[Y][X].feat != FEAT_MON_TRAP) && \
- (cave[Y][X].o_idx == 0) && \
- (cave[Y][X].m_idx == 0))
-
-
-
-/*
- * Determine if a "legal" grid is "permanent"
- *
- * Line 1 -- perma-walls
- * Line 2-3 -- stairs
- * Line 4-5 -- building doors -KMW-
- * Line 6-7 -- shop doors
- */
-#define cave_perma_bold(Y,X) \
- (f_info[cave[Y][X].feat].flags1 & FF1_PERMANENT)
-
-
-/*
- * Grid based version of "cave_floor_bold()"
- */
-#define cave_floor_grid(C) \
- ((f_info[(C)->feat].flags1 & FF1_FLOOR) && ((C)->feat != FEAT_MON_TRAP))
-
-
-/*
- * Grid based version of "cave_plain_floor_bold()"
- */
-#define cave_plain_floor_grid(C) \
- ((f_info[(C)->feat].flags1 & FF1_FLOOR) && \
- !(f_info[(C)->feat].flags1 & FF1_REMEMBER))
-
-
-/*
- * Grid based version of "cave_clean_bold()"
- */
-#define cave_clean_grid(C) \
- ((f_info[(C)->feat].flags1 & FF1_FLOOR) && ((C)->feat != FEAT_MON_TRAP) && \
- (!(C)->o_idx))
-
-/*
- * Grid based version of "cave_sight_bold()"
- */
-#define cave_sight_grid(C) \
- (!(f_info[(C)->feat].flags1 & FF1_NO_VISION))
-
-/*
- * Grid based version of "cave_empty_bold()"
- */
-#define cave_empty_grid(C) \
- (cave_floor_grid(C) && \
- !((C)->m_idx) && \
- !((C) == &cave[p_ptr->py][p_ptr->px]))
-
-/*
- * Grid based version of "cave_empty_bold()"
- */
-#define cave_naked_grid(C) \
- ((f_info[(C)->feat].flags1 & FF1_FLOOR) && ((C)->feat != FEAT_MON_TRAP) && \
- !((C)->o_idx) && \
- !((C)->m_idx) && \
- !((C) == &cave[p_ptr->py][p_ptr->px]))
-
-
-/*
- * Grid based version of "cave_perma_bold()"
- */
-#define cave_perma_grid(C) \
- (f_info[(C)->feat].flags1 & FF1_PERMANENT)
-
-
-
-/*
- * Determine if a "legal" grid is within "los" of the player
- *
- * Note the use of comparison to zero to force a "boolean" result
- */
-#define player_has_los_bold(Y,X) \
- ((cave[Y][X].info & (CAVE_VIEW)) != 0)
-
-
-
-/*
- * Determine if a "legal" grid can be "seen" by the player
- *
- * Note the use of comparison to zero to force a "boolean" result
- */
-#define player_can_see_bold(Y,X) \
- ((cave[Y][X].info & (CAVE_SEEN)) != 0)
-
-
-
-/*** Color constants ***/
-
-
-/*
- * Angband "attributes" (with symbols, and base (R,G,B) codes)
- *
- * The "(R,G,B)" codes are given in "fourths" of the "maximal" value,
- * and should "gamma corrected" on most (non-Macintosh) machines.
- */
-#define TERM_DARK 0 /* 'd' */ /* 0,0,0 */
-#define TERM_WHITE 1 /* 'w' */ /* 4,4,4 */
-#define TERM_SLATE 2 /* 's' */ /* 2,2,2 */
-#define TERM_ORANGE 3 /* 'o' */ /* 4,2,0 */
-#define TERM_RED 4 /* 'r' */ /* 3,0,0 */
-#define TERM_GREEN 5 /* 'g' */ /* 0,2,1 */
-#define TERM_BLUE 6 /* 'b' */ /* 0,0,4 */
-#define TERM_UMBER 7 /* 'u' */ /* 2,1,0 */
-#define TERM_L_DARK 8 /* 'D' */ /* 1,1,1 */
-#define TERM_L_WHITE 9 /* 'W' */ /* 3,3,3 */
-#define TERM_VIOLET 10 /* 'v' */ /* 4,0,4 */
-#define TERM_YELLOW 11 /* 'y' */ /* 4,4,0 */
-#define TERM_L_RED 12 /* 'R' */ /* 4,0,0 */
-#define TERM_L_GREEN 13 /* 'G' */ /* 0,4,0 */
-#define TERM_L_BLUE 14 /* 'B' */ /* 0,4,4 */
-#define TERM_L_UMBER 15 /* 'U' */ /* 3,2,1 */
-
-
-/*** Graphics constants ***/
-
-/*
- * Possible values of graphics_mode
- * Good only when use_graphics is set to TRUE
- * Set by reset_visuals() and used by map_info()
- */
-#define GRAPHICS_NONE 0
-#define GRAPHICS_UNKNOWN 1
-#define GRAPHICS_IBM 2
-#define GRAPHICS_OLD 3
-#define GRAPHICS_NEW 4
-#define GRAPHICS_ISO 5
-
-
-/*** Sound constants ***/
-
-
-/*
- * Mega-Hack -- some primitive sound support (see "main-win.c")
- *
- * Some "sound" constants for "Term_xtra(TERM_XTRA_SOUND, val)"
- */
-#define SOUND_HIT 1
-#define SOUND_MISS 2
-#define SOUND_FLEE 3
-#define SOUND_DROP 4
-#define SOUND_KILL 5
-#define SOUND_LEVEL 6
-#define SOUND_DEATH 7
-#define SOUND_STUDY 8
-#define SOUND_TELEPORT 9
-#define SOUND_SHOOT 10
-#define SOUND_QUAFF 11
-#define SOUND_ZAP 12
-#define SOUND_WALK 13
-#define SOUND_TPOTHER 14
-#define SOUND_HITWALL 15
-#define SOUND_EAT 16
-#define SOUND_STORE1 17
-#define SOUND_STORE2 18
-#define SOUND_STORE3 19
-#define SOUND_STORE4 20
-#define SOUND_DIG 21
-#define SOUND_OPENDOOR 22
-#define SOUND_SHUTDOOR 23
-#define SOUND_TPLEVEL 24
-#define SOUND_SCROLL 25
-#define SOUND_BUY 26
-#define SOUND_SELL 27
-#define SOUND_WARN 28
-#define SOUND_ROCKET 29 /* Somebody's shooting rockets */
-#define SOUND_N_KILL 30 /* The player kills a non-living/undead monster */
-#define SOUND_U_KILL 31 /* The player kills a unique */
-#define SOUND_QUEST 32 /* The player has just completed a quest */
-#define SOUND_HEAL 33 /* The player was healed a little bit */
-#define SOUND_X_HEAL 34 /* The player was healed full health */
-#define SOUND_BITE 35 /* A monster bites you */
-#define SOUND_CLAW 36 /* A monster claws you */
-#define SOUND_M_SPELL 37 /* A monster casts a miscellaneous spell */
-#define SOUND_SUMMON 38 /* A monster casts a summoning spell */
-#define SOUND_BREATH 39 /* A monster breathes */
-#define SOUND_BALL 40 /* A monster casts a ball / bolt spell */
-#define SOUND_M_HEAL 41 /* A monster heals itself somehow */
-#define SOUND_ATK_SPELL 42 /* A monster casts a misc. offensive spell */
-#define SOUND_EVIL 43 /* Something nasty has just happened! */
-#define SOUND_TOUCH 44 /* A monster touches you */
-#define SOUND_STING 45 /* A monster stings you */
-#define SOUND_CRUSH 46 /* A monster crushes / envelopes you */
-#define SOUND_SLIME 47 /* A monster drools/spits/etc on you */
-#define SOUND_WAIL 48 /* A monster wails */
-#define SOUND_WINNER 49 /* Just won the game! */
-#define SOUND_FIRE 50 /* An item was burned */
-#define SOUND_ACID 51 /* An item was destroyed by acid */
-#define SOUND_ELEC 52 /* An item was destroyed by electricity */
-#define SOUND_COLD 53 /* An item was shattered */
-#define SOUND_ILLEGAL 54 /* Illegal command attempted */
-#define SOUND_FAIL 55 /* Fail to get a spell off / activate an item */
-#define SOUND_WAKEUP 56 /* A monster wakes up */
-#define SOUND_INVULN 57 /* Invulnerability! */
-#define SOUND_FALL 58 /* Falling through a trapdoor... */
-#define SOUND_PAIN 59 /* A monster is in pain! */
-#define SOUND_DESTITEM 60 /* An item was destroyed by misc. means */
-#define SOUND_MOAN 61 /* A monster makes a moan/beg/insult attack */
-#define SOUND_SHOW 62 /* A monster makes a "show" attack */
-#define SOUND_UNUSED 63 /* (no sound for gaze attacks) */
-#define SOUND_EXPLODE 64 /* Something (or somebody) explodes */
-
-/*
- * Mega-Hack -- maximum known sounds
- */
-#define SOUND_MAX 65
-
-
-
-/*** Hack ***/
/*
@@ -3990,55 +2091,38 @@
#define BACT_RESEARCH_ITEM 1
#define BACT_TOWN_HISTORY 2
#define BACT_RACE_LEGENDS 3
-#define BACT_GREET_KING 4
#define BACT_KING_LEGENDS 5
#define BACT_QUEST1 6
-#define BACT_POSTER 8
-#define BACT_ARENA_RULES 9
-#define BACT_ARENA 10
-#define BACT_ARENA_LEGENDS 11
#define BACT_IN_BETWEEN 12
#define BACT_GAMBLE_RULES 13
#define BACT_CRAPS 14
-#define BACT_SPIN_WHEEL 15
#define BACT_DICE_SLOTS 16
#define BACT_REST 17
#define BACT_FOOD 18
#define BACT_RUMORS 19
-#define BACT_RESEARCH_MONSTER 20
#define BACT_COMPARE_WEAPONS 21
-#define BACT_LEGENDS 22
#define BACT_ENCHANT_WEAPON 23
#define BACT_ENCHANT_ARMOR 24
#define BACT_RECHARGE 25
#define BACT_IDENTS 26
-#define BACT_LEARN 27
#define BACT_HEALING 28
#define BACT_RESTORE 29
#define BACT_ENCHANT_ARROWS 30
#define BACT_ENCHANT_BOW 31
-#define BACT_GREET 32
#define BACT_RECALL 33
#define BACT_TELEPORT_LEVEL 34
-/* XXX */
-/* XXX */
#define BACT_MIMIC_NORMAL 37
-#define BACT_VIEW_BOUNTIES 38
-#define BACT_SELL_CORPSES 39
-#define BACT_VIEW_QUEST_MON 40
-#define BACT_SELL_QUEST_MON 41
#define BACT_DIVINATION 42
#define BACT_SELL 43
#define BACT_BUY 44
#define BACT_EXAMINE 45
#define BACT_STEAL 46
-#define BACT_QUEST2 47
-#define BACT_QUEST3 48
-#define BACT_QUEST4 49
#define BACT_STAR_HEAL 50
-#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
+#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 */
@@ -4071,44 +2155,6 @@
#define INIT_POSITION 0x10
/*
- * Alchemists defines
- */
-#define MAX_ALCHEMIST_RECIPES 20
-#define ALCHEMIST_ENCHANT_DAM 0x01
-#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
*/
#define MAX_FATES 200
@@ -4122,19 +2168,6 @@
#define FATE_DIE 6
/*
- * Runes definition
- */
-#define RUNE_SELF 0x00000001
-#define RUNE_ARROW 0x00000002
-#define RUNE_RAY 0x00000004
-#define RUNE_SPHERE 0x00000008
-#define RUNE_POWER_SURGE 0x00000010
-#define RUNE_ARMAGEDDON 0x00000020
-#define RUNE_MOD_MAX 6
-#define RUNE_STONE 0x000000FF
-
-
-/*
* Defines of the different dungeon types
*/
#define DUNGEON_WILDERNESS 0
@@ -4166,7 +2199,7 @@
*/
#define level_or_feat(DTYPE, DLEVEL) \
((DTYPE) == DUNGEON_WILDERNESS ? \
- wild_map[p_ptr->wilderness_y][p_ptr->wilderness_x].feat : \
+ (game->wilderness)(p_ptr->wilderness_x, p_ptr->wilderness_y).feat : \
(DLEVEL) )
@@ -4191,13 +2224,7 @@
* Various class dependant defines
*/
#define CLASS_NONE 0
-#define CLASS_MANA_PATH 1
-#define CLASS_CANALIZE_MANA 2
-#define CLASS_WINDS_MANA 3
-#define CLASS_MANA_PATH_ERASE 0x0001
-#define CLASS_FLOOD_LEVEL 0x0002
-#define CLASS_CANALIZE_MANA_EXTRA 0x0004
#define CLASS_UNDEAD 0x0008
#define CLASS_ANTIMAGIC 0x0010
#define CLASS_LEGS 0x0020
@@ -4219,14 +2246,6 @@
#define NOTE_SAVE_GAME 3
#define NOTE_ENTER_DUNGEON 4
-/*
- * Player monsters & ghost defines
- * NO MORE USED but for savefile compatibility
- */
-#define GHOST_R_IDX_HEAD 967
-#define GHOST_R_IDX_TAIL 977
-#define MAX_GHOSTS (GHOST_R_IDX_TAIL - GHOST_R_IDX_HEAD)
-
/* Stores/buildings defines */
#define STORE_HATED 0
#define STORE_LIKED 1
@@ -4257,14 +2276,6 @@
#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))
-
-/* Object generation */
-#define OBJ_GENE_TREASURE 20
-#define OBJ_GENE_COMBAT 20
-#define OBJ_GENE_MAGIC 20
-#define OBJ_GENE_TOOL 20
-
/*
* Used (or should be) by various functions and tables needing access to
* single bits
@@ -4273,97 +2284,10 @@
/* Town defines */
#define TOWN_RANDOM 20 /* First random town */
-#define TOWN_DUNGEON 4 /* Maximun number of towns per dungeon */
#define TOWN_CHANCE 50 /* Chance of 1 town */
/*
- * Store flags
- */
-#define SF1_DEPEND_LEVEL 0x00000001L
-#define SF1_SHALLOW_LEVEL 0x00000002L
-#define SF1_MEDIUM_LEVEL 0x00000004L
-#define SF1_DEEP_LEVEL 0x00000008L
-#define SF1_RARE 0x00000010L
-#define SF1_VERY_RARE 0x00000020L
-#define SF1_COMMON 0x00000040L
-#define SF1_ALL_ITEM 0x00000080L /* Works as the BM */
-#define SF1_RANDOM 0x00000100L
-#define SF1_FORCE_LEVEL 0x00000200L
-#define SF1_MUSEUM 0x00000400L
-
-/*
- * Powers (mutation, activations, ...)
- */
-#define POWER_MAX_INIT 62
-
-#define PWR_SPIT_ACID 0
-#define PWR_BR_FIRE 1
-#define PWR_HYPN_GAZE 2
-#define PWR_TELEKINES 3
-#define PWR_VTELEPORT 4
-#define PWR_MIND_BLST 5
-#define PWR_RADIATION 6
-#define PWR_VAMPIRISM 7
-#define PWR_SMELL_MET 8
-#define PWR_SMELL_MON 9
-#define PWR_BLINK 10
-#define PWR_EAT_ROCK 11
-#define PWR_SWAP_POS 12
-#define PWR_SHRIEK 13
-#define PWR_ILLUMINE 14
-#define PWR_DET_CURSE 15
-#define PWR_BERSERK 16
-#define PWR_POLYMORPH 17
-#define PWR_MIDAS_TCH 18
-#define PWR_GROW_MOLD 19
-#define PWR_RESIST 20
-#define PWR_EARTHQUAKE 21
-#define PWR_EAT_MAGIC 22
-#define PWR_WEIGH_MAG 23
-#define PWR_STERILITY 24
-#define PWR_PANIC_HIT 25
-#define PWR_DAZZLE 26
-#define PWR_DARKRAY 27
-#define PWR_RECALL 28
-#define PWR_BANISH 29
-#define PWR_COLD_TOUCH 30
-#define PWR_LAUNCHER 31
-
-#define PWR_PASSWALL 32
-#define PWR_DETECT_TD 33
-#define PWR_COOK_FOOD 34
-#define PWR_UNFEAR 35
-#define PWR_EXPL_RUNE 36
-#define PWR_STM 37
-#define PWR_POIS_DART 38
-#define PWR_MAGIC_MISSILE 39
-#define PWR_GROW_TREE 40
-#define PWR_BR_COLD 41
-#define PWR_BR_CHAOS 42
-#define PWR_BR_ELEM 43
-#define PWR_WRECK_WORLD 44
-#define PWR_SCARE 45
-#define PWR_REST_LIFE 46
-#define PWR_SUMMON_MONSTER 47
-#define PWR_NECRO 48
-#define PWR_ROHAN 49
-#define PWR_THUNDER 50
-#define PWR_DEATHMOLD 51
-#define PWR_HYPNO 52
-#define PWR_UNHYPNO 53
-#define PWR_INCARNATE 54
-#define PWR_MAGIC_MAP 55
-#define PWR_LAY_TRAP 56
-#define PWR_MERCHANT 57
-#define PWR_COMPANION 58
-#define PWR_BEAR 59
-#define PWR_DODGE 60
-#define PWR_BALROG 61
-
-#define ADD_POWER(pow, p) ((pow)[(p)] = TRUE)
-
-/*
* Shield effect options
*/
#define SHIELD_NONE 0x0000
@@ -4406,7 +2330,11 @@
#define QUEST_DRAGONS 23
#define QUEST_HAUNTED 24
#define QUEST_EVIL 25
-#define MAX_Q_IDX_INIT 26
+#define QUEST_BOUNTY 26
+#define QUEST_FIREPROOF 27
+#define QUEST_LIBRARY 28
+#define QUEST_GOD 29
+#define MAX_Q_IDX 30
#define PLOT_MAIN 0
#define PLOT_BREE 1
@@ -4418,10 +2346,47 @@
#define MAX_PLOTS 7
/*
+ * Modules
+ */
+#define MODULE_TOME 0
+#define MODULE_THEME 1
+#define MAX_MODULES 2
+
+/*
+ * 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
*/
#define HOOK_MONSTER_DEATH 0
-#define HOOK_OPEN 1
#define HOOK_GEN_QUEST 2
#define HOOK_END_TURN 3
#define HOOK_FEELING 4
@@ -4442,84 +2407,29 @@
#define HOOK_MONSTER_AI 19
#define HOOK_PLAYER_LEVEL 20
#define HOOK_WIELD 21
-#define HOOK_INIT 22
-#define HOOK_QUAFF 23
+#define HOOK_NEW_MONSTER_END 22
#define HOOK_AIM 24
#define HOOK_USE 25
-#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
#define HOOK_MON_SPEAK 33
-#define HOOK_MKEY 34
#define HOOK_BIRTH_OBJECTS 35
-#define HOOK_ACTIVATE_DESC 36
-#define HOOK_INIT_GAME 37
-#define HOOK_ACTIVATE_POWER 38
-#define HOOK_ITEM_NAME 39
#define HOOK_SAVE_GAME 40
#define HOOK_LOAD_GAME 41
#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
#define HOOK_GEN_LEVEL_BEGIN 49
#define HOOK_GET 50
-#define HOOK_REDRAW 51
#define HOOK_RECALC_SKILLS 52
#define HOOK_ENTER_DUNGEON 53
-#define HOOK_FIRE 54
#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
-#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
-#define HOOK_BIRTH 68
-#define HOOK_CALC_LITE 69
-#define HOOK_LEARN_ABILITY 70
-#define HOOK_MOVED 71
+#define HOOK_MON_ASK_HELP 69
#define HOOK_GAME_START 72
-#define HOOK_TAKEOFF 73
-#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 HOOK_TYPE_C 0
-#define HOOK_TYPE_LUA 1
-
-/*
- * Defines for loadsave.c
- * Why 3 and 7? So if it's uninitialized, the code will be able to catch it, as
- * 0 is an invalid flag. Also, having them apart means that it being accidentally
- * modified will also result in an invalid value -- Improv
- */
-#define LS_LOAD 3
-#define LS_SAVE 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
/*
* Special weapon effects
@@ -4548,84 +2458,11 @@
#define SKILL_EXCLUSIVE 9999 /* Flag to tell exclusive skills */
-#define SKILL_CONVEYANCE 1
-#define SKILL_MANA 2
-#define SKILL_FIRE 3
-#define SKILL_AIR 4
-#define SKILL_WATER 5
-#define SKILL_NATURE 6
-#define SKILL_EARTH 7
-#define SKILL_SYMBIOTIC 8
-#define SKILL_MUSIC 9
-#define SKILL_DIVINATION 10
-#define SKILL_TEMPORAL 11
-#define SKILL_DRUID 12
-#define SKILL_DAEMON 13
-#define SKILL_META 14
-#define SKILL_MAGIC 15
-#define SKILL_COMBAT 16
-#define SKILL_MASTERY 17
-#define SKILL_SWORD 18
-#define SKILL_AXE 19
-#define SKILL_POLEARM 20
-#define SKILL_HAFTED 21
-#define SKILL_BACKSTAB 22
-#define SKILL_ARCHERY 23
-#define SKILL_SLING 24
-#define SKILL_BOW 25
-#define SKILL_XBOW 26
-#define SKILL_BOOMERANG 27
-#define SKILL_SPIRITUALITY 28
-#define SKILL_MINDCRAFT 29
-#define SKILL_MISC 30
-#define SKILL_NECROMANCY 31
-#define SKILL_MIMICRY 32
-#define SKILL_ANTIMAGIC 33
-#define SKILL_RUNECRAFT 34
-#define SKILL_SNEAK 35
-#define SKILL_STEALTH 36
-#define SKILL_DISARMING 37
-/* XXX */
-#define SKILL_ALCHEMY 39
-#define SKILL_STEALING 40
-#define SKILL_SORCERY 41
-#define SKILL_HAND 42
-#define SKILL_THAUMATURGY 43
-#define SKILL_SUMMON 44
-#define SKILL_SPELL 45
-#define SKILL_DODGE 46
-#define SKILL_BEAR 47
-#define SKILL_LORE 48
-#define SKILL_PRESERVATION 49
-#define SKILL_POSSESSION 50
-#define SKILL_MIND 51
-#define SKILL_CRITS 52
-#define SKILL_PRAY 53
-#define SKILL_LEARN 54
-#define SKILL_UDUN 55
-#define SKILL_DEVICE 56
-#define SKILL_STUN 57
-#define SKILL_BOULDER 58
-#define SKILL_GEOMANCY 59
-
-/* Ugly but needed */
-#define MAX_SKILLS 200
-
/* Number of skill choices for Lost Sword quests. */
#define LOST_SWORD_NSKILLS 4
-/* SKill flags */
-#define SKF1_HIDDEN 0x00000001 /* Starts hidden */
-#define SKF1_AUTO_HIDE 0x00000002 /* Tries to rehide at calc_bonus */
-#define SKF1_RANDOM_GAIN 0x00000004 /* Can be randomly gained by certain quests & such */
-
#define MAX_MELEE 3
-/*
- * Player specialities, should be external but ti would be a mess
- */
-#define MAX_SPEC 20
-
/*
* Spellbinder triggers
@@ -4644,11 +2481,11 @@
#define GOD_TULKAS 3
#define GOD_MELKOR 4
#define GOD_YAVANNA 5
-#define MAX_GODS_INIT 6
-
-#define GOD(g) if (p_ptr->pgod == (g))
-#define PRAY_GOD(g) if ((p_ptr->pgod == (g)) && (p_ptr->praying))
-#define NOT_PRAY_GOD(g) if ((p_ptr->pgod == (g)) && (!p_ptr->praying))
+#define GOD_AULE 6
+#define GOD_VARDA 7
+#define GOD_ULMO 8
+#define GOD_MANDOS 9
+#define MAX_GODS 10
/*
* Command numbers for do_cmd_cli().
@@ -4667,7 +2504,6 @@
#define CMD_DUMP_HTML -8186
#define CMD_MACRO -8185
#define CMD_QUEST -8184
-#define CMD_BLUNDER -8183
#define CMD_SHOW_ABILITY -8182
#define CLI_MAX 128
@@ -4689,7 +2525,62 @@
#define AB_MAX_BLOW2 4
#define AB_AMMO_CREATION 5
#define AB_DEATH_TOUCH 6
-#define AB_CREATE_ART 7
#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
+
+/**
+ * Macro to generate a memoizing named monster lookup function.
+ *
+ * This is meant as a stopgap measure until a better method
+ * can be implemented.
+ */
+#define GENERATE_MONSTER_LOOKUP_FN(fn, name) \
+ static int fn()\
+ {\
+ static int r_idx = -1;\
+ if (r_idx < 0)\
+ {\
+ r_idx = test_monster_name(name);\
+ assert(r_idx);\
+ }\
+ return r_idx;\
+ }
diff --git a/src/deity_type.hpp b/src/deity_type.hpp
new file mode 100644
index 00000000..0dcbb818
--- /dev/null
+++ b/src/deity_type.hpp
@@ -0,0 +1,11 @@
+#pragma once
+
+/**
+ * A structure for deity information.
+ */
+struct deity_type
+{
+ int modules[3]; /* terminated with -1 */
+ char const *name;
+ char desc[10][80];
+};
diff --git a/src/deity_type_fwd.hpp b/src/deity_type_fwd.hpp
new file mode 100644
index 00000000..492bf1fa
--- /dev/null
+++ b/src/deity_type_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct deity_type;
diff --git a/src/device_allocation.cc b/src/device_allocation.cc
new file mode 100644
index 00000000..ec2d208c
--- /dev/null
+++ b/src/device_allocation.cc
@@ -0,0 +1,20 @@
+#include "device_allocation.hpp"
+
+#include <cassert>
+
+static 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 *device_allocation_new(byte tval)
+{
+ device_allocation *d = new device_allocation;
+ device_allocation_init(d, tval);
+ return d;
+}
diff --git a/src/device_allocation.hpp b/src/device_allocation.hpp
new file mode 100644
index 00000000..28854eac
--- /dev/null
+++ b/src/device_allocation.hpp
@@ -0,0 +1,17 @@
+#pragma once
+
+#include "device_allocation_fwd.hpp"
+#include "range.hpp"
+
+/*
+ * Device allocation for skill
+ */
+struct device_allocation
+{
+ byte tval;
+ s32b rarity;
+ range_type base_level;
+ range_type max_level;
+};
+
+struct device_allocation *device_allocation_new(byte tval);
diff --git a/src/device_allocation_fwd.hpp b/src/device_allocation_fwd.hpp
new file mode 100644
index 00000000..70e53fca
--- /dev/null
+++ b/src/device_allocation_fwd.hpp
@@ -0,0 +1,8 @@
+#pragma once
+
+#include "h-basic.h"
+
+typedef struct device_allocation device_allocation;
+struct device_allocation;
+
+struct device_allocation *device_allocation_new(byte tval);
diff --git a/src/dice.cc b/src/dice.cc
new file mode 100644
index 00000000..187bae68
--- /dev/null
+++ b/src/dice.cc
@@ -0,0 +1,98 @@
+#include "dice.hpp"
+
+#include "z-rand.hpp"
+
+#include <cassert>
+
+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.hpp b/src/dice.hpp
new file mode 100644
index 00000000..40a49e37
--- /dev/null
+++ b/src/dice.hpp
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "dice_fwd.hpp"
+
+/**
+ * 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.hpp b/src/dice_fwd.hpp
new file mode 100644
index 00000000..72b3b5ca
--- /dev/null
+++ b/src/dice_fwd.hpp
@@ -0,0 +1,12 @@
+#pragma once
+
+#include "h-basic.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/dungeon.c b/src/dungeon.cc
index 6d732f00..f8671387 100644
--- a/src/dungeon.c
+++ b/src/dungeon.cc
@@ -1,7 +1,3 @@
-/* File: dungeon.c */
-
-/* Purpose: Angband game engine */
-
/*
* Copyright (c) 1989 James E. Wilson, Robert A. Koeneke
*
@@ -10,21 +6,98 @@
* included in all such copies.
*/
-#include "angband.h"
-#include "lua/lua.h"
-#include "tolua.h"
-extern lua_State* L;
+#include "dungeon.hpp"
+#include "dungeon.h"
+
+#include "birth.hpp"
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "cmd1.hpp"
+#include "cmd2.hpp"
+#include "cmd3.hpp"
+#include "cmd4.hpp"
+#include "cmd5.hpp"
+#include "cmd6.hpp"
+#include "cmd7.hpp"
+#include "corrupt.hpp"
+#include "dungeon_flag.hpp"
+#include "dungeon_info_type.hpp"
+#include "feature_flag.hpp"
+#include "feature_type.hpp"
+#include "files.h"
+#include "files.hpp"
+#include "game.hpp"
+#include "generate.hpp"
+#include "gen_evol.hpp"
+#include "gods.hpp"
+#include "help.hpp"
+#include "hooks.hpp"
+#include "init2.hpp"
+#include "levels.hpp"
+#include "loadsave.h"
+#include "loadsave.hpp"
+#include "lua_bind.hpp"
+#include "melee1.hpp"
+#include "melee2.hpp"
+#include "monster2.hpp"
+#include "monster3.hpp"
+#include "monster_race.hpp"
+#include "monster_race_flag.hpp"
+#include "monster_type.hpp"
+#include "modules.hpp"
+#include "notes.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_flag.hpp"
+#include "object_kind.hpp"
+#include "object_type.hpp"
+#include "options.hpp"
+#include "player_race.hpp"
+#include "player_race_flag.hpp"
+#include "player_race_mod.hpp"
+#include "player_spec.hpp"
+#include "player_type.hpp"
+#include "powers.hpp"
+#include "quest.hpp"
+#include "skills.hpp"
+#include "spell_type.hpp"
+#include "spells1.hpp"
+#include "spells2.hpp"
+#include "spells5.hpp"
+#include "squeltch.hpp"
+#include "stats.hpp"
+#include "store.hpp"
+#include "tables.hpp"
+#include "timer_type.hpp"
+#include "util.hpp"
+#include "util.h"
+#include "variable.h"
+#include "variable.hpp"
+#include "wild.hpp"
+#include "wilderness_map.hpp"
+#include "wilderness_type_info.hpp"
+#include "wizard2.hpp"
+#include "xtra1.hpp"
+#include "xtra2.hpp"
+#include "z-rand.hpp"
+
+#include <boost/filesystem.hpp>
+#include <cassert>
#define TY_CURSE_CHANCE 100
#define DG_CURSE_CHANCE 50
#define AUTO_CURSE_CHANCE 15
#define CHAINSWORD_NOISE 100
+/**
+ * Type of a "sense" function
+ */
+typedef byte (*sense_function_t)(object_type const *o_ptr);
/*
* Return a "feeling" (or NULL) about an item. Method 1 (Heavy).
*/
-byte value_check_aux1(object_type *o_ptr)
+static byte value_check_aux1(object_type const *o_ptr)
{
/* Artifacts */
if (artifact_p(o_ptr))
@@ -59,9 +132,11 @@ byte value_check_aux1(object_type *o_ptr)
return (SENSE_AVERAGE);
}
-byte value_check_aux1_magic(object_type *o_ptr)
+static byte value_check_aux1_magic(object_type const *o_ptr)
{
- object_kind *k_ptr = &k_info[o_ptr->k_idx];
+ auto const &k_info = game->edit_data.k_info;
+
+ auto k_ptr = &k_info[o_ptr->k_idx];
switch (o_ptr->tval)
@@ -126,7 +201,7 @@ byte value_check_aux1_magic(object_type *o_ptr)
/*
* Return a "feeling" (or NULL) about an item. Method 2 (Light).
*/
-byte value_check_aux2(object_type *o_ptr)
+static byte value_check_aux2(object_type const *o_ptr)
{
/* Cursed items (all of them) */
if (cursed_p(o_ptr)) return (SENSE_CURSED);
@@ -148,9 +223,11 @@ byte value_check_aux2(object_type *o_ptr)
}
-byte value_check_aux2_magic(object_type *o_ptr)
+static byte value_check_aux2_magic(object_type const *o_ptr)
{
- object_kind *k_ptr = &k_info[o_ptr->k_idx];
+ auto const &k_info = game->edit_data.k_info;
+
+ auto k_ptr = &k_info[o_ptr->k_idx];
switch (o_ptr->tval)
@@ -215,9 +292,9 @@ byte value_check_aux2_magic(object_type *o_ptr)
/*
* Can a player be resurrected?
*/
-static bool_ granted_resurrection(void)
+static bool_ granted_resurrection()
{
- PRAY_GOD(GOD_ERU)
+ if (praying_to(GOD_ERU))
{
if (p_ptr->grace > 100000)
{
@@ -228,9 +305,8 @@ static bool_ granted_resurrection(void)
return (FALSE);
}
-static byte select_sense(object_type *o_ptr)
+static sense_function_t select_sense(object_type *o_ptr, sense_function_t combat, sense_function_t magic)
{
- /* Valid "tval" codes */
switch (o_ptr->tval)
{
case TV_SHOT:
@@ -253,10 +329,8 @@ static byte select_sense(object_type *o_ptr)
case TV_HARD_ARMOR:
case TV_DRAG_ARMOR:
case TV_BOOMERANG:
- case TV_TRAPKIT:
{
- return 1;
- break;
+ return combat;
}
case TV_POTION:
@@ -267,22 +341,21 @@ static byte select_sense(object_type *o_ptr)
case TV_ROD:
case TV_ROD_MAIN:
{
- return 2;
- break;
+ return magic;
}
/* Dual use? */
case TV_DAEMON_BOOK:
{
- return 1;
- break;
+ return combat;
}
}
- return 0;
+
+ return nullptr;
}
/*
- * Sense the inventory
+ * Sense quality of specific list of objects.
*
* Combat items (weapons and armour) - Fast, weak if combat skill < 10, strong
* otherwise.
@@ -294,21 +367,8 @@ static byte select_sense(object_type *o_ptr)
* they learn one form of ID or another, and because most magic items are
* easy_know.
*/
-void sense_inventory(void)
+void sense_objects(std::vector<int> const &object_idxs)
{
- 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;
@@ -338,24 +398,21 @@ void sense_inventory(void)
*/
/* The combat skill affects weapon/armour pseudo-ID */
- combat_lev = get_skill(SKILL_COMBAT);
+ int combat_lev = get_skill(SKILL_COMBAT);
/* The magic skill affects magic item pseudo-ID */
- magic_lev = get_skill(SKILL_MAGIC);
+ int 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;
-
+ auto feel_combat = (combat_lev > 10) ? value_check_aux1 : value_check_aux2;
+ auto feel_magic = (magic_lev > 10) ? value_check_aux1_magic : value_check_aux2_magic;
/*** Sense everything ***/
/* Check everything */
- for (i = 0; i < INVEN_TOTAL; i++)
+ for (auto i : object_idxs)
{
- byte okay = 0;
-
- o_ptr = &p_ptr->inventory[i];
+ object_type *o_ptr = get_object(i);
/* Skip empty slots */
if (!o_ptr->k_idx) continue;
@@ -366,37 +423,39 @@ void sense_inventory(void)
/* 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;
+ /* Select appropriate sensing function, if any */
+ sense_function_t sense = select_sense(o_ptr, feel_combat, feel_magic);
- /* Check for a feeling */
- if (okay == 1)
+ /* Skip non-sensed items */
+ if (!sense)
{
- 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));
+ continue;
}
+ /* Check for a feeling */
+ byte feel = sense(o_ptr);
+
/* Skip non-feelings */
- if (feel == SENSE_NONE) continue;
+ if (feel == SENSE_NONE)
+ {
+ continue;
+ }
/* Get an object description */
+ char o_name[80];
object_desc(o_name, o_ptr, FALSE, 0);
- /* Message (equipment) */
- if (i >= INVEN_WIELD)
+ /* Messages */
+ if (i < 0) {
+ // We get a message from the floor handling code, so
+ // it would be overkill to have a message here too.
+ }
+ else 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...",
@@ -421,11 +480,25 @@ void sense_inventory(void)
squeltch_inventory();
}
+void sense_inventory()
+{
+ static std::vector<int> idxs;
+ // Initialize static vector if necessary
+ if (idxs.empty())
+ {
+ idxs.reserve(INVEN_TOTAL);
+ for (int i = 0; i < INVEN_TOTAL; i++)
+ {
+ idxs.push_back(i);
+ }
+ }
+ sense_objects(idxs);
+}
/*
* Go to any level (ripped off from wiz_jump)
*/
-static void pattern_teleport(void)
+static void pattern_teleport()
{
/* Ask for level */
if (get_check("Teleport level? "))
@@ -478,27 +551,27 @@ static void pattern_teleport(void)
/*
* Returns TRUE if we are on the Straight Road...
*/
-static bool_ pattern_effect(void)
+static bool_ pattern_effect()
{
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);
+ set_poisoned(0);
+ set_image(0);
+ set_stun(0);
+ set_cut(0);
+ set_blind(0);
+ set_afraid(0);
+ do_res_stat(A_STR, TRUE);
+ do_res_stat(A_INT, TRUE);
+ do_res_stat(A_WIS, TRUE);
+ do_res_stat(A_DEX, TRUE);
+ do_res_stat(A_CON, TRUE);
+ do_res_stat(A_CHR, TRUE);
+ restore_level();
+ 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.");
}
@@ -540,16 +613,14 @@ static bool_ pattern_effect(void)
*/
static void recharged_notice(object_type *o_ptr)
{
- char o_name[80];
-
- cptr s;
-
-
/* No inscription */
- if (!o_ptr->note) return;
+ if (o_ptr->inscription.empty())
+ {
+ return;
+ }
/* Find a '!' */
- s = strchr(quark_str(o_ptr->note), '!');
+ auto s = strchr(o_ptr->inscription.c_str(), '!');
/* Process notification request. */
while (s)
@@ -558,6 +629,7 @@ static void recharged_notice(object_type *o_ptr)
if (s[1] == '!')
{
/* Describe (briefly) */
+ char o_name[80];
object_desc(o_name, o_ptr, FALSE, 0);
/* Notify the player */
@@ -630,7 +702,7 @@ static void regenhp(int percent)
if (old_chp != p_ptr->chp)
{
/* Redraw */
- p_ptr->redraw |= (PR_HP);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
@@ -687,7 +759,7 @@ static void regenmana(int percent)
if (old_csp != p_ptr->csp)
{
/* Redraw */
- p_ptr->redraw |= (PR_MANA);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
@@ -704,8 +776,10 @@ static void regenmana(int percent)
*
* XXX XXX XXX Should probably be done during monster turns.
*/
-static void regen_monsters(void)
+static void regen_monsters()
{
+ auto const &r_info = game->edit_data.r_info;
+
int i, frac;
object_type *o_ptr = &p_ptr->inventory[INVEN_CARRY];
@@ -713,7 +787,7 @@ static void regen_monsters(void)
if (o_ptr->k_idx)
{
- monster_race *r_ptr = &r_info[o_ptr->pval];
+ auto r_ptr = &r_info[o_ptr->pval];
/* Allow regeneration (if needed) */
if (o_ptr->pval2 < o_ptr->pval3)
@@ -725,7 +799,7 @@ static void regen_monsters(void)
if (!frac) frac = 1;
/* Hack -- Some monsters regenerate quickly */
- if (r_ptr->flags2 & (RF2_REGENERATE)) frac *= 2;
+ if (r_ptr->flags & RF_REGENERATE) frac *= 2;
/* Hack -- Regenerate */
@@ -735,7 +809,7 @@ static void regen_monsters(void)
if (o_ptr->pval2 > o_ptr->pval3) o_ptr->pval2 = o_ptr->pval3;
/* Redraw (later) */
- p_ptr->redraw |= (PR_MH);
+ p_ptr->redraw |= (PR_FRAME);
}
}
@@ -744,7 +818,6 @@ static void regen_monsters(void)
{
/* 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;
@@ -762,8 +835,8 @@ static void regen_monsters(void)
if (!frac) frac = 1;
/* Hack -- Some monsters regenerate quickly */
- if (r_ptr->flags2 & (RF2_REGENERATE)) frac *= 2;
-
+ auto const r_ptr = m_ptr->race();
+ if (r_ptr->flags & RF_REGENERATE) frac *= 2;
/* Hack -- Regenerate */
m_ptr->hp += frac;
@@ -772,7 +845,7 @@ static void regen_monsters(void)
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);
+ if (health_who == i) p_ptr->redraw |= (PR_FRAME);
}
}
}
@@ -783,159 +856,19 @@ static void regen_monsters(void)
*
* Should belong to object1.c, renamed to object_decays() -- pelpel
*/
-bool_ decays(object_type *o_ptr)
+static 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);
+ auto const flags = object_flags(o_ptr);
+ return bool(flags & TR_DECAY);
}
static int process_lasting_spell(s16b music)
{
- int oldtop, use_mana;
-
- 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;
-}
-
-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);
+ spell_type *spell = spell_at(-music);
+ return spell_type_produce_effect_lasting(spell);
}
-
static void check_music()
{
int use_mana;
@@ -948,15 +881,14 @@ 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;
}
else
{
p_ptr->csp -= use_mana;
/* Redraw mana */
- p_ptr->redraw |= (PR_MANA);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
@@ -967,11 +899,13 @@ static void check_music()
/*
* Generate the feature effect
*/
-void apply_effect(int y, int x)
+static void apply_effect(int y, int x)
{
+ auto const &f_info = game->edit_data.f_info;
+
cave_type *c_ptr = &cave[y][x];
- feature_type *f_ptr = &f_info[c_ptr->feat];
+ auto f_ptr = &f_info[c_ptr->feat];
if (f_ptr->d_frequency[0] != 0)
@@ -1012,8 +946,273 @@ void apply_effect(int y, int x)
/* XXX XXX XXX */
-bool_ is_recall = FALSE;
+static 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();
+ 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()
+{
+ auto const &race_name = rp_ptr->title;
+ auto const &subrace_name = rmp_ptr->title;
+
+ if (p_ptr->pgod == 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 ((race_name == "Orc") ||
+ (race_name == "Troll") ||
+ (race_name == "Dragon") ||
+ (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);
+ }
+ }
+ }
+
+ if (p_ptr->pgod == GOD_ULMO)
+ {
+ if (grace_delay_trigger())
+ {
+ int i;
+ /* Ulmo likes the Edain (except Easterlings) */
+ if ((race_name == "Human") ||
+ (race_name == "Dunadan") ||
+ (race_name == "Druadan") ||
+ (race_name == "RohanKnight"))
+ {
+ inc_piety(GOD_ALL, 2);
+ }
+ else if ((race_name == "Easterling") ||
+ (race_name == "Demon") ||
+ (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);
+ }
+ }
+ }
+ }
+
+ if (p_ptr->pgod == GOD_AULE)
+ {
+ if (grace_delay_trigger())
+ {
+ int i;
+
+ /* Aule likes Dwarves and Dark Elves (Eol's
+ * influence here) */
+ if (!((race_name == "Dwarf") ||
+ (race_name == "Petty-dwarf") ||
+ (race_name == "Gnome") ||
+ (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.");
+ }
+ }
+ }
+ }
+ if (p_ptr->pgod == GOD_MANDOS)
+ {
+ if (grace_delay_trigger())
+ {
+ /* He loves astral beings */
+ if (subrace_name == "LostSoul")
+ {
+ inc_piety(GOD_ALL, 1);
+ }
+
+ /* He likes High Elves only, though, as races */
+ if (!(race_name == "High-Elf"))
+ {
+ inc_piety(GOD_ALL, -1);
+ }
+
+ /* Really hates vampires and demons */
+ if ((subrace_name == "Vampire") ||
+ (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
@@ -1021,9 +1220,12 @@ bool_ is_recall = FALSE;
* 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)
+static void process_world()
{
- timer_type *t_ptr;
+ auto const &d_info = game->edit_data.d_info;
+ auto const &r_info = game->edit_data.r_info;
+ auto const &f_info = game->edit_data.f_info;
+ auto &timers = game->timers;
int x, y, i, j;
@@ -1031,13 +1233,11 @@ static void process_world(void)
bool_ cave_no_regen = FALSE;
int upkeep_factor = 0;
- dungeon_info_type *d_ptr = &d_info[dungeon_type];
+ auto 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
@@ -1058,31 +1258,24 @@ 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();
+
+ /* 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)
+ /* Process timers */
+ for (auto &&timer: timers)
{
- if (!t_ptr->enabled) continue;
-
- t_ptr->countdown--;
- if (!t_ptr->countdown)
- {
- t_ptr->countdown = t_ptr->delay;
- call_lua(t_ptr->callback, "()", "");
- }
+ timer->count_down();
}
- /* Handle class special actions */
- gere_class_special();
-
/* Check the fate */
- if (fate_option && (p_ptr->lev > 10))
+ if (options->fate_option && (p_ptr->lev > 10))
{
/*
* WAS: == 666 against randint(50000).
@@ -1098,20 +1291,20 @@ static void process_world(void)
if (o_ptr->k_idx)
{
- monster_race *r_ptr = &r_info[o_ptr->pval];
+ auto 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));
+ symbiote_name(true).c_str());
carried_make_attack_normal(o_ptr->pval);
}
}
/*** Attempt timed autosave ***/
- if (autosave_t && autosave_freq)
+ if (options->autosave_t && options->autosave_freq)
{
- if ((turn % ((s32b)autosave_freq * 10)) == 0)
+ if ((turn % (static_cast<s32b>(options->autosave_freq) * 10)) == 0)
{
is_autosave = TRUE;
msg_print("Autosaving the game...");
@@ -1149,10 +1342,13 @@ static void process_world(void)
c_ptr = &cave[y][x];
/* Assume lit */
- c_ptr->info |= (CAVE_GLOW);
+ c_ptr->info |= CAVE_GLOW;
/* Hack -- Memorize lit grids if allowed */
- if (view_perma_grids) c_ptr->info |= (CAVE_MARK);
+ if (options->view_perma_grids)
+ {
+ c_ptr->info |= CAVE_MARK;
+ }
/* Hack -- Notice spot */
note_spot(y, x);
@@ -1198,122 +1394,17 @@ static void process_world(void)
}
}
- /* 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))
+ if (!(dungeon_flags & DF_NO_NEW_MONSTER))
{
- (void)alloc_monster(MAX_SIGHT + 5, FALSE);
+ alloc_monster(MAX_SIGHT + 5, FALSE);
}
}
@@ -1372,7 +1463,7 @@ static void process_world(void)
/* 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 &&
+ if (!p_ptr->ffall && !p_ptr->magical_breath &&
!p_ptr->water_breath &&
(cave[p_ptr->py][p_ptr->px].feat == FEAT_DEEP_WATER))
{
@@ -1399,16 +1490,16 @@ static void process_world(void)
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))
+ if ((p_ptr->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))
+ else if ((p_ptr->climb) && (f_info[feature].flags & FF_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))
+ else if (race_flags_p(PR_SEMI_WRAITH) && (!p_ptr->wraith_form) && (f_info[cave[p_ptr->py][p_ptr->px].feat].flags & FF_CAN_PASS))
{
int amt = 1 + ((p_ptr->lev) / 5);
@@ -1489,10 +1580,10 @@ static void process_world(void)
o_ptr = &p_ptr->inventory[INVEN_WIELD];
/* Examine the sword */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ auto const flags = object_flags(o_ptr);
/* Hitpoints multiplier consume a lot of food */
- if (o_ptr->k_idx && (f2 & (TR2_LIFE))) i += o_ptr->pval * 5;
+ if (o_ptr->k_idx && (flags & TR_LIFE)) i += o_ptr->pval * 5;
/* Slow digestion takes less food */
if (p_ptr->slow_digest) i -= 10;
@@ -1501,7 +1592,7 @@ static void process_world(void)
if (i < 1) i = 1;
/* Digest some food */
- (void)set_food(p_ptr->food - i);
+ set_food(p_ptr->food - i);
}
}
@@ -1509,7 +1600,7 @@ static void process_world(void)
else
{
/* Digest a lot of food */
- (void)set_food(p_ptr->food - 100);
+ set_food(p_ptr->food - 100);
}
/* Starve to death (slowly) */
@@ -1550,10 +1641,10 @@ static void process_world(void)
{
/* Message */
msg_print("You faint from the lack of food.");
- disturb(1, 0);
+ disturb();
/* Hack -- faint (bypass free action) */
- (void)set_paralyzed(p_ptr->paralyzed + 1 + rand_int(5));
+ set_paralyzed(1 + rand_int(5));
}
}
}
@@ -1573,8 +1664,8 @@ static void process_world(void)
}
- /* Searching or Resting */
- if (p_ptr->searching || resting)
+ /* Resting boosts regeneration */
+ if (resting)
{
regen_amount = regen_amount * 2;
}
@@ -1583,28 +1674,15 @@ static void process_world(void)
{
int upkeep_divider = 20;
- if (has_ability(AB_PERFECT_CASTING))
+ if (p_ptr->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 */
}
}
@@ -1615,15 +1693,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
{
@@ -1634,7 +1703,7 @@ static void process_world(void)
/* Eru piety incraese with time */
if (((turn % 100) == 0) && (!p_ptr->did_nothing) && (!p_ptr->wild_mode))
{
- NOT_PRAY_GOD(GOD_ERU)
+ if ((p_ptr->pgod == GOD_ERU) && !p_ptr->praying)
{
int inc = wisdom_scale(10);
@@ -1646,47 +1715,65 @@ static void process_world(void)
/* Most gods piety decrease with time */
if (((turn % 300) == 0) && (!p_ptr->did_nothing) && (!p_ptr->wild_mode) && (dun_level))
{
- GOD(GOD_MANWE)
+ if (p_ptr->pgod == GOD_MANWE)
{
int dec = 4 - wisdom_scale(3);
- PRAY_GOD(GOD_MANWE)
- dec++;
- if (PRACE_FLAG(PR1_ELF))
+ if (p_ptr->praying)
+ {
+ dec++;
+ }
+
+ if (race_flags_p(PR_ELF))
+ {
dec -= wisdom_scale(2);
- if (dec < 1) dec = 1;
+ }
+
+ dec = std::max(1, dec);
+
inc_piety(GOD_MANWE, -dec);
}
- GOD(GOD_MELKOR)
+
+ if (p_ptr->pgod == GOD_MELKOR)
{
int dec = 8 - wisdom_scale(6);
- PRAY_GOD(GOD_MELKOR)
- dec++;
- if (PRACE_FLAG(PR1_ELF))
+ if (p_ptr->praying)
+ {
+ dec++;
+ }
+
+ if (race_flags_p(PR_ELF))
+ {
dec += 5 - wisdom_scale(4);
- if (dec < 1) dec = 1;
+ }
+
+ dec = std::max(1, dec);
+
inc_piety(GOD_MELKOR, -dec);
}
- PRAY_GOD(GOD_TULKAS)
+
+ if (praying_to(GOD_TULKAS))
{
- int dec = 4 - wisdom_scale(3);
+ int dec = std::max(1, 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)
+ if (p_ptr->pgod == GOD_YAVANNA)
{
int dec = 5 - wisdom_scale(3);
/* Blech what an hideous hack */
- if (!strcmp(rp_ptr->title + rp_name, "Ent"))
+ if (!(rp_ptr->title == "Ent"))
+ {
dec -= wisdom_scale(2);
- if (dec < 1) dec = 1;
+ }
+
+ dec = std::max(1, dec);
inc_piety(GOD_YAVANNA, -dec);
}
}
@@ -1703,7 +1790,7 @@ static void process_world(void)
if (cave_no_regen) regen_amount = 0;
/* Being over grass allows Yavanna to regen you */
- PRAY_GOD(GOD_YAVANNA)
+ if (praying_to(GOD_YAVANNA))
{
if (cave[p_ptr->py][p_ptr->px].feat == FEAT_GRASS)
{
@@ -1745,32 +1832,32 @@ static void process_world(void)
/* Hack -- Hallucinating */
if (p_ptr->image)
{
- (void)set_image(p_ptr->image - 1);
+ set_image(p_ptr->image - 1);
}
/* Holy Aura */
if (p_ptr->holy)
{
- (void)set_holy(p_ptr->holy - 1);
+ set_holy(p_ptr->holy - 1);
}
/* Soul absorbtion */
if (p_ptr->absorb_soul)
{
- (void)set_absorb_soul(p_ptr->absorb_soul - 1);
+ 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);
+ int warning = (p_ptr->mhp * options->hitpoint_warn / 10);
/* Bypass invulnerability and wraithform */
p_ptr->chp--;
/* Display the hitpoints */
- p_ptr->redraw |= (PR_HP);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
@@ -1778,13 +1865,10 @@ static void process_world(void)
/* Dead player */
if (p_ptr->chp < 0)
{
- bool_ old_quick = quick_messages;
-
- /* Sound */
- sound(SOUND_DEATH);
+ bool_ old_quick = options->quick_messages;
/* Hack -- Note death */
- if (!last_words)
+ if (!options->last_words)
{
msg_print("You die.");
msg_print(NULL);
@@ -1793,14 +1877,16 @@ static void process_world(void)
{
char death_message[80];
- (void)get_rnd_line("death.txt", death_message);
+ 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, "(?)");
+ /* Note cause of death; hallucinating characters don't get to know. */
+ game->died_from = "being undead too long";
+ if (p_ptr->image)
+ {
+ game->died_from = "(?)";
+ }
/* No longer a winner */
total_winner = FALSE;
@@ -1811,12 +1897,12 @@ static void process_world(void)
/* Note death */
death = TRUE;
- quick_messages = FALSE;
+ options->quick_messages = FALSE;
if (get_check("Make a last screenshot? "))
{
do_cmd_html_dump();
}
- quick_messages = old_quick;
+ options->quick_messages = old_quick;
/* Dead */
return;
@@ -1826,9 +1912,10 @@ static void process_world(void)
if (p_ptr->chp < warning)
{
/* Hack -- bell on first notice */
- if (alert_hitpoint && (old_chp > warning)) bell();
-
- sound(SOUND_WARN);
+ if (old_chp > warning)
+ {
+ bell();
+ }
/* Message */
msg_print("*** LOW DEATHPOINT WARNING! ***");
@@ -1836,90 +1923,78 @@ static void process_world(void)
}
}
- /* 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);
+ set_strike(p_ptr->strike - 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ set_prob_travel(p_ptr->prob_travel - 1);
}
/* Timed Levitation */
if (p_ptr->tim_ffall)
{
- (void)set_tim_ffall(p_ptr->tim_ffall - 1);
+ set_tim_ffall(p_ptr->tim_ffall - 1);
}
if (p_ptr->tim_fly)
{
- (void)set_tim_fly(p_ptr->tim_fly - 1);
+ set_tim_fly(p_ptr->tim_fly - 1);
}
/* Thunderstorm */
@@ -1961,43 +2036,37 @@ static void process_world(void)
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);
+ 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);
+ set_poison(p_ptr->tim_poison - 1);
}
/* Brightness */
if (p_ptr->tim_lite)
{
- (void)set_lite(p_ptr->tim_lite - 1);
+ set_lite(p_ptr->tim_lite - 1);
}
/* Blindness */
if (p_ptr->blind)
{
- (void)set_blind(p_ptr->blind - 1);
+ set_blind(p_ptr->blind - 1);
}
/* Timed no_breeds */
if (no_breeds)
{
- (void)set_no_breeders(no_breeds - 1);
+ 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);
+ set_mimic(p_ptr->tim_mimic - 1, p_ptr->mimic_form, p_ptr->mimic_level);
}
/* Timed special move commands */
@@ -2009,189 +2078,141 @@ static void process_world(void)
/* Timed invisibility */
if (p_ptr->tim_invisible)
{
- (void)set_invis(p_ptr->tim_invisible - 1, p_ptr->tim_inv_pow);
+ 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);
- }
-
- if (multi_rew)
- {
- multi_rew = FALSE;
+ set_tim_invis(p_ptr->tim_invis - 1);
}
/* Timed esp */
if (p_ptr->tim_esp)
{
- (void)set_tim_esp(p_ptr->tim_esp - 1);
+ 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);
+ set_tim_infra(p_ptr->tim_infra - 1);
}
/* Paralysis */
if (p_ptr->paralyzed)
{
- (void)set_paralyzed(p_ptr->paralyzed - 1);
+ dec_paralyzed();
}
/* Confusion */
if (p_ptr->confused)
{
- (void)set_confused(p_ptr->confused - 1);
+ set_confused(p_ptr->confused - 1);
}
/* Afraid */
if (p_ptr->afraid)
{
- (void)set_afraid(p_ptr->afraid - 1);
+ set_afraid(p_ptr->afraid - 1);
}
/* Fast */
if (p_ptr->fast)
{
- (void)set_fast(p_ptr->fast - 1, p_ptr->speed_factor);
+ set_fast(p_ptr->fast - 1, p_ptr->speed_factor);
}
/* Light speed */
if (p_ptr->lightspeed)
{
- (void)set_light_speed(p_ptr->lightspeed - 1);
+ set_light_speed(p_ptr->lightspeed - 1);
}
/* Slow */
if (p_ptr->slow)
{
- (void)set_slow(p_ptr->slow - 1);
+ 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);
+ set_protevil(p_ptr->protevil - 1);
}
/* Invulnerability */
if (p_ptr->invuln)
{
- (void)set_invuln(p_ptr->invuln - 1);
+ set_invuln(p_ptr->invuln - 1);
}
/* Wraith form */
if (p_ptr->tim_wraith)
{
- (void)set_shadow(p_ptr->tim_wraith - 1);
+ set_shadow(p_ptr->tim_wraith - 1);
}
/* Heroism */
if (p_ptr->hero)
{
- (void)set_hero(p_ptr->hero - 1);
+ set_hero(p_ptr->hero - 1);
}
/* Super Heroism */
if (p_ptr->shero)
{
- (void)set_shero(p_ptr->shero - 1);
+ set_shero(p_ptr->shero - 1);
}
/* Blessed */
if (p_ptr->blessed)
{
- (void)set_blessed(p_ptr->blessed - 1);
+ 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);
+ 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);
+ set_oppose_acid(p_ptr->oppose_acid - 1);
}
/* Oppose Lightning */
if (p_ptr->oppose_elec)
{
- (void)set_oppose_elec(p_ptr->oppose_elec - 1);
+ set_oppose_elec(p_ptr->oppose_elec - 1);
}
/* Oppose Fire */
if (p_ptr->oppose_fire)
{
- (void)set_oppose_fire(p_ptr->oppose_fire - 1);
+ set_oppose_fire(p_ptr->oppose_fire - 1);
}
/* Oppose Cold */
if (p_ptr->oppose_cold)
{
- (void)set_oppose_cold(p_ptr->oppose_cold - 1);
+ 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);
+ set_oppose_pois(p_ptr->oppose_pois - 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);
+ set_oppose_cc(p_ptr->oppose_cc - 1);
}
- /* The rush */
- if (p_ptr->rush)
- {
- (void)set_rush(p_ptr->rush - 1);
- }
-
-
/* Timed mimicry */
if (get_skill(SKILL_MIMICRY))
{
@@ -2214,7 +2235,7 @@ static void process_world(void)
att &= ~(CLASS_LEGS);
att &= ~(CLASS_WALL);
- if (disturb_state) disturb(0, 0);
+ disturb_on_state();
}
p_ptr->update |= (PU_BODY);
@@ -2231,7 +2252,7 @@ static void process_world(void)
int adjust = (adj_con_fix[p_ptr->stat_ind[A_CON]] + 1);
/* Apply some healing */
- (void)set_poisoned(p_ptr->poisoned - adjust);
+ set_poisoned(p_ptr->poisoned - adjust);
}
/* Stun */
@@ -2240,7 +2261,7 @@ static void process_world(void)
int adjust = (adj_con_fix[p_ptr->stat_ind[A_CON]] + 1);
/* Apply some healing */
- (void)set_stun(p_ptr->stun - adjust);
+ set_stun(p_ptr->stun - adjust);
}
/* Cut */
@@ -2252,7 +2273,7 @@ static void process_world(void)
if (p_ptr->cut > 1000) adjust = 0;
/* Apply some healing */
- (void)set_cut(p_ptr->cut - adjust);
+ set_cut(p_ptr->cut - adjust);
}
/* Hack - damage done by the dungeon -SC- */
@@ -2275,10 +2296,10 @@ static void process_world(void)
{
int l, dam = 0;
- if (!(dungeon_flags1 & DF1_DAMAGE_FEAT))
+ if (!(dungeon_flags & DF_DAMAGE_FEAT))
{
/* If the grid is empty, skip it */
- if ((cave[j][k].o_idx == 0) &&
+ if ((cave[j][k].o_idxs.empty()) &&
((j != p_ptr->py) && (i != p_ptr->px))) continue;
}
@@ -2508,14 +2529,14 @@ static void process_world(void)
}
/* Arg cannot breath? */
- if ((dungeon_flags2 & DF2_WATER_BREATH) && (!p_ptr->water_breath))
+ if ((dungeon_flags & DF_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))
+ if ((dungeon_flags & DF_NO_BREATH) && (!p_ptr->magical_breath))
{
- cmsg_print(TERM_L_RED, "There is no air there! You suffocate!");
+ cmsg_print(TERM_L_RED, "There is no air here! You suffocate!");
take_hit(damroll(3, p_ptr->lev), "suffocating");
}
@@ -2527,8 +2548,6 @@ static void process_world(void)
*/
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. */
@@ -2540,10 +2559,10 @@ static void process_world(void)
if (!o_ptr->k_idx) continue;
/* Extract the item flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ auto const flags = object_flags(o_ptr);
/* No messages if object has the flag, to avoid annoyance. */
- if (f4 & (TR4_BLACK_BREATH)) be_silent = TRUE;
+ if (flags & TR_BLACK_BREATH) be_silent = TRUE;
}
/* If we are allowed to speak, warn and disturb. */
@@ -2551,7 +2570,7 @@ static void process_world(void)
if (!be_silent)
{
cmsg_print(TERM_L_DARK, "The Black Breath saps your soul!");
- disturb(0, 0);
+ disturb();
}
}
@@ -2565,10 +2584,10 @@ static void process_world(void)
if (o_ptr->tval == TV_LITE)
{
/* Extract the item flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ auto const flags = object_flags(o_ptr);
/* Hack -- Use some fuel */
- if ((f4 & TR4_FUEL_LITE) && (o_ptr->timeout > 0))
+ if ((flags & TR_FUEL_LITE) && (o_ptr->timeout > 0))
{
/* Decrease life-span */
o_ptr->timeout--;
@@ -2590,14 +2609,17 @@ static void process_world(void)
/* The light is now out */
else if (o_ptr->timeout < 1)
{
- disturb(0, 0);
+ disturb();
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 (options->disturb_minor)
+ {
+ disturb();
+ }
cmsg_print(TERM_YELLOW, "Your light is growing faint.");
}
}
@@ -2619,14 +2641,14 @@ static void process_world(void)
byte chance = 0;
int plev = p_ptr->lev;
- if (PRACE_FLAG(PR1_RESIST_BLACK_BREATH)) chance = 2;
+ if (race_flags_p(PR_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);
+ do_dec_stat(rand_int(6), STAT_DEC_NORMAL);
check_experience();
}
}
@@ -2640,11 +2662,11 @@ static void process_world(void)
if (p_ptr->csp < 0)
{
p_ptr->csp = 0;
- disturb(0, 0);
+ disturb();
}
/* Redraw */
- p_ptr->redraw |= (PR_MANA);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
@@ -2659,7 +2681,7 @@ static void process_world(void)
if (p_ptr->csp < 0)
{
p_ptr->csp = 0;
- disturb(0, 0);
+ disturb();
p_ptr->maintain_sum = 0;
}
@@ -2670,7 +2692,7 @@ static void process_world(void)
}
/* Redraw */
- p_ptr->redraw |= (PR_MANA);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
@@ -2686,11 +2708,11 @@ static void process_world(void)
if (p_ptr->chp == 0)
{
- disturb(0, 0);
+ disturb();
}
/* Redraw */
- p_ptr->redraw |= (PR_HP);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
@@ -2714,17 +2736,17 @@ static void process_world(void)
/* Get the object */
o_ptr = &p_ptr->inventory[i];
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ auto const flags = object_flags(o_ptr);
/* TY Curse */
- if ((f3 & TR3_TY_CURSE) && (rand_int(TY_CURSE_CHANCE) == 0))
+ if ((flags & TR_TY_CURSE) && (rand_int(TY_CURSE_CHANCE) == 0))
{
activate_ty_curse();
}
/* DG Curse */
- if ((f4 & TR4_DG_CURSE) && (rand_int(DG_CURSE_CHANCE) == 0))
+ if ((flags & TR_DG_CURSE) && (rand_int(DG_CURSE_CHANCE) == 0))
{
activate_dg_curse();
@@ -2733,7 +2755,7 @@ static void process_world(void)
}
/* Auto Curse */
- if ((f3 & TR3_AUTO_CURSE) && (rand_int(AUTO_CURSE_CHANCE) == 0))
+ if ((flags & TR_AUTO_CURSE) && (rand_int(AUTO_CURSE_CHANCE) == 0))
{
/* The object recurse itself ! */
o_ptr->ident |= IDENT_CURSED;
@@ -2743,26 +2765,24 @@ static void process_world(void)
* Hack: Uncursed teleporting items (e.g. Dragon Weapons)
* can actually be useful!
*/
- if ((f3 & TR3_TELEPORT) && (rand_int(100) < 1))
+ if ((flags & TR_TELEPORT) && (rand_int(100) < 1))
{
if ((o_ptr->ident & IDENT_CURSED) && !p_ptr->anti_tele)
{
- disturb(0, 0);
+ disturb();
/* Teleport player */
teleport_player(40);
}
else
{
- if (p_ptr->wild_mode ||
- (o_ptr->note && strchr(quark_str(o_ptr->note), '.')))
+ if (p_ptr->wild_mode || strchr(o_ptr->inscription.c_str(), '.'))
{
- /* Do nothing */
- /* msg_print("Teleport aborted.") */;
+ /* Suppress teleportation */
}
else if (get_check("Teleport? "))
{
- disturb(0, 0);
+ disturb();
teleport_player(50);
}
}
@@ -2773,7 +2793,7 @@ static void process_world(void)
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;
+ if ((i == INVEN_LITE) && (o_ptr->tval == TV_LITE) && (flags & TR_FUEL_LITE)) continue;
/* Recharge activatable objects */
if (o_ptr->timeout > 0)
@@ -2788,16 +2808,6 @@ static void process_world(void)
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 */
@@ -2816,10 +2826,10 @@ static void process_world(void)
if (!o_ptr->k_idx) continue;
/* Examine the rod */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ auto const flags = object_flags(o_ptr);
/* Temporary items are destroyed */
- if (f5 & TR5_TEMPORARY)
+ if (flags & TR_TEMPORARY)
{
o_ptr->timeout--;
@@ -2836,7 +2846,7 @@ static void process_world(void)
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;
+ o_ptr->timeout += (flags & TR_CHARGING) ? 2 : 1;
/* Always notice */
j++;
@@ -2850,7 +2860,7 @@ static void process_world(void)
}
/* Examine all charging random artifacts */
- if ((f5 & TR5_ACTIVATE_NO_WIELD) && (o_ptr->timeout > 0))
+ if ((flags & TR_ACTIVATE_NO_WIELD) && (o_ptr->timeout > 0))
{
/* Charge it */
o_ptr->timeout--;
@@ -2871,11 +2881,11 @@ static void process_world(void)
{
if (o_ptr->timeout > 0)
{
- if (dungeon_flags1 & DF1_HOT)
+ if (dungeon_flags & DF_HOT)
{
o_ptr->pval -= 2;
}
- else if ((dungeon_flags1 & DF1_COLD) && rand_int(2))
+ else if ((dungeon_flags & DF_COLD) && rand_int(2))
{
if (magik(50)) o_ptr->pval--;
}
@@ -2899,8 +2909,6 @@ static void process_world(void)
/* Hatch eggs */
if (o_ptr->tval == TV_EGG)
{
- int mx, my;
-
if (o_ptr->timeout == 0)
{
o_ptr->pval--;
@@ -2908,22 +2916,18 @@ static void process_world(void)
/* Notice changes */
if (o_ptr->pval <= 0)
{
- monster_type *m_ptr;
- monster_race *r_ptr;
-
- mx = p_ptr->px;
- my = p_ptr->py + 1;
+ int mx = p_ptr->px;
+ int 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);
+ monster_type *m_ptr = &m_list[cave[my][mx].m_idx];
+ auto const r_ptr = m_ptr->race();
- if ((r_ptr->flags9 & RF9_IMPRESED) && can_create_companion())
+ if ((r_ptr->flags & RF_IMPRESED) && can_create_companion())
{
- msg_format("And you have given the imprint to your %s!",
- r_name + r_ptr->name);
+ msg_format("And you have given the imprint to your %s!", r_ptr->name);
m_ptr->status = MSTATUS_COMPANION;
}
@@ -2957,10 +2961,10 @@ static void process_world(void)
if (!o_ptr->k_idx) continue;
/* Examine the rod */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ auto const flags = object_flags(o_ptr);
/* Temporary items are destroyed */
- if (f5 & TR5_TEMPORARY)
+ if (flags & TR_TEMPORARY)
{
o_ptr->timeout--;
@@ -2978,7 +2982,7 @@ static void process_world(void)
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;
+ o_ptr->timeout += (flags & TR_CHARGING) ? 2 : 1;
/* Do not overflow */
if (o_ptr->timeout >= o_ptr->pval2)
@@ -2995,11 +2999,11 @@ static void process_world(void)
{
if (o_ptr->timeout > 0)
{
- if (dungeon_flags1 & DF1_HOT)
+ if (dungeon_flags & DF_HOT)
{
o_ptr->pval -= 2;
}
- else if ((dungeon_flags1 & DF1_COLD) && rand_int(2))
+ else if ((dungeon_flags & DF_COLD) && rand_int(2))
{
if (magik(50)) o_ptr->pval--;
}
@@ -3047,13 +3051,13 @@ static void process_world(void)
if (p_ptr->word_recall)
{
/* Can we ? */
- if (process_hooks(HOOK_RECALL, "()", ""))
+ if (process_hooks_new(HOOK_RECALL, NULL, NULL))
{
p_ptr->word_recall = 0;
}
/* No recall. sorry */
- else if (dungeon_flags2 & DF2_NO_RECALL_OUT)
+ else if (dungeon_flags & DF_NO_RECALL_OUT)
{
cmsg_print(TERM_L_DARK, "You cannot recall from here.");
p_ptr->word_recall = 0;
@@ -3101,7 +3105,7 @@ static void process_world(void)
if (p_ptr->word_recall == 0)
{
/* Disturbing! */
- disturb(0, 0);
+ disturb();
/* Determine the level */
if (p_ptr->inside_quest)
@@ -3140,9 +3144,6 @@ static void process_world(void)
p_ptr->leaving = TRUE;
p_ptr->wild_mode = FALSE;
}
-
- /* Sound */
- sound(SOUND_TPLEVEL);
}
}
}
@@ -3152,7 +3153,7 @@ static void process_world(void)
/*
* Verify use of "wizard" mode
*/
-static bool_ enter_wizard_mode(void)
+static bool_ enter_wizard_mode()
{
/* Ask first time, but not while loading a dead char with the -w option */
if (!noscore && !(p_ptr->chp < 0))
@@ -3180,7 +3181,7 @@ static bool_ enter_wizard_mode(void)
/*
* Verify use of "debug" commands
*/
-static bool_ enter_debug_mode(void)
+static bool_ enter_debug_mode()
{
/* Ask first time */
if (!noscore && !wizard)
@@ -3206,27 +3207,20 @@ 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.
*
* XXX XXX XXX Make some "blocks"
*/
-static void process_command(void)
+static void process_command()
{
+ auto const &wf_info = game->edit_data.wf_info;
+
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)
{
@@ -3244,15 +3238,6 @@ static void process_command(void)
break;
}
-#ifdef ALLOW_QUITTING
-
- case KTRL('L'):
- {
- quit("CHEATER");
- break;
- }
-
-#endif
/*** Wizard Commands ***/
@@ -3275,7 +3260,7 @@ static void process_command(void)
p_ptr->update |= (PU_MONSTERS);
/* Redraw "title" */
- p_ptr->redraw |= (PR_TITLE);
+ p_ptr->redraw |= (PR_FRAME);
break;
}
@@ -3307,7 +3292,7 @@ static void process_command(void)
{
if (p_ptr->control) break;
if (!p_ptr->wild_mode) do_cmd_takeoff();
- p_ptr->redraw |= (PR_MH);
+ p_ptr->redraw |= (PR_FRAME);
break;
}
@@ -3384,7 +3369,7 @@ static void process_command(void)
{
if (do_control_walk()) break;
- do_cmd_walk(always_pickup, TRUE);
+ do_cmd_walk(options->always_pickup);
break;
}
@@ -3394,7 +3379,7 @@ static void process_command(void)
{
if (do_control_walk()) break;
- do_cmd_walk(!always_pickup, TRUE);
+ do_cmd_walk(!options->always_pickup);
break;
}
@@ -3414,7 +3399,7 @@ static void process_command(void)
case ',':
{
if (do_control_pickup()) break;
- do_cmd_stay(always_pickup);
+ do_cmd_stay(options->always_pickup);
break;
}
@@ -3422,7 +3407,7 @@ static void process_command(void)
case 'g':
{
if (p_ptr->control) break;
- do_cmd_stay(!always_pickup);
+ do_cmd_stay(!options->always_pickup);
break;
}
@@ -3434,23 +3419,6 @@ static void process_command(void)
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 */
@@ -3464,16 +3432,8 @@ static void process_command(void)
/* 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);
+ /* Get the light being wielded */
+ auto o_ptr = &p_ptr->inventory[INVEN_LITE];
/* Cannot move if rooted in place */
if (p_ptr->tim_roots) break;
@@ -3513,7 +3473,7 @@ static void process_command(void)
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, "()"))
+ else if (!process_hooks_new(HOOK_FORBID_TRAVEL, NULL, NULL))
{
p_ptr->oldpx = p_ptr->px;
p_ptr->oldpy = p_ptr->py;
@@ -3544,8 +3504,9 @@ static void process_command(void)
/* 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))
+ auto const &wilderness = game->wilderness;
+ auto const &tile = wilderness(p_ptr->px, p_ptr->py);
+ if ((wf_info[tile.feat].entrance >= 1000) || (tile.entrance > 1000))
{
p_ptr->wilderness_x = p_ptr->px;
p_ptr->wilderness_y = p_ptr->py;
@@ -3622,15 +3583,6 @@ static void process_command(void)
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 */
@@ -3665,13 +3617,6 @@ static void process_command(void)
/* 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();
@@ -3750,13 +3695,6 @@ static void process_command(void)
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();
@@ -3787,18 +3725,8 @@ static void process_command(void)
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();
@@ -3817,13 +3745,6 @@ static void process_command(void)
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;
}
@@ -3834,13 +3755,6 @@ static void process_command(void)
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();
@@ -3853,13 +3767,6 @@ static void process_command(void)
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();
@@ -3872,13 +3779,6 @@ static void process_command(void)
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();
@@ -3912,13 +3812,6 @@ static void process_command(void)
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();
@@ -3931,13 +3824,6 @@ static void process_command(void)
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();
@@ -3950,13 +3836,6 @@ static void process_command(void)
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();
@@ -3969,7 +3848,7 @@ static void process_command(void)
if (p_ptr->control) break;
if (p_ptr->wild_mode) break;
- if (PRACE_FLAG(PR1_NO_GOD))
+ if (race_flags_p(PR_NO_GOD))
{
msg_print("You cannot worship gods.");
}
@@ -4052,13 +3931,6 @@ static void process_command(void)
/*** System Commands ***/
- /* Hack -- User interface */
- case '!':
- {
- (void)Term_user(0);
- break;
- }
-
/* Single line from a pref file */
case '"':
{
@@ -4180,22 +4052,6 @@ static void process_command(void)
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 '#':
{
@@ -4254,12 +4110,7 @@ static void process_command(void)
do_cmd_macro_recorder();
break;
}
- case CMD_BLUNDER:
- {
- if (do_control_walk()) break;
- do_cmd_walk(always_pickup, FALSE);
- break;
- }
+
/* Hack -- Unknown command */
default:
{
@@ -4269,7 +4120,6 @@ static void process_command(void)
if (rand_int(100) < insanity)
{
get_rnd_line("error.txt", error_m);
- sound(SOUND_ILLEGAL);
msg_print(error_m);
}
else
@@ -4292,8 +4142,11 @@ static void process_command(void)
* must come first just in case somebody manages to corrupt
* the savefiles by clever use of menu commands or something.
*/
-void process_player(void)
+static void process_player()
{
+ auto const &f_info = game->edit_data.f_info;
+ auto const &k_info = game->edit_data.k_info;
+
int i, j;
int speed_use;
@@ -4301,13 +4154,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;
@@ -4341,7 +4187,7 @@ void process_player(void)
/* Stop resting */
if ((p_ptr->chp == p_ptr->mhp) && (p_ptr->csp >= p_ptr->msp))
{
- disturb(0, 0);
+ disturb();
}
}
@@ -4372,29 +4218,26 @@ void process_player(void)
if (stop)
{
- disturb(0, 0);
+ disturb();
}
- p_ptr->redraw |= (PR_STATE);
+ p_ptr->redraw |= (PR_FRAME);
}
}
/* Handle "abort" */
- if (!avoid_abort)
+ if (!options->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())
+ if (inkey_scan())
{
/* Flush input */
flush();
/* Disturb */
- disturb(0, 0);
+ disturb();
/* Hack -- Show a Message */
msg_print("Cancelled.");
@@ -4422,14 +4265,17 @@ void process_player(void)
/* 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;
+ {
+ auto &wilderness = game->wilderness;
+ wilderness(p_ptr->wilderness_x, p_ptr->wilderness_y).known = TRUE;
+ }
/* Place the cursor on the player */
move_cursor_relative(p_ptr->py, p_ptr->px);
/* Refresh (optional) */
- if (fresh_before) Term_fresh();
+ if (options->fresh_before) Term_fresh();
/* Hack -- Pack Overflow */
if (p_ptr->inventory[INVEN_PACK].k_idx)
@@ -4444,7 +4290,7 @@ void process_player(void)
o_ptr = &p_ptr->inventory[item];
/* Disturbing */
- disturb(0, 0);
+ disturb();
/* Warning */
msg_print("Your pack overflows!");
@@ -4496,7 +4342,7 @@ void process_player(void)
resting--;
/* Redraw the state */
- p_ptr->redraw |= (PR_STATE);
+ p_ptr->redraw |= (PR_FRAME);
}
p_ptr->did_nothing = TRUE;
@@ -4527,7 +4373,7 @@ void process_player(void)
command_rep--;
/* Redraw the state */
- p_ptr->redraw |= (PR_STATE);
+ p_ptr->redraw |= (PR_FRAME);
/* Redraw stuff */
redraw_stuff();
@@ -4572,7 +4418,7 @@ void process_player(void)
/* Shimmer monsters if needed */
- if (!avoid_other && !use_graphics && shimmer_monsters)
+ if (!options->avoid_other && shimmer_monsters)
{
/* Clear the flag */
shimmer_monsters = FALSE;
@@ -4580,20 +4426,17 @@ void process_player(void)
/* 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];
+ monster_type *m_ptr = &m_list[i];
/* Skip dead monsters */
if (!m_ptr->r_idx) continue;
/* Access the monster race */
- r_ptr = race_inf(m_ptr);
+ auto const r_ptr = m_ptr->race();
/* Skip non-multi-hued monsters */
- if (!(r_ptr->flags1 & (RF1_ATTR_MULTI))) continue;
+ if (!(r_ptr->flags & RF_ATTR_MULTI)) continue;
/* Reset the flag */
shimmer_monsters = TRUE;
@@ -4604,8 +4447,7 @@ void process_player(void)
}
/* Shimmer objects if needed and requested */
- if (!avoid_other && !avoid_shimmer && !use_graphics &&
- shimmer_objects)
+ if (!options->avoid_other && !options->avoid_shimmer && shimmer_objects)
{
/* Clear the flag */
shimmer_objects = FALSE;
@@ -4615,13 +4457,13 @@ void process_player(void)
{
/* 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];
+ auto 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;
+ if (!(k_ptr->flags & TR_ATTR_MULTI)) continue;
/* Reset the flag */
shimmer_objects = TRUE;
@@ -4641,7 +4483,7 @@ void process_player(void)
* fast, and that's why shimmering has been limited to small
* number of monsters -- pelpel
*/
- if (!avoid_other && !avoid_shimmer && !use_graphics &&
+ if (!options->avoid_other && !options->avoid_shimmer &&
!resting && !running)
{
for (j = panel_row_min; j <= panel_row_max; j++)
@@ -4649,21 +4491,16 @@ void process_player(void)
for (i = panel_col_min; i <= panel_col_max; i++)
{
cave_type *c_ptr = &cave[j][i];
- feature_type *f_ptr;
+ auto f_ptr = c_ptr->mimic
+ ? &f_info[c_ptr->mimic]
+ : &f_info[f_info[c_ptr->feat].mimic];
- /* Apply terrain feature mimics */
- if (c_ptr->mimic)
- {
- f_ptr = &f_info[c_ptr->mimic];
- }
- else
+ /* Skip normal features */
+ if (!(f_ptr->flags & FF_ATTR_MULTI))
{
- f_ptr = &f_info[f_info[c_ptr->feat].mimic];
+ continue;
}
- /* Skip normal features */
- if (!(f_ptr->flags1 & (FF1_ATTR_MULTI))) continue;
-
/* Redraw a shimmering spot */
lite_spot(j, i);
}
@@ -4734,7 +4571,7 @@ void process_player(void)
*
* Forget everything when requested hehe I'm *NASTY*
*/
- if (dun_level && (dungeon_flags1 & DF1_FORGET))
+ if (dun_level && (dungeon_flags & DF_FORGET))
{
wiz_dark();
}
@@ -4757,8 +4594,10 @@ void process_player(void)
* This function will not exit until the level is completed,
* the user dies, or the game is terminated.
*/
-static void dungeon(void)
+static void dungeon()
{
+ auto const &d_info = game->edit_data.d_info;
+
/* Reset various flags */
hack_mind = FALSE;
@@ -4786,11 +4625,10 @@ static void dungeon(void)
shimmer_monsters = TRUE;
shimmer_objects = TRUE;
repair_monsters = TRUE;
- repair_objects = TRUE;
/* Disturb */
- disturb(1, 0);
+ disturb();
/* Track maximum player level */
if (p_ptr->max_plv < p_ptr->lev)
@@ -4816,12 +4654,12 @@ static void dungeon(void)
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;
+ if (!options->dungeon_stair) create_down_stair = create_up_stair = FALSE;
+ if (!options->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;
+ if (!(dungeon_flags & DF_NO_STAIR)) create_down_stair = create_up_stair = FALSE;
+ if (!(dungeon_flags & DF_NO_STAIR)) create_down_shaft = create_up_shaft = FALSE;
/* Make a stairway. */
if ((create_up_stair || create_down_stair ||
@@ -4837,19 +4675,19 @@ static void dungeon(void)
/* Make stairs */
if (create_down_stair)
{
- cave_set_feat(p_ptr->py, p_ptr->px, (dungeon_flags1 & DF1_FLAT) ? FEAT_WAY_MORE : FEAT_MORE);
+ cave_set_feat(p_ptr->py, p_ptr->px, (dungeon_flags & DF_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);
+ cave_set_feat(p_ptr->py, p_ptr->px, (dungeon_flags & DF_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);
+ cave_set_feat(p_ptr->py, p_ptr->px, (dungeon_flags & DF_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);
+ cave_set_feat(p_ptr->py, p_ptr->px, (dungeon_flags & DF_FLAT) ? FEAT_WAY_LESS : FEAT_LESS);
}
}
@@ -4881,7 +4719,7 @@ static void dungeon(void)
p_ptr->window |= (PW_MONSTER);
/* Redraw dungeon */
- p_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA);
+ p_ptr->redraw |= (PR_WIPE | PR_FRAME);
/* Redraw map */
p_ptr->redraw |= (PR_MAP);
@@ -5024,7 +4862,7 @@ static void dungeon(void)
move_cursor_relative(p_ptr->py, p_ptr->px);
/* Optional fresh */
- if (fresh_after) Term_fresh();
+ if (options->fresh_after) Term_fresh();
/* Hack -- Notice death or departure */
if (!alive || death) break;
@@ -5052,7 +4890,7 @@ static void dungeon(void)
move_cursor_relative(p_ptr->py, p_ptr->px);
/* Optional fresh */
- if (fresh_after) Term_fresh();
+ if (options->fresh_after) Term_fresh();
/* Hack -- Notice death or departure */
if (!alive || death) break;
@@ -5062,10 +4900,10 @@ static void dungeon(void)
process_world();
/* Process the appropriate hooks */
- process_hooks(HOOK_END_TURN, "(d)", is_quest(dun_level));
+ process_hooks_new(HOOK_END_TURN, NULL, NULL);
/* Make it pulsate and live !!!! */
- if ((dungeon_flags1 & DF1_EVOLVE) && dun_level)
+ if ((dungeon_flags & DF_EVOLVE) && dun_level)
{
if (!(turn % 10)) evolve_level(TRUE);
}
@@ -5086,7 +4924,7 @@ static void dungeon(void)
move_cursor_relative(p_ptr->py, p_ptr->px);
/* Optional fresh */
- if (fresh_after) Term_fresh();
+ if (options->fresh_after) Term_fresh();
/* Hack -- Notice death or departure */
if (!alive || death) break;
@@ -5134,47 +4972,59 @@ static void dungeon(void)
/*
* Load some "user pref files"
*/
-static void load_all_pref_files(void)
+static void load_all_pref_files()
{
char buf[1024];
+ std::string const &player_name = game->player_name;
/* Access the "race" pref file */
- sprintf(buf, "%s.prf", rp_ptr->title + rp_name);
+ sprintf(buf, "%s.prf", rp_ptr->title.c_str());
/* Process that file */
process_pref_file(buf);
/* Access the "class" pref file */
- sprintf(buf, "%s.prf", spp_ptr->title + c_name);
+ sprintf(buf, "%s.prf", spp_ptr->title);
/* Process that file */
process_pref_file(buf);
/* Access the "character" pref file */
- sprintf(buf, "%s.prf", player_name);
+ sprintf(buf, "%s.prf", player_name.c_str());
/* Process that file */
process_pref_file(buf);
- /* Process player specific automatizer sets */
- tome_dofile_anywhere(ANGBAND_DIR_USER, format("%s.atm", player_name), FALSE);
+ /* Load automatizer settings. Character-specific automatizer
+ * file gets priority over the "template" file. We do not try
+ * to merge the two files since that would require tracking
+ * the providence of rules and such to avoid the same
+ * duplication problems as caused when saving macros/keymaps. */
+ boost::filesystem::path userDirectory(ANGBAND_DIR_USER);
+ if (automatizer_load(userDirectory / (player_name + ".atm")))
+ {
+ // Done
+ }
+ else if (automatizer_load(userDirectory / "automat.atm"))
+ {
+ // Done
+ }
}
/*
* 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)
+void play_game()
{
+ auto const &d_info = game->edit_data.d_info;
+
int i, tmp_dun;
bool_ cheat_death = FALSE;
- hack_corruption = FALSE;
+ /* Initialize player */
+ p_ptr = new player_type();
/* Hack -- Character is "icky" */
character_icky = TRUE;
@@ -5183,11 +5033,9 @@ void play_game(bool_ new_game)
/* Make sure main term is active */
Term_activate(angband_term[0]);
- /* Initialise the resize hook XXX XXX XXX */
+ /* Initialise the resize hooks for all the terminals */
angband_term[0]->resize_hook = resize_map;
-
- /* XXX XXX XXX hardcoded number of terms */
- for (i = 1; i < 8; i++)
+ for (i = 1; i < ANGBAND_TERM_MAX; i++)
{
if (angband_term[i])
{
@@ -5198,10 +5046,11 @@ void play_game(bool_ new_game)
/* Hack -- turn off the cursor */
- (void)Term_set_cursor(0);
+ Term_set_cursor(0);
/* Character list */
- if (!new_game && !no_begin_screen) new_game = begin_screen();
+ bool_ new_game = FALSE;
+ if (!no_begin_screen) new_game = begin_screen();
no_begin_screen = FALSE;
/* Attempt to load */
@@ -5220,22 +5069,6 @@ void play_game(bool_ new_game)
/* 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);
- }
- }
-
-#if 1
/* Process old character */
if (!new_game)
@@ -5244,81 +5077,20 @@ void play_game(bool_ new_game)
process_player_name(FALSE);
}
-#endif
-
- /* 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;
- }
- }
- }
+ /* Force "complex" RNG */
+ set_complex_rng();
/* 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, "()");
+ /* Show intro */
+ modules[game_module_idx].intro();
/* The dungeon is not ready */
character_dungeon = FALSE;
- /* Hack -- seed for flavors */
- seed_flavor = rand_int(0x10000000);
+ /* Set the seed for flavors */
+ seed_flavor() = seed_t::system();
/* Roll up a new character */
player_birth();
@@ -5327,17 +5099,16 @@ void play_game(bool_ new_game)
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))
+ /* Mega-hack Vampires and Spectres start at midnight */
+ if (race_flags_p(PR_UNDEAD))
{
- turn = (10L * DAY / 2) + (START_DAY * 10) + 1;
+ turn = (10L * DAY / 2) + 1;
}
else
{
- turn = (START_DAY * 10) + 1;
+ turn = 1;
}
}
@@ -5375,15 +5146,16 @@ void play_game(bool_ new_game)
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;
+ if (arg_force_original) options->rogue_like_commands = FALSE;
+ if (arg_force_roguelike) options->rogue_like_commands = TRUE;
/* Initialize vault info */
if (init_v_info()) quit("Cannot initialize vaults");
/* Initialize hooks */
- init_hooks();
- ingame_help(p_ptr->help.enabled);
+ init_hooks_quests();
+ init_hooks_help();
+ init_hooks_module();
/* React to changes */
Term_xtra(TERM_XTRA_REACT, 0);
@@ -5396,7 +5168,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);
}
@@ -5405,7 +5177,7 @@ void play_game(bool_ new_game)
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;
@@ -5421,13 +5193,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)
{
@@ -5528,7 +5293,7 @@ void play_game(bool_ new_game)
cheat_death = FALSE;
/* Can we die ? please let us die ! */
- if (process_hooks(HOOK_DIE, "()"))
+ if (process_hooks_new(HOOK_DIE, NULL, NULL))
{
cheat_death = TRUE;
}
@@ -5558,16 +5323,10 @@ void play_game(bool_ new_game)
}
/* Cheat death option */
- else if ((wizard || cheat_live) && !get_check("Die? "))
+ else if ((wizard || options->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.");
@@ -5595,14 +5354,14 @@ void play_game(bool_ new_game)
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);
+ set_blind(0);
+ set_confused(0);
+ set_poisoned(0);
+ set_afraid(0);
+ set_paralyzed(0);
+ set_image(0);
+ set_stun(0);
+ set_cut(0);
/* accounting for a new ailment. -LM- */
p_ptr->black_breath = FALSE;
@@ -5611,7 +5370,7 @@ void play_game(bool_ new_game)
p_ptr->necro_extra &= ~CLASS_UNDEAD;
/* Hack -- Prevent starvation */
- (void)set_food(PY_FOOD_MAX - 1);
+ set_food(PY_FOOD_MAX - 1);
/* Hack -- cancel recall */
if (p_ptr->word_recall)
@@ -5624,15 +5383,14 @@ void play_game(bool_ new_game)
p_ptr->word_recall = 0;
}
- /* Note cause of death XXX XXX XXX */
- (void)strcpy(died_from, "Cheating death");
+ /* Note cause of death */
+ game->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;
@@ -5651,7 +5409,7 @@ void play_game(bool_ new_game)
if (dun_level) p_ptr->wild_mode = FALSE;
/* Make a new level */
- process_hooks(HOOK_NEW_LEVEL, "(d)", is_quest(dun_level));
+ process_hooks_new(HOOK_NEW_LEVEL, NULL, NULL);
generate_cave();
}
diff --git a/src/dungeon.h b/src/dungeon.h
new file mode 100644
index 00000000..b5a81a59
--- /dev/null
+++ b/src/dungeon.h
@@ -0,0 +1,12 @@
+#pragma once
+
+// C linkage required for these functions since main-* code uses them.
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void play_game();
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/src/dungeon.hpp b/src/dungeon.hpp
new file mode 100644
index 00000000..e14f4a12
--- /dev/null
+++ b/src/dungeon.hpp
@@ -0,0 +1,6 @@
+#pragma once
+
+#include <vector>
+
+void sense_inventory();
+void sense_objects(std::vector<int> const &object_idxs);
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/dungeon_flag.hpp b/src/dungeon_flag.hpp
new file mode 100644
index 00000000..bf8d77d8
--- /dev/null
+++ b/src/dungeon_flag.hpp
@@ -0,0 +1,12 @@
+#pragma once
+
+#include "dungeon_flag_set.hpp"
+#include <boost/preprocessor/cat.hpp>
+
+//
+// Define flag set for each flag.
+//
+#define DF(tier, index, name) \
+ DECLARE_FLAG(dungeon_flag_set, BOOST_PP_CAT(DF_,name), tier, index)
+#include "dungeon_flag_list.hpp"
+#undef DF
diff --git a/src/dungeon_flag_list.hpp b/src/dungeon_flag_list.hpp
new file mode 100644
index 00000000..8fdefc95
--- /dev/null
+++ b/src/dungeon_flag_list.hpp
@@ -0,0 +1,55 @@
+/**
+ * X-macro list of all the dungeon flags
+ */
+
+/* DF(<tier>, <index>, <name>) */
+DF(1, 0, PRINCIPAL)
+DF(1, 1, MAZE)
+DF(1, 2, SMALLEST)
+DF(1, 3, SMALL)
+DF(1, 4, BIG)
+DF(1, 5, NO_DOORS)
+DF(1, 6, WATER_RIVER)
+DF(1, 7, LAVA_RIVER)
+DF(1, 8, WATER_RIVERS)
+DF(1, 9, LAVA_RIVERS)
+DF(1, 10, CAVE)
+DF(1, 11, CAVERN)
+DF(1, 12, NO_UP)
+DF(1, 13, HOT)
+DF(1, 14, COLD)
+DF(1, 15, FORCE_DOWN)
+DF(1, 16, FORGET)
+DF(1, 17, NO_DESTROY)
+DF(1, 18, SAND_VEIN)
+DF(1, 19, CIRCULAR_ROOMS)
+DF(1, 20, EMPTY)
+DF(1, 21, DAMAGE_FEAT)
+DF(1, 22, FLAT)
+DF(1, 23, TOWER)
+DF(1, 24, RANDOM_TOWNS)
+DF(1, 25, DOUBLE)
+DF(1, 26, LIFE_LEVEL)
+DF(1, 27, EVOLVE)
+DF(1, 28, ADJUST_LEVEL_1)
+DF(1, 29, ADJUST_LEVEL_2)
+DF(1, 30, NO_RECALL)
+DF(1, 31, NO_STREAMERS)
+
+DF(2, 0, ADJUST_LEVEL_1_2)
+DF(2, 1, NO_SHAFT)
+DF(2, 2, ADJUST_LEVEL_PLAYER)
+DF(2, 3, NO_TELEPORT)
+DF(2, 4, ASK_LEAVE)
+DF(2, 5, NO_STAIR)
+DF(2, 6, SPECIAL)
+DF(2, 7, NO_NEW_MONSTER)
+DF(2, 8, DESC)
+DF(2, 9, NO_GENO)
+DF(2, 10, NO_BREATH)
+DF(2, 11, WATER_BREATH)
+DF(2, 12, ELVEN)
+DF(2, 13, DWARVEN)
+DF(2, 14, NO_EASY_MOVE)
+DF(2, 15, NO_RECALL_OUT)
+DF(2, 16, DESC_ALWAYS)
diff --git a/src/dungeon_flag_set.hpp b/src/dungeon_flag_set.hpp
new file mode 100644
index 00000000..539a574a
--- /dev/null
+++ b/src/dungeon_flag_set.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "flag_set.hpp"
+
+constexpr std::size_t DF_MAX_TIERS = 2;
+
+typedef flag_set<DF_MAX_TIERS> dungeon_flag_set;
diff --git a/src/dungeon_info_type.hpp b/src/dungeon_info_type.hpp
new file mode 100644
index 00000000..2f8fefde
--- /dev/null
+++ b/src/dungeon_info_type.hpp
@@ -0,0 +1,78 @@
+#pragma once
+
+#include "h-basic.h"
+#include "rule_type.hpp"
+#include "obj_theme.hpp"
+#include "dungeon_flag_set.hpp"
+
+#include <array>
+#include <string>
+
+/**
+ * Maximum number of towns per dungeon
+ */
+constexpr int TOWN_DUNGEON = 4;
+
+/* A structure for the != dungeon types */
+struct dungeon_info_type
+{
+ std::string name; /* Name */
+ std::string text; /* Description */
+ std::string short_name; /* Short name */
+
+ std::string generator; /* Name of the level generator */
+
+ s16b floor1 = 0; /* Floor tile 1 */
+ byte floor_percent1[2] = { 0 }; /* Chance of type 1 */
+ s16b floor2 = 0; /* Floor tile 2 */
+ byte floor_percent2[2] = { 0 }; /* Chance of type 2 */
+ s16b floor3 = 0; /* Floor tile 3 */
+ byte floor_percent3[2] = { 0 }; /* Chance of type 3 */
+ s16b outer_wall = 0; /* Outer wall tile */
+ s16b inner_wall = 0; /* Inner wall tile */
+ s16b fill_type1 = 0; /* Cave tile 1 */
+ byte fill_percent1[2] = { 0 }; /* Chance of type 1 */
+ s16b fill_type2 = 0; /* Cave tile 2 */
+ byte fill_percent2[2] = { 0 }; /* Chance of type 2 */
+ s16b fill_type3 = 0; /* Cave tile 3 */
+ byte fill_percent3[2] = { 0 }; /* Chance of type 3 */
+ byte fill_method = 0; /* Smoothing parameter for the above */
+
+ s16b mindepth = 0; /* Minimal depth */
+ s16b maxdepth = 0; /* Maximal depth */
+
+ bool_ principal = 0; /* If it's a part of the main dungeon */
+ byte min_plev = 0; /* Minimal plev needed to enter -- it's an anti-cheating mesure */
+
+ int min_m_alloc_level = 0; /* Minimal number of monsters per level */
+ int max_m_alloc_chance = 0; /* There is a 1/max_m_alloc_chance chance per round of creating a new monster */
+
+ dungeon_flag_set flags { }; /* Dungeon flags */
+
+ int size_x = 0;
+ int size_y = 0;
+
+ byte rule_percents[100] = {0}; /* Flat rule percents */
+ std::array<rule_type, 5> rules { }; /* Monster generation rules */
+
+ int final_object = 0; /* The object you'll find at the bottom */
+ int final_artifact = 0; /* The artifact you'll find at the bottom */
+ int final_guardian = 0; /* The artifact's guardian. If an artifact is specified, then it's NEEDED */
+
+ int ix = 0; /* Wilderness coordinates of entrance */
+ int iy = 0; /* Wilderness coordinates of entrance */
+ int ox = 0; /* Wilderness coordinates of exit */
+ int oy = 0; /* Wilderness coordinates of exit */
+
+ obj_theme objs; /* The drops type */
+
+ int d_dice[4] = { 0 }; /* Number of dices */
+ int d_side[4] = { 0 }; /* Number of sides */
+ int d_frequency[4] = { 0 }; /* Frequency of damage (1 is the minimum) */
+ int d_type[4] = { 0 }; /* Type of damage */
+
+ s16b t_idx[TOWN_DUNGEON] = { 0 }; /* The towns */
+ s16b t_level[TOWN_DUNGEON] = { 0 }; /* The towns levels */
+ s16b t_num = 0; /* Number of towns */
+};
+
diff --git a/src/dungeon_info_type_fwd.hpp b/src/dungeon_info_type_fwd.hpp
new file mode 100644
index 00000000..26ed0289
--- /dev/null
+++ b/src/dungeon_info_type_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct dungeon_info_type;
diff --git a/src/effect_type.hpp b/src/effect_type.hpp
new file mode 100644
index 00000000..8cd638c6
--- /dev/null
+++ b/src/effect_type.hpp
@@ -0,0 +1,17 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * Lasting spell effects. (Clouds, etc.)
+ */
+struct effect_type
+{
+ s16b time; /* For how long */
+ s16b dam; /* How much damage */
+ s16b type; /* Of which type */
+ s16b cy; /* Center of the cast*/
+ s16b cx; /* Center of the cast*/
+ s16b rad; /* Radius -- if needed */
+ u32b flags; /* Flags */
+};
diff --git a/src/ego_flag.hpp b/src/ego_flag.hpp
new file mode 100644
index 00000000..8afb6b19
--- /dev/null
+++ b/src/ego_flag.hpp
@@ -0,0 +1,12 @@
+#pragma once
+
+#include "ego_flag_set.hpp"
+#include <boost/preprocessor/cat.hpp>
+
+//
+// Define flag set for each flag.
+//
+#define ETR(tier, index, name) \
+ DECLARE_FLAG(ego_flag_set, BOOST_PP_CAT(ETR_,name), tier, index)
+#include "ego_flag_list.hpp"
+#undef ETR
diff --git a/src/ego_flag_list.hpp b/src/ego_flag_list.hpp
new file mode 100644
index 00000000..b05fb9b1
--- /dev/null
+++ b/src/ego_flag_list.hpp
@@ -0,0 +1,38 @@
+/**
+ * X-macro list of all the ego flags
+ */
+
+/* ETR(<tier>, <index>, <name>) */
+
+ETR(1, 0, SUSTAIN ) /* Ego-Item gives a Random Sustain */
+ETR(1, 1, OLD_RESIST ) /* The old "extra power" random high resist */
+ETR(1, 2, ABILITY ) /* Ego-Item has a random Sustain */
+ETR(1, 3, R_ELEM ) /* Item resists Acid/Fire/Cold/Elec or Poison */
+ETR(1, 4, R_LOW ) /* Item has a random low resist */
+ETR(1, 5, R_HIGH ) /* Item has a random high resist */
+ETR(1, 6, R_ANY ) /* Item has one additional resist */
+ETR(1, 7, R_DRAGON ) /* Item gets "Dragon" Resist */
+ETR(1, 8, SLAY_WEAP ) /* Special 'Slaying' bonus */
+ETR(1, 9, DAM_DIE ) /* Item has an additional dam die */
+ETR(1, 10, DAM_SIZE ) /* Item has greater damage dice */
+ETR(1, 11, PVAL_M1 ) /* Item has +1 to pval */
+ETR(1, 12, PVAL_M2 ) /* Item has +(up to 2) to pval */
+ETR(1, 13, PVAL_M3 ) /* Item has +(up to 3) to pval */
+ETR(1, 14, PVAL_M5 ) /* Item has +(up to 5) to pval */
+ETR(1, 15, AC_M1 ) /* Item has +1 to AC */
+ETR(1, 16, AC_M2 ) /* Item has +(up to 2) to AC */
+ETR(1, 17, AC_M3 ) /* Item has +(up to 3) to AC */
+ETR(1, 18, AC_M5 ) /* Item has +(up to 5) to AC */
+ETR(1, 19, TH_M1 ) /* Item has +1 to hit */
+ETR(1, 20, TH_M2 ) /* Item has +(up to 2) to hit */
+ETR(1, 21, TH_M3 ) /* Item has +(up to 3) to hit */
+ETR(1, 22, TH_M5 ) /* Item has +(up to 5) to hit */
+ETR(1, 23, TD_M1 ) /* Item has +1 to dam */
+ETR(1, 24, TD_M2 ) /* Item has +(up to 2) to dam */
+ETR(1, 25, TD_M3 ) /* Item has +(up to 3) to dam */
+ETR(1, 26, TD_M5 ) /* Item has +(up to 5) to dam */
+ETR(1, 27, R_P_ABILITY) /* Item has a random pval-affected ability */
+ETR(1, 28, R_STAT ) /* Item affects a random stat */
+ETR(1, 29, R_STAT_SUST) /* Item affects a random stat & sustains it */
+ETR(1, 30, R_IMMUNITY ) /* Item gives a random immunity */
+ETR(1, 31, LIMIT_BLOWS) /* switch the "limit blows" feature */
diff --git a/src/ego_flag_set.hpp b/src/ego_flag_set.hpp
new file mode 100644
index 00000000..0e77d5e0
--- /dev/null
+++ b/src/ego_flag_set.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "flag_set.hpp"
+
+constexpr std::size_t ETR_MAX_TIERS = 1;
+
+typedef flag_set<ETR_MAX_TIERS> ego_flag_set;
diff --git a/src/ego_item_type.hpp b/src/ego_item_type.hpp
new file mode 100644
index 00000000..2082c083
--- /dev/null
+++ b/src/ego_item_type.hpp
@@ -0,0 +1,62 @@
+#pragma once
+
+#include "ego_flag_set.hpp"
+#include "h-basic.h"
+#include "object_flag_set.hpp"
+
+#include <array>
+
+/*
+ * Size of flag rarity tables
+ */
+constexpr int FLAG_RARITY_MAX = 6;
+
+/**
+ * Ego item descriptors.
+ */
+struct ego_item_type
+{
+ const char *name = nullptr; /* Name */
+
+ bool_ before = FALSE; /* Before or after the object name ? */
+
+ byte tval[10] = { 0 };
+ byte min_sval[10] = { 0 };
+ byte max_sval[10] = { 0 };
+
+ byte rating = 0; /* Rating boost */
+
+ byte level = 0; /* Minimum level */
+ byte rarity = 0; /* Object rarity */
+ byte mrarity = 0; /* Object rarity */
+
+ s16b max_to_h = 0; /* Maximum to-hit bonus */
+ s16b max_to_d = 0; /* Maximum to-dam bonus */
+ s16b max_to_a = 0; /* Maximum to-ac bonus */
+
+ s16b activate = 0; /* Activation Number */
+
+ s32b max_pval = 0; /* Maximum pval */
+
+ s32b cost = 0; /* Ego-item "cost" */
+
+ byte rar[FLAG_RARITY_MAX] = { 0 };
+
+ std::array<object_flag_set, FLAG_RARITY_MAX> flags;
+ std::array<object_flag_set, FLAG_RARITY_MAX> oflags;
+
+ std::array<ego_flag_set, FLAG_RARITY_MAX> fego;
+
+ object_flag_set need_flags;
+ object_flag_set forbid_flags;
+
+ s16b power = -1; /* Power granted, if any */
+
+public:
+ ego_item_type()
+ {
+ std::fill(std::begin(tval),
+ std::end(tval),
+ 255);
+ }
+};
diff --git a/src/externs.h b/src/externs.h
deleted file mode 100644
index 197c1c8a..00000000
--- a/src/externs.h
+++ /dev/null
@@ -1,1851 +0,0 @@
-/* File: externs.h */
-
-/* Purpose: extern declarations (variables and functions) */
-
-/*
- * Note that some files have their own header files
- * (z-virt.h, z-util.h, z-form.h, term.h, random.h)
- */
-
-/*
- * Options for inc_stack_size_ex
- */
-typedef enum { OPTIMIZE, NO_OPTIMIZE } optimize_flag;
-typedef enum { DESCRIBE, NO_DESCRIBE } describe_flag;
-
-
-/*
- * Automatically generated "variable" declarations
- */
-
-extern int max_macrotrigger;
-extern char *macro_template;
-extern char *macro_modifier_chr;
-extern char *macro_modifier_name[MAX_MACRO_MOD];
-extern char *macro_trigger_name[MAX_MACRO_TRIG];
-extern char *macro_trigger_keycode[2][MAX_MACRO_TRIG];
-
-/* tables.c */
-extern s16b ddd[9];
-extern s16b ddx[10];
-extern s16b ddy[10];
-extern s16b ddx_ddd[9];
-extern s16b ddy_ddd[9];
-extern char hexsym[16];
-extern byte adj_val_min[];
-extern byte adj_val_max[];
-extern byte adj_mag_study[];
-extern byte adj_mag_mana[];
-extern byte adj_mag_fail[];
-extern byte adj_mag_stat[];
-extern byte adj_chr_gold[];
-extern byte adj_int_dev[];
-extern byte adj_wis_sav[];
-extern byte adj_dex_dis[];
-extern byte adj_int_dis[];
-extern byte adj_dex_ta[];
-extern byte adj_str_td[];
-extern byte adj_dex_th[];
-extern byte adj_str_th[];
-extern byte adj_str_wgt[];
-extern byte adj_str_hold[];
-extern byte adj_str_dig[];
-extern byte adj_str_blow[];
-extern byte adj_dex_blow[];
-extern byte adj_dex_safe[];
-extern byte adj_con_fix[];
-extern byte adj_con_mhp[];
-extern byte blows_table[12][12];
-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];
-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];
-extern magic_power necro_powers[MAX_NECRO_POWERS];
-extern magic_power mimic_powers[MAX_MIMIC_POWERS];
-extern magic_power symbiotic_powers[MAX_SYMBIOTIC_POWERS];
-extern cptr deity_rarity[2];
-extern cptr deity_niceness[10];
-extern cptr deity_standing[11];
-extern move_info_type move_info[9];
-extern tactic_info_type tactic_info[9];
-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 quest_type quest_info[MAX_Q_IDX_INIT];
-extern cptr artifact_names_list;
-extern monster_power monster_powers[96];
-extern tval_desc tval_descs[];
-extern between_exit between_exits[MAX_BETWEEN_EXITS];
-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 int max_body_part[BODY_MAX];
-extern gf_name_type gf_names[];
-
-
-/* variable.c */
-extern cptr copyright[5];
-extern byte version_major;
-extern byte version_minor;
-extern byte version_patch;
-extern byte version_extra;
-extern byte sf_major;
-extern byte sf_minor;
-extern byte sf_patch;
-extern byte sf_extra;
-extern u32b sf_xtra;
-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;
-extern bool_ arg_force_original;
-extern bool_ arg_force_roguelike;
-extern bool_ arg_bigtile;
-extern bool_ character_generated;
-extern bool_ character_dungeon;
-extern bool_ character_loaded;
-extern bool_ character_saved;
-extern bool_ character_icky;
-extern bool_ character_xtra;
-extern u32b seed_flavor;
-extern s16b command_cmd;
-extern s16b command_arg;
-extern s16b command_rep;
-extern s16b command_dir;
-extern s16b command_wrk;
-extern s16b command_new;
-extern s32b energy_use;
-extern s16b choose_default;
-extern bool_ create_up_stair;
-extern bool_ create_down_stair;
-extern bool_ create_up_shaft;
-extern bool_ create_down_shaft;
-extern bool_ msg_flag;
-extern bool_ alive;
-extern bool_ death;
-extern s16b running;
-extern s16b resting;
-extern s16b cur_hgt;
-extern s16b cur_wid;
-extern s16b dun_level;
-extern s16b old_dun_level;
-extern s16b num_repro;
-extern s16b object_level;
-extern s16b monster_level;
-extern s32b turn;
-extern s32b old_turn;
-extern bool_ wizard;
-extern bool_ use_sound;
-extern bool_ use_graphics;
-extern bool_ use_bigtile;
-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;
-extern bool_ inkey_flag;
-extern s16b coin_type;
-extern bool_ opening_chest;
-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;
-extern s16b o_cnt;
-extern s16b m_max;
-extern s16b m_cnt;
-extern s16b hack_m_idx;
-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;
-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;
-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;
-extern bool_ always_repeat;
-extern bool_ use_old_target;
-extern bool_ depth_in_feet;
-extern bool_ hilite_player;
-extern bool_ ring_bell;
-extern bool_ find_ignore_stairs;
-extern bool_ find_ignore_doors;
-extern bool_ find_cut;
-extern bool_ find_examine;
-extern bool_ disturb_near;
-extern bool_ disturb_move;
-extern bool_ disturb_panel;
-extern bool_ disturb_detect;
-extern bool_ disturb_state;
-extern bool_ disturb_minor;
-extern bool_ disturb_other;
-extern bool_ avoid_abort;
-extern bool_ avoid_shimmer;
-extern bool_ avoid_other;
-extern bool_ flush_disturb;
-extern bool_ flush_failure;
-extern bool_ flush_command;
-extern bool_ fresh_before;
-extern bool_ fresh_after;
-extern bool_ fresh_message;
-extern bool_ alert_hitpoint;
-extern bool_ alert_failure;
-extern bool_ view_yellow_lite;
-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;
-extern bool_ disturb_pets;
-extern bool_ view_perma_grids;
-extern bool_ view_torch_grids;
-extern bool_ monster_lite;
-extern bool_ flow_by_sound;
-extern bool_ track_follow;
-extern bool_ track_target;
-extern bool_ stack_allow_items;
-extern bool_ stack_allow_wands;
-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;
-extern bool_ dungeon_align;
-extern bool_ dungeon_stair;
-extern bool_ smart_learn;
-extern bool_ smart_cheat;
-extern bool_ show_labels;
-extern bool_ show_weights;
-extern bool_ show_choices;
-extern bool_ show_details;
-extern bool_ testing_stack;
-extern bool_ testing_carry;
-extern bool_ cheat_peek;
-extern bool_ cheat_hear;
-extern bool_ cheat_room;
-extern bool_ cheat_xtra;
-extern bool_ cheat_know;
-extern bool_ cheat_live;
-extern bool_ last_words; /* Zangband options */
-extern bool_ speak_unique;
-extern bool_ small_levels;
-extern bool_ empty_levels;
-extern bool_ always_small_level;
-extern bool_ player_symbols;
-extern byte hitpoint_warn;
-extern byte delay_factor;
-extern s16b autosave_freq;
-extern bool_ autosave_t;
-extern bool_ autosave_l;
-extern s16b feeling;
-extern s16b rating;
-extern bool_ good_item_flag;
-extern bool_ closing_flag;
-extern s16b max_panel_rows, max_panel_cols;
-extern s16b panel_row_min, panel_row_max;
-extern s16b panel_col_min, panel_col_max;
-extern s16b panel_col_prt, panel_row_prt;
-extern byte feat_wall_outer;
-extern byte feat_wall_inner;
-extern s16b floor_type[100];
-extern s16b fill_type[100];
-extern s16b py;
-extern s16b px;
-extern s16b target_who;
-extern s16b target_col;
-extern s16b target_row;
-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];
-extern char history[4][60];
-extern char savefile[1024];
-extern s16b lite_n;
-extern s16b lite_y[LITE_MAX];
-extern s16b lite_x[LITE_MAX];
-extern s16b view_n;
-extern byte view_y[VIEW_MAX];
-extern byte view_x[VIEW_MAX];
-extern s16b temp_n;
-extern byte temp_y[TEMP_MAX];
-extern byte temp_x[TEMP_MAX];
-extern s16b macro__num;
-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 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];
-extern u32b window_mask[ANGBAND_TERM_MAX];
-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 object_type *o_list;
-extern monster_type *m_list;
-extern monster_type *km_list;
-extern u16b max_real_towns;
-extern u16b max_towns;
-extern town_type *town_info;
-extern s16b alloc_kind_size;
-extern alloc_entry *alloc_kind_table;
-extern bool_ alloc_kind_table_valid;
-extern s16b alloc_race_size;
-extern alloc_entry *alloc_race_table;
-extern byte misc_to_attr[256];
-extern char misc_to_char[256];
-extern byte tval_to_attr[128];
-extern char tval_to_char[128];
-extern cptr keymap_act[KEYMAP_MODES][256];
-extern player_type p_body;
-extern player_type *p_ptr;
-extern player_sex *sp_ptr;
-extern player_race *rp_ptr;
-extern player_race_mod *rmp_ptr;
-extern player_class *cp_ptr;
-extern player_spec *spp_ptr;
-extern u32b alchemist_known_egos[32];
-extern alchemist_recipe *alchemist_recipes;
-extern u32b alchemist_known_artifacts[6];
-extern u32b alchemist_gained;
-extern s16b player_hp[PY_MAX_LEVEL];
-extern header *al_head;
-extern char *al_name;
-extern artifact_select_flag *a_select_flags;
-
-extern header *ab_head;
-extern ability_type *ab_info;
-extern char *ab_name;
-extern char *ab_text;
-
-extern header *s_head;
-extern skill_type *s_info;
-extern char *s_name;
-extern char *s_text;
-
-extern header *v_head;
-extern vault_type *v_info;
-extern char *v_name;
-extern char *v_text;
-extern header *f_head;
-extern feature_type *f_info;
-extern char *f_name;
-extern char *f_text;
-extern header *k_head;
-extern object_kind *k_info;
-extern char *k_name;
-extern char *k_text;
-extern header *a_head;
-extern artifact_type *a_info;
-extern char *a_name;
-extern char *a_text;
-extern header *e_head;
-extern ego_item_type *e_info;
-extern char *e_name;
-extern char *e_text;
-extern header *ra_head;
-extern randart_part_type *ra_info;
-extern randart_gen_type ra_gen[30];
-extern header *r_head;
-extern monster_race *r_info;
-extern char *r_name;
-extern char *r_text;
-extern header *re_head;
-extern monster_ego *re_info;
-extern char *re_name;
-extern header *d_head;
-extern dungeon_info_type *d_info;
-extern char *d_name;
-extern char *d_text;
-extern header *c_head;
-extern player_class *class_info;
-extern char *c_name;
-extern char *c_text;
-extern meta_class_type *meta_class_info;
-extern header *rp_head;
-extern player_race *race_info;
-extern char *rp_name;
-extern char *rp_text;
-extern header *rmp_head;
-extern player_race_mod *race_mod_info;
-extern char *rmp_name;
-extern char *rmp_text;
-extern header *t_head;
-extern trap_type *t_info;
-extern char *t_name;
-extern char *t_text;
-extern header *wf_head;
-extern wilderness_type_info *wf_info;
-extern char *wf_name;
-extern char *wf_text;
-extern int wildc2i[256];
-extern header *st_head;
-extern store_info_type *st_info;
-extern char *st_name;
-extern header *ba_head;
-extern store_action_type *ba_info;
-extern char *ba_name;
-extern header *ow_head;
-extern owner_type *ow_info;
-extern char *ow_name;
-extern header *set_head;
-extern set_type *set_info;
-extern char *set_name;
-extern char *set_text;
-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;
-extern cptr ANGBAND_DIR_EDIT;
-extern cptr ANGBAND_DIR_FILE;
-extern cptr ANGBAND_DIR_HELP;
-extern cptr ANGBAND_DIR_INFO;
-extern cptr ANGBAND_DIR_MODULES;
-extern cptr ANGBAND_DIR_NOTE;
-extern cptr ANGBAND_DIR_SAVE;
-extern cptr ANGBAND_DIR_SCPT;
-extern cptr ANGBAND_DIR_PATCH;
-extern cptr ANGBAND_DIR_PREF;
-extern cptr ANGBAND_DIR_USER;
-extern cptr ANGBAND_DIR_XTRA;
-extern cptr ANGBAND_DIR_CMOV;
-extern char pref_tmp_value[8];
-extern bool_ item_tester_full;
-extern byte item_tester_tval;
-extern bool_ (*item_tester_hook)(object_type *o_ptr);
-extern bool_ (*ang_sort_comp)(vptr u, vptr v, int a, int b);
-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;
-extern u16b old_max_s_idx;
-extern u16b max_ab_idx;
-extern u16b max_s_idx;
-extern u16b max_al_idx;
-extern u16b max_r_idx;
-extern u16b max_re_idx;
-extern u16b max_k_idx;
-extern u16b max_v_idx;
-extern u16b max_f_idx;
-extern u16b max_a_idx;
-extern u16b max_e_idx;
-extern u16b max_ra_idx;
-extern u16b max_d_idx;
-extern u16b max_o_idx;
-extern u16b max_m_idx;
-extern u16b max_t_idx;
-extern u16b max_rp_idx;
-extern u16b max_c_idx;
-extern u16b max_mc_idx;
-extern u16b max_rmp_idx;
-extern u16b max_st_idx;
-extern u16b max_ba_idx;
-extern u16b max_ow_idx;
-extern u16b max_wf_idx;
-extern s16b max_set_idx;
-extern int init_flags;
-extern bool_ ambush_flag;
-extern bool_ fate_flag;
-extern s16b no_breeds;
-extern bool_ carried_monster_hit;
-extern random_artifact random_artifacts[MAX_RANDARTS];
-extern s32b RANDART_WEAPON;
-extern s32b RANDART_ARMOR;
-extern s32b RANDART_JEWEL;
-extern s16b bounties[MAX_BOUNTIES][2];
-extern random_spell random_spells[MAX_SPELLS];
-extern s16b spell_num;
-extern rune_spell rune_spells[MAX_RUNES];
-extern s16b rune_num;
-extern fate fates[MAX_FATES];
-extern byte dungeon_type;
-extern s16b *max_dlv;
-extern u32b total_bounties;
-extern s16b doppleganger;
-extern bool_ generate_encounter;
-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;
-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];
-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;
-extern bool_ auto_more;
-extern u32b dungeon_flags1;
-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;
-extern bool_ player_char_health;
-extern s16b max_spells;
-extern spell_type *school_spells;
-extern s16b max_schools;
-extern school_type *schools;
-extern int project_time;
-extern s32b project_time_effect;
-extern effect_type effects[MAX_EFFECTS];
-extern char gen_skill_basem[MAX_SKILLS];
-extern u32b gen_skill_base[MAX_SKILLS];
-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;
-extern s16b last_teleportation_x;
-extern cptr game_module;
-extern s32b VERSION_MAJOR;
-extern s32b VERSION_MINOR;
-extern s32b VERSION_PATCH;
-extern s32b max_plev;
-extern s32b DUNGEON_DEATH;
-extern deity_type *deity_info;
-extern s32b 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_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 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, ...);
-
-/* help.c */
-extern void ingame_help(bool_ enable);
-
-/* birth.c */
-extern void print_desc_aux(cptr txt, int y, int x);
-extern void save_savefile_names(void);
-extern bool_ no_begin_screen;
-extern bool_ begin_screen(void);
-extern errr init_randart(void);
-extern void get_height_weight(void);
-extern void player_birth(void);
-
-/* cave.c */
-extern int distance(int y1, int x1, int y2, int x2);
-extern bool_ los(int y1, int x1, int y2, int x2);
-extern bool_ cave_valid_bold(int y, int x);
-extern bool_ no_lite(void);
-extern void map_info(int y, int x, byte *ap, char *cp, byte *tap, char *tcp, byte *eap, char *ecp);
-extern void map_info_default(int y, int x, byte *ap, char *cp);
-extern void move_cursor_relative(int row, int col);
-extern void print_rel(char c, byte a, int y, int x);
-extern void note_spot(int y, int x);
-extern void lite_spot(int y, int x);
-extern void prt_map(void);
-extern void display_map(int *cy, int *cx);
-extern void do_cmd_view_map(void);
-extern errr vinfo_init(void);
-extern void forget_view(void);
-extern void update_view(void);
-extern void forget_mon_lite(void);
-extern void update_mon_lite(void);
-extern void forget_flow(void);
-extern void update_flow(void);
-extern void map_area(void);
-extern void wiz_lite(void);
-extern void wiz_lite_extra(void);
-extern void wiz_dark(void);
-extern void cave_set_feat(int y, int x, int feat);
-extern void place_floor(int y, int x);
-extern void place_floor_convert_glass(int y, int x);
-extern void place_filler(int y, int x);
-extern void mmove2(int *y, int *x, int y1, int x1, int y2, int x2);
-extern bool_ projectable(int y1, int x1, int y2, int x2);
-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 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);
-
-/* cmovie.c */
-extern void cmovie_init_second(void);
-extern s16b do_play_cmovie(cptr cmov_file);
-extern void do_record_cmovie(cptr cmovie);
-extern void do_stop_cmovie(void);
-extern void do_start_cmovie(void);
-extern void cmovie_clean_line(int y, char *abuf, char *cbuf);
-extern void cmovie_record_line(int y);
-extern void do_cmovie_insert(void);
-
-/* cmd1.c */
-extern void attack_special(monster_type *m_ptr, s32b special, int dam);
-extern bool_ test_hit_fire(int chance, int ac, int vis);
-extern bool_ test_hit_norm(int chance, int ac, int vis);
-extern s16b critical_shot(int weight, int plus, int dam, int skill);
-extern s16b critical_norm(int weight, int plus, int dam, int weapon_tval, bool_ *done_crit);
-extern s16b tot_dam_aux(object_type *o_ptr, int tdam, monster_type *m_ptr, s32b *special);
-extern void search(void);
-extern void carry(int pickup);
-extern void py_attack(int y, int x, int max_blow);
-extern bool_ player_can_enter(byte feature);
-extern void move_player(int dir, int do_pickup, bool_ disarm);
-extern void move_player_aux(int dir, int do_pickup, int run, bool_ disarm);
-extern void run_step(int dir);
-extern void step_effects(int y, int x, int do_pickup);
-extern void do_cmd_pet(void);
-extern bool_ do_cmd_integrate_body(void);
-extern bool_ do_cmd_leave_body(bool_ drop_body);
-extern bool_ execute_inscription(byte i, byte y, byte x);
-extern void do_cmd_engrave(void);
-extern void do_spin(void);
-
-/* cmd2.c */
-extern byte show_monster_inven(int m_idx, int *monst_list);
-extern int breakage_chance(object_type *o_ptr);
-extern void do_cmd_go_up(void);
-extern void do_cmd_go_down(void);
-extern void do_cmd_search(void);
-extern void do_cmd_toggle_search(void);
-extern void do_cmd_open(void);
-extern void do_cmd_close(void);
-extern void do_cmd_chat(void);
-extern void do_cmd_give(void);
-extern bool_ do_cmd_tunnel_aux(int y, int x, int dir);
-extern void do_cmd_tunnel(void);
-extern void do_cmd_disarm(void);
-extern void do_cmd_disarm(void);
-extern void do_cmd_bash(void);
-extern void do_cmd_alter(void);
-extern void do_cmd_spike(void);
-extern void do_cmd_walk(int pickup, bool_ disarm);
-extern void do_cmd_stay(int pickup);
-extern void do_cmd_run(void);
-extern void do_cmd_rest(void);
-extern int get_shooter_mult(object_type *o_ptr);
-extern void do_cmd_fire(void);
-extern void do_cmd_throw(void);
-extern void do_cmd_boomerang(void);
-extern void do_cmd_unwalk(void);
-extern void do_cmd_immovable_special(void);
-extern void fetch(int dir, int wgt, bool_ require_los);
-extern void do_cmd_sacrifice(void);
-extern void do_cmd_create_artifact(object_type *q_ptr);
-extern void do_cmd_steal(void);
-extern void do_cmd_racial_power(void);
-
-/* cmd3.c */
-extern void do_cmd_html_dump(void);
-extern void cli_add(cptr active, cptr trigger, cptr descr);
-extern void do_cmd_cli(void);
-extern void do_cmd_cli_help(void);
-extern void do_cmd_inven(void);
-extern void do_cmd_equip(void);
-extern void do_cmd_wield(void);
-extern void do_cmd_takeoff(void);
-extern void do_cmd_drop(void);
-extern void do_cmd_destroy(void);
-extern void do_cmd_observe(void);
-extern void do_cmd_uninscribe(void);
-extern void do_cmd_inscribe(void);
-extern void do_cmd_refill(void);
-extern void do_cmd_target(void);
-extern void do_cmd_look(void);
-extern void do_cmd_locate(void);
-extern void do_cmd_query_symbol(void);
-extern bool_ do_cmd_sense_grid_mana(void);
-extern bool_ research_mon(void);
-extern s32b portable_hole_weight(void);
-extern void set_portable_hole_weight(void);
-extern void do_cmd_portable_hole(void);
-
-/* cmd4.c */
-extern bool_ change_option(cptr name, bool_ value);
-extern void macro_recorder_start(void);
-extern void macro_recorder_add(char c);
-extern void macro_recorder_stop(void);
-extern void do_cmd_macro_recorder(void);
-extern void do_cmd_redraw(void);
-extern void do_cmd_change_name(void);
-extern void do_cmd_message_one(void);
-extern void do_cmd_messages(void);
-extern void do_cmd_options(void);
-extern void do_cmd_pref(void);
-extern void do_cmd_macros(void);
-extern void do_cmd_visuals(void);
-extern void do_cmd_colors(void);
-extern void do_cmd_note(void);
-extern void do_cmd_version(void);
-extern void do_cmd_feeling(void);
-extern void do_cmd_load_screen(void);
-extern void do_cmd_save_screen(void);
-extern void do_cmd_knowledge(void);
-extern void plural_aux(char * Name);
-extern void do_cmd_checkquest(void);
-extern void do_cmd_change_tactic(int i);
-extern void do_cmd_change_movement(int i);
-extern void do_cmd_time(void);
-extern void do_cmd_options_aux(int page, cptr info, bool_ read_only);
-
-
-/* cmd5.c */
-extern bool_ is_magestaff(void);
-extern void calc_magic_bonus(void);
-extern void do_cmd_browse_aux(object_type *o_ptr);
-extern void do_cmd_browse(void);
-extern void do_cmd_cast(void);
-extern void do_cmd_pray(void);
-extern void do_cmd_rerate(void);
-extern void corrupt_player(void);
-extern bool_ item_tester_hook_armour(object_type *o_ptr);
-extern void fetch(int dir, int wgt, bool_ require_los);
-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 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 bool_ is_school_book(object_type *o_ptr);
-
-/* cmd6.c */
-extern void set_stick_mode(object_type *o_ptr);
-extern void unset_stick_mode(void);
-extern void do_cmd_eat_food(void);
-extern void do_cmd_quaff_potion(void);
-extern void do_cmd_read_scroll(void);
-extern void do_cmd_aim_wand(void);
-extern void do_cmd_use_staff(void);
-extern void do_cmd_zap_rod(void);
-extern const char *activation_aux(object_type *o_ptr, bool_ desc, int item);
-extern void do_cmd_activate(void);
-extern void do_cmd_rerate(void);
-extern void do_cmd_cut_corpse(void);
-extern void do_cmd_cure_meat(void);
-extern void do_cmd_drink_fountain(void);
-extern void do_cmd_fill_bottle(void);
-
-/* cmd7.c */
-extern void do_cmd_create_boulder(void);
-extern int rune_exec(rune_spell *spell, int cost);
-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);
-extern void do_cmd_mimic(void);
-extern void do_cmd_blade(void);
-extern void use_ability_blade(void);
-extern bool_ alchemist_exists(int tval, int sval, int ego, int artifact);
-extern void rod_tip_extract(object_type *o_ptr);
-extern void do_cmd_toggle_artifact(object_type *o_ptr);
-extern bool_ alchemist_items_check(int tval, int sval, int ego, int tocreate, bool_ message);
-extern void alchemist_display_recipe(int tval, int sval, int ego);
-extern void alchemist_recipe_book(void);
-extern int alchemist_recipe_select(int *tval, int sval, int ego, bool_ recipe);
-extern int alchemist_learn_object(object_type *o_ptr);
-extern void alchemist_gain_level(int lev);
-extern void do_cmd_alchemist(void);
-extern void do_cmd_beastmaster(void);
-extern void do_cmd_powermage(void);
-extern void do_cmd_possessor(void);
-extern void do_cmd_archer(void);
-extern void do_cmd_set_piercing(void);
-extern void do_cmd_necromancer(void);
-extern void do_cmd_unbeliever(void);
-extern void cast_daemon_spell(int spell, byte level);
-extern void do_cmd_unbeliever(void);
-extern void do_cmd_runecrafter(void);
-extern void do_cmd_symbiotic(void);
-extern s32b sroot(s32b n);
-extern int clamp_failure_chance(int chance, int minfail);
-
-/* dungeon.c */
-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 void play_game(bool_ new_game);
-extern void sense_inventory();
-
-/* files.c */
-extern void html_screenshot(cptr name);
-extern void help_file_screenshot(cptr name);
-extern void player_flags(u32b* f1, u32b* f2, u32b* f3, u32b* f4, u32b* f5, u32b* esp);
-extern void wipe_saved(void);
-extern s16b tokenize(char *buf, s16b num, char **tokens, char delim1, char delim2);
-extern void display_player(int mode);
-extern cptr describe_player_location(void);
-extern errr file_character(cptr name, bool_ full);
-extern errr process_pref_file_aux(char *buf);
-extern errr process_pref_file(cptr name);
-extern void read_times(void);
-extern bool_ txt_to_html(cptr head, cptr food, cptr base, cptr ext, bool_ force, bool_ recur);
-extern bool_ show_file(cptr name, cptr what, int line, int mode);
-extern void do_cmd_help(void);
-extern void process_player_base(void);
-extern void process_player_name(bool_ sf);
-extern void get_name(void);
-extern void do_cmd_suicide(void);
-extern void do_cmd_save_game(void);
-extern void autosave_checkpoint();
-extern long total_points(void);
-extern void display_scores(int from, int to);
-extern errr predict_score(void);
-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);
-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);
-
-/* gen_maze.c */
-extern bool_ level_generate_maze();
-
-/* gen_life.c */
-extern bool_ level_generate_life();
-extern void evolve_level(bool_ noise);
-
-/* generate.c */
-extern bool_ new_player_spot(int branch);
-extern void add_level_generator(cptr name, bool_ (*generator)(), bool_ stairs, bool_ monsters, bool_ objects, bool_ miscs);
-extern bool_ level_generate_dungeon();
-extern bool_ generate_fracave(int y0, int x0,int xsize,int ysize,int cutoff,bool_ light,bool_ room);
-extern void generate_hmap(int y0, int x0,int xsiz,int ysiz,int grd,int roug,int cutoff);
-extern bool_ room_alloc(int x,int y,bool_ crowded,int by0,int bx0,int *xx,int *yy);
-extern void generate_grid_mana(void);
-extern byte calc_dungeon_type(void);
-extern void generate_cave(void);
-extern void build_rectangle(int y1, int x1, int y2, int x2, int feat, int info);
-
-
-/* wild.c */
-extern int generate_area(int y, int x, bool_ border, bool_ corner, bool_ refresh);
-extern void wilderness_gen(int refresh);
-extern void wilderness_gen_small(void);
-extern void reveal_wilderness_around_player(int y, int x, int h, int w);
-extern void town_gen(int t_idx);
-
-
-/* init1.c */
-extern int color_char_to_attr(char c);
-extern byte conv_color[16];
-extern errr init_player_info_txt(FILE *fp, char *buf);
-extern errr init_ab_info_txt(FILE *fp, char *buf);
-extern errr init_s_info_txt(FILE *fp, char *buf);
-extern errr init_set_info_txt(FILE *fp, char *buf);
-extern errr init_v_info_txt(FILE *fp, char *buf, bool_ start);
-extern errr init_f_info_txt(FILE *fp, char *buf);
-extern errr init_k_info_txt(FILE *fp, char *buf);
-extern errr init_a_info_txt(FILE *fp, char *buf);
-extern errr init_al_info_txt(FILE *fp, char *buf);
-extern errr init_ra_info_txt(FILE *fp, char *buf);
-extern errr init_e_info_txt(FILE *fp, char *buf);
-extern errr init_r_info_txt(FILE *fp, char *buf);
-extern errr init_re_info_txt(FILE *fp, char *buf);
-extern errr grab_one_dungeon_flag(u32b *flags1, u32b *flags2, cptr what);
-extern errr init_d_info_txt(FILE *fp, char *buf);
-extern errr init_t_info_txt(FILE *fp, char *buf);
-extern errr init_ba_info_txt(FILE *fp, char *buf);
-extern errr init_st_info_txt(FILE *fp, char *buf);
-extern errr init_ow_info_txt(FILE *fp, char *buf);
-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_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);
-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;
-
-/* 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);
-extern void wr_scripts(void);
-extern bool_ load_dungeon(char *ext);
-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 */
-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 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);
-extern bool_ make_attack_normal(int m_idx, byte divis);
-extern bool_ make_attack_spell(int m_idx);
-extern void process_monsters(void);
-extern void curse_equipment(int chance, int heavy_chance);
-extern void curse_equipment_dg(int chance, int heavy_chance);
-
-/* monster1.c */
-extern void screen_roff(int r_idx, int ego, int remember);
-extern void display_roff(int r_idx, int ego);
-extern void monster_description_out(int r_idx, int ego);
-
-/* monster2.c */
-extern void monster_set_level(int m_idx, int level);
-extern s32b modify_aux(s32b a, s32b b, char mod);
-extern void monster_msg(cptr fmt, ...);
-extern void cmonster_msg(char a, cptr fmt, ...);
-extern bool_ mego_ok(int r_idx, int ego);
-extern void monster_check_experience(int m_idx, bool_ silent);
-extern void monster_gain_exp(int m_idx, u32b exp, bool_ silent);
-extern monster_race* race_info_idx(int r_idx, int ego);
-extern int get_wilderness_flag(void);
-extern void sanity_blast(monster_type * m_ptr, bool_ necro);
-extern void delete_monster_idx(int i);
-extern void delete_monster(int y, int x);
-extern void compact_monsters(int size);
-extern void wipe_m_list(void);
-extern s16b m_pop(void);
-extern errr get_mon_num_prep(void);
-extern s16b get_mon_num(int level);
-extern void monster_desc(char *desc, monster_type *m_ptr, int mode);
-extern void monster_race_desc(char *desc, int r_idx, int ego);
-extern void lore_do_probe(int m_idx);
-extern void lore_treasure(int m_idx, int num_item, int num_gold);
-extern void update_mon(int m_idx, bool_ full);
-extern void update_monsters(bool_ full);
-extern void monster_carry(monster_type *m_ptr, int m_idx, object_type *q_ptr);
-extern bool_ bypass_r_ptr_max_num ;
-extern bool_ place_monster_aux(int y, int x, int r_idx, bool_ slp, bool_ grp, int status);
-extern bool_ place_monster(int y, int x, bool_ slp, bool_ grp);
-extern bool_ alloc_horde(int y, int x);
-extern bool_ alloc_monster(int dis, bool_ slp);
-extern bool_ summon_specific_okay(int r_idx);
-extern int summon_specific_level;
-extern bool_ summon_specific(int y1, int x1, int lev, int type);
-extern void monster_swap(int y1, int x1, int y2, int x2);
-extern bool_ multiply_monster(int m_idx, bool_ charm, bool_ clone);
-extern bool_ hack_message_pain_may_silent;
-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);
-extern bool_ monster_dungeon(int r_idx);
-extern bool_ monster_quest(int r_idx);
-extern bool_ monster_ocean(int r_idx);
-extern bool_ monster_shore(int r_idx);
-extern bool_ monster_town(int r_idx);
-extern bool_ monster_wood(int r_idx);
-extern bool_ monster_volcano(int r_idx);
-extern bool_ monster_mountain(int r_idx);
-extern bool_ monster_grass(int r_idx);
-extern bool_ monster_deep_water(int r_idx);
-extern bool_ monster_shallow_water(int r_idx);
-extern bool_ monster_lava(int r_idx);
-extern void set_mon_num_hook(void);
-extern void set_mon_num2_hook(int y, int x);
-extern bool_ monster_can_cross_terrain(byte feat, monster_race *r_ptr);
-extern void corrupt_corrupted(void);
-
-/* monster3.c */
-extern void dump_companions(FILE *outfile);
-extern void do_cmd_companion(void);
-extern bool_ do_control_reconnect(void);
-extern bool_ do_control_drop(void);
-extern bool_ do_control_magic(void);
-extern bool_ do_control_pickup(void);
-extern bool_ do_control_inven(void);
-extern bool_ do_control_walk(void);
-extern bool_ can_create_companion(void);
-extern void ai_deincarnate(int m_idx);
-extern bool_ ai_possessor(int m_idx, int o_idx);
-extern bool_ ai_multiply(int m_idx);
-extern bool_ change_side(monster_type *m_ptr);
-extern int is_friend(monster_type *m_ptr);
-extern bool_ is_enemy(monster_type *m_ptr, monster_type *t_ptr);
-
-/* object1.c */
-/* object2.c */
-extern byte get_item_letter_color(object_type *o_ptr);
-extern void describe_device(object_type *o_ptr);
-extern void inc_stack_size(int item, int delta);
-extern void inc_stack_size_ex(int item, int delta, optimize_flag opt, describe_flag desc);
-extern void object_pickup(int this_o_idx);
-extern int get_slot(int slot);
-extern bool_ apply_flags_set(s16b a_idx, s16b set_idx, u32b *f1, u32b *f2, u32b *f3, u32b *f4, u32b *f5, u32b *esp);
-extern bool_ apply_set(s16b a_idx, s16b set_idx);
-extern bool_ takeoff_set(s16b a_idx, s16b set_idx);
-extern bool_ wield_set(s16b a_idx, s16b set_idx, bool_ silent);
-extern object_type *get_object(int item);
-extern s32b calc_total_weight(void);
-extern void add_random_ego_flag(object_type *o_ptr, int fego, bool_ *limit_blows);
-extern bool_ info_spell;
-extern char spell_txt[50];
-extern bool_ grab_tval_desc(int tval);
-extern void init_match_theme(obj_theme theme);
-extern bool_ kind_is_artifactable(int k_idx);
-extern bool_ kind_is_good(int k_idx);
-extern int kind_is_legal_special;
-extern bool_ kind_is_legal(int k_idx);
-extern bool_ verify(cptr prompt, int item);
-extern void flavor_init(void);
-extern void reset_visuals(void);
-extern int object_power(object_type *o_ptr);
-extern bool_ object_flags_no_set;
-extern void object_flags(object_type *o_ptr, u32b *f1, u32b *f2, u32b *f3, u32b *f4, u32b *f5, u32b *esp);
-extern void object_flags_known(object_type *o_ptr, u32b *f1, u32b *f2, u32b *f3, u32b *f4, u32b *f5, u32b *esp);
-extern void object_desc(char *buf, object_type *o_ptr, int pref, int mode);
-extern void object_desc_store(char *buf, 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 char index_to_label(int i);
-extern s16b label_to_inven(int c);
-extern s16b label_to_equip(int c);
-extern s16b wield_slot_ideal(object_type *o_ptr, bool_ ideal);
-extern s16b wield_slot(object_type *o_ptr);
-extern cptr mention_use(int i);
-extern cptr describe_use(int i);
-extern void inven_item_charges(int item);
-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_charges(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 bool_ inven_carry_okay(object_type *o_ptr);
-extern s16b inven_carry(object_type *o_ptr, bool_ final);
-extern s16b inven_takeoff(int item, int amt, bool_ force_drop);
-extern void inven_drop(int item, int amt, int dy, int dx, bool_ silent);
-extern bool_ item_tester_okay(object_type *o_ptr);
-extern void display_inven(void);
-extern void display_equip(void);
-extern void show_inven();
-extern void show_equip();
-extern void toggle_inven_equip(void);
-extern bool_ (*get_item_extra_hook)(int *cp);
-extern bool_ get_item(int *cp, cptr pmt, cptr str, int mode);
-extern void excise_object_idx(int o_idx);
-extern void delete_object_idx(int o_idx);
-extern void delete_object(int y, int x);
-extern void compact_objects(int size);
-extern void wipe_o_list(void);
-extern s16b o_pop(void);
-extern errr get_obj_num_prep(void);
-extern s16b get_obj_num(int level);
-extern void object_known(object_type *o_ptr);
-extern void object_aware(object_type *o_ptr);
-extern void object_tried(object_type *o_ptr);
-extern s32b object_value(object_type *o_ptr);
-extern s32b object_value_real(object_type *o_ptr);
-extern bool_ object_similar(object_type *o_ptr, object_type *j_ptr);
-extern void object_absorb(object_type *o_ptr, object_type *j_ptr);
-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 int hack_apply_magic_power;
-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 void place_object(int y, int x, bool_ good, bool_ great, int where);
-extern bool_ make_gold(object_type *j_ptr);
-extern void place_gold(int y, int x);
-extern void process_objects(void);
-extern s16b drop_near(object_type *o_ptr, int chance, int y, int x);
-extern void acquirement(int y1, int x1, int num, bool_ great, bool_ known);
-extern void pick_trap(int y, int x);
-extern cptr item_activation(object_type *o_ptr,byte num);
-extern void combine_pack(void);
-extern void reorder_pack(void);
-extern void display_koff(int k_idx);
-extern void random_artifact_resistance (object_type * o_ptr);
-extern void random_resistance (object_type * o_ptr, bool_ is_scroll, int specific);
-extern s16b floor_carry(int y, int x, object_type *j_ptr);
-extern void pack_decay(int item);
-extern void floor_decay(int item);
-extern bool_ scan_floor(int *items, int *item_num, int y, int x, int mode);
-extern void show_floor(int y, int x);
-extern bool_ get_item_floor(int *cp, cptr pmt, cptr str, int mode);
-extern void py_pickup_floor(int pickup);
-extern s16b m_bonus(int max, int level);
-extern void object_gain_level(object_type *o_ptr);
-extern void gain_flag_group_flag(object_type *o_ptr, bool_ silent);
-extern void gain_flag_group(object_type *o_ptr, bool_ silent);
-extern void get_table_name(char * out_string);
-extern s32b flag_cost(object_type * o_ptr, int plusses);
-
-/* powers.c */
-extern void do_cmd_power(void);
-
-/* traps.c */
-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_object(object_type *o_ptr);
-extern void wiz_place_trap(int y, int x, int idx);
-extern void do_cmd_set_trap(void);
-extern bool_ mon_hit_trap(int);
-
-/* spells1.c */
-extern byte spell_color(int type);
-extern s16b poly_r_idx(int r_idx);
-extern void get_pos_player(int dis, int *ny, int *nx);
-extern bool_ teleport_player_bypass;
-extern void teleport_to_player(int m_idx);
-extern void teleport_player_directed(int rad, int dir);
-extern void teleport_away(int m_idx, int dis);
-extern void teleport_player(int dis);
-extern void teleport_player_to(int ny, int nx);
-extern void teleport_monster_to(int m_idx, int ny, int nx);
-extern void teleport_player_level(void);
-extern void recall_player(int d, int f);
-extern void take_hit(int damage, cptr kb_str);
-extern void take_sanity_hit(int damage, cptr hit_from);
-extern void acid_dam(int dam, cptr kb_str);
-extern void elec_dam(int dam, cptr kb_str);
-extern void fire_dam(int dam, cptr kb_str);
-extern void cold_dam(int dam, cptr kb_str);
-extern bool_ inc_stat(int stat);
-extern bool_ dec_stat(int stat, int amount, int mode);
-extern bool_ res_stat(int stat, bool_ full);
-extern bool_ apply_disenchant(int mode);
-extern bool_ project_m(int who, int r, int y, int x, int dam, int typ);
-extern sint project_path(u16b *gp, int range, int y1, int x1, int y2, int x2, int flg);
-extern bool_ project(int who, int rad, int y, int x, int dam, int typ, int flg);
-extern bool_ potion_smash_effect(int who, int y, int x, int o_sval);
-extern void do_poly_self(void);
-extern void corrupt_player(void);
-extern void generate_spell(int plev);
-extern bool_ unsafe;
-extern void describe_attack_fully(int type, char* r);
-extern s16b do_poly_monster(int y, int x);
-
-
-/* spells2.c */
-extern bool_ remove_curse_object(object_type *o_ptr, bool_ all);
-extern void curse_artifact(object_type * o_ptr);
-extern void grow_things(s16b type, int rad);
-extern void grow_grass(int rad);
-extern void grow_trees(int rad);
-extern bool_ hp_player(int num);
-extern bool_ heal_insanity(int val);
-extern void warding_glyph(void);
-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 void identify_pack_fully(void);
-extern bool_ remove_curse(void);
-extern bool_ remove_all_curse(void);
-extern bool_ restore_level(void);
-extern void self_knowledge(FILE *fff);
-extern bool_ lose_all_info(void);
-extern bool_ detect_traps(int rad);
-extern bool_ detect_doors(int rad);
-extern bool_ detect_stairs(int rad);
-extern bool_ detect_treasure(int rad);
-extern bool_ hack_no_detect_message;
-extern bool_ detect_objects_gold(int rad);
-extern bool_ detect_objects_normal(int rad);
-extern bool_ detect_objects_magic(int rad);
-extern bool_ detect_monsters_normal(int rad);
-extern bool_ detect_monsters_invis(int rad);
-extern bool_ detect_monsters_evil(int rad);
-extern bool_ detect_monsters_good(int rad);
-extern bool_ detect_monsters_xxx(u32b match_flag, int rad);
-extern bool_ detect_monsters_string(cptr chars, int rad);
-extern bool_ detect_monsters_nonliving(int rad);
-extern bool_ detect_all(int rad);
-extern void stair_creation(void);
-extern bool_ wall_stone(int y, int x);
-extern bool_ enchant(object_type *o_ptr, int n, int eflag);
-extern bool_ enchant_spell(int num_hit, int num_dam, int num_ac, int num_pval);
-extern bool_ ident_spell(void);
-extern bool_ ident_all(void);
-extern bool_ identify_fully(void);
-extern bool_ recharge(int num);
-extern bool_ speed_monsters(void);
-extern bool_ slow_monsters(void);
-extern bool_ sleep_monsters(void);
-extern bool_ conf_monsters(void);
-extern void aggravate_monsters(int who);
-extern bool_ genocide_aux(bool_ player_cast, char typ);
-extern bool_ genocide(bool_ player_cast);
-extern bool_ mass_genocide(bool_ player_cast);
-extern void do_probe(int m_idx);
-extern bool_ probing(void);
-extern void change_wild_mode(void);
-extern bool_ banish_evil(int dist);
-extern bool_ dispel_evil(int dam);
-extern bool_ dispel_good(int dam);
-extern bool_ dispel_undead(int dam);
-extern bool_ dispel_monsters(int dam);
-extern bool_ dispel_living(int dam);
-extern bool_ dispel_demons(int dam);
-extern bool_ turn_undead(void);
-extern void wipe(int y1, int x1, int r);
-extern void destroy_area(int y1, int x1, int r, bool_ full, bool_ bypass);
-extern void earthquake(int cy, int cx, int r);
-extern void lite_room(int y1, int x1);
-extern void unlite_room(int y1, int x1);
-extern bool_ lite_area(int dam, int rad);
-extern bool_ unlite_area(int dam, int rad);
-extern bool_ fire_ball_beam(int typ, int dir, int dam, int rad);
-extern bool_ fire_cloud(int typ, int dir, int dam, int rad, int time);
-extern bool_ fire_wave(int typ, int dir, int dam, int rad, int time, s32b eff);
-extern bool_ fire_wall(int typ, int dir, int dam, int time);
-extern bool_ fire_ball(int typ, int dir, int dam, int rad);
-extern bool_ fire_bolt(int typ, int dir, int dam);
-extern bool_ fire_beam(int typ, int dir, int dam);
-extern bool_ fire_druid_ball(int typ, int dir, int dam, int rad);
-extern bool_ fire_druid_bolt(int typ, int dir, int dam);
-extern bool_ fire_druid_beam(int typ, int dir, int dam);
-extern void call_chaos(void);
-extern bool_ fire_bolt_or_beam(int prob, int typ, int dir, int dam);
-extern bool_ lite_line(int dir);
-extern bool_ drain_life(int dir, int dam);
-extern bool_ death_ray(int dir, int plev);
-extern bool_ wall_to_mud(int dir);
-extern bool_ destroy_door(int dir);
-extern bool_ disarm_trap(int dir);
-extern bool_ wizard_lock(int dir);
-extern bool_ heal_monster(int dir);
-extern bool_ speed_monster(int dir);
-extern bool_ slow_monster(int dir);
-extern bool_ sleep_monster(int dir);
-extern bool_ stasis_monster(int dir);
-extern bool_ confuse_monster(int dir, int plev);
-extern bool_ stun_monster(int dir, int plev);
-extern bool_ fear_monster(int dir, int plev);
-extern bool_ scare_monsters(void);
-extern bool_ poly_monster(int dir);
-extern bool_ clone_monster(int dir);
-extern bool_ teleport_monster(int dir);
-extern bool_ door_creation(void);
-extern bool_ trap_creation(void);
-extern bool_ glyph_creation(void);
-extern bool_ destroy_doors_touch(void);
-extern bool_ destroy_traps_touch(void);
-extern bool_ sleep_monsters_touch(void);
-extern bool_ alchemy(void);
-extern void activate_ty_curse(void);
-extern void activate_dg_curse(void);
-extern void activate_hi_summon(void);
-extern void summon_cyber(void);
-extern void wall_breaker(void);
-extern void bless_weapon(void);
-extern bool_ confuse_monsters(int dam);
-extern bool_ charm_monsters(int dam);
-extern bool_ charm_animals(int dam);
-extern bool_ charm_demons(int dam);
-extern bool_ stun_monsters(int dam);
-extern bool_ stasis_monsters(int dam);
-extern bool_ banish_monsters(int dist);
-extern bool_ turn_monsters(int dam);
-extern bool_ turn_evil(int dam);
-extern bool_ deathray_monsters(void);
-extern bool_ charm_monster(int dir, int plev);
-extern bool_ star_charm_monster(int dir, int plev);
-extern bool_ control_one_undead(int dir, int plev);
-extern bool_ charm_animal(int dir, int plev);
-extern bool_ mindblast_monsters(int dam);
-extern void alter_reality(void);
-extern void report_magics(void);
-extern void teleport_swap(int dir);
-extern void swap_position(int lty, int ltx);
-extern bool_ item_tester_hook_recharge(object_type *o_ptr);
-extern bool_ fire_explosion(int y, int x, int typ, int rad, int dam);
-extern bool_ fire_godly_wrath(int y, int x, int typ, int dir, int dam);
-extern bool_ invoke(int dam, int typ);
-extern bool_ project_hack(int typ, int dam);
-extern void project_meteor(int radius, int typ, int dam, u32b flg);
-extern bool_ item_tester_hook_artifactable(object_type *o_ptr);
-extern bool_ passwall(int dir, bool_ safe);
-extern bool_ project_hook(int typ, int dir, int dam, int flg);
-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);
-
-/* randart.c */
-extern int get_activation_power(void);
-extern void build_prob(cptr learn);
-extern bool_ create_artifact(object_type *o_ptr, bool_ a_scroll, bool_ get_name);
-extern bool_ artifact_scroll(void);
-
-/* store.c */
-extern bool_ is_blessed(object_type *o_ptr);
-extern void do_cmd_store(void);
-extern void store_shuffle(int which);
-extern void store_maint(int town_num, int store_num);
-extern void store_init(int town_num, int store_num);
-extern void move_to_black_market(object_type * o_ptr);
-extern void do_cmd_home_trump(void);
-extern void store_sell(void);
-extern void store_purchase(void);
-extern void store_examine(void);
-extern void store_stole(void);
-extern void store_prt_gold(void);
-extern void store_request_item(void);
-
-/* bldg.c -KMW- */
-extern bool_ bldg_process_command(store_type *s_ptr, int i);
-extern void show_building(store_type *s_ptr);
-extern bool_ is_state(store_type *s_ptr, int state);
-extern void do_cmd_bldg(void);
-extern bool_ show_god_info(bool_ ext);
-extern void enter_quest(void);
-extern void select_bounties(void);
-
-/* util.c */
-extern void scansubdir(cptr dir);
-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);
-extern cptr get_day(int day);
-extern s32b bst(s32b what, s32b t);
-extern errr path_parse(char *buf, int max, cptr file);
-extern errr path_temp(char *buf, int max);
-extern errr path_build(char *buf, int max, cptr path, cptr file);
-extern FILE *my_fopen(cptr file, cptr mode);
-extern errr my_fgets(FILE *fff, char *buf, huge n);
-extern errr my_fputs(FILE *fff, cptr buf, huge n);
-extern errr my_fclose(FILE *fff);
-extern errr fd_kill(cptr file);
-extern errr fd_move(cptr file, cptr what);
-extern errr fd_copy(cptr file, cptr what);
-extern int fd_make(cptr file, int mode);
-extern int fd_open(cptr file, int flags);
-extern errr fd_lock(int fd, int what);
-extern errr fd_seek(int fd, huge n);
-extern errr fd_read(int fd, char *buf, huge n);
-extern errr fd_write(int fd, cptr buf, huge n);
-extern errr fd_close(int fd);
-extern void flush(void);
-extern void bell(void);
-extern void sound(int num);
-extern void move_cursor(int row, int col);
-extern void text_to_ascii(char *buf, cptr str);
-extern void ascii_to_text(char *buf, cptr str);
-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 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);
-extern void cmsg_format(byte color, cptr fmt, ...);
-extern void msg_format(cptr fmt, ...);
-extern void screen_save(void);
-extern void screen_load(void);
-extern void c_put_str(byte attr, cptr str, int row, int col);
-extern void put_str(cptr str, int row, int col);
-extern void c_prt(byte attr, cptr str, int row, int col);
-extern void prt(cptr str, int row, int col);
-extern void text_out_to_screen(byte a, cptr str);
-extern void text_out_to_file(byte a, cptr str);
-extern void text_out(cptr str);
-extern void text_out_c(byte a, cptr str);
-extern void clear_screen(void);
-extern void clear_from(int row);
-extern bool_ askfor_aux_complete;
-extern bool_ askfor_aux(char *buf, int len);
-extern bool_ get_string(cptr prompt, char *buf, int len);
-extern bool_ get_check(cptr prompt);
-extern bool_ get_com(cptr prompt, char *command);
-extern s32b get_quantity(cptr prompt, s32b max);
-extern void pause_line(int row);
-extern char request_command_ignore_keymaps[];
-extern bool_ request_command_inven_mode;
-extern void request_command(int shopping);
-extern bool_ is_a_vowel(int ch);
-extern int get_keymap_dir(char ch);
-extern byte count_bits(u32b array);
-extern void strlower(char *buf);
-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 void del_timer(timer_type *t_ptr);
-extern int get_keymap_mode();
-
-/* main.c */
-extern bool_ private_check_user_directory(cptr dirpath);
-
-/* 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);
-extern int luck(int min, int max);
-extern int weight_limit(void);
-extern bool_ calc_powers_silent;
-extern void cnv_stat(int i, char *out_val);
-extern s16b modify_stat_value(int value, int amount);
-extern void calc_hitpoints(void);
-extern void notice_stuff(void);
-extern void update_stuff(void);
-extern void redraw_stuff(void);
-extern void window_stuff(void);
-extern void handle_stuff(void);
-extern bool_ monk_empty_hands(void);
-extern bool_ monk_heavy_armor(void);
-extern bool_ beastmaster_whip(void);
-extern void calc_bonuses(bool_ silent);
-extern void calc_sanity(void);
-extern void gain_fate(byte fate);
-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);
-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);
-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);
-extern bool_ set_parasite(int v, int r);
-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_deadly(int v);
-extern bool_ set_tim_res_time(int v);
-extern bool_ set_tim_reflect(int v);
-extern bool_ set_tim_thunder(int v, int p1, int p2);
-extern bool_ set_meditation(int v);
-extern bool_ set_strike(int v);
-extern bool_ set_walk_water(int v);
-extern bool_ set_tim_regen(int v, int p);
-extern bool_ set_tim_ffall(int v);
-extern bool_ set_tim_fly(int v);
-extern bool_ set_poison(int v);
-extern bool_ set_tim_fire_aura(int v);
-extern bool_ set_holy(int v);
-extern void set_grace(s32b v);
-extern bool_ set_mimic(int v, int p, int level);
-extern bool_ set_no_breeders(int v);
-extern bool_ set_invis(int v,int p);
-extern bool_ set_lite(int v);
-extern bool_ set_blind(int v);
-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 bool_ set_image(int v);
-extern bool_ set_fast(int v, int p);
-extern bool_ set_light_speed(int v);
-extern bool_ set_slow(int v);
-extern bool_ set_shield(int v, int p, s16b o, s16b d1, s16b d2);
-extern bool_ set_blessed(int v);
-extern bool_ set_hero(int v);
-extern bool_ set_shero(int v);
-extern bool_ set_protevil(int v);
-extern bool_ set_protgood(int v);
-extern bool_ set_protundead(int v);
-extern bool_ set_invuln(int v);
-extern bool_ set_tim_invis(int v);
-extern bool_ set_tim_infra(int v);
-extern bool_ set_mental_barrier(int v);
-extern bool_ set_oppose_acid(int v);
-extern bool_ set_oppose_elec(int v);
-extern bool_ set_oppose_fire(int v);
-extern bool_ set_oppose_cold(int v);
-extern bool_ set_oppose_pois(int v);
-extern bool_ set_oppose_ld(int v);
-extern bool_ set_oppose_cc(int v);
-extern bool_ set_oppose_ss(int v);
-extern bool_ set_oppose_nex(int v);
-extern bool_ set_stun(int v);
-extern bool_ set_cut(int v);
-extern bool_ set_food(int v);
-extern void check_experience(void);
-extern void check_experience_obj(object_type *o_ptr);
-extern void gain_exp(s32b amount);
-extern void lose_exp(s32b amount);
-extern int get_coin_type(monster_race *r_ptr);
-extern void monster_death(int m_idx);
-extern bool_ mon_take_hit(int m_idx, int dam, bool_ *fear, cptr note);
-extern bool_ change_panel(int dy, int dx);
-extern void verify_panel(void);
-extern void resize_map(void);
-extern void resize_window(void);
-extern cptr look_mon_desc(int m_idx);
-extern void ang_sort_aux(vptr u, vptr v, int p, int q);
-extern void ang_sort(vptr u, vptr v, int n);
-extern bool_ target_able(int m_idx);
-extern bool_ target_okay(void);
-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);
-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 bool_ lose_all_corruptions(void);
-extern void great_side_effect(void);
-extern void nasty_side_effect(void);
-extern void deadly_side_effect(bool_ god);
-extern void godly_wrath_blast(void);
-extern int interpret_grace(void);
-extern int interpret_favor(void);
-extern void make_wish(void);
-extern bool_ set_sliding(s16b v);
-extern void create_between_gate(int dist, int y, int x);
-
-/* levels.c */
-extern bool_ get_dungeon_generator(char *buf);
-extern bool_ get_level_desc(char *buf);
-extern void get_level_flags(void);
-extern bool_ get_dungeon_name(char *buf);
-extern bool_ get_dungeon_special(char *buf);
-extern bool_ get_command(const char *file, char comm, char *param);
-extern int get_branch(void);
-extern int get_fbranch(void);
-extern int get_flevel(void);
-extern bool_ get_dungeon_save(char *buf);
-
-/* wizard2.c */
-extern void do_cmd_wiz_cure_all(void);
-extern void do_cmd_wiz_named_friendly(int r_idx, bool_ slp);
-extern tval_desc2 tvals[];
-
-/* notes.c */
-extern void show_notes_file(void);
-extern void output_note(char *final_note);
-extern void add_note(char *note, char code);
-extern void add_note_type(int note_number);
-
-/* squeltch.c */
-extern void squeltch_inventory(void);
-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;
-
-
-
-/*
- * Hack -- conditional (or "bizarre") externs
- */
-
-#ifdef SET_UID
-/* util.c */
-extern void user_name(char *buf, int id);
-#endif
-
-#ifndef HAS_MEMSET
-/* util.c */
-extern char *memset(char*, int, huge);
-#endif
-
-#ifndef HAS_STRICMP
-/* util.c */
-extern int stricmp(cptr a, cptr b);
-#endif
-
-#ifndef HAS_USLEEP
-/* util.c */
-extern int usleep(huge usecs);
-#endif
-
-#ifdef MACINTOSH
-/* main-mac.c */
-/* extern void main(void); */
-#endif
-
-#ifdef MACH_O_CARBON
-/* main-crb.c */
-extern int fsetfileinfo(char *path, u32b fcreator, u32b ftype);
-extern u32b _fcreator;
-extern u32b _ftype;
-#endif /* MACH_O_CARBON */
-
-#ifdef WINDOWS
-/* main-win.c */
-/* extern int FAR PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, ...); */
-#endif
-
-#if !defined(WINDOWS) && !defined(MACINTOSH)
-/* files.c */
-extern bool_ chg_to_txt(cptr base, cptr newname);
-#endif /* !WINDOWS && !MACINTOSH */
-
-/* util.c */
-extern void repeat_push(int what);
-extern bool_ repeat_pull(int *what);
-extern void repeat_check(void);
-extern void get_count(int number, int max);
-
-/* variable.c */
-extern bool_ easy_open;
-extern bool_ easy_tunnel;
-extern bool_ easy_disarm;
-
-/* cmd2.c */
-extern bool_ easy_open_door(int y, int x);
-
-/* cmd2.c */
-extern bool_ do_cmd_disarm_aux(int y, int x, int dir, int do_pickup);
-
-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);
-extern cptr force_module;
-extern bool_ select_module(void);
-
-
-/* lua_bind.c */
-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);
-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 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);
-extern void desc_god(int g_idx, int d, char *desc);
-
-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 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 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 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);
-
-/* skills.c */
-extern void dump_skills(FILE *fff);
-extern s16b find_skill(cptr name);
-extern s16b find_skill_i(cptr name);
-extern s16b get_skill(int skill);
-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 s16b get_melee_skills(void);
-extern s16b get_melee_skill(void);
-extern bool_ forbid_gloves(void);
-extern bool_ forbid_non_blessed(void);
-extern void compute_skills(s32b *v, s32b *m, int i);
-extern void select_default_melee(void);
-extern void do_get_new_skill(void);
-extern void init_skill(s32b value, s32b mod, int i);
-extern s16b find_ability(cptr name);
-extern void dump_abilities(FILE *fff);
-extern void do_cmd_ability(void);
-extern bool_ has_ability(int ab);
-extern void apply_level_abilities(int level);
-extern void recalc_skills(bool_ init);
-
-/* gods.c */
-extern void inc_piety(int god, s32b amt);
-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);
diff --git a/src/fate.hpp b/src/fate.hpp
new file mode 100644
index 00000000..906bc99d
--- /dev/null
+++ b/src/fate.hpp
@@ -0,0 +1,22 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * Fate descritpor.
+ */
+struct fate
+{
+ byte fate; /* Which fate */
+ byte level; /* On which level */
+ byte serious; /* Is it sure? */
+ s16b o_idx; /* Object to find */
+ s16b e_idx; /* Ego-Item to find */
+ s16b a_idx; /* Artifact to find */
+ s16b v_idx; /* Vault to find */
+ s16b r_idx; /* Monster to find */
+ s16b count; /* Number of things */
+ s16b time; /* Turn before */
+ bool_ know; /* Has it been predicted? */
+ bool_ icky; /* Hackish runtime-only flag */
+};
diff --git a/src/feature_flag.hpp b/src/feature_flag.hpp
new file mode 100644
index 00000000..09aa5b43
--- /dev/null
+++ b/src/feature_flag.hpp
@@ -0,0 +1,12 @@
+#pragma once
+
+#include "feature_flag_set.hpp"
+#include <boost/preprocessor/cat.hpp>
+
+//
+// Define flag set for each flag.
+//
+#define FF(tier, index, name) \
+ DECLARE_FLAG(feature_flag_set, BOOST_PP_CAT(FF_,name), tier, index)
+#include "feature_flag_list.hpp"
+#undef FF
diff --git a/src/feature_flag_list.hpp b/src/feature_flag_list.hpp
new file mode 100644
index 00000000..0a433c3a
--- /dev/null
+++ b/src/feature_flag_list.hpp
@@ -0,0 +1,25 @@
+/**
+ * X-macro list of all the feature flags
+ */
+
+/* FF(<tier>, <index>, <name>) */
+
+FF(1, 0, NO_WALK)
+FF(1, 1, NO_VISION)
+FF(1, 2, CAN_LEVITATE)
+FF(1, 3, CAN_PASS)
+FF(1, 4, FLOOR)
+FF(1, 5, WALL)
+FF(1, 6, PERMANENT)
+FF(1, 7, CAN_FLY)
+FF(1, 8, REMEMBER)
+FF(1, 9, NOTICE)
+FF(1, 10, DONT_NOTICE_RUNNING)
+FF(1, 11, CAN_RUN)
+FF(1, 12, DOOR)
+FF(1, 13, SUPPORT_LIGHT)
+FF(1, 14, CAN_CLIMB)
+FF(1, 15, TUNNELABLE)
+FF(1, 16, WEB)
+FF(1, 17, ATTR_MULTI)
+FF(1, 18, SUPPORT_GROWTH)
diff --git a/src/feature_flag_set.hpp b/src/feature_flag_set.hpp
new file mode 100644
index 00000000..abc4f47d
--- /dev/null
+++ b/src/feature_flag_set.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "flag_set.hpp"
+
+constexpr std::size_t FF_MAX_TIERS = 1;
+
+typedef flag_set<FF_MAX_TIERS> feature_flag_set;
diff --git a/src/feature_type.hpp b/src/feature_type.hpp
new file mode 100644
index 00000000..e818f17a
--- /dev/null
+++ b/src/feature_type.hpp
@@ -0,0 +1,34 @@
+#pragma once
+
+#include "h-basic.h"
+
+#include "feature_flag_set.hpp"
+
+/**
+ * Terrain feature descriptor.
+ */
+struct feature_type
+{
+ char *name = nullptr; /* Name */
+
+ const char *text = nullptr; /* Text. May point to shared read-only memory, DO NOT FREE! */
+ const char *tunnel = nullptr; /* Text for tunneling. May point to shared read-only memory, DO NOT FREE! */
+ const char *block = nullptr; /* Text for blocking. May point to shared read-only memory, DO NOT FREE! */
+
+ byte mimic = 0; /* Feature to mimic */
+
+ feature_flag_set flags; /* First set of flags */
+
+ byte d_attr = 0; /* Default feature attribute */
+ char d_char = '\0'; /* Default feature character */
+
+ byte x_attr = 0; /* Desired feature attribute */
+ char x_char = '\0'; /* Desired feature character */
+
+ byte shimmer[7]; /* Shimmer colors */
+
+ int d_dice[4] = { 0 }; /* Number of dice */
+ int d_side[4] = { 0 }; /* Number of sides */
+ int d_frequency[4] = { 0 }; /* Frequency of damage (1 is the minimum) */
+ int d_type[4] = { 0 }; /* Type of damage */
+};
diff --git a/src/files.c b/src/files.cc
index 56e57975..6b3de0f0 100644
--- a/src/files.c
+++ b/src/files.cc
@@ -1,7 +1,3 @@
-/* File: files.c */
-
-/* Purpose: code dealing with files (and death) */
-
/*
* Copyright (c) 1989 James E. Wilson, Robert A. Koeneke
*
@@ -10,8 +6,67 @@
* included in all such copies.
*/
-#include "angband.h"
-
+#include "files.hpp"
+#include "files.h"
+
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "corrupt.hpp"
+#include "cmd3.hpp"
+#include "dungeon_info_type.hpp"
+#include "feature_type.hpp"
+#include "game.hpp"
+#include "hiscore.hpp"
+#include "hook_chardump_in.hpp"
+#include "hooks.hpp"
+#include "init1.hpp"
+#include "levels.hpp"
+#include "loadsave.h"
+#include "loadsave.hpp"
+#include "mimic.hpp"
+#include "monoid.hpp"
+#include "monster2.hpp"
+#include "monster3.hpp"
+#include "monster_ego.hpp"
+#include "monster_race.hpp"
+#include "monster_race_flag.hpp"
+#include "monster_type.hpp"
+#include "notes.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_flag.hpp"
+#include "object_flag_meta.hpp"
+#include "object_kind.hpp"
+#include "options.hpp"
+#include "player_class.hpp"
+#include "player_race.hpp"
+#include "player_race_flag.hpp"
+#include "player_race_mod.hpp"
+#include "player_spec.hpp"
+#include "player_type.hpp"
+#include "skills.hpp"
+#include "spells2.hpp"
+#include "store_info_type.hpp"
+#include "store_type.hpp"
+#include "tables.hpp"
+#include "town_type.hpp"
+#include "util.hpp"
+#include "util.h"
+#include "variable.h"
+#include "variable.hpp"
+#include "wilderness_map.hpp"
+#include "wilderness_type_info.hpp"
+#include "xtra1.hpp"
+#include "z-rand.hpp"
+
+#include <boost/algorithm/string.hpp>
+#include <boost/filesystem.hpp>
+#include <iostream>
+#include <fmt/format.h>
+#include <fstream>
+#include <limits>
+#include <memory>
+#include <unordered_set>
/*
* Extract the first few "tokens" from a buffer
@@ -160,6 +215,13 @@ s16b tokenize(char *buf, s16b num, char **tokens, char delim1, char delim2)
*/
errr process_pref_file_aux(char *buf)
{
+ auto &race_mod_info = game->edit_data.race_mod_info;
+ auto &st_info = game->edit_data.st_info;
+ auto &re_info = game->edit_data.re_info;
+ auto &r_info = game->edit_data.r_info;
+ auto &f_info = game->edit_data.f_info;
+ auto &k_info = game->edit_data.k_info;
+
int i, j, n1, n2;
char *zz[16];
@@ -191,17 +253,26 @@ errr process_pref_file_aux(char *buf)
{
if (tokenize(buf + 2, 3, zz, ':', '/') == 3)
{
- monster_race *r_ptr;
- i = (huge)strtol(zz[0], NULL, 0);
+ std::size_t i = strtoul(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 (i >= r_info.size())
+ {
+ return (1);
+ }
+
+ auto r_ptr = &r_info[i];
+
+ if (n1)
+ {
+ r_ptr->x_attr = n1;
+ }
if (n2)
{
r_ptr->x_char = n2;
}
+
return (0);
}
}
@@ -215,18 +286,27 @@ errr process_pref_file_aux(char *buf)
{
if (tokenize(buf + 4, 3, zz, ':', '/') == 3)
{
- monster_ego *re_ptr;
- i = (huge)strtol(zz[0], NULL, 0);
+ std::size_t i = strtoul(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 (i >= re_info.size())
+ {
+ return 1;
+ }
+
+ auto re_ptr = &re_info[i];
+
+ if (n1)
+ {
+ re_ptr->g_attr = n1;
+ }
if (n2)
{
re_ptr->g_char = n2;
}
- return (0);
+
+ return 0;
}
}
@@ -239,7 +319,7 @@ errr process_pref_file_aux(char *buf)
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);
+ if (i >= static_cast<int>(race_mod_info.size())) return (1);
rmp_ptr = &race_mod_info[i];
if (n1) rmp_ptr->g_attr = n1;
if (n2)
@@ -249,26 +329,6 @@ errr process_pref_file_aux(char *buf)
return (0);
}
}
-
- /* Process "G:T:<num>:<a>/<c>" -- 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);
- }
- }
}
@@ -277,13 +337,21 @@ errr process_pref_file_aux(char *buf)
{
if (tokenize(buf + 2, 3, zz, ':', '/') == 3)
{
- object_kind *k_ptr;
- i = (huge)strtol(zz[0], NULL, 0);
+ std::size_t i = strtoul(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 (i >= k_info.size())
+ {
+ return (1);
+ }
+
+ auto k_ptr = &k_info[i];
+
+ if (n1)
+ {
+ k_ptr->x_attr = n1;
+ }
if (n2)
{
k_ptr->x_char = n2;
@@ -298,13 +366,18 @@ errr process_pref_file_aux(char *buf)
{
if (tokenize(buf + 2, 3, zz, ':', '/') == 3)
{
- feature_type *f_ptr;
- i = (huge)strtol(zz[0], NULL, 0);
+ std::size_t f_idx = strtoul(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 (f_idx >= f_info.size()) return (1);
+
+ auto f_ptr = &f_info[f_idx];
+
+ if (n1)
+ {
+ f_ptr->x_attr = n1;
+ }
if (n2)
{
f_ptr->x_char = n2;
@@ -318,12 +391,13 @@ errr process_pref_file_aux(char *buf)
{
if (tokenize(buf + 2, 3, zz, ':', '/') == 3)
{
- store_info_type *st_ptr;
- i = (huge)strtol(zz[0], NULL, 0);
+ std::size_t i = std::stoul(zz[0], 0, 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 (i >= st_info.size()) return (1);
+
+ auto st_ptr = &st_info[i];
if (n1) st_ptr->x_attr = n1;
if (n2) st_ptr->x_char = n2;
return (0);
@@ -349,16 +423,23 @@ errr process_pref_file_aux(char *buf)
{
if (tokenize(buf + 2, 3, zz, ':', '/') == 3)
{
- j = (huge)strtol(zz[0], NULL, 0);
+ j = strtoul(zz[0], NULL, 0);
n1 = strtol(zz[1], NULL, 0);
n2 = strtol(zz[2], NULL, 0);
- for (i = 1; i < max_k_idx; i++)
+
+ for (auto &k_ref: k_info)
{
- object_kind *k_ptr = &k_info[i];
+ auto k_ptr = &k_ref;
if (k_ptr->tval == j)
{
- if (n1) k_ptr->d_attr = n1;
- if (n2) k_ptr->d_char = n2;
+ if (n1)
+ {
+ k_ref.d_attr = n1;
+ }
+ if (n2)
+ {
+ k_ref.d_char = n2;
+ }
}
}
return (0);
@@ -427,9 +508,9 @@ errr process_pref_file_aux(char *buf)
if (!tmp[0] || tmp[1]) return (1);
i = (byte)(tmp[0]);
- string_free(keymap_act[mode][i]);
+ free(keymap_act[mode][i]);
- keymap_act[mode][i] = string_make(macro__buf);
+ keymap_act[mode][i] = strdup(macro__buf);
return (0);
}
@@ -462,10 +543,14 @@ errr process_pref_file_aux(char *buf)
if (macro_template != NULL)
{
- free(macro_template);
+ delete[] macro_template;
macro_template = NULL;
+
for (i = 0; i < max_macrotrigger; i++)
- free(macro_trigger_name[i]);
+ {
+ delete[] macro_trigger_name[i];
+ macro_trigger_name[i] = nullptr;
+ }
max_macrotrigger = 0;
}
@@ -476,7 +561,7 @@ errr process_pref_file_aux(char *buf)
len = strlen(zz[0]) + 1 + num + 1;
for (i = 0; i < num; i++)
len += strlen(zz[2 + i]) + 1;
- macro_template = malloc(len);
+ macro_template = new char[len];
strcpy(macro_template, zz[0]);
macro_modifier_chr =
@@ -506,7 +591,7 @@ errr process_pref_file_aux(char *buf)
len = strlen(zz[0]) + 1 + strlen(zz[1]) + 1;
if (tok == 3)
len += strlen(zz[2]) + 1;
- macro_trigger_name[m] = malloc(len);
+ macro_trigger_name[m] = new char[len];
t = macro_trigger_name[m];
s = zz[0];
@@ -537,14 +622,12 @@ errr process_pref_file_aux(char *buf)
/* Process "X:<str>" -- turn option off */
else if (buf[0] == 'X')
{
- for (i = 0; option_info[i].o_desc; i++)
+ for (auto const &option: options->standard_options)
{
- if (option_info[i].o_var &&
- option_info[i].o_text &&
- streq(option_info[i].o_text, buf + 2))
+ if (option.o_var && streq(option.o_text, buf + 2))
{
- (*option_info[i].o_var) = FALSE;
- return (0);
+ *option.o_var = FALSE;
+ return 0;
}
}
}
@@ -552,14 +635,12 @@ errr process_pref_file_aux(char *buf)
/* Process "Y:<str>" -- turn option on */
else if (buf[0] == 'Y')
{
- for (i = 0; option_info[i].o_desc; i++)
+ for (auto const &option: options->standard_options)
{
- if (option_info[i].o_var &&
- option_info[i].o_text &&
- streq(option_info[i].o_text, buf + 2))
+ if (option.o_var && streq(option.o_text, buf + 2))
{
- (*option_info[i].o_var) = TRUE;
- return (0);
+ *option.o_var = TRUE;
+ return 0;
}
}
}
@@ -834,39 +915,28 @@ static cptr process_pref_file_expr(char **sp, char *fp)
v = ANGBAND_SYS;
}
- else if (streq(b + 1, "KEYBOARD"))
- {
- v = ANGBAND_KEYBOARD;
- }
-
- /* Graphics */
- if (streq(b + 1, "GRAF"))
- {
- v = ANGBAND_GRAF;
- }
-
/* Race */
else if (streq(b + 1, "RACE"))
{
- v = rp_ptr->title + rp_name;
+ v = rp_ptr->title.c_str(); // The string SHOULD be stable enough for this
}
/* Race */
else if (streq(b + 1, "RACEMOD"))
{
- v = rmp_ptr->title + rmp_name;
+ v = rmp_ptr->title.c_str(); // The string SHOULD be stable enough for this
}
/* Class */
else if (streq(b + 1, "CLASS"))
{
- v = spp_ptr->title + c_name;
+ v = spp_ptr->title;
}
/* Player */
else if (streq(b + 1, "PLAYER"))
{
- v = player_base;
+ v = game->player_base.c_str(); // The string SHOULD be stable enough for this
}
}
@@ -975,7 +1045,7 @@ errr process_pref_file(cptr name)
if (buf[0] == '%')
{
/* Process that file if allowed */
- (void)process_pref_file(buf + 2);
+ process_pref_file(buf + 2);
/* Continue */
continue;
@@ -1018,7 +1088,7 @@ static void prt_lnum(cptr header, s32b num, int row, int col, byte color)
char out_val[32];
put_str(header, row, col);
- (void)sprintf(out_val, "%9ld", (long)num);
+ sprintf(out_val, "%9ld", (long)num);
c_put_str(color, out_val, row, col + len);
}
@@ -1027,14 +1097,14 @@ 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];
put_str(header, row, col);
put_str(space, row, col + len);
- (void)sprintf(out_val, "%6ld", (long)num);
+ sprintf(out_val, "%6ld", (long)num);
c_put_str(color, out_val, row, col + len + strlen(space));
}
@@ -1049,7 +1119,7 @@ static void prt_str(cptr header, cptr str, int row, int col, byte color)
put_str(header, row, col);
put_str(" ", row, col + len);
- (void)sprintf(out_val, "%6s", str);
+ sprintf(out_val, "%6s", str);
c_put_str(color, out_val, row, col + len + 3);
}
@@ -1060,7 +1130,7 @@ static void prt_str(cptr header, cptr str, int row, int col, byte color)
* For this to look right, the following should be spaced the
* same as in the prt_lnum code... -CFT
*/
-static void display_player_middle(void)
+static void display_player_middle()
{
int show_tohit = p_ptr->dis_to_h;
int show_todam = p_ptr->dis_to_d;
@@ -1108,7 +1178,7 @@ static void display_player_middle(void)
prt_lnum("Max Exp ", p_ptr->max_exp, 11, 28, TERM_L_GREEN);
- if ((p_ptr->lev >= PY_MAX_LEVEL) || (p_ptr->lev >= max_plev))
+ if (p_ptr->lev >= PY_MAX_LEVEL)
{
put_str("Exp to Adv.", 12, 28);
c_put_str(TERM_L_GREEN, " *****", 12, 28 + 11);
@@ -1129,7 +1199,7 @@ static void display_player_middle(void)
{
color = TERM_L_BLUE;
}
- else if (p_ptr->chp > (p_ptr->mhp * hitpoint_warn) / 10)
+ else if (p_ptr->chp > (p_ptr->mhp * options->hitpoint_warn) / 10)
{
color = TERM_VIOLET;
}
@@ -1137,10 +1207,10 @@ static void display_player_middle(void)
{
color = TERM_L_RED;
}
- (void)sprintf(num, "%6ld", (long)p_ptr->chp);
+ sprintf(num, "%6ld", (long)p_ptr->chp);
c_put_str(color, num, 9, 65);
put_str("/", 9, 71);
- (void)sprintf(num, "%6ld", (long)p_ptr->mhp);
+ sprintf(num, "%6ld", (long)p_ptr->mhp);
c_put_str(TERM_L_BLUE, num, 9, 72);
}
else
@@ -1150,7 +1220,7 @@ static void display_player_middle(void)
{
color = TERM_L_GREEN;
}
- else if (p_ptr->chp > (p_ptr->mhp * hitpoint_warn) / 10)
+ else if (p_ptr->chp > (p_ptr->mhp * options->hitpoint_warn) / 10)
{
color = TERM_YELLOW;
}
@@ -1158,10 +1228,10 @@ static void display_player_middle(void)
{
color = TERM_RED;
}
- (void)sprintf(num, "%6ld", (long)p_ptr->chp);
+ sprintf(num, "%6ld", (long)p_ptr->chp);
c_put_str(color, num, 9, 65);
put_str("/", 9, 71);
- (void)sprintf(num, "%6ld", (long)p_ptr->mhp);
+ sprintf(num, "%6ld", (long)p_ptr->mhp);
c_put_str(TERM_L_GREEN, num, 9, 72);
}
@@ -1170,7 +1240,7 @@ static void display_player_middle(void)
{
color = TERM_L_GREEN;
}
- else if (p_ptr->csp > (p_ptr->msp * hitpoint_warn) / 10)
+ else if (p_ptr->csp > (p_ptr->msp * options->hitpoint_warn) / 10)
{
color = TERM_YELLOW;
}
@@ -1178,10 +1248,10 @@ static void display_player_middle(void)
{
color = TERM_RED;
}
- (void)sprintf(num, "%6ld", (long)p_ptr->csp);
+ sprintf(num, "%6ld", (long)p_ptr->csp);
c_put_str(color, num, 10, 65);
put_str("/", 10, 71);
- (void)sprintf(num, "%6ld", (long)p_ptr->msp);
+ sprintf(num, "%6ld", (long)p_ptr->msp);
c_put_str(TERM_L_GREEN, num, 10, 72);
put_str("Sanity ", 11, 52);
@@ -1189,7 +1259,7 @@ static void display_player_middle(void)
{
color = TERM_L_GREEN;
}
- else if (p_ptr->csane > (p_ptr->msane * hitpoint_warn) / 10)
+ else if (p_ptr->csane > (p_ptr->msane * options->hitpoint_warn) / 10)
{
color = TERM_YELLOW;
}
@@ -1197,10 +1267,10 @@ static void display_player_middle(void)
{
color = TERM_RED;
}
- (void)sprintf(num, "%6ld", (long)p_ptr->csane);
+ sprintf(num, "%6ld", (long)p_ptr->csane);
c_put_str(color, num, 11, 65);
put_str("/", 11, 71);
- (void)sprintf(num, "%6ld", (long)p_ptr->msane);
+ sprintf(num, "%6ld", (long)p_ptr->msane);
c_put_str(TERM_L_GREEN, num, 11, 72);
if (p_ptr->pgod != GOD_NONE)
@@ -1210,18 +1280,16 @@ static void display_player_middle(void)
put_str("Speed ", 13, 52);
speed = p_ptr->pspeed;
- /* Hack -- Visually "undo" the Search Mode Slowdown */
- if (p_ptr->searching) speed += 10;
if (speed > 110)
{
char s[11];
- (void)sprintf(s, "Fast (+%d)", speed - 110);
+ sprintf(s, "Fast (+%d)", speed - 110);
c_put_str(TERM_L_GREEN, s, 13, (speed >= 120) ? 68 : 69);
}
else if (speed < 110)
{
char s[11];
- (void)sprintf(s, "Slow (-%d)", 110 - speed);
+ sprintf(s, "Slow (-%d)", 110 - speed);
c_put_str(TERM_L_UMBER, s, 13, (speed <= 100) ? 68 : 69);
}
else
@@ -1324,11 +1392,13 @@ static cptr likert(int x, int y)
*
* This code is "imitated" elsewhere to "dump" a character sheet.
*/
-static void display_player_various(void)
+static void display_player_various()
{
+ auto const &r_info = game->edit_data.r_info;
+
int tmp, tmp2, damdice, damsides, dambonus, blows;
- int xthn, xthb, xfos, xsrh;
- int xdis, xdev, xsav, xstl;
+ int xthn, xthb;
+ int xdev, xsav, xstl;
cptr desc;
int i;
@@ -1350,12 +1420,9 @@ static void display_player_various(void)
blows = p_ptr->num_blow;
/* Basic abilities */
- xdis = p_ptr->skill_dis;
xdev = p_ptr->skill_dev;
xsav = p_ptr->skill_sav;
xstl = p_ptr->skill_stl;
- xsrh = p_ptr->skill_srh;
- xfos = p_ptr->skill_fos;
put_str("Fighting :", 16, 1);
@@ -1375,21 +1442,9 @@ static void display_player_various(void)
c_put_str(likert_color, desc, 19, 15);
- put_str("Perception :", 16, 28);
- desc = likert(xfos, 6);
- c_put_str(likert_color, desc, 16, 42);
-
- put_str("Searching :", 17, 28);
- desc = likert(xsrh, 6);
- c_put_str(likert_color, desc, 17, 42);
-
- put_str("Disarming :", 18, 28);
- desc = likert(xdis, 8);
- c_put_str(likert_color, desc, 18, 42);
-
- put_str("Magic Device:", 19, 28);
+ put_str("Magic Device:", 20, 1);
desc = likert(xdev, 6);
- c_put_str(likert_color, desc, 19, 42);
+ c_put_str(likert_color, desc, 20, 15);
put_str("Blows/Round:", 16, 55);
@@ -1436,7 +1491,7 @@ static void display_player_various(void)
}
else if (!r_info[p_ptr->body_monster].body_parts[BODY_WEAPON])
{
- if (r_info[p_ptr->body_monster].flags1 & RF1_NEVER_BLOW)
+ if (r_info[p_ptr->body_monster].flags & RF_NEVER_BLOW)
desc = "nil!";
else
{
@@ -1505,29 +1560,38 @@ static void display_player_various(void)
* Obtain the "flags" of the wielded symbiote
*/
-void wield_monster_flags(u32b *f1, u32b *f2, u32b *f3, u32b *f4, u32b *f5, u32b *esp)
+static object_flag_set wield_monster_flags()
{
- object_type *o_ptr;
- monster_race *r_ptr;
+ auto const &r_info = game->edit_data.r_info;
- /* Clear */
- (*f1) = (*f2) = (*f3) = (*f4) = (*f5) = (*esp) = 0L;
+ object_flag_set flags;
/* Get the carried monster */
- o_ptr = &p_ptr->inventory[INVEN_CARRY];
-
+ auto o_ptr = &p_ptr->inventory[INVEN_CARRY];
if (o_ptr->k_idx)
{
- r_ptr = &r_info[o_ptr->pval];
+ auto r_ptr = &r_info[o_ptr->pval];
- if (r_ptr->flags2 & RF2_INVISIBLE)
- (*f2) |= TR2_INVIS;
- if (r_ptr->flags2 & RF2_REFLECTING)
- (*f2) |= TR2_REFLECT;
- if (r_ptr->flags7 & RF7_CAN_FLY)
- (*f3) |= TR3_FEATHER;
- if (r_ptr->flags7 & RF7_AQUATIC)
- (*f5) |= TR5_WATER_BREATH;
+ if (r_ptr->flags & RF_INVISIBLE)
+ flags |= TR_INVIS;
+ if (r_ptr->flags & RF_REFLECTING)
+ flags |= TR_REFLECT;
+ if (r_ptr->flags & RF_CAN_FLY)
+ flags |= TR_FEATHER;
+ if (r_ptr->flags & RF_AQUATIC)
+ flags |= TR_WATER_BREATH;
+ }
+
+ return flags;
+}
+
+
+template<class LF>
+static void apply_lflags(LF const &lflags, object_flag_set *f)
+{
+ for (int i = 1; i <= p_ptr->lev; i++)
+ {
+ (*f) |= lflags[i].oflags;
}
}
@@ -1535,565 +1599,620 @@ void wield_monster_flags(u32b *f1, u32b *f2, u32b *f3, u32b *f4, u32b *f5, u32b
/*
* Obtain the "flags" for the player as if he was an item
*/
-void player_flags(u32b *f1, u32b *f2, u32b *f3, u32b *f4, u32b *f5, u32b *esp)
+object_flag_set player_flags()
{
- int i;
+ auto const &r_info = game->edit_data.r_info;
/* Clear */
- (*f1) = (*f2) = (*f3) = (*f4) = (*f5) = (*esp) = 0L;
+ object_flag_set f;
/* Astral chars */
if (p_ptr->astral)
{
- (*f3) |= TR3_WRAITH;
+ f |= TR_WRAITH;
}
/* Skills */
- if (get_skill(SKILL_DAEMON) > 20) (*f2) |= TR2_RES_CONF;
- if (get_skill(SKILL_DAEMON) > 30) (*f2) |= TR2_RES_FEAR;
- if (get_skill(SKILL_MINDCRAFT) >= 40) (*esp) |= ESP_ALL;
+ if (get_skill(SKILL_DAEMON) > 20) f |= TR_RES_CONF;
+ if (get_skill(SKILL_DAEMON) > 30) f |= TR_RES_FEAR;
+ if (get_skill(SKILL_MINDCRAFT) >= 40) f |= ESP_ALL;
if (p_ptr->melee_style == SKILL_HAND && get_skill(SKILL_HAND) > 24 && !monk_heavy_armor())
- (*f2) |= TR2_FREE_ACT;
-/* Hack - from Lua */
- if (get_skill(SKILL_MANA) >= 35) (*f1) |= TR1_MANA;
- if (get_skill(SKILL_AIR) >= 50) (*f5) |= (TR5_MAGIC_BREATH | TR5_WATER_BREATH);
- if (get_skill(SKILL_WATER) >= 30) (*f5) |= TR5_WATER_BREATH;
+ {
+ f |= TR_FREE_ACT;
+ }
+ if (get_skill(SKILL_MANA) >= 35) f |= TR_MANA;
+ if (get_skill(SKILL_AIR) >= 50) f |= (TR_MAGIC_BREATH | TR_WATER_BREATH);
+ if (get_skill(SKILL_WATER) >= 30) f |= TR_WATER_BREATH;
/* Gods */
- GOD(GOD_ERU)
+ if (p_ptr->pgod == GOD_ERU)
{
- if ((p_ptr->grace >= 100) || (p_ptr->grace <= -100)) (*f1) |= TR1_MANA;
- if (p_ptr->grace > 10000) (*f1) |= TR1_WIS;
+ if ((p_ptr->grace >= 100) || (p_ptr->grace <= -100)) f |= TR_MANA;
+ if (p_ptr->grace > 10000) f |= TR_WIS;
}
- GOD(GOD_MELKOR)
+ if (p_ptr->pgod == GOD_MELKOR)
{
- (*f2) |= TR2_RES_FIRE;
- if (p_ptr->melkor_sacrifice > 0) (*f2) |= TR2_LIFE;
- if (p_ptr->grace > 10000) (*f1) |= (TR1_STR | TR1_CON | TR1_INT | TR1_WIS | TR1_CHR);
- PRAY_GOD(GOD_MELKOR)
+ f |= TR_RES_FIRE;
+ if (p_ptr->melkor_sacrifice > 0) f |= TR_LIFE;
+ if (p_ptr->grace > 10000) f |= (TR_STR | TR_CON | TR_INT | TR_WIS | TR_CHR);
+ if (p_ptr->praying)
{
- if (p_ptr->grace > 5000) (*f2) |= TR2_INVIS;
- if (p_ptr->grace > 15000) (*f2) |= TR2_IM_FIRE;
+ if (p_ptr->grace > 5000) f |= TR_INVIS;
+ if (p_ptr->grace > 15000) f |= TR_IM_FIRE;
}
}
- GOD(GOD_MANWE)
+ if (p_ptr->pgod == GOD_MANWE)
{
- if (p_ptr->grace >= 2000) (*f3) |= TR3_FEATHER;
- PRAY_GOD(GOD_MANWE)
+ if (p_ptr->grace >= 2000) f |= TR_FEATHER;
+ if (p_ptr->praying)
{
- if (p_ptr->grace >= 7000) (*f2) |= TR2_FREE_ACT;
- if (p_ptr->grace >= 15000) (*f4) |= TR4_FLY;
- if ((p_ptr->grace >= 5000) || (p_ptr->grace <= -5000)) (*f1) |= TR1_SPEED;
+ if (p_ptr->grace >= 7000) f |= TR_FREE_ACT;
+ if (p_ptr->grace >= 15000) f |= TR_FLY;
+ if ((p_ptr->grace >= 5000) || (p_ptr->grace <= -5000)) f |= TR_SPEED;
}
}
- GOD(GOD_TULKAS)
+ if (p_ptr->pgod == GOD_TULKAS)
{
- if (p_ptr->grace > 5000) (*f1) |= TR1_CON;
- if (p_ptr->grace > 10000) (*f1) |= TR1_STR;
+ if (p_ptr->grace > 5000) f |= TR_CON;
+ if (p_ptr->grace > 10000) f |= TR_STR;
}
- /* Classes */
- for (i = 1; i <= p_ptr->lev; i++)
+ if (p_ptr->pgod == GOD_AULE)
{
- (*f1) |= cp_ptr->oflags1[i];
- (*f2) |= cp_ptr->oflags2[i];
- (*f3) |= cp_ptr->oflags3[i];
- (*f4) |= cp_ptr->oflags4[i];
- (*f5) |= cp_ptr->oflags5[i];
- (*esp) |= cp_ptr->oesp[i];
+ if (p_ptr->grace > 5000)
+ {
+ f |= TR_RES_FIRE;
+ }
}
- /* Races */
- if ((!p_ptr->mimic_form) && (!p_ptr->body_monster))
+ if (p_ptr->pgod == GOD_MANDOS)
+ {
+ f |= TR_RES_NETHER;
+
+ if ((p_ptr->grace > 10000) &&
+ (p_ptr->praying == TRUE))
+ {
+ f |= TR_NO_TELE;
+ }
+
+ if ((p_ptr->grace > 20000) &&
+ (p_ptr->praying == TRUE))
+ {
+ f |= TR_IM_NETHER;
+ }
+ }
+
+ if (p_ptr->pgod == GOD_ULMO)
{
- for (i = 1; i <= p_ptr->lev; i++)
+ f |= TR_WATER_BREATH;
+
+ if ((p_ptr->grace > 1000) &&
+ (p_ptr->praying == TRUE))
{
- (*f1) |= rp_ptr->oflags1[i];
- (*f2) |= rp_ptr->oflags2[i];
- (*f3) |= rp_ptr->oflags3[i];
- (*f4) |= rp_ptr->oflags4[i];
- (*f5) |= rp_ptr->oflags5[i];
- (*esp) |= rp_ptr->oesp[i];
+ f |= TR_RES_POIS;
+ }
- (*f1) |= rmp_ptr->oflags1[i];
- (*f2) |= rmp_ptr->oflags2[i];
- (*f3) |= rmp_ptr->oflags3[i];
- (*f4) |= rmp_ptr->oflags4[i];
- (*f5) |= rmp_ptr->oflags5[i];
- (*esp) |= rmp_ptr->oesp[i];
+ if ((p_ptr->grace > 15000) &&
+ (p_ptr->praying == TRUE))
+ {
+ f |= TR_MAGIC_BREATH;
}
}
+
+ /* Classes */
+ apply_lflags(cp_ptr->lflags, &f);
+
+ /* Races */
+ if ((!p_ptr->mimic_form) && (!p_ptr->body_monster))
+ {
+ apply_lflags(rp_ptr->lflags, &f);
+ apply_lflags(rmp_ptr->lflags, &f);
+ }
else
{
- monster_race *r_ptr = &r_info[p_ptr->body_monster];
-
- if (r_ptr->flags2 & RF2_REFLECTING) (*f2) |= TR2_REFLECT;
- if (r_ptr->flags2 & RF2_REGENERATE) (*f3) |= TR3_REGEN;
- if (r_ptr->flags2 & RF2_AURA_FIRE) (*f3) |= TR3_SH_FIRE;
- if (r_ptr->flags2 & RF2_AURA_ELEC) (*f3) |= TR3_SH_ELEC;
- if (r_ptr->flags2 & RF2_PASS_WALL) (*f3) |= TR3_WRAITH;
- if (r_ptr->flags3 & RF3_SUSCEP_FIRE) (*f2) |= TR2_SENS_FIRE;
- if (r_ptr->flags3 & RF3_IM_ACID) (*f2) |= TR2_RES_ACID;
- if (r_ptr->flags3 & RF3_IM_ELEC) (*f2) |= TR2_RES_ELEC;
- if (r_ptr->flags3 & RF3_IM_FIRE) (*f2) |= TR2_RES_FIRE;
- if (r_ptr->flags3 & RF3_IM_POIS) (*f2) |= TR2_RES_POIS;
- if (r_ptr->flags3 & RF3_IM_COLD) (*f2) |= TR2_RES_COLD;
- if (r_ptr->flags3 & RF3_RES_NETH) (*f2) |= TR2_RES_NETHER;
- if (r_ptr->flags3 & RF3_RES_NEXU) (*f2) |= TR2_RES_NEXUS;
- if (r_ptr->flags3 & RF3_RES_DISE) (*f2) |= TR2_RES_DISEN;
- if (r_ptr->flags3 & RF3_NO_FEAR) (*f2) |= TR2_RES_FEAR;
- if (r_ptr->flags3 & RF3_NO_SLEEP) (*f2) |= TR2_FREE_ACT;
- if (r_ptr->flags3 & RF3_NO_CONF) (*f2) |= TR2_RES_CONF;
- if (r_ptr->flags7 & RF7_CAN_FLY) (*f3) |= TR3_FEATHER;
- }
-
- (*f1) |= p_ptr->xtra_f1;
- (*f2) |= p_ptr->xtra_f2;
- (*f3) |= p_ptr->xtra_f3;
- (*f4) |= p_ptr->xtra_f4;
- (*f5) |= p_ptr->xtra_f5;
- (*esp) |= p_ptr->xtra_esp;
+ auto &r_ref = r_info[p_ptr->body_monster];
+
+ if (r_ref.flags & RF_REFLECTING) f |= TR_REFLECT;
+ if (r_ref.flags & RF_REGENERATE) f |= TR_REGEN;
+ if (r_ref.flags & RF_AURA_FIRE) f |= TR_SH_FIRE;
+ if (r_ref.flags & RF_AURA_ELEC) f |= TR_SH_ELEC;
+ if (r_ref.flags & RF_PASS_WALL) f |= TR_WRAITH;
+ if (r_ref.flags & RF_SUSCEP_FIRE) f |= TR_SENS_FIRE;
+ if (r_ref.flags & RF_IM_ACID) f |= TR_RES_ACID;
+ if (r_ref.flags & RF_IM_ELEC) f |= TR_RES_ELEC;
+ if (r_ref.flags & RF_IM_FIRE) f |= TR_RES_FIRE;
+ if (r_ref.flags & RF_IM_POIS) f |= TR_RES_POIS;
+ if (r_ref.flags & RF_IM_COLD) f |= TR_RES_COLD;
+ if (r_ref.flags & RF_RES_NETH) f |= TR_RES_NETHER;
+ if (r_ref.flags & RF_RES_NEXU) f |= TR_RES_NEXUS;
+ if (r_ref.flags & RF_RES_DISE) f |= TR_RES_DISEN;
+ if (r_ref.flags & RF_NO_FEAR) f |= TR_RES_FEAR;
+ if (r_ref.flags & RF_NO_SLEEP) f |= TR_FREE_ACT;
+ if (r_ref.flags & RF_NO_CONF) f |= TR_RES_CONF;
+ if (r_ref.flags & RF_CAN_FLY) f |= TR_FEATHER;
+ }
+
+ f |= p_ptr->xtra_flags;
if (p_ptr->black_breath)
{
- (*f4) |= TR4_BLACK_BREATH;
+ f |= TR_BLACK_BREATH;
}
if (p_ptr->hp_mod != 0)
{
- (*f2) |= TR2_LIFE;
+ f |= TR_LIFE;
}
+
+ return f;
}
+namespace { // <anonymous>
+
/*
- * Object flag names
+ * Build an return a (static) index of all the object_flag_meta
+ * information indexed by page->column->row.
*/
-static cptr object_flag_names[192] =
+static std::vector<object_flag_meta const *> const &object_flag_metas_by_pcr(int page, int column, int row)
{
- "Add Str",
- "Add Int",
- "Add Wis",
- "Add Dex",
- "Add Con",
- "Add Chr",
- "Mul Mana",
- "Mul SPower",
- "Add Stea.",
- "Add Sear.",
- "Add Infra",
- "Add Tun..",
- "Add Speed",
- "Add Blows",
- "Chaotic",
- "Vampiric",
- "Slay Anim.",
- "Slay Evil",
- "Slay Und.",
- "Slay Demon",
- "Slay Orc",
- "Slay Troll",
- "Slay Giant",
- "Slay Drag.",
- "Kill Drag.",
- "Sharpness",
- "Impact",
- "Poison Brd",
- "Acid Brand",
- "Elec Brand",
- "Fire Brand",
- "Cold Brand",
-
- "Sust Str",
- "Sust Int",
- "Sust Wis",
- "Sust Dex",
- "Sust Con",
- "Sust Chr",
- "Invisible",
- "Mul life",
- "Imm Acid",
- "Imm Elec",
- "Imm Fire",
- "Imm Cold",
- "Sens Fire",
- "Reflect",
- "Free Act",
- "Hold Life",
- "Res Acid",
- "Res Elec",
- "Res Fire",
- "Res Cold",
- "Res Pois",
- "Res Fear",
- "Res Light",
- "Res Dark",
- "Res Blind",
- "Res Conf",
- "Res Sound",
- "Res Shard",
- "Res Neth",
- "Res Nexus",
- "Res Chaos",
- "Res Disen",
-
-
-
- "Aura Fire",
- "Aura Elec",
- "Auto Curse",
- NULL,
- "NoTeleport",
- "AntiMagic",
- "WraithForm",
- "EvilCurse",
- NULL,
- NULL,
- NULL,
- NULL,
- "Levitate",
- "Lite",
- "See Invis",
- NULL,
- "Digestion",
- "Regen",
- "Xtra Might",
- "Xtra Shots",
- NULL,
- NULL,
- NULL,
- NULL,
- "Activate",
- "Drain Exp",
- "Teleport",
- "Aggravate",
- "Blessed",
- "Cursed",
- "Hvy Curse",
- "Prm Curse",
-
- "No blows",
- "Precogn.",
- "B.Breath",
- "Recharge",
- "Fly",
- "Mrg.Curse",
- NULL,
- NULL,
- "Sentient",
- "Clone",
- NULL,
- "Climb",
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- "Imm Neth",
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
-
- "Orc.ESP",
- "Troll.ESP",
- "Dragon.ESP",
- "Giant.ESP",
- "Demon.ESP",
- "Undead.ESP",
- "Evil.ESP",
- "Animal.ESP",
- "TLord.ESP",
- "Good.ESP",
- "Nlive.ESP",
- "Unique.ESP",
- "Spider ESP",
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- "Full ESP",
+ static std::vector<std::vector<std::vector<std::vector<object_flag_meta const *>>>> instance;
+
+ if (instance.empty())
+ {
+ // Find number of pages, columns and rows.
+ std::size_t n_pages = 0;
+ std::size_t n_columns = 0;
+ std::size_t n_rows = 0;
+
+ for (auto const &object_flag_meta: object_flags_meta())
+ {
+ n_pages = std::max<std::size_t>(n_pages, object_flag_meta->c_page + 1);
+ n_columns = std::max<std::size_t>(n_columns, object_flag_meta->c_column + 1);
+ n_rows = std::max<std::size_t>(n_rows, object_flag_meta->c_row + 1);
+ }
+
+ // Sanity check; we should always have enough data.
+ assert(n_pages > 0);
+ assert(n_columns > 0);
+ assert(n_rows > 0);
+
+ // Build the scaffolding structure without the actual data.
+ instance.reserve(n_pages);
+ for (std::size_t i = 0; i < n_pages; i++)
+ {
+ std::vector<std::vector<std::vector<object_flag_meta const *>>> page;
+ page.reserve(n_columns);
+
+ for (std::size_t j = 0; j < n_columns; j++)
+ {
+ std::vector<std::vector<object_flag_meta const *>> column;
+ column.reserve(n_rows);
+
+ for (std::size_t k = 0; k < n_rows; k++)
+ {
+ std::vector<object_flag_meta const *> row;
+ column.push_back(row);
+ }
+
+ page.push_back(column);
+ }
+
+ instance.push_back(page);
+ }
+
+ // Insert all the data.
+ for (auto const object_flag_meta: object_flags_meta())
+ {
+ // Ignore if not mapped to any page.
+ if (!object_flag_meta->c_name)
+ {
+ continue;
+ }
+
+ // Find the row
+ auto &row = instance
+ .at(object_flag_meta->c_page)
+ .at(object_flag_meta->c_column)
+ .at(object_flag_meta->c_row);
+
+ // Insert
+ row.push_back(object_flag_meta);
+ }
+ }
+
+ return instance.at(page).at(column).at(row);
+}
+
+
+/**
+ * Convert a number to a digit, capping at '9'. Ignores the sign of the number.
+ */
+static char number_to_digit(int n) {
+ // Throw away sign.
+ n = std::abs(n);
+ // Convert to digit or '*'
+ return (n > 9 ? '*' : I2D(n));
};
-/*
- * Summarize resistances
+
+/**
+ * Check that two object_flag types are compatible.
*/
-static void display_player_ben_one(int mode)
+static bool object_flag_types_are_compatible(char type_a, char type_b)
{
- int i, n, x, y, z, dispx, modetemp, xtemp;
+ switch (type_a)
+ {
+ case 'n':
+ return (type_b == 'n');
+ case 'b':
+ return (type_b == 'b');
+ case '+':
+ case '*':
+ return (type_b == '+') || (type_b == '*');
+ case 'f':
+ return (type_b == 'f');
+ case '\0':
+ return true;
+ default:
+ abort();
+ }
+}
- object_type *o_ptr;
+/**
+ * Object flag data for calculating cells on the character sheet.
+ */
+struct object_flag_cell {
+ /**
+ * Type designator for the cell, if any.
+ */
+ char type;
- char dummy[80], c;
+ /**
+ * Associated PVAL, if any.
+ */
+ int pval;
- u32b f1, f2, f3, f4, f5, esp;
+ /**
+ * Label for the cell, given its current contents.
+ */
+ const char *label;
- u16b b[INVEN_TOTAL - INVEN_WIELD + 1][10];
+ /**
+ * Create object_flag_cell from object_flag_meta.
+ */
+ static object_flag_cell from_object_flag_meta(object_flag_meta const &object_flag_meta, int pval)
+ {
+ // The FIXED type flags require special handling.
+ if ((object_flag_meta.c_type == '1') || (object_flag_meta.c_type == '2') || (object_flag_meta.c_type == '3'))
+ {
+ return object_flag_cell {
+ 'f',
+ D2I(object_flag_meta.c_type),
+ object_flag_meta.c_name
+ };
+ }
+ else
+ {
+ return object_flag_cell {
+ object_flag_meta.c_type,
+ pval,
+ object_flag_meta.c_name
+ };
+ }
+ }
- int d[INVEN_TOTAL - INVEN_WIELD + 1];
+};
- bool_ got;
+namespace detail { // "hide" from surrounding scope; should only be accessed through the monoid
- byte a;
+static object_flag_cell object_flag_cell_append(object_flag_cell const &a, object_flag_cell const &b)
+{
+ // The "empty" value automatically gets swallowed, whatever
+ // "side" of the append it's on.
+ if (a.type == '\0')
+ {
+ return b;
+ }
- cptr name;
+ if (b.type == '\0')
+ {
+ return a;
+ }
- /* Scan equipment */
- for (i = INVEN_WIELD; i < INVEN_TOTAL; i++)
+ // The rest of the code assumes compatible types, so we
+ // assert this to a) avoid over-complicated logic, and
+ // b) breaking under 'unexpected' changes to the object
+ // flag list.
+ if (!object_flag_types_are_compatible(a.type, b.type))
{
- /* Index */
- n = (i - INVEN_WIELD);
+ abort();
+ }
- /* Object */
- o_ptr = &p_ptr->inventory[i];
+ // Any boolean flag which is "set" overrides the previous
+ // flag. (If the flag was already set we won't lose any
+ // information.)
+ if (b.type == 'b')
+ {
+ return b;
+ }
- /* Known object flags */
- object_flags_known(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ // Flags with a numerical value get added together.
+ if (b.type == 'n') // (a.type == 'n') by symmetry and object_flag_types_are_compatible()
+ {
+ // Arbitrary choice of label -- the labels *should* be the same, by definition
+ return object_flag_cell { 'n', a.pval + b.pval, a.label };
+ }
- /* Incorporate */
- b[n][0] = (u16b)(f1 & 0xFFFF);
- b[n][1] = (u16b)(f1 >> 16);
- b[n][2] = (u16b)(f2 & 0xFFFF);
- b[n][3] = (u16b)(f2 >> 16);
- b[n][4] = (u16b)(f3 & 0xFFFF);
- b[n][5] = (u16b)(f3 >> 16);
- b[n][6] = (u16b)(f4 & 0xFFFF);
- b[n][7] = (u16b)(f4 >> 16);
- b[n][8] = (u16b)(esp & 0xFFFF);
- b[n][9] = (u16b)(esp >> 16);
- d[n] = o_ptr->pval;
+ // Fixed-value flags.
+ if (a.type == 'f') // (b.type == 'f') by symmetry and object_flag_types_are_compatible()
+ {
+ // Arbitrary choice of label -- the labels *should* be the same, by definition
+ return object_flag_cell { 'f', a.pval + b.pval, a.label };
}
- /* Carried symbiote */
- n = INVEN_CARRY - INVEN_WIELD;
+ // Flags of the TERNARY variety have a "supercedes" rule
+ // where immunity supercedes resistance.
+ if (a.type == '*')
+ {
+ return object_flag_cell { '*', 0, a.label };
+ }
+ else if (b.type == '*')
+ {
+ return object_flag_cell { '*', 0, b.label };
+ }
+ else // Both must be '+'
+ {
+ // Arbitrary choice of label -- the labels *should* be the same, by definition
+ return object_flag_cell { '+', 0, a.label };
+ }
+}
- /* Player flags */
- wield_monster_flags(&f1, &f2, &f3, &f4, &f5, &esp);
+constexpr object_flag_cell object_flag_cell_empty { '\0', 0, nullptr };
- /* Incorporate */
- b[n][0] = (u16b)(f1 & 0xFFFF);
- b[n][1] = (u16b)(f1 >> 16);
- b[n][2] = (u16b)(f2 & 0xFFFF);
- b[n][3] = (u16b)(f2 >> 16);
- b[n][4] = (u16b)(f3 & 0xFFFF);
- b[n][5] = (u16b)(f3 >> 16);
- b[n][6] = (u16b)(f4 & 0xFFFF);
- b[n][7] = (u16b)(f4 >> 16);
- b[n][8] = (u16b)(esp & 0xFFFF);
- b[n][9] = (u16b)(esp >> 16);
+} // namespace "detail"
- /* Index */
- n = INVEN_TOTAL - INVEN_WIELD;
+using object_flag_cell_monoid = monoid<object_flag_cell, detail::object_flag_cell_append, detail::object_flag_cell_empty>;
- /* Player flags */
- player_flags(&f1, &f2, &f3, &f4, &f5, &esp);
+} // namespace <anonymous>
- /* Incorporate */
- b[n][0] = (u16b)(f1 & 0xFFFF);
- b[n][1] = (u16b)(f1 >> 16);
- b[n][2] = (u16b)(f2 & 0xFFFF);
- b[n][3] = (u16b)(f2 >> 16);
- b[n][4] = (u16b)(f3 & 0xFFFF);
- b[n][5] = (u16b)(f3 >> 16);
- b[n][6] = (u16b)(f4 & 0xFFFF);
- b[n][7] = (u16b)(f4 >> 16);
- b[n][8] = (u16b)(esp & 0xFFFF);
- b[n][9] = (u16b)(esp >> 16);
+namespace { // <anonymous>
+
+static object_flag_meta const *get_lowest_priority_object_flag_meta(std::vector<object_flag_meta const *> const &object_flag_metas)
+{
+ object_flag_meta const *found = nullptr;
- /* Generate the equip chars */
- sprintf(dummy, " ");
- for (i = 0; i < INVEN_TOTAL - INVEN_WIELD; i++)
+ for (auto object_flag_meta: object_flag_metas)
{
- /* If you have that body part then show it */
- if (p_ptr->body_parts[i])
+ if ((!found) || (found->c_priority > object_flag_meta->c_priority))
{
- strcat(dummy, format("%c", i + 'a'));
+ found = object_flag_meta;
}
}
- strcat(dummy, "@");
- /* Scan cols */
- for (x = 1; x > -1; x--)
+ return found;
+}
+
+
+static std::tuple<char, int> object_flag_cell_to_char(object_flag_cell const &object_flag_cell)
+{
+ switch (object_flag_cell.type)
+ {
+ case 'n':
+ case 'f':
+ // If we have no pval, we use a simple '+'. This applies
+ // to the 'player' slot.
+ if (object_flag_cell.pval == 0)
+ {
+ return std::make_tuple('+', 1);
+ }
+ else
+ {
+ return std::make_tuple(
+ number_to_digit(object_flag_cell.pval),
+ (object_flag_cell.pval >= 0) ? 1 : -1);
+ }
+ break;
+
+ case 'b':
+ case '+':
+ return std::make_tuple('+', 1);
+ break;
+
+ case '*':
+ return std::make_tuple('*', 1);
+ break;
+
+ default:
+ return std::make_tuple('.', 0);
+ break;
+ }
+
+ abort();
+}
+
+
+/*
+ * Output a slot
+ */
+static void display_flag_row(
+ int y,
+ int x0,
+ std::vector<std::tuple<char, int, object_flag_set>> const &slots,
+ std::vector<object_flag_meta const *> const &object_flag_metas_at_pcr)
+{
+ assert(!object_flag_metas_at_pcr.empty());
+
+ // Accumulated value of all of the slots
+ auto acc = object_flag_cell_monoid::empty;
+
+ // Go through each slot
+ for (std::size_t i = 0; i < slots.size(); i++)
{
- /* Label */
- Term_putstr(x * 40 + 11, 3, -1, TERM_WHITE, dummy);
+ object_flag_cell combined = object_flag_cell_monoid::empty;
- /* Scan rows */
- for (y = 0; y < 16; y++)
+ // Go through all flags that are actually set for this 'cell'.
{
- if (mode == 3 && x == 1)
- {
- modetemp = 4;
- xtemp = 0;
- }
- else
+ auto const &slot = slots[i];
+ auto const pval = std::get<1>(slot);
+ auto const flags = std::get<2>(slot);
+
+ for (auto const object_flag_meta: object_flag_metas_at_pcr)
{
- modetemp = mode;
- xtemp = x;
+ if (object_flag_meta->flag_set & flags)
+ {
+ combined = object_flag_cell_monoid::append(
+ combined,
+ object_flag_cell::from_object_flag_meta(*object_flag_meta, pval));
+ }
}
+ }
- for (z = mode; z <= modetemp; z++)
- {
- if (mode == 3 && x == 1 && z == modetemp) xtemp = 1;
- name = object_flag_names[32 * modetemp + 16 * xtemp + y];
- got = FALSE;
+ // Accumulate into the global accumulator
+ acc = object_flag_cell_monoid::append(acc, combined);
- /* No name */
- if (!name) continue;
+ // Write the cell's value.
+ auto const char_and_rating = object_flag_cell_to_char(combined);
+ auto const ch = std::get<0>(char_and_rating);
+ auto const rating = std::get<1>(char_and_rating);
- /* Dump colon */
- if (!(modetemp == 1 && x == 0 && y > 7 && y < 12))
- {
- Term_putch(x * 40 + 10, y + 4, TERM_WHITE, ':');
- }
+ // Convert good flag into a color.
+ byte a;
+ if (rating == 0)
+ {
+ a = (i & 0x02) ? TERM_GREEN : TERM_SLATE;
+ }
+ else if (rating < 0)
+ {
+ a = TERM_RED;
+ }
+ else
+ {
+ a = TERM_L_GREEN;
+ }
- /* Check flags */
- dispx = 0;
- for (n = 0; n < INVEN_TOTAL - INVEN_WIELD + 1; n++)
- {
- /* Change colour every two columns */
- bool_ is_green = (dispx & 0x02);
- a = (is_green ? TERM_GREEN : TERM_SLATE);
- c = '.';
+ // Output the flag
+ Term_putch(x0 + 11 + i, y, a, ch);
+ }
- /* If the body part doesn't exists then skip it :) */
- if ((n < INVEN_TOTAL - INVEN_WIELD) && (!p_ptr->body_parts[n])) continue;
+ // Extract the label. If the flag isn't set at all then we don't have
+ // an actual label, so we'll use the one from the meta-level object
+ // flag definition. Note that the prioritization is crucial for the
+ // labeling to work properly; e.g. IMM_FIRE comes *before* the
+ // RES_FIRE flag in the object flag list, but we don't want the *label*
+ // from IMM_FIRE to be used when the flag is not set at all.
+ auto const label = (acc.label != nullptr)
+ ? acc.label
+ : get_lowest_priority_object_flag_meta(object_flag_metas_at_pcr)->c_name;
- /* Increment the drawing coordinates */
- dispx++;
+ // Get the "rating" for the label.
+ auto const rating = std::get<1>(object_flag_cell_to_char(acc));
- /* Check flag */
- if (b[n][2 * modetemp + xtemp] & (1 << y))
- {
- a = (is_green ? TERM_L_GREEN : TERM_WHITE);
- if (modetemp == 1 && x == 0 && y > 7 && y < 12)
- {
- c = '*';
- }
- else if (modetemp == 0 && x == 0 && y < 14 && (y < 6 || y > 7))
- {
- if (n == INVEN_TOTAL - INVEN_WIELD)
- {
- c = '+';
- }
- else
- {
- c = d[n];
- if (c < 0)
- {
- c = -c;
- a = TERM_RED;
- }
- c = (c > 9 ? '*' : I2D(c));
- }
- }
- else
- {
- c = '+';
- }
- got = TRUE;
- }
+ byte label_attr;
+ if (rating == 0) {
+ label_attr = TERM_WHITE;
+ } else if (rating < 0) {
+ label_attr = TERM_RED;
+ } else {
+ label_attr = TERM_L_GREEN;
+ }
- /* HACK - Check for nether immunity and
- apply to Res Neth line */
- if (modetemp == 1 && x == 1 && y == 12)
- {
- if (b[n][7] & (1 << 6))
- {
- a = (is_green ? TERM_L_GREEN : TERM_WHITE);
- c = '*';
- got = TRUE;
- }
- }
+ Term_putch(x0 + 10, y, TERM_WHITE, ':');
+ Term_putstr(x0, y, -1, label_attr, label);
+}
- /* Dump flag */
- if (modetemp == 1 && x == 0 && y > 7 && y < 12)
- {
- if (c == '*') Term_putch(40 + 11 + dispx, y - 4, a, c);
- }
- else
- {
- Term_putch(x * 40 + 11 + dispx, y + 4, a, c);
- }
- }
+/*
+ * Summarize resistances
+ */
+static void display_player_ben_one(int page)
+{
+ // Slots of flags to show.
+ std::vector<std::tuple<char, int, object_flag_set>> slots;
+ slots.reserve(INVEN_TOTAL - INVEN_WIELD + 1);
- a = TERM_WHITE;
- if (got)
- {
- if (modetemp == 1 && x == 0 && y > 7 && y < 12)
- {
- a = TERM_L_GREEN;
- }
- else if (modetemp != 0)
- {
- a = TERM_GREEN;
- }
- }
+ // Scan equipment
+ for (std::size_t i = INVEN_WIELD; i < INVEN_TOTAL; i++)
+ {
+ // Skip inventory slots that don't exist on the body.
+ auto n = i - INVEN_WIELD;
+ if ((n < INVEN_TOTAL - INVEN_WIELD) && (!p_ptr->body_parts[n])) continue;
- /* HACK - Check for nether immunity and change "Res Neth" */
- if (modetemp == 1 && x == 1 && y == 12 && p_ptr->immune_neth)
- {
- name = "Imm Neth";
- a = TERM_L_GREEN;
- }
+ // Extract object flags
+ auto const o_ptr = &p_ptr->inventory[i];
+ auto const flags = object_flags_known(o_ptr);
+ // Add slot
+ slots.emplace_back(
+ std::make_tuple('a' + i - INVEN_WIELD, o_ptr->pval, flags));
+ }
- /* Dump name */
- if (modetemp == 1 && x == 0 && y > 7 && y < 12)
- {
- if (got) Term_putstr(40, y - 4, -1, a, name);
- }
- else
- {
- Term_putstr(x * 40, y + 4, -1, a, name);
- }
+ // Carried symbiote
+ {
+ // Extract flags
+ auto const flags = wield_monster_flags();
+ // Add slot
+ slots.emplace_back(
+ std::make_tuple('z', 0, flags));
+ }
+
+ // Player
+ slots.emplace_back(
+ std::make_tuple('@', 0, player_flags()));
+
+ // Go through each column
+ for (int col = 0; col < 2; col++)
+ {
+ // Base coordinate for output
+ const auto x0 = col * 40;
+ const auto y0 = 3;
+
+ // Add slot headings.
+ {
+ std::string buf;
+ buf.reserve(slots.size());
+
+ for (auto const &slot: slots)
+ {
+ buf += std::get<0>(slot);
}
+
+ Term_putstr(x0 + 11, y0, -1, TERM_WHITE, buf.c_str());
+ }
+
+ // Scan rows
+ for (int row = 0; row < 16; row++)
+ {
+ // Extract the flag metadata for the current page/col/row
+ auto const object_flag_metas_at_pcr =
+ object_flag_metas_by_pcr(page, col, row);
+
+ // Ignore flags which we don't actually map to anything.
+ if (object_flag_metas_at_pcr.empty())
+ {
+ continue;
+ }
+
+ // Y coordinate for the row
+ auto const y = y0 + 1 + row;
+
+ // Show the row
+ display_flag_row(y, x0, slots, object_flag_metas_at_pcr);
}
}
}
+} // namespace <anonymous>
/*
- * Display the character on the screen (various modes)
- *
- * The top two and bottom two lines are left blank.
- *
- * Mode 0 = standard display with skills
- * Mode 1 = standard display with history
- * Mode 2 = current flags (part 1)
- * Mode 3 = current flags (part 2)
- * Mode 4 = current flags (part 3)
- * Mode 5 = current flags (part 4)
- * Mode 6 = current flags (part 5 -- esp)
+ * Display the character on the screen
*/
void display_player(int mode)
{
- int i;
+ auto const &r_info = game->edit_data.r_info;
+
+ assert(mode >= 0);
+ assert(mode < 5);
char buf[80];
@@ -2102,47 +2221,29 @@ void display_player(int mode)
clear_from(0);
/* Standard */
- if ((mode == 0) || (mode == 1))
+ if (mode == 0)
{
- monster_race *r_ptr = &r_info[p_ptr->body_monster];
+ auto r_ptr = &r_info[p_ptr->body_monster];
/* Name, Sex, Race, Class */
put_str("Name :", 2, 1);
- put_str("Sex :", 3, 1);
- put_str("Race :", 4, 1);
- put_str("Class :", 5, 1);
- put_str("Body :", 6, 1);
- put_str("God :", 7, 1);
- c_put_str(TERM_L_BLUE, player_name, 2, 9);
- if (p_ptr->body_monster != 0)
- {
- monster_race *r_ptr = &r_info[p_ptr->body_monster];
- char tmp[12];
-
- if ((r_ptr->flags1 & RF1_MALE) != 0)
- strcpy(tmp, "Male");
- else if ((r_ptr->flags1 & RF1_FEMALE) != 0)
- strcpy(tmp, "Female");
- else
- strcpy(tmp, "Neuter");
- c_put_str(TERM_L_BLUE, tmp, 3, 9);
- }
- else
- c_put_str(TERM_L_BLUE, sp_ptr->title, 3, 9);
- sprintf(buf, "%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);
- c_put_str(TERM_L_BLUE, r_name + r_ptr->name, 6, 9);
- c_put_str(TERM_L_BLUE, deity_info[p_ptr->pgod].name, 7, 9);
-
- /* Age, Height, Weight, Social */
- prt_num("Age ", (int)p_ptr->age + bst(YEAR, turn - (START_DAY * 10)), 2, 32, TERM_L_BLUE, " ");
- prt_num("Height ", (int)p_ptr->ht, 3, 32, TERM_L_BLUE, " ");
- prt_num("Weight ", (int)p_ptr->wt, 4, 32, TERM_L_BLUE, " ");
- prt_num("Social Class ", (int)p_ptr->sc, 5, 32, TERM_L_BLUE, " ");
+ c_put_str(TERM_L_BLUE, game->player_name.c_str(), 2, 9);
+
+ put_str("Race :", 3, 1);
+ auto const player_race_name = get_player_race_name(p_ptr->prace, p_ptr->pracem);
+ c_put_str(TERM_L_BLUE, player_race_name.c_str(), 3, 9);
+
+ put_str("Class :", 4, 1);
+ c_put_str(TERM_L_BLUE, spp_ptr->title, 4, 9);
+
+ put_str("Body :", 5, 1);
+ c_put_str(TERM_L_BLUE, r_ptr->name, 5, 9);
+
+ put_str("God :", 6, 1);
+ c_put_str(TERM_L_BLUE, deity_info[p_ptr->pgod].name, 6, 9);
/* Display the stats */
- for (i = 0; i < 6; i++)
+ for (int i = 0; i < 6; i++)
{
char punctuation = p_ptr->stat_max[i] == 18 + 100 ? '!' : ':';
/* Special treatment of "injured" stats */
@@ -2195,30 +2296,15 @@ void display_player(int mode)
/* Extra info */
display_player_middle();
- /* Display "history" info */
- if (mode == 1)
- {
- put_str("(Character Background)", 15, 25);
-
- for (i = 0; i < 4; i++)
- {
- put_str(history[i], i + 16, 10);
- }
- }
-
/* Display "various" info */
- else
- {
- put_str("(Miscellaneous Abilities)", 15, 25);
-
- display_player_various();
- }
+ put_str("(Miscellaneous Abilities)", 15, 25);
+ display_player_various();
}
/* Special */
else
{
- display_player_ben_one(mode - 2);
+ display_player_ben_one(mode - 1);
}
}
@@ -2228,20 +2314,30 @@ void display_player(int mode)
* Describe the player's location -- either by dungeon level, town, or in
* wilderness with landmark reference.
*/
-cptr describe_player_location()
+std::string describe_player_location()
{
- int i;
- static char desc[80];
+ auto const &wilderness = game->wilderness;
+ auto const &d_info = game->edit_data.d_info;
+ auto const &wf_info = game->edit_data.wf_info;
+
+ std::string desc;
+
int pwx = (p_ptr->wild_mode ? p_ptr->px : p_ptr->wilderness_x);
int pwy = (p_ptr->wild_mode ? p_ptr->py : p_ptr->wilderness_y);
- int feat = wild_map[pwy][pwx].feat;
+ int feat = wilderness(pwx, pwy).feat;
if (dungeon_type != DUNGEON_WILDERNESS && dun_level > 0)
- sprintf(desc, "on level %d of %s", dun_level, d_info[dungeon_type].name + d_name);
+ {
+ desc += fmt::format("on level {:d} of {}", dun_level, d_info[dungeon_type].name);
+ }
else if (wf_info[feat].terrain_idx == TERRAIN_TOWN)
- sprintf(desc, "in the town of %s", wf_info[feat].name + wf_name);
+ {
+ desc += fmt::format("in the town of {}", wf_info[feat].name);
+ }
else if (wf_info[feat].entrance)
- sprintf(desc, "near %s", wf_info[feat].name + wf_name);
+ {
+ desc += fmt::format("near {}", wf_info[feat].name);
+ }
else
{
/*
@@ -2253,21 +2349,19 @@ cptr describe_player_location()
*/
int landmark = 0, lwx = 0, lwy = 0;
int l_dist = -1;
- int i;
- for (i = 0; i < max_wf_idx; i++)
+ for (std::size_t i = 0; i < wf_info.size(); i++)
{
int wx = wf_info[i].wild_x;
int wy = wf_info[i].wild_y;
- int dist;
/* Skip if not a landmark */
if (!wf_info[i].entrance) continue;
/* Skip if we haven't seen it */
- if (!wild_map[wy][wx].known) continue;
+ if (!wilderness(wx, wy).known) continue;
- dist = distance(wy, wx, pwy, pwx);
+ int dist = distance(wy, wx, pwy, pwx);
if (dist < l_dist || l_dist < 0)
{
landmark = i;
@@ -2278,10 +2372,14 @@ cptr describe_player_location()
}
if (!landmark)
- sprintf(desc, "in %s", wf_info[feat].text + wf_text);
+ {
+ desc += fmt::format("in {}", wf_info[feat].text);
+ }
else if (pwx == lwx && pwy == lwy)
+ {
/* Paranoia; this should have been caught above */
- sprintf(desc, "near %s", wf_info[feat].name + wf_name);
+ desc += fmt::format("near {}", wf_info[feat].name);
+ }
else
{
/*
@@ -2302,16 +2400,17 @@ cptr describe_player_location()
if (dy * 81 < dx * 31) ns = "";
if (dx * 81 < dy * 31) ew = "";
- sprintf(desc, "in %s %s%s of %s",
- wf_info[feat].text + wf_text, ns, ew,
- wf_info[landmark].name + wf_name);
+ desc += fmt::format(
+ "in {} {}{} of {}",
+ wf_info[feat].text,
+ ns,
+ ew,
+ wf_info[landmark].name);
}
}
- /* strip trailing whitespace */
- for (i = 0; desc[i]; ++i);
- while (desc[--i] == ' ')
- desc[i] = 0;
+ /* Strip trailing whitespace */
+ boost::trim_right(desc);
return desc;
}
@@ -2355,7 +2454,7 @@ static void file_character_print_grid(FILE *fff, bool_ show_gaps, bool_ show_leg
{
for (x = 0; x < 40; x++)
{
- (void)(Term_what(x, y, &a, &c));
+ (Term_what(x, y, &a, &c));
buf[x] = c;
}
@@ -2368,7 +2467,7 @@ static void file_character_print_grid(FILE *fff, bool_ show_gaps, bool_ show_leg
{
for (x = 40; x < 80; x++)
{
- (void)(Term_what(x, y, &a, &c));
+ (Term_what(x, y, &a, &c));
buf[x - 40] = c;
}
@@ -2403,19 +2502,20 @@ void file_character_print_item(FILE *fff, char label, object_type *obj, bool_ fu
*
* Prints out one "store" (for Home and Mathom-house)
*/
-void file_character_print_store(FILE *fff, wilderness_type_info *place, int store, bool_ full)
+static void file_character_print_store(FILE *fff, wilderness_type_info const *place, std::size_t store, bool_ full)
{
- int i;
+ auto const &st_info = game->edit_data.st_info;
+
town_type *town = &town_info[place->entrance];
store_type *st_ptr = &town->store[store];
- if (st_ptr->stock_num)
+ if (st_ptr->stock.size())
{
/* Header with name of the town */
- fprintf(fff, " [%s Inventory - %s]\n\n", st_name + st_info[store].name, wf_name + place->name);
+ fprintf(fff, " [%s Inventory - %s]\n\n", st_info[store].name.c_str(), place->name);
/* Dump all available items */
- for (i = 0; i < st_ptr->stock_num; i++)
+ for (std::size_t i = 0; i < st_ptr->stock.size(); i++)
{
file_character_print_item(fff, I2A(i%24), &st_ptr->stock[i], full);
}
@@ -2425,46 +2525,26 @@ void file_character_print_store(FILE *fff, wilderness_type_info *place, int stor
}
}
-/*
+/**
* Helper function for file_character
*
* Checks if the store hasn't been added to the list yet, and then adds it if it
* was not already there. XXX This is an ugly workaround for the double Gondolin
* problem.
- *
- * Beware of the ugly pointer gymnastics.
*/
-bool_ file_character_check_stores(store_type ***store_list, int *store_list_count, wilderness_type_info *place, int store)
+static bool_ file_character_check_stores(std::unordered_set<store_type *> *seen_stores, wilderness_type_info const *place, int store)
{
town_type *town = &town_info[place->entrance];
store_type *st_ptr = &town->store[store];
- store_type **head = *store_list;
- int i;
-
- /* check the list for this store */
- for (i = 0; i < *store_list_count; ++i)
- {
- if (*head == st_ptr) return FALSE;
- ++head;
- }
- /* make room for the new one in the array */
- if (*store_list)
- {
- head = *store_list;
- *store_list = C_RNEW(*store_list_count + 1, store_type *);
- C_COPY(*store_list, head, *store_list_count, store_type *);
- C_FREE(head, *store_list_count, store_type *);
- }
- else
+ // Already seen store?
+ if (seen_stores->find(st_ptr) != seen_stores->end())
{
- *store_list = RNEW(store_type *);
+ return FALSE;
}
- /* update data */
- (*store_list)[*store_list_count] = st_ptr;
- ++*store_list_count;
-
+ // Add
+ seen_stores->insert(st_ptr);
return TRUE;
}
@@ -2476,21 +2556,20 @@ bool_ file_character_check_stores(store_type ***store_list, int *store_list_coun
*/
errr file_character(cptr name, bool_ full)
{
- int i, j, x, y;
+ auto const &d_info = game->edit_data.d_info;
+ auto const &wf_info = game->edit_data.wf_info;
+ auto const &r_info = game->edit_data.r_info;
+
+ int i, x, y;
byte a;
char c;
int fd = -1;
FILE *fff = NULL;
char buf[1024];
- store_type **store_list = NULL;
- int store_list_count = 0;
/* Build the filename */
path_build(buf, 1024, ANGBAND_DIR_USER, name);
- /* File type is "TEXT" */
- FILE_TYPE(FILE_TYPE_TEXT);
-
/* Check for existing file */
fd = fd_open(buf, O_RDONLY);
@@ -2500,10 +2579,10 @@ errr file_character(cptr name, bool_ full)
char out_val[160];
/* Close the file */
- (void)fd_close(fd);
+ fd_close(fd);
/* Build query */
- (void)sprintf(out_val, "Replace existing file %s? ", buf);
+ sprintf(out_val, "Replace existing file %s? ", buf);
/* Ask */
if (get_check(out_val)) fd = -1;
@@ -2538,7 +2617,7 @@ errr file_character(cptr name, bool_ full)
for (x = 0; x < 79; x++)
{
/* Get the attr/char */
- (void)(Term_what(x, y, &a, &c));
+ (Term_what(x, y, &a, &c));
/* Dump it */
buf[x] = c;
@@ -2561,7 +2640,7 @@ errr file_character(cptr name, bool_ full)
for (x = 0; x < 79; x++)
{
/* Get the attr/char */
- (void)(Term_what(x, y, &a, &c));
+ (Term_what(x, y, &a, &c));
/* Dump it */
buf[x] = c;
@@ -2575,66 +2654,55 @@ 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)
+ if (options->joke_monsters)
fprintf(fff, "\n Joke monsters: ON");
else
fprintf(fff, "\n Joke monsters: OFF");
- if (p_ptr->maximize)
- fprintf(fff, "\n Maximize mode: ON");
- else
- fprintf(fff, "\n Maximize mode: OFF");
-
- if (p_ptr->preserve)
+ if (options->preserve)
fprintf(fff, "\n Preserve Mode: ON");
else
fprintf(fff, "\n Preserve Mode: OFF");
- if (auto_scum)
+ if (options->auto_scum)
fprintf(fff, "\n Autoscum: ON");
else
fprintf(fff, "\n Autoscum: OFF");
- if (always_small_level)
+ if (options->always_small_level)
fprintf(fff, "\n Small Levels: ALWAYS");
- else if (small_levels)
+ else if (options->small_levels)
fprintf(fff, "\n Small Levels: ON");
else
fprintf(fff, "\n Small Levels: OFF");
- if (empty_levels)
+ if (options->empty_levels)
fprintf(fff, "\n Arena Levels: ON");
else
fprintf(fff, "\n Arena Levels: OFF");
- if (ironman_rooms)
+ if (options->ironman_rooms)
fprintf(fff, "\n Always unusual rooms: ON");
else
fprintf(fff, "\n Always unusual rooms: OFF");
fprintf(fff, "\n\n Recall Depth:");
- for (y = 1; y < max_d_idx; y++)
+ for (y = 1; y < static_cast<int>(d_info.size()); y++)
{
if (max_dlv[y])
- fprintf(fff, "\n %s: Level %d (%d')",
- d_name + d_info[y].name,
- max_dlv[y], 50 * (max_dlv[y]));
+ fprintf(fff, "\n %s: Level %d",
+ d_info[y].name.c_str(),
+ max_dlv[y]);
}
fprintf(fff, "\n");
if (noscore)
fprintf(fff, "\n You have done something illegal.");
- if (PRACE_FLAGS(PR1_EXPERIMENTAL))
+ if (race_flags_p(PR_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;
@@ -2644,24 +2712,26 @@ 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);
}
}
/* Where we are, if we're alive */
- if (!death) fprintf(fff, "\n You are currently %s.", describe_player_location());
+ if (!death)
+ {
+ fprintf(fff, "\n You are currently %s.", describe_player_location().c_str());
+ }
/* Monsters slain */
{
- int k;
s32b Total = 0;
- for (k = 1; k < max_r_idx; k++)
+ for (auto const &r_ref: r_info)
{
- monster_race *r_ptr = &r_info[k];
+ auto r_ptr = &r_ref;
- if (r_ptr->flags1 & (RF1_UNIQUE))
+ if (r_ptr->flags & RF_UNIQUE)
{
bool_ dead = (r_ptr->max_num == 0);
if (dead)
@@ -2687,22 +2757,12 @@ errr file_character(cptr name, bool_ full)
fprintf(fff, "\n You have defeated %ld enemies.", (long int) Total);
}
- hook_file = fff;
- process_hooks(HOOK_CHAR_DUMP, "()");
+ struct hook_chardump_in in = { fff };
+ process_hooks_new(HOOK_CHAR_DUMP, &in, NULL);
/* Date */
{
- char buf2[20];
- u32b days = bst(DAY, turn - (START_DAY * 10));
-
- strnfmt(buf2, 20, get_day(bst(YEAR, START_DAY * 10) + START_YEAR));
- fprintf(fff, "\n\n You started your adventure the %s of the %s year of the third age.",
- get_month_name(bst(DAY, START_DAY * 10), wizard, FALSE), buf2);
-
- strnfmt(buf2, 20, get_day(bst(YEAR, turn) + START_YEAR));
- fprintf(fff, "\n %s the %s of the %s year of the third age.",
- (death ? "You ended your adventure" : "It is currently"),
- get_month_name(bst(DAY, turn), wizard, FALSE), buf2);
+ u32b days = bst(DAY, turn);
fprintf(fff,
(death ? "\n Your adventure lasted %ld day%s." : "\n You have been adventuring for %ld day%s."),
(long int) days, (days == 1) ? "" : "s");
@@ -2710,37 +2770,24 @@ errr file_character(cptr name, bool_ full)
fprintf (fff, "\n\n");
- /* Emit the self-knowledge lines, even though they duplicate the
- information in the grids (below), because they contain information
- that's not in the grids (racial abilities, luck, etc.). */
- if (full)
- {
- self_knowledge(fff);
- fprintf(fff, "\n\n");
- }
-
/* adds and slays */
- display_player (2);
+ display_player(1);
file_character_print_grid(fff, FALSE, TRUE);
/* sustains and resistances */
- display_player (3);
+ display_player(2);
file_character_print_grid(fff, TRUE, FALSE);
/* stuff */
- display_player (4);
+ display_player(3);
file_character_print_grid(fff, FALSE, FALSE);
/* a little bit of stuff */
- display_player (5);
+ display_player(4);
file_character_print_grid(fff, FALSE, FALSE);
/* Dump corruptions */
- if (got_corruptions())
- {
- fprintf(fff, "\n Corruption list:\n");
- dump_corruptions(fff, FALSE);
- }
+ fprintf(fff, "\n%s\n", dump_corruptions(false, true).c_str());
/* Dump skills */
dump_skills(fff);
@@ -2762,7 +2809,7 @@ errr file_character(cptr name, bool_ full)
if ((fates[i].fate) && (fates[i].know))
{
fprintf(fff, "\n\n [Fates]\n\n");
- dump_fates(fff);
+ fprintf(fff, "%s", dump_fates().c_str());
break;
}
}
@@ -2794,24 +2841,30 @@ errr file_character(cptr name, bool_ full)
fprintf(fff, "\n\n");
/* Print all homes in the different towns */
- for (j = 0; j < max_wf_idx; j++)
{
- if (wf_info[j].feat == FEAT_TOWN &&
- file_character_check_stores(&store_list, &store_list_count, &wf_info[j], 7))
- file_character_print_store(fff, &wf_info[j], 7, full);
+ std::unordered_set<store_type *> seen_stores;
+ for (auto const &wf_ref: wf_info)
+ {
+ if (wf_ref.feat == FEAT_TOWN &&
+ file_character_check_stores(&seen_stores, &wf_ref, 7))
+ {
+ file_character_print_store(fff, &wf_ref, 7, full);
+ }
+ }
}
- store_list = C_FREE(store_list, store_list_count, store_type *);
- store_list_count = 0;
/* Print all Mathom-houses in the different towns */
- for (j = 0; j < max_wf_idx; j++)
{
- if (wf_info[j].feat == FEAT_TOWN &&
- file_character_check_stores(&store_list, &store_list_count, &wf_info[j], 57))
- file_character_print_store(fff, &wf_info[j], 57, full);
+ std::unordered_set<store_type *> seen_stores;
+ for (auto const &wf_ref: wf_info)
+ {
+ if (wf_ref.feat == FEAT_TOWN &&
+ file_character_check_stores(&seen_stores, &wf_ref, 57))
+ {
+ file_character_print_store(fff, &wf_ref, 57, full);
+ }
+ }
}
- store_list = C_FREE(store_list, store_list_count, store_type *);
- store_list_count = 0;
text_out_indent = 0;
@@ -2870,7 +2923,7 @@ struct hyperlink
typedef struct hyperlink hyperlink_type;
-bool_ show_file(cptr name, cptr what, int line, int mode)
+static bool_ show_file_aux(cptr name, cptr what, int line)
{
int i, k, x;
@@ -2897,9 +2950,6 @@ bool_ show_file(cptr name, cptr what, int line, int mode)
/* Find this string (if any) */
cptr find = NULL;
- /* Char array type of hyperlink info */
- hyperlink_type *h_ptr;
-
/* Pointer to general buffer in the above */
char *buf;
@@ -2909,7 +2959,8 @@ bool_ show_file(cptr name, cptr what, int line, int mode)
int wid, hgt;
/* Allocate hyperlink data */
- MAKE(h_ptr, hyperlink_type);
+ std::unique_ptr<hyperlink_type> h_ptr(new hyperlink_type);
+ memset(h_ptr.get(), 0, sizeof(hyperlink_type));
/* Setup buffer pointer */
buf = h_ptr->rbuf;
@@ -2979,9 +3030,6 @@ bool_ show_file(cptr name, cptr what, int line, int mode)
msg_format("Cannot open '%s'.", name);
msg_print(NULL);
- /* Free hyperlink info */
- KILL(h_ptr, hyperlink_type);
-
/* Oops */
return (TRUE);
}
@@ -3109,9 +3157,6 @@ bool_ show_file(cptr name, cptr what, int line, int mode)
/* Oops */
if (!fff)
{
- /* Free hyperlink info */
- KILL(h_ptr, hyperlink_type);
-
return (FALSE);
}
@@ -3336,7 +3381,7 @@ bool_ show_file(cptr name, cptr what, int line, int mode)
{
/* Get "h_ptr->shower" */
prt("Show: ", hgt - 1, 0);
- (void)askfor_aux(h_ptr->shower, 80);
+ askfor_aux(h_ptr->shower, 80);
}
/* Hack -- try finding */
@@ -3376,7 +3421,7 @@ bool_ show_file(cptr name, cptr what, int line, int mode)
strcpy(tmp, "help.hlp");
if (askfor_aux(tmp, 80))
{
- if (!show_file(tmp, NULL, 0, mode)) k = ESCAPE;
+ if (!show_file_aux(tmp, NULL, 0)) k = ESCAPE;
}
}
@@ -3430,7 +3475,7 @@ bool_ show_file(cptr name, cptr what, int line, int mode)
if (h_ptr->link_x[cur_link] != -1)
{
/* Recurse on that file */
- if (!show_file(h_ptr->link[cur_link], NULL, h_ptr->link_line[cur_link], mode)) k = ESCAPE;
+ if (!show_file_aux(h_ptr->link[cur_link], NULL, h_ptr->link_line[cur_link])) k = ESCAPE;
}
}
@@ -3443,7 +3488,7 @@ bool_ show_file(cptr name, cptr what, int line, int mode)
if (h_ptr->link_key[i] == k)
{
/* Recurse on that file */
- if (!show_file(h_ptr->link[i], NULL, h_ptr->link_line[i], mode)) k = ESCAPE;
+ if (!show_file_aux(h_ptr->link[i], NULL, h_ptr->link_line[i])) k = ESCAPE;
break;
}
}
@@ -3452,9 +3497,6 @@ bool_ show_file(cptr name, cptr what, int line, int mode)
/* Close the file */
my_fclose(fff);
- /* Free hyperlink buffers */
- KILL(h_ptr, hyperlink_type);
-
/* Escape */
if (k == ESCAPE) return (FALSE);
@@ -3462,332 +3504,78 @@ bool_ show_file(cptr name, cptr what, int line, int mode)
return (TRUE);
}
-bool_ txt_to_html(cptr head, cptr foot, cptr base, cptr ext, bool_ force, bool_ recur)
+void show_string(const char *lines, const char *title, int line)
{
- int i, x;
-
- /* Number of "real" lines passed by */
- int next = 0;
-
- char buf_name[80];
-
- /* Color of the next line */
- byte color = TERM_WHITE;
-
- /* Current help file */
- FILE *fff = NULL;
+ // Temporary file
+ auto const file_name = boost::filesystem::unique_path().string();
- /* Current aux file */
- FILE *aux = NULL;
+ // Open a new file
+ std::ofstream ofs(file_name);
+ ofs.exceptions(std::ofstream::failbit);
+ ofs << lines;
+ ofs.close();
- /* Current html file */
- FILE *htm = NULL;
+ // Display the file contents
+ show_file_aux(file_name.c_str(), title, line);
- /* Char array type of hyperlink info */
- hyperlink_type *h_ptr;
-
- cptr file_ext;
- cptr link_prefix;
- cptr link_suffix;
-
- /* Pointer to general buffer in the above */
- char *buf;
-
- /* Allocate hyperlink data */
- MAKE(h_ptr, hyperlink_type);
-
- /* Setup buffer pointer */
- buf = h_ptr->rbuf;
-
- /* Wipe the links */
- for (i = 0; i < MAX_LINKS; i++)
- {
- 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;
-
- /* Build the filename */
- path_build(h_ptr->path, 1024, ANGBAND_DIR_HELP, buf_name);
-
- /* Open the file */
- htm = my_fopen(h_ptr->path, "w");
-
- sprintf(buf_name, "%s.%s", base, ext);
-
- /* h_ptr->caption */
- sprintf(h_ptr->caption, "Help file '%s'", buf_name);
-
- /* Build the filename */
- path_build(h_ptr->path, 1024, ANGBAND_DIR_HELP, buf_name);
-
- /* Open the file */
- fff = my_fopen(h_ptr->path, "r");
+ // Remove the file
+ fd_kill(file_name.c_str());
+}
- /* Oops */
- if (!fff || !htm)
- {
- /* Free hyperlink info */
- KILL(h_ptr, hyperlink_type);
+void show_file(cptr name, cptr what, int line)
+{
+ show_file_aux(name, what, line);
+}
- my_fclose(fff);
- my_fclose(htm);
+static void cmovie_clean_line(int y, char *abuf, char *cbuf)
+{
+ const byte *ap = Term->scr->a[y];
+ const char *cp = Term->scr->c[y];
- /* Oops */
- return (TRUE);
- }
+ byte a;
+ char c;
- /* Build the filename */
- path_build(h_ptr->path, 1024, ANGBAND_DIR_HELP, head);
+ int x;
+ int wid, hgt;
+ int screen_wid, screen_hgt;
- /* Open the file */
- aux = my_fopen(h_ptr->path, "r");
- /* Copy the header */
- if (aux)
- {
- while (TRUE)
- {
- char *find;
+ /* Retrieve current screen size */
+ Term_get_size(&wid, &hgt);
- if (my_fgets(aux, h_ptr->rbuf, 1024)) break;
- find = strstr(h_ptr->rbuf, "%t");
- if (find != NULL)
- {
- *find = '\0';
- find += 2;
- fprintf(htm, "%s", h_ptr->rbuf);
- fprintf(htm, "%s", base);
- fprintf(htm, "%s\n", find);
- }
- else
- fprintf(htm, "%s\n", h_ptr->rbuf);
- }
- my_fclose(aux);
- }
+ /* Calculate the size of dungeon map area */
+ screen_wid = wid - (COL_MAP + 1);
+ screen_hgt = hgt - (ROW_MAP + 1);
- /* Display the file */
- while (TRUE)
+ /* For the time being, assume 80 column display XXX XXX XXX */
+ for (x = 0; x < wid; x++)
{
- bool_ do_color = FALSE;
-
- /* Skip a line */
- if (my_fgets(fff, h_ptr->rbuf, 1024)) break;
-
- color = TERM_WHITE;
-
+ /* 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))
{
- int print_x;
-
- /* Get a color */
- if (prefix(h_ptr->rbuf, "#####"))
- {
- color = color_char_to_attr(h_ptr->rbuf[5]);
- do_color = TRUE;
- fprintf(htm, "<FONT COLOR=\"#%02X%02X%02X\">",
- angband_color_table[color][1],
- angband_color_table[color][2],
- angband_color_table[color][3]);
- buf = &h_ptr->rbuf[6];
- }
- else buf = h_ptr->rbuf;
-
- /* Count the "real" lines */
- next++;
-
- /* Skip link colors */
- if (prefix(buf, "|||||")) continue;
-
- /* Skip tags */
- if (prefix(buf, "~~~~~"))
- {
- int i;
-
- for (i = 5; (buf[i] >= '0') && (buf[i] <= '9'); i++)
- ;
- buf[i] = '\0';
- fprintf(htm, "<A NAME=\"%s\"></A>", buf + 5);
- continue;
- }
-
- /* Dump the line */
- print_x = 0;
- if (!prefix(buf, "&&&&&"))
- {
- x = 0;
- while (buf[x])
- {
- /* Hyperlink ? */
- if (prefix(buf + x, "*****"))
- {
- int xx = x + 5, z = 0;
- char buff[80];
- char link_line[80], *s;
-
- if (buf[xx] == '/') xx += 2;
-
- /* Zap the link info */
- while (buf[xx] != '*')
- {
- buff[z++] = buf[xx];
- xx++;
- }
- xx++;
- buff[z] = '\0';
-
- /* Zap the link info */
- z = 0;
- while (buf[xx] != '[')
- {
- link_line[z++] = buf[xx];
- xx++;
- }
- xx++;
- link_line[z] = '\0';
-
- /* parse it */
- s = buff;
- while (*s != '.') s++;
- *s = '\0';
- s++;
- if (recur) txt_to_html(head, foot, buff, s, FALSE, recur);
-
- if (atoi(link_line)) fprintf(htm, "<A HREF=\"%s%s.%s%s#%d\">", link_prefix, buff, file_ext, link_suffix, atoi(link_line));
- else fprintf(htm, "<A HREF=\"%s%s.%s%s\">", link_prefix, buff, file_ext, link_suffix);
-
- /* Ok print the link name */
- while (buf[xx] != ']')
- {
- /* Now we treat the next char as printable */
- if (buf[xx] == '\\')
- xx++;
- fprintf(htm, "%c", buf[xx]);
- xx++;
- print_x++;
- }
- x = xx;
-
- fprintf(htm, "</A>");
- }
- /* Color ? */
- else if (prefix(buf + x, "[[[[["))
- {
- int xx = x + 6;
+ /* Retrieve default attr/char */
+ map_info_default(y + panel_row_prt, x + panel_col_prt, &a, &c);
- color = color_char_to_attr(buf[x + 5]);
- fprintf(htm, "<FONT COLOR=\"#%02X%02X%02X\">",
- angband_color_table[color][1],
- angband_color_table[color][2],
- angband_color_table[color][3]);
+ abuf[x] = conv_color[a & 0xf];
- /* Ok print the link name */
- while (buf[xx] != ']')
- {
- /* Now we treat the next char as printable */
- if (buf[xx] == '\\')
- xx++;
- fprintf(htm, "%c", buf[xx]);
- xx++;
- print_x++;
- }
- x++;
- x = xx;
-
- fprintf(htm, "</FONT>");
- }
- /* Hidden HTML tag? */
- else if (prefix(buf + x, "{{{{{"))
- {
- int xx = x + 5;
-
- /* Ok output the tag inside */
- while (buf[xx] != '}')
- {
- fprintf(htm, "%c", buf[xx]);
- xx++;
- }
- x++;
- x = xx;
- }
- else
- {
- fprintf(htm, "%c", buf[x]);
- print_x++;
- }
-
- x++;
- }
- }
- /* Verbatim mode: i.e: acacacac */
- else
- {
- byte old_color;
-
- x = 5;
- old_color = color_char_to_attr(buf[x]);
- fprintf(htm, "<FONT COLOR=\"#%02X%02X%02X\">",
- angband_color_table[color][1],
- angband_color_table[color][2],
- angband_color_table[color][3]);
- while (buf[x])
- {
- color = color_char_to_attr(buf[x]);
- if (color != old_color)
- fprintf(htm, "</FONT><FONT COLOR=\"#%02X%02X%02X\">",
- angband_color_table[color][1],
- angband_color_table[color][2],
- angband_color_table[color][3]);
-
- fprintf(htm, "%c", buf[x + 1]);
- print_x++;
- x += 2;
- }
- fprintf(htm, "</FONT>");
- }
+ if (c == '\0') cbuf[x] = ' ';
+ else cbuf[x] = c;
}
- if (do_color)
- {
- fprintf(htm, "</FONT>");
- }
- fprintf(htm, "\n");
- }
-
- /* Build the filename */
- path_build(h_ptr->path, 1024, ANGBAND_DIR_HELP, foot);
- /* Open the file */
- aux = my_fopen(h_ptr->path, "r");
-
- /* Copy the footer */
- if (aux)
- {
- while (TRUE)
+ else
{
- if (my_fgets(aux, h_ptr->rbuf, 1024)) break;
- fprintf(htm, "%s\n", h_ptr->rbuf);
+ abuf[x] = conv_color[ap[x] & 0xf];
+ cbuf[x] = cp[x];
}
- my_fclose(aux);
}
- /* Close the file */
- my_fclose(htm);
- my_fclose(fff);
-
- /* Free hyperlink buffers */
- KILL(h_ptr, hyperlink_type);
-
- /* Normal return */
- return (TRUE);
+ /* Null-terminate the prepared strings */
+ abuf[x] = '\0';
+ cbuf[x] = '\0';
}
/* Take an help file screenshot(yes yes I know..) */
@@ -3811,9 +3599,6 @@ void help_file_screenshot(cptr name)
/* Build the filename */
path_build(buf, 1024, ANGBAND_DIR_USER, name);
- /* File type is "TEXT" */
- FILE_TYPE(FILE_TYPE_TEXT);
-
/* Append to the file */
htm = my_fopen(buf, "w");
@@ -3867,9 +3652,6 @@ void html_screenshot(cptr name)
/* Build the filename */
path_build(buf, 1024, ANGBAND_DIR_USER, name);
- /* File type is "TEXT" */
- FILE_TYPE(FILE_TYPE_TEXT);
-
/* Append to the file */
htm = my_fopen(buf, "w");
@@ -3936,13 +3718,13 @@ void html_screenshot(cptr name)
/*
* Peruse the On-Line-Help
*/
-void do_cmd_help(void)
+void do_cmd_help()
{
/* Save screen */
screen_save();
/* Peruse the main help file */
- (void)show_file("help.hlp", NULL, 0, 0);
+ show_file("help.hlp", NULL);
/* Load screen */
screen_load();
@@ -3951,98 +3733,53 @@ void do_cmd_help(void)
-/*
- * Process the player name.
- * Extract a clean "base name".
- * Build the savefile name if needed.
- */
void process_player_base()
{
- char temp[128];
-
- /* Rename the savefile, using the player_base */
- (void)sprintf(temp, "%s", player_base);
-
- /* Build the filename */
- path_build(savefile, 1024, ANGBAND_DIR_SAVE, temp);
+ path_build(savefile, 1024, ANGBAND_DIR_SAVE, game->player_base.c_str());
}
void process_player_name(bool_ sf)
{
- int i, k = 0;
- char tmp[50];
-
/* Cannot be too long */
- if (strlen(player_base) > 15)
+ if (game->player_base.size() > 15)
{
- /* Name too long */
- quit_fmt("The name '%s' is too long!", player_base);
+ quit_fmt("The name '%s' is too long!", game->player_base.c_str());
}
- /* Cannot contain "icky" characters */
- for (i = 0; player_base[i]; i++)
+ /* Cannot contain control characters */
+ for (auto c : game->player_base)
{
- /* No control characters */
- if (iscntrl(player_base[i]))
+ if (iscntrl(c))
{
- /* Illegal characters */
- quit_fmt("The name '%s' contains control chars!", player_base);
+ quit_fmt("The name '%s' contains control chars!", game->player_base.c_str());
}
}
-
-#ifdef MACINTOSH
-
/* Extract "useful" letters */
- for (i = 0; player_base[i]; i++)
+ std::string buf;
+ for (auto c : game->player_base)
{
- char c = player_base[i];
-
- /* Convert "dot" to "underscore" */
- if (c == '@.') c = '_';
-
- /* Accept all the letters */
- tmp[k++] = c;
- }
-
-#else
-
- /* Extract "useful" letters */
- for (i = 0; player_base[i]; i++)
- {
- char c = player_base[i];
-
/* Accept some letters */
- if (isalpha(c) || isdigit(c)) tmp[k++] = c;
+ if (isalpha(c) || isdigit(c))
+ {
+ buf += c;
+ }
/* Convert space, dot, and underscore to underscore */
- else if (strchr("@. _", c)) tmp[k++] = '_';
+ else if (strchr("@. _", c))
+ {
+ buf += '_';
+ }
}
-#endif
-
-
-#if defined(WINDOWS) || defined(MSDOS)
-
- /* Hack -- max length */
- if (k > 8) k = 8;
-
-#endif
-
/* Terminate */
- tmp[k] = '\0';
- sprintf(player_base, "%s", tmp);
+ game->player_base = buf;
/* Require a "base" name */
- if (!player_base[0]) strcpy(player_base, "PLAYER");
-
-
-#ifdef SAVEFILE_MUTABLE
-
- /* Accept */
- sf = TRUE;
-
-#endif
+ if (game->player_base.empty())
+ {
+ game->player_base = "PLAYER";
+ }
/* Change the savefile name */
if (sf)
@@ -4062,7 +3799,7 @@ void process_player_name(bool_ sf)
*
* What a horrible name for a global function. XXX XXX XXX
*/
-void get_name(void)
+void get_name()
{
char tmp[32];
@@ -4079,10 +3816,13 @@ void get_name(void)
move_cursor(2, 9);
/* Save the player name */
- strcpy(tmp, player_name);
+ strcpy(tmp, game->player_name.c_str());
/* Get an input, ignore "Escape" */
- if (askfor_aux(tmp, 31)) strcpy(player_name, tmp);
+ if (askfor_aux(tmp, 31))
+ {
+ game->player_name = tmp;
+ }
/* Process the player name */
process_player_name(FALSE);
@@ -4092,7 +3832,7 @@ void get_name(void)
}
/* Pad the name (to clear junk) */
- sprintf(tmp, "%-31.31s", player_name);
+ sprintf(tmp, "%-31.31s", game->player_name.c_str());
/* Re-Draw the name (in light blue) */
c_put_str(TERM_L_BLUE, tmp, 2, 9);
@@ -4106,7 +3846,7 @@ void get_name(void)
/*
* Hack -- commit suicide
*/
-void do_cmd_suicide(void)
+void do_cmd_suicide()
{
int i;
@@ -4147,7 +3887,7 @@ void do_cmd_suicide(void)
p_ptr->leaving = TRUE;
/* Cause of death */
- (void)strcpy(died_from, "Quitting");
+ game->died_from = "Quitting";
}
@@ -4183,7 +3923,7 @@ void remove_cave_view(bool_ remove)
/*
* Save the game
*/
-void do_cmd_save_game(void)
+void do_cmd_save_game()
{
remove_cave_view(TRUE);
@@ -4194,7 +3934,7 @@ void do_cmd_save_game(void)
if (!is_autosave)
{
/* Disturb the player */
- disturb(1, 0);
+ disturb();
}
/* Clear messages */
@@ -4210,10 +3950,7 @@ void do_cmd_save_game(void)
Term_fresh();
/* The player is not dead */
- (void)strcpy(died_from, "(saved)");
-
- /* Forbid suspend */
- signals_ignore_tstp();
+ game->died_from = "(saved)";
/* Save the player */
if (save_player())
@@ -4229,14 +3966,11 @@ void do_cmd_save_game(void)
remove_cave_view(FALSE);
- /* Allow suspend again */
- signals_handle_tstp();
-
/* Refresh */
Term_fresh();
/* Note that the player is not dead */
- (void)strcpy(died_from, "(alive and well)");
+ game->died_from = "(alive and well)";
}
/*
@@ -4244,7 +3978,7 @@ void do_cmd_save_game(void)
*/
void autosave_checkpoint()
{
- if (autosave_l)
+ if (options->autosave_l)
{
is_autosave = TRUE;
msg_print("Autosaving the game...");
@@ -4256,30 +3990,36 @@ void autosave_checkpoint()
/*
* Hack -- Calculates the total number of points earned -JWT-
*/
-long total_points(void)
+static long total_points()
{
- s16b max_dl = 0, i, k;
+ auto const &d_info = game->edit_data.d_info;
+ auto const &r_info = game->edit_data.r_info;
+ auto const &k_info = game->edit_data.k_info;
+
+ s16b max_dl = 0;
long temp, Total = 0;
long mult = 20; /* was 100. Divided values by 5 because of an overflow error */
long comp_death = (p_ptr->companion_killed * 2 / 5);
if (!comp_death) comp_death = 1;
- 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;
- if (smart_cheat) mult += 4;
+ if (options->preserve) mult -= 1; /* Penalize preserve, maximize modes */
+ mult -= 1; /* maximize pentalty, always on */
+ if (options->auto_scum) mult -= 4;
+ if (options->small_levels) mult += ((options->always_small_level) ? 4 : 10);
+ if (options->empty_levels) mult += 2;
+ if (options->smart_learn) mult += 4;
if (mult < 2) mult = 2; /* At least 10% of the original score */
/* mult is now between 2 and 40, i.e. 10% and 200% */
- for (i = 0; i < max_d_idx; i++)
+ for (std::size_t i = 0; i < d_info.size(); i++)
+ {
if (max_dlv[i] > max_dl)
+ {
max_dl = max_dlv[i];
+ }
+ }
temp = p_ptr->lev * p_ptr->lev * p_ptr->lev * p_ptr->lev + (100 * max_dl);
@@ -4291,7 +4031,7 @@ long total_points(void)
temp += p_ptr->au / 5;
/* Completing quest increase score */
- for (i = 0; i < max_q_idx; i++)
+ for (std::size_t i = 0; i < MAX_Q_IDX; i++)
{
if (quest[i].status >= QUEST_STATUS_COMPLETED)
{
@@ -4303,14 +4043,13 @@ long total_points(void)
/* Death of a companion is BAD */
temp /= comp_death;
- /* The know objects increase the score */
- /* Scan the object kinds */
- for (k = 1; k < max_k_idx; k++)
+ /* The known objects increase the score */
+ for (std::size_t k = 1; k < k_info.size(); k++)
{
- object_kind *k_ptr = &k_info[k];
+ auto k_ptr = &k_info[k];
/* Hack -- skip artifacts */
- if (k_ptr->flags3 & (TR3_INSTA_ART)) continue;
+ if (k_ptr->flags & TR_INSTA_ART) continue;
/* List known flavored objects */
if (k_ptr->flavor && k_ptr->aware)
@@ -4328,11 +4067,11 @@ long total_points(void)
}
}
- for (k = 1; k < max_r_idx; k++)
+ for (auto const &r_ref: r_info)
{
- monster_race *r_ptr = &r_info[k];
+ auto r_ptr = &r_ref;
- if (r_ptr->flags1 & (RF1_UNIQUE))
+ if (r_ptr->flags & RF_UNIQUE)
{
bool_ dead = (r_ptr->max_num == 0);
@@ -4354,8 +4093,6 @@ long total_points(void)
}
temp += Total * 50;
- temp += total_bounties * 100;
-
if (total_winner) temp += 1000000;
@@ -4364,161 +4101,75 @@ long total_points(void)
}
-
-/*
- * Centers a string within a 31 character string -JWT-
- */
-static void center_string(char *buf, cptr str)
-{
- int i, j;
-
- /* Total length */
- i = strlen(str);
-
- /* Necessary border */
- j = 15 - i / 2;
-
- /* Mega-Hack */
- (void)sprintf(buf, "%*s%s%*s", j, "", str, 31 - i - j, "");
-}
-
-
-/*
- * Redefinable "print_tombstone" action
- */
-bool_ (*tombstone_aux)(void) = NULL;
-
-
/*
* Display a "tomb-stone"
*/
-static void print_tomb(void)
+static void print_tomb()
{
- bool_ done = FALSE;
+ time_t ct = time(nullptr);
- /* Do we use a special tombstone ? */
- if (tombstone_aux)
- {
- /* Use tombstone hook */
- done = (*tombstone_aux)();
- }
+ auto center = [](std::string const &s) -> std::string {
+ return fmt::format("{:^31s}", s);
+ };
- /* Print the text-tombstone */
- if (!done)
- {
- cptr p;
-
- char tmp[160];
-
- char buf[1024];
- char dummy[80];
-
- FILE *fp;
-
- time_t ct = time((time_t)0);
-
-
- /* Clear screen */
- Term_clear();
-
- /* Build the filename */
- path_build(buf, 1024, ANGBAND_DIR_FILE, "dead.txt");
-
- /* Open the News file */
- fp = my_fopen(buf, "r");
-
- /* Dump */
- if (fp)
- {
- int i = 0;
-
- /* Dump the file to the screen */
- while (0 == my_fgets(fp, buf, 1024))
- {
- /* Display and advance */
- display_message(0, i++, strlen(buf), TERM_WHITE, buf);
- }
-
- /* Close */
- my_fclose(fp);
- }
-
-
- /* King or Queen */
- if (total_winner || (p_ptr->lev > PY_MAX_LEVEL))
- {
- p = "Magnificent";
- }
-
- /* Normal */
- else
- {
- p = cp_ptr->titles[(p_ptr->lev - 1) / 5] + c_text;
- }
-
- center_string(buf, player_name);
- put_str(buf, 6, 11);
-
- center_string(buf, "the");
- put_str(buf, 7, 11);
-
- center_string(buf, p);
- put_str(buf, 8, 11);
-
-
- center_string(buf, spp_ptr->title + c_name);
- put_str(buf, 10, 11);
-
- (void)sprintf(tmp, "Level: %d", (int)p_ptr->lev);
- center_string(buf, tmp);
- put_str(buf, 11, 11);
-
- (void)sprintf(tmp, "Exp: %ld", (long)p_ptr->exp);
- center_string(buf, tmp);
- put_str(buf, 12, 11);
+ /* Clear screen */
+ Term_clear();
- (void)sprintf(tmp, "AU: %ld", (long)p_ptr->au);
- center_string(buf, tmp);
- put_str(buf, 13, 11);
+ /* Build the filename */
+ char buf[1024];
+ path_build(buf, 1024, ANGBAND_DIR_FILE, "dead.txt");
- (void)sprintf(tmp, "Killed on Level %d", dun_level);
- center_string(buf, tmp);
- put_str(buf, 14, 11);
+ /* Open the News file */
+ FILE *fp = my_fopen(buf, "r");
+ /* Dump */
+ if (fp)
+ {
+ int i = 0;
- if (strlen(died_from) > 24)
+ /* Dump the file to the screen */
+ while (0 == my_fgets(fp, buf, 1024))
{
- strncpy(dummy, died_from, 24);
- dummy[24] = '\0';
- (void)sprintf(tmp, "by %s.", dummy);
+ /* Display and advance */
+ display_message(0, i++, strlen(buf), TERM_WHITE, buf);
}
- else
- (void)sprintf(tmp, "by %s.", died_from);
-
- center_string(buf, tmp);
- put_str(buf, 15, 11);
+ /* Close */
+ my_fclose(fp);
+ }
- (void)sprintf(tmp, "%-.24s", ctime(&ct));
- center_string(buf, tmp);
- put_str(buf, 17, 11);
+ std::string p_title;
+ if (total_winner || (p_ptr->lev > PY_MAX_LEVEL))
+ {
+ p_title = "Magnificent";
}
+ else
+ {
+ p_title = cp_ptr->titles[(p_ptr->lev - 1) / 5];
+ }
+
+ put_str(center(game->player_name), 6, 11);
+ put_str(center("the"), 7, 11);
+ put_str(center(p_title), 8, 11);
+ put_str(center(spp_ptr->title), 10, 11);
+ put_str(center(fmt::format("Level: {}", p_ptr->lev)), 11, 11);
+ put_str(center(fmt::format("Exp: {}", p_ptr->exp)), 12, 11);
+ put_str(center(fmt::format("AU: {}", p_ptr->au)), 13, 11);
+ put_str(center(fmt::format("Killed on Level {}", dun_level)), 14, 11);
+ put_str(center(fmt::format("by {}.", game->died_from.substr(0, 24))), 15, 11);
+ put_str(center(std::string(ctime(&ct)).substr(0, 24)), 17, 11);
}
/*
* Display some character info
*/
-static void show_info(void)
+static void show_info()
{
- int i, j, k;
- object_type *o_ptr;
- store_type *st_ptr;
-
/* Hack -- Know everything in the inven/equip */
- for (i = 0; i < INVEN_TOTAL; i++)
+ for (auto &o_ref: p_ptr->inventory)
{
- o_ptr = &p_ptr->inventory[i];
+ auto o_ptr = &o_ref;
/* Skip non-objects */
if (!o_ptr->k_idx) continue;
@@ -4528,14 +4179,13 @@ static void show_info(void)
object_known(o_ptr);
}
- for (i = 1; i < max_towns; i++)
+ /* Hack -- Know everything in the home */
+ for (int i = 1; i < max_towns; i++)
{
- st_ptr = &town_info[i].store[7];
-
- /* Hack -- Know everything in the home */
- for (j = 0; j < st_ptr->stock_num; j++)
+ auto st_ptr = &town_info[i].store[7];
+ for (auto &o_ref: st_ptr->stock)
{
- o_ptr = &st_ptr->stock[j];
+ auto o_ptr = &o_ref;
/* Skip non-objects */
if (!o_ptr->k_idx) continue;
@@ -4585,7 +4235,7 @@ static void show_info(void)
Term_save();
/* Dump a character file */
- (void)file_character(out_val, TRUE);
+ file_character(out_val, TRUE);
/* Load screen */
Term_load();
@@ -4609,8 +4259,7 @@ static void show_info(void)
if (equip_cnt)
{
Term_clear();
- item_tester_full = TRUE;
- show_equip();
+ show_equip_full();
prt("You are using: -more-", 0, 0);
if (inkey() == ESCAPE) return;
}
@@ -4619,34 +4268,34 @@ static void show_info(void)
if (inven_cnt)
{
Term_clear();
- item_tester_full = TRUE;
- show_inven();
+ show_inven_full();
prt("You are carrying: -more-", 0, 0);
if (inkey() == ESCAPE) return;
}
/* Homes in the different towns */
- for (k = 1; k < max_towns; k++)
+ for (int k = 1; k < max_towns; k++)
{
- st_ptr = &town_info[k].store[7];
+ store_type *st_ptr = &town_info[k].store[7];
/* Home -- if anything there */
- if (st_ptr->stock_num)
+ if (!st_ptr->stock.empty())
{
+ std::size_t i;
/* Display contents of the home */
- for (k = 0, i = 0; i < st_ptr->stock_num; k++)
+ for (k = 0, i = 0; i < st_ptr->stock.size(); k++)
{
/* Clear screen */
Term_clear();
/* Show 12 items */
- for (j = 0; (j < 12) && (i < st_ptr->stock_num); j++, i++)
+ for (int j = 0; (j < 12) && (i < st_ptr->stock.size()); j++, i++)
{
char o_name[80];
char tmp_val[80];
/* Acquire item */
- o_ptr = &st_ptr->stock[i];
+ auto o_ptr = &st_ptr->stock[i];
/* Print header, clear line */
sprintf(tmp_val, "%c) ", I2A(j));
@@ -4672,169 +4321,16 @@ 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 uid[8]; /* Player UID (number) */
-
- 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 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(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(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(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(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 (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(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(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(i)) return ( -1);
- if (highscore_read(&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);
-
- /* 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.
* Only five entries per line, too much info.
*
* 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)
{
+ auto const &class_info = game->edit_data.class_info;
+
int i, j, k, n, place;
byte attr;
char out_val[256];
@@ -4853,12 +4349,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 */
@@ -4889,9 +4385,9 @@ static void display_scores_aux(int from, int to, int note, high_score *score)
{
int pcs, pr, ps, pc, clev, mlev, cdun, mdun;
- cptr user, gold, when, aged;
+ cptr gold, when, aged;
- int in_arena, in_quest;
+ int in_quest;
/* Hack -- indicate death in yellow */
attr = (j == note) ? TERM_YELLOW : TERM_WHITE;
@@ -4911,8 +4407,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 */
@@ -4927,19 +4423,21 @@ static void display_scores_aux(int from, int to, int note, high_score *score)
cdun = atoi(the_score.cur_dun);
mdun = atoi(the_score.max_dun);
- in_arena = atoi(the_score.inside_arena);
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 */;
/* Dump some info */
+ auto const player_race_name = get_player_race_name(pr, ps);
sprintf(out_val, "%3d.%9s %s the %s %s, Level %d",
- place, the_score.pts, the_score.who,
- get_player_race_name(pr, ps), class_info[pc].spec[pcs].title + c_name,
+ place,
+ the_score.pts,
+ the_score.who,
+ player_race_name.c_str(),
+ class_info[pc].spec[pcs].title,
clev);
/* Append a "maximum level" */
@@ -4949,12 +4447,7 @@ static void display_scores_aux(int from, int to, int note, high_score *score)
c_put_str(attr, out_val, n*4 + 2, 0);
/* Another line of info */
- if (in_arena)
- {
- sprintf(out_val, " Killed by %s in the Arena",
- the_score.how);
- }
- else if (in_quest)
+ if (in_quest)
{
sprintf(out_val, " Killed by %s while questing",
the_score.how);
@@ -4979,8 +4472,8 @@ static void display_scores_aux(int from, int to, int note, high_score *score)
/* 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);
}
@@ -4997,52 +4490,18 @@ static void display_scores_aux(int from, int to, int note, high_score *score)
/*
- * Hack -- Display the scores in a given range and quit.
- *
- * This function is only called from "main.c" when the user asks
- * to see the "high scores".
- */
-void display_scores(int from, int to)
-{
- char buf[1024];
-
- /* Build the filename */
- path_build(buf, 1024, ANGBAND_DIR_APEX, "scores.raw");
-
- /* Open the binary high score file, for reading */
- highscore_fd = fd_open(buf, O_RDONLY);
-
- /* Paranoia -- No score file */
- if (highscore_fd < 0) quit("Score file unavailable.");
-
- /* Clear screen */
- Term_clear();
-
- /* Display the scores */
- display_scores_aux(from, to, -1, NULL);
-
- /* Shut the high score file */
- (void)fd_close(highscore_fd);
-
- /* Forget the high score fd */
- highscore_fd = -1;
-
- /* Quit */
- quit(NULL);
-}
-
-
-/*
* show_highclass - selectively list highscores based on class
* -KMW-
*/
void show_highclass(int building)
{
+ auto const &race_info = game->edit_data.race_info;
- register int i = 0, j, m = 0;
- int pr, pc, clev, al;
+ int i = 0, j, m = 0;
+ int pr, pc, clev;
high_score the_score;
- char buf[1024], out_val[256];
+ char buf[1024];
+ int highscore_fd;
switch (building)
{
@@ -5079,7 +4538,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);
@@ -5091,30 +4550,31 @@ 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;
clev = 0;
+ auto const format_num = "{:>3d}) {} the {} (Level {:>2d})"; // See also race_score()
+ auto const format_you = "You) {} the {} (Level {:>2d})";
+
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);
- al = atoi(the_score.arena_number);
- if (((pc == (building - 10)) && (building != 1) && (building != 2)) ||
- ((building == 1) && (clev >= PY_MAX_LEVEL)) ||
- ((building == 2) && (al > MAX_ARENA_MONS)))
- {
- sprintf(out_val, "%3d) %s the %s (Level %2d)",
- (m + 1), the_score.who, rp_name + race_info[pr].title, clev);
- prt(out_val, (m + 7), 0);
+ if (((pc == (building - 10)) && (building != 1)) ||
+ ((building == 1) && (clev >= PY_MAX_LEVEL)))
+ {
+ auto out_val = fmt::format(format_num,
+ (m + 1), the_score.who, race_info[pr].title, clev);
+ prt(out_val.c_str(), (m + 7), 0);
m++;
}
j++;
@@ -5123,28 +4583,26 @@ void show_highclass(int building)
/* Now, list the active player if they qualify */
if ((building == 1) && (p_ptr->lev >= PY_MAX_LEVEL))
{
- sprintf(out_val, "You) %s the %s (Level %2d)",
- player_name, rp_name + race_info[p_ptr->prace].title, p_ptr->lev);
- prt(out_val, (m + 8), 0);
+ auto out_val = fmt::format(format_you,
+ game->player_name,
+ race_info[p_ptr->prace].title,
+ p_ptr->lev);
+ prt(out_val.c_str(), (m + 8), 0);
}
- else if ((building == 2) && (p_ptr->arena_number > MAX_ARENA_MONS))
- {
- sprintf(out_val, "You) %s the %s (Level %2d)",
- player_name, rp_name + race_info[p_ptr->prace].title, p_ptr->lev);
- prt(out_val, (m + 8), 0);
- }
- else if ((building != 1) && (building != 2))
+ else if ((building != 1))
{
if ((p_ptr->lev > clev) && (p_ptr->pclass == (building - 10)))
{
- sprintf(out_val, "You) %s the %s (Level %2d)",
- player_name, rp_name + race_info[p_ptr->prace].title, p_ptr->lev);
- prt(out_val, (m + 8), 0);
+ auto out_val = fmt::format(format_you,
+ game->player_name,
+ race_info[p_ptr->prace].title,
+ p_ptr->lev);
+ prt(out_val.c_str(), (m + 8), 0);
}
}
- (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++)
@@ -5158,19 +4616,22 @@ void show_highclass(int building)
*/
void race_score(int race_num)
{
- register int i = 0, j, m = 0;
+ auto const &race_info = game->edit_data.race_info;
+
+ int i = 0, j, m = 0;
int pr, clev, lastlev;
high_score the_score;
- char buf[1024], out_val[256], tmp_str[80];
+ char buf[1024], tmp_str[80];
+ int highscore_fd;
lastlev = 0;
/* rr9: TODO - pluralize the race */
- sprintf(tmp_str, "The Greatest of all the %s", rp_name + race_info[race_num].title);
+ sprintf(tmp_str, "The Greatest of all the %s", race_info[race_num].title.c_str());
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);
@@ -5182,28 +4643,33 @@ 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;
j = 0;
+ auto const format_num = "{:>3d}) {} the {} (Level {:>2d})"; // See also show_highclass()
+ auto const format_you = "You) {} the {} (Level {:>2d})";
+
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)
{
- sprintf(out_val, "%3d) %s the %s (Level %3d)",
- (m + 1), the_score.who,
- rp_name + race_info[pr].title, clev);
- prt(out_val, (m + 7), 0);
+ auto out_val = fmt::format(format_num,
+ (m + 1),
+ the_score.who,
+ race_info[pr].title,
+ clev);
+ prt(out_val.c_str(), (m + 7), 0);
m++;
lastlev = clev;
}
@@ -5213,13 +4679,14 @@ void race_score(int race_num)
/* add player if qualified */
if ((p_ptr->prace == race_num) && (p_ptr->lev >= lastlev))
{
- sprintf(out_val, "You) %s the %s (Level %3d)",
- player_name, rp_name + race_info[p_ptr->prace].title, p_ptr->lev);
- prt(out_val, (m + 8), 0);
+ auto out_val = fmt::format(format_you,
+ game->player_name,
+ race_info[p_ptr->prace].title,
+ p_ptr->lev);
+ prt(out_val.c_str(), (m + 8), 0);
}
- (void)fd_close(highscore_fd);
- highscore_fd = -1;
+ fd_close(highscore_fd);
}
@@ -5227,17 +4694,19 @@ void race_score(int race_num)
* Race Legends
* -KMW-
*/
-void race_legends(void)
+void race_legends()
{
- int i, j;
+ auto const &race_info = game->edit_data.race_info;
- for (i = 0; i < max_rp_idx; i++)
+ for (size_t i = 0; i < race_info.size(); i++)
{
race_score(i);
msg_print("Hit any key to continue");
msg_print(NULL);
- for (j = 5; j < 19; j++)
+ for (int j = 5; j < 19; j++)
+ {
prt("", j, 0);
+ }
}
}
@@ -5247,10 +4716,8 @@ 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)
+static errr top_twenty()
{
int j;
@@ -5258,72 +4725,58 @@ 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;
}
-#ifndef SCORE_WIZARDS
+ /* Clear screen */
+ Term_clear();
+
/* 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
-#ifndef SCORE_BORGS
- /* Borg-mode pre-empts scoring */
- if (noscore & 0x00F0)
- {
- msg_print("Score not registered for borgs.");
- msg_print(NULL);
- display_scores_aux(0, 10, -1, NULL);
- return (0);
- }
-#endif
-
-#ifndef SCORE_CHEATERS
/* Cheaters are not scored */
if (noscore & 0xFF00)
{
msg_print("Score not registered for cheaters.");
msg_print(NULL);
- display_scores_aux(0, 10, -1, NULL);
- return (0);
- }
-#endif
-
- /* Interupted */
- if (!total_winner && streq(died_from, "Interrupting"))
- {
- 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 */
- if (!total_winner && streq(died_from, "Quitting"))
+ if (!total_winner && (game->died_from == "Quitting"))
{
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;
}
/* Clear the record */
- WIPE(&the_score, high_score);
+ static_assert(std::is_pod<high_score>::value,
+ "Cannot memset a non-POD type");
+ memset(&the_score, 0, sizeof(high_score));
/* Save the version */
sprintf(the_score.what, "%ld.%ld.%ld",
@@ -5338,23 +4791,16 @@ static errr top_twenty(void)
the_score.gold[9] = '\0';
/* Save the current turn */
- sprintf(the_score.turns, "%9lu", (long)turn - (START_DAY * 10L));
+ sprintf(the_score.turns, "%9lu", (long)turn);
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);
+ sprintf(the_score.who, "%-.15s", game->player_name.c_str());
/* 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);
sprintf(the_score.p_c, "%2d", p_ptr->pclass);
@@ -5366,39 +4812,36 @@ static errr top_twenty(void)
sprintf(the_score.max_lev, "%3d", p_ptr->max_plv);
sprintf(the_score.max_dun, "%3d", max_dlv[dungeon_type]);
- sprintf(the_score.arena_number, "%3d", p_ptr->arena_number); /* -KMW- */
- sprintf(the_score.inside_arena, "%3d", p_ptr->inside_arena);
sprintf(the_score.inside_quest, "%3d", p_ptr->inside_quest);
- sprintf(the_score.exit_bldg, "%3d", p_ptr->exit_bldg); /* -KMW- */
/* Save the cause of death (31 chars) */
- sprintf(the_score.how, "%-.31s", died_from);
+ sprintf(the_score.how, "%-.31s", game->died_from.c_str());
- /* 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);
}
@@ -5407,21 +4850,33 @@ static errr top_twenty(void)
/*
* Predict the players location, and display it.
*/
-errr predict_score(void)
+static errr predict_score()
{
int j;
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;
}
+ /* Clear the record */
+ static_assert(std::is_pod<high_score>::value,
+ "Cannot memset a non-POD type");
+ memset(&the_score, 0, sizeof(high_score));
/* Save the version */
sprintf(the_score.what, "%ld.%ld.%ld",
@@ -5436,18 +4891,16 @@ errr predict_score(void)
the_score.gold[9] = '\0';
/* Save the current turn */
- sprintf(the_score.turns, "%9lu", (long)turn - (START_DAY * 10L));
+ sprintf(the_score.turns, "%9lu", (long)turn);
the_score.turns[9] = '\0';
/* Hack -- no time needed */
strcpy(the_score.day, "TODAY");
/* Save the player name (15 chars) */
- sprintf(the_score.who, "%-.15s", player_name);
+ sprintf(the_score.who, "%-.15s", game->player_name.c_str());
/* 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);
sprintf(the_score.p_c, "%2d", p_ptr->pclass);
@@ -5459,49 +4912,109 @@ errr predict_score(void)
sprintf(the_score.max_lev, "%3d", p_ptr->max_plv);
sprintf(the_score.max_dun, "%3d", max_dlv[dungeon_type]);
- sprintf(the_score.arena_number, "%3d", p_ptr->arena_number); /* -KMW- */
- sprintf(the_score.inside_arena, "%3d", p_ptr->inside_arena);
sprintf(the_score.inside_quest, "%3d", p_ptr->inside_quest);
- sprintf(the_score.exit_bldg, "%3d", p_ptr->exit_bldg); /* -KMW- */
/* Hack -- no cause of death */
strcpy(the_score.how, "nobody (yet!)");
/* 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 */
+ 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-
*/
-static void kingly(void)
+static void kingly()
{
/* Hack -- retire in town */
dun_level = 0;
/* Fake death */
- (void)strcpy(died_from, "Ripe Old Age");
+ game->died_from = "Ripe Old Age";
/* Restore the experience */
p_ptr->exp = p_ptr->max_exp;
@@ -5534,7 +5047,7 @@ static void kingly(void)
/* Display a message */
put_str("Veni, Vidi, Vici!", 15, 26);
put_str("I came, I saw, I conquered!", 16, 21);
- put_str(format("All Hail the Mighty %s!", sp_ptr->winner), 17, 22);
+ put_str(format("All Hail the Mighty %s!", game->player_name.c_str()), 17, 22);
/* Flush input */
flush();
@@ -5549,13 +5062,16 @@ static void kingly(void)
*/
void wipe_saved()
{
- int d, l, od = dungeon_type, ol = dun_level;
+ auto const &d_info = game->edit_data.d_info;
+
+ int od = dungeon_type;
+ int ol = dun_level;
- for (d = 0; d < max_d_idx; d++)
+ for (std::size_t d = 0; d < d_info.size(); d++)
{
- dungeon_info_type *d_ptr = &d_info[d];
+ auto d_ptr = &d_info[d];
- for (l = d_ptr->mindepth; l <= d_ptr->maxdepth; l++)
+ for (auto l = d_ptr->mindepth; l <= d_ptr->maxdepth; l++)
{
char buf[10];
@@ -5563,10 +5079,10 @@ void wipe_saved()
dungeon_type = d;
if (get_dungeon_save(buf))
{
- char tmp[80], name[1024];
+ auto tmp = fmt::format("{}.{}", game->player_base, buf);
- sprintf(tmp, "%s.%s", player_base, buf);
- path_build(name, 1024, ANGBAND_DIR_SAVE, tmp);
+ char name[1024];
+ path_build(name, 1024, ANGBAND_DIR_SAVE, tmp.c_str());
/* Remove the dungeon save file */
fd_kill(name);
@@ -5584,11 +5100,8 @@ void wipe_saved()
*
* This function is called only from "main.c" and "signals.c".
*/
-void close_game(void)
+void close_game()
{
- char buf[1024];
-
-
/* Handle stuff */
handle_stuff();
@@ -5599,30 +5112,18 @@ void close_game(void)
flush();
- /* No suspending now */
- signals_ignore_tstp();
-
/* Hack -- Character is now "icky" */
character_icky = TRUE;
- /* Build the filename */
- path_build(buf, 1024, ANGBAND_DIR_APEX, "scores.raw");
-
- /* Open the high score file, for reading/writing */
- highscore_fd = fd_open(buf, O_RDWR);
-
/* Handle death */
if (death)
{
/* 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();
}
@@ -5639,11 +5140,9 @@ 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];
time_t ct = time((time_t*)NULL);
/* Get the date */
@@ -5651,11 +5150,13 @@ void close_game(void)
"%Y-%m-%d at %H:%M:%S", localtime(&ct));
/* Create string */
- sprintf(buf, "\n%s was killed by %s on %s\n", player_name,
- died_from, long_day);
+ auto buf = fmt::format("\n{} was killed by {} on {}\n",
+ game->player_name,
+ game->died_from,
+ long_day);
/* Output to the notes file */
- output_note(buf);
+ output_note(buf.c_str());
}
/* Handle score, show Top scores */
@@ -5670,11 +5171,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);
@@ -5682,23 +5180,13 @@ void close_game(void)
/* Predict score (or ESCAPE) */
if (inkey() != ESCAPE) predict_score();
}
-
-
- /* Shut the high score file */
- (void)fd_close(highscore_fd);
-
- /* Forget the high score fd */
- highscore_fd = -1;
-
- /* Allow suspending now */
- signals_handle_tstp();
}
/*
* 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;
@@ -5715,7 +5203,7 @@ errr get_rnd_line(char *file_name, char *output)
strcpy(output, "");
/* test hack */
- if (wizard && cheat_xtra) msg_print(file_name);
+ if (wizard && options->cheat_xtra) msg_print(file_name);
/* Build the filename */
path_build(buf, 1024, ANGBAND_DIR_FILE, file_name);
@@ -5775,7 +5263,7 @@ errr get_rnd_line(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;
@@ -5823,7 +5311,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];
@@ -5837,7 +5325,7 @@ errr get_xtra_line(char *file_name, monster_type *m_ptr, char *output)
strcpy(output, "");
/* test and DEBUG hack */
- if (wizard && cheat_xtra)
+ if (wizard && options->cheat_xtra)
{
msg_print(file_name);
}
@@ -5916,7 +5404,7 @@ errr get_xtra_line(char *file_name, monster_type *m_ptr, char *output)
line = rand_int(num_entries);
/* test and DEBUG hack */
- if (wizard && cheat_xtra)
+ if (wizard && options->cheat_xtra)
{
sprintf(buf, "Line number %d", line);
msg_print(buf);
@@ -5945,114 +5433,3 @@ errr get_xtra_line(char *file_name, monster_type *m_ptr, char *output)
/* Success */
return (0);
}
-
-
-#ifdef HANDLE_SIGNALS
-
-
-#include <signal.h>
-
-
-/*
- * 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/files.h b/src/files.h
new file mode 100644
index 00000000..78521f4c
--- /dev/null
+++ b/src/files.h
@@ -0,0 +1,15 @@
+#pragma once
+
+#include "h-basic.h"
+
+// C linkage required for these functions since main-* code uses them.
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void do_cmd_save_game();
+void predict_score_gui(bool_ *initialized, bool_ *game_in_progress);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/src/files.hpp b/src/files.hpp
new file mode 100644
index 00000000..f431eb69
--- /dev/null
+++ b/src/files.hpp
@@ -0,0 +1,33 @@
+#pragma once
+
+#include "h-basic.h"
+#include "monster_type_fwd.hpp"
+#include "object_flag_set.hpp"
+
+#include <string>
+#include <vector>
+
+void html_screenshot(cptr name);
+void help_file_screenshot(cptr name);
+object_flag_set player_flags();
+void wipe_saved();
+s16b tokenize(char *buf, s16b num, char **tokens, char delim1, char delim2);
+void display_player(int mode);
+std::string describe_player_location();
+errr file_character(cptr name, bool_ full);
+errr process_pref_file_aux(char *buf);
+errr process_pref_file(cptr name);
+void show_string(const char *lines, const char *title, int line = 0);
+void show_file(cptr name, cptr what, int line = 0);
+void do_cmd_help();
+void process_player_base();
+void get_name();
+void do_cmd_suicide();
+void autosave_checkpoint();
+void close_game();
+errr get_rnd_line(const char * file_name, char * output);
+char *get_line(const char* fname, cptr fdir, char *linbuf, int line);
+void race_legends();
+void show_highclass(int building);
+errr get_xtra_line(const char * file_name, monster_type *m_ptr, char * output);
+void process_player_name(bool_ sf);
diff --git a/src/flag_set.hpp b/src/flag_set.hpp
new file mode 100644
index 00000000..7960de42
--- /dev/null
+++ b/src/flag_set.hpp
@@ -0,0 +1,201 @@
+#pragma once
+
+#include <array>
+#include <cassert>
+#include <cstdint>
+
+#include "tome/pp/global_constexpr.hpp"
+
+/**
+ * Set of binary flags.
+ */
+template<std::size_t Tiers> struct flag_set
+{
+private:
+ static constexpr std::size_t tiers = Tiers;
+ std::uint32_t m_data[tiers];
+
+public:
+ static constexpr const std::size_t nbits = tiers * 32;
+
+public:
+
+ constexpr flag_set()
+ : m_data { 0 }
+ {
+ // It is *extremely* important that there are absolutely
+ // NO dependencies on any global objects in here; lest we
+ // fall into SIOF territory; see DECLARE_FLAG_ZERO_IMPL
+ }
+
+ // This method is a workaround for a a segmentation fault
+ // when compiling with GCC 5.3.0 (Arch Linux). We should be
+ // able to use make() directly in DECLARE_FLAG_MAKE_INIT,
+ // but GCC segfaults.
+ template<std::uint32_t tier, std::size_t index> static constexpr flag_set make_static()
+ {
+ static_assert(tier < tiers, "tier >= tiers");
+ static_assert(index < 32, "index >= 32");
+ flag_set f;
+ f.m_data[tier] = (1UL << index);
+ return f;
+ }
+
+ static constexpr flag_set make(std::uint32_t tier, std::size_t index)
+ {
+ assert(tier < tiers);
+ assert(index < 32);
+ flag_set f;
+ f.m_data[tier] = (1UL << index);
+ return f;
+ }
+
+ static constexpr flag_set make_bit(std::size_t ibit)
+ {
+ assert(ibit < nbits);
+ flag_set f;
+ f.m_data[ibit / 32] = (1UL << (ibit % 32));
+ return f;
+ }
+
+ constexpr std::size_t size() const
+ {
+ return tiers;
+ }
+
+ constexpr bool empty() const
+ {
+ for (std::size_t i = 0; i < tiers; i++)
+ {
+ if (m_data[i])
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ constexpr std::size_t count() const
+ {
+ std::size_t n = 0;
+ for (std::size_t i = 0; i < nbits; i++)
+ {
+ if (bit(i))
+ {
+ n += 1;
+ }
+ }
+ return n;
+ }
+
+ uint32_t &operator[](std::size_t i)
+ {
+ assert(i < tiers);
+ return m_data[i];
+ }
+
+ constexpr uint32_t const &operator [](std::size_t i) const
+ {
+ assert(i < tiers);
+ return m_data[i];
+ }
+
+ explicit constexpr operator bool() const
+ {
+ return !empty();
+ }
+
+ constexpr bool operator == (flag_set const &other) const
+ {
+ for (std::size_t i = 0; i < tiers; i++)
+ {
+ if (m_data[i] != other.m_data[i])
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ constexpr bool operator != (flag_set const &other) const
+ {
+ return !(*this == other);
+ }
+
+ constexpr bool bit(std::size_t i) const
+ {
+ assert(i < nbits);
+ return (m_data[i / 32] & (1UL << (i % 32)));
+ }
+
+ flag_set &operator |= (flag_set const &other)
+ {
+ for (std::size_t i = 0; i < tiers; i++)
+ {
+ m_data[i] |= other.m_data[i];
+ }
+ return *this;
+ }
+
+ constexpr flag_set operator | (flag_set const &other) const
+ {
+ flag_set f;
+ for (std::size_t i = 0; i < tiers; i++)
+ {
+ f.m_data[i] = m_data[i] | other.m_data[i];
+ }
+ return f;
+ }
+
+ flag_set &operator &= (flag_set const &other)
+ {
+ for (std::size_t i = 0; i < tiers; i++)
+ {
+ m_data[i] &= other.m_data[i];
+ }
+ return *this;
+ }
+
+ constexpr flag_set operator & (flag_set const &other) const
+ {
+ flag_set f;
+ for (std::size_t i = 0; i < tiers; i++)
+ {
+ f.m_data[i] = m_data[i] & other.m_data[i];
+ }
+ return f;
+ }
+
+ constexpr flag_set operator ~ () const
+ {
+ flag_set f;
+ for (std::size_t i = 0; i < tiers; i++)
+ {
+ f.m_data[i] = ~m_data[i];
+ }
+ return f;
+ }
+
+};
+
+// Implementation details, because preprocessor.
+#define DECLARE_FLAG_MAKE_INIT(type, tier, index) \
+ type::make_static<tier-1,index>()
+
+/**
+ * Macro for declaring a "flag" constant.
+ */
+#define DECLARE_FLAG(type, name, tier, index) \
+ PP_GLOBAL_CONSTEXPR_CONST(type, name, DECLARE_FLAG_MAKE_INIT(type, tier, index))
+
+/**
+ * Macro for declaring a zero'ed "flag" variable.
+ */
+#define DECLARE_FLAG_ZERO_INTF(type, name) \
+ extern type name
+
+/**
+ * Macro for declaring the implementation of a zero'ed "flag" variable.
+ */
+#define DECLARE_FLAG_ZERO_IMPL(type, name) \
+ type name { };
diff --git a/src/flags_group.hpp b/src/flags_group.hpp
new file mode 100644
index 00000000..84809e37
--- /dev/null
+++ b/src/flags_group.hpp
@@ -0,0 +1,17 @@
+#pragma once
+
+#include "h-basic.h"
+#include "object_flag_set.hpp"
+
+/**
+ * For level gaining artifacts
+ */
+struct flags_group
+{
+ char name[30] { }; /* Name */
+ byte color = 0; /* Color */
+
+ byte price = 0; /* Price to "buy" it */
+
+ object_flag_set flags; /* Flags set */
+};
diff --git a/src/game.cc b/src/game.cc
new file mode 100644
index 00000000..284c9ccc
--- /dev/null
+++ b/src/game.cc
@@ -0,0 +1,3 @@
+#include "game.hpp"
+
+Game *game;
diff --git a/src/game.hpp b/src/game.hpp
new file mode 100644
index 00000000..4f84f52c
--- /dev/null
+++ b/src/game.hpp
@@ -0,0 +1,97 @@
+#pragma once
+
+#include "game_fwd.hpp"
+
+#include "alloc.hpp"
+#include "birther.hpp"
+#include "game_edit_data.hpp"
+#include "grid.hpp"
+#include "h-basic.h"
+#include "level_marker.hpp"
+#include "messages.hpp"
+#include "player_defs.hpp"
+#include "random_artifact.hpp"
+#include "skill_type.hpp"
+#include "timer_type_fwd.hpp"
+#include "wilderness_map.hpp"
+
+#include <boost/multi_array.hpp>
+
+/**
+ * All structures for the game itself.
+ */
+struct Game {
+
+ /**
+ * Player character name
+ */
+ std::string player_name;
+
+ /*
+ * Stripped version of "player_name"
+ */
+ std::string player_base;
+
+ /**
+ * What did the player die from?
+ */
+ std::string died_from;
+
+ /**
+ * Previous character
+ */
+ birther previous_char;
+
+ /**
+ * Wilderness map
+ */
+ grid<wilderness_map> wilderness;
+
+ /**
+ * Random artifacts
+ */
+ std::vector<random_artifact> random_artifacts;
+
+ /**
+ * Allocations
+ */
+ Alloc alloc;
+
+ /**
+ * Player's un-adjusted HP at every level.
+ * Stored to avoid shenanigans with draininging levels
+ * and restoring them back, &c.
+ */
+ std::array<s16b, PY_MAX_LEVEL> player_hp { };
+
+ /**
+ * Message buffer.
+ */
+ Messages messages { 2048 };
+
+ /**
+ * Game edit data
+ */
+ GameEditData edit_data;
+
+ /**
+ * Current skill values.
+ */
+ std::vector<skill_type> s_info;
+
+ /**
+ * Timers
+ */
+ std::vector<timer_type *> timers;
+
+ /**
+ * Level markers for 'special' levels.
+ */
+ boost::multi_array<level_marker, 2> level_markers { };
+
+ /**
+ * Generate a special level feeling?
+ */
+ bool generate_special_feeling = false;
+
+};
diff --git a/src/game_edit_data.hpp b/src/game_edit_data.hpp
new file mode 100644
index 00000000..a4727d90
--- /dev/null
+++ b/src/game_edit_data.hpp
@@ -0,0 +1,138 @@
+#pragma once
+
+#include "ability_type.hpp"
+#include "artifact_type.hpp"
+#include "dungeon_info_type.hpp"
+#include "ego_item_type.hpp"
+#include "feature_type.hpp"
+#include "monster_ego.hpp"
+#include "monster_race.hpp"
+#include "object_kind.hpp"
+#include "owner_type.hpp"
+#include "player_class.hpp"
+#include "player_race.hpp"
+#include "player_race_mod.hpp"
+#include "randart_gen_type.hpp"
+#include "randart_part_type.hpp"
+#include "set_type.hpp"
+#include "skill_descriptor.hpp"
+#include "store_action_type.hpp"
+#include "store_info_type.hpp"
+#include "vault_type.hpp"
+#include "wilderness_type_info.hpp"
+
+#include <vector>
+
+/**
+ * Game edit data, i.e. the parsed contents of the edit .txt
+ * files.
+ */
+struct GameEditData {
+
+ /**
+ * Dungeons
+ */
+ std::vector<dungeon_info_type> d_info;
+
+ /**
+ * Vaults
+ */
+ std::vector<vault_type> v_info;
+
+ /**
+ * Random artifact part descriptors, i.e. the bits that
+ * randarts are made up of.
+ */
+ std::vector<randart_part_type> ra_info;
+
+ /**
+ * Random artifact generation parameters.
+ */
+ std::vector<randart_gen_type> ra_gen;
+
+ /**
+ * Artifacts
+ */
+ std::vector<artifact_type> a_info;
+
+ /**
+ * Ego items
+ */
+ std::vector<ego_item_type> e_info;
+
+ /**
+ * Artifact sets
+ */
+ std::vector<set_type> set_info;
+
+ /**
+ * Object kinds
+ */
+ std::vector<object_kind> k_info;
+
+ /**
+ * Building actions.
+ */
+ std::vector<store_action_type> ba_info;
+
+ /**
+ * Buildings
+ */
+ std::vector<store_info_type> st_info;
+
+ /**
+ * Building owners.
+ */
+ std::vector<owner_type> ow_info;
+
+ /**
+ * Player classes.
+ */
+ std::vector<player_class> class_info;
+
+ /**
+ * Player races.
+ */
+ std::vector<player_race> race_info;
+
+ /**
+ * Player subraces.
+ */
+ std::vector<player_race_mod> race_mod_info;
+
+ /**
+ * Player skills
+ */
+ std::vector<skill_descriptor> s_descriptors;
+
+ /*
+ * The monster races
+ */
+ std::vector<monster_race> r_info;
+
+ /**
+ * Monster race egos
+ */
+ std::vector<monster_ego> re_info;
+
+ /*
+ * Terrain features
+ */
+ std::vector<feature_type> f_info;
+
+ /**
+ * Wilderness features
+ */
+ std::vector<wilderness_type_info> wf_info;
+
+ /**
+ * Base skills for all characters.
+ */
+ skill_modifiers gen_skill;
+
+ /**
+ * Player abilities.
+ */
+ std::vector<ability_type> ab_info;
+
+};
diff --git a/src/game_edit_data_fwd.hpp b/src/game_edit_data_fwd.hpp
new file mode 100644
index 00000000..3c986dfa
--- /dev/null
+++ b/src/game_edit_data_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct GameEditData;
diff --git a/src/game_fwd.hpp b/src/game_fwd.hpp
new file mode 100644
index 00000000..840e5f3b
--- /dev/null
+++ b/src/game_fwd.hpp
@@ -0,0 +1,4 @@
+#pragma once
+
+struct Game;
+extern Game *game;
diff --git a/src/gen_evol.c b/src/gen_evol.cc
index bfdfbd68..7dca5b9a 100644
--- a/src/gen_evol.c
+++ b/src/gen_evol.cc
@@ -1,8 +1,4 @@
/*
- * Generate a game of life level and make it evolve
- */
-
-/*
* Copyright (c) 2003 DarkGod.
*
* This software may be copied and distributed for educational, research, and
@@ -10,14 +6,26 @@
* included in all such copies.
*/
-#include "angband.h"
+#include "gen_evol.hpp"
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "feature_flag.hpp"
+#include "feature_type.hpp"
+#include "game.hpp"
+#include "generate.hpp"
+#include "levels.hpp"
+#include "player_type.hpp"
+#include "variable.hpp"
+#include "z-rand.hpp"
/*
* Generate a game of life level :) and make it evolve
*/
void evolve_level(bool_ noise)
{
+ auto const &f_info = game->edit_data.f_info;
+
int i, j;
int cw = 0, cf = 0;
@@ -30,8 +38,8 @@ void evolve_level(bool_ noise)
{
for (j = 1; j < cur_hgt - 1; j++)
{
- if (f_info[cave[j][i].feat].flags1 & FF1_WALL) cw++;
- if (f_info[cave[j][i].feat].flags1 & FF1_FLOOR) cf++;
+ if (f_info[cave[j][i].feat].flags & FF_WALL) cw++;
+ if (f_info[cave[j][i].feat].flags & FF_FLOOR) cf++;
}
}
@@ -45,10 +53,10 @@ void evolve_level(bool_ noise)
c_ptr = &cave[j][i];
/* Permanent features should stay */
- if (f_info[c_ptr->feat].flags1 & FF1_PERMANENT) continue;
+ if (f_info[c_ptr->feat].flags & FF_PERMANENT) continue;
/* Avoid evolving grids with object or monster */
- if (c_ptr->o_idx || c_ptr->m_idx) continue;
+ if ((!c_ptr->o_idxs.empty()) || c_ptr->m_idx) continue;
/* Avoid evolving player grid */
if ((j == p_ptr->py) && (i == p_ptr->px)) continue;
@@ -79,10 +87,10 @@ void evolve_level(bool_ noise)
c_ptr = &cave[j][i];
/* Permanent features should stay */
- if (f_info[c_ptr->feat].flags1 & FF1_PERMANENT) continue;
+ if (f_info[c_ptr->feat].flags & FF_PERMANENT) continue;
/* Avoid evolving grids with object or monster */
- if (c_ptr->o_idx || c_ptr->m_idx) continue;
+ if ((!c_ptr->o_idxs.empty()) || c_ptr->m_idx) continue;
/* Avoid evolving player grid */
if ((j == p_ptr->py) && (i == p_ptr->px)) continue;
@@ -97,7 +105,7 @@ void evolve_level(bool_ noise)
for (y = j - 1; y <= j + 1; y++)
{
if ((x == i) && (y == j)) continue;
- if (f_info[cave[y][x].feat].flags1 & FF1_WALL) c++;
+ if (f_info[cave[y][x].feat].flags & FF_WALL) c++;
}
}
@@ -108,7 +116,7 @@ void evolve_level(bool_ noise)
/* Starved or suffocated */
if ((c < 4) || (c >= 7))
{
- if (f_info[c_ptr->feat].flags1 & FF1_WALL)
+ if (f_info[c_ptr->feat].flags & FF_WALL)
{
place_floor(j, i);
}
@@ -117,7 +125,7 @@ void evolve_level(bool_ noise)
/* Spawned */
else if ((c == 4) || (c == 5))
{
- if (!(f_info[c_ptr->feat].flags1 & FF1_WALL))
+ if (!(f_info[c_ptr->feat].flags & FF_WALL))
{
place_filler(j, i);
}
diff --git a/src/gen_evol.hpp b/src/gen_evol.hpp
new file mode 100644
index 00000000..6e5087c8
--- /dev/null
+++ b/src/gen_evol.hpp
@@ -0,0 +1,6 @@
+#pragma once
+
+#include "h-basic.h"
+
+bool_ level_generate_life();
+void evolve_level(bool_ noise);
diff --git a/src/gen_maze.c b/src/gen_maze.cc
index 92cb482f..22722e0a 100644
--- a/src/gen_maze.c
+++ b/src/gen_maze.cc
@@ -1,8 +1,4 @@
/*
- * Maze dungeon generator
- */
-
-/*
* Copyright (c) 2003 DarkGod. And somebody who posted the algorith on
* rec.games.roguelike.development. I can't remember teh name :( please mail me
*
@@ -11,7 +7,15 @@
* included in all such copies.
*/
-#include "angband.h"
+#include "gen_evol.hpp"
+
+#include "cave.hpp"
+#include "generate.hpp"
+#include "levels.hpp"
+#include "variable.hpp"
+#include "z-rand.hpp"
+
+#include <memory>
/*
* If we wasted static memory for this, it would look like:
@@ -20,7 +24,7 @@
*/
typedef signed char maze_row[(MAX_WID / 2) + 2];
-void dig(maze_row *maze, int y, int x, int d)
+static void dig(maze_row *maze, int y, int x, int d)
{
int k;
int dy = 0, dx = 0;
@@ -145,10 +149,9 @@ bool_ level_generate_maze()
int y, dy = 0;
int x, dx = 0;
int m_1 = 0, m_2 = 0;
- maze_row *maze;
/* Allocate temporary memory */
- C_MAKE(maze, (MAX_HGT / 2) + 2, maze_row);
+ std::unique_ptr<maze_row[]> maze(new maze_row[(MAX_HGT / 2) + 2]);
/*
* the empty maze is:
@@ -209,7 +212,7 @@ bool_ level_generate_maze()
x = rand_range(1, (cur_wid / 2));
d = rand_range(0, 3);
- dig(maze, y, x, d);
+ dig(maze.get(), y, x, d);
maze[y][x] = 0;
@@ -283,9 +286,6 @@ bool_ level_generate_maze()
}
}
- /* Free temporary memory */
- C_FREE(maze, (MAX_HGT / 2) + 2, maze_row);
-
/* Determine the character location */
if (!new_player_spot(get_branch()))
return FALSE;
diff --git a/src/gen_maze.hpp b/src/gen_maze.hpp
new file mode 100644
index 00000000..bc03b575
--- /dev/null
+++ b/src/gen_maze.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+bool_ level_generate_maze();
diff --git a/src/generate.c b/src/generate.cc
index 6d83c321..ba485faf 100644
--- a/src/generate.c
+++ b/src/generate.cc
@@ -1,7 +1,3 @@
-/* File: generate.c */
-
-/* Purpose: Dungeon generation */
-
/*
* Copyright (c) 1989 James E. Wilson, Robert A. Koeneke
*
@@ -10,7 +6,46 @@
* included in all such copies.
*/
-#include "angband.h"
+#include "generate.hpp"
+
+#include "artifact_type.hpp"
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "dungeon_info_type.hpp"
+#include "dungeon_flag.hpp"
+#include "feature_flag.hpp"
+#include "feature_type.hpp"
+#include "game.hpp"
+#include "hook_build_room1_in.hpp"
+#include "hooks.hpp"
+#include "init1.hpp"
+#include "levels.hpp"
+#include "loadsave.hpp"
+#include "monster2.hpp"
+#include "monster_race.hpp"
+#include "monster_race_flag.hpp"
+#include "monster_spell_flag.hpp"
+#include "monster_type.hpp"
+#include "object2.hpp"
+#include "object_flag.hpp"
+#include "object_kind.hpp"
+#include "options.hpp"
+#include "player_type.hpp"
+#include "randart.hpp"
+#include "spells1.hpp"
+#include "tables.hpp"
+#include "town_type.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+#include "vault_type.hpp"
+#include "wild.hpp"
+#include "wilderness_map.hpp"
+#include "z-rand.hpp"
+
+#include <cassert>
+#include <memory>
+#include <vector>
+
#define SAFE_MAX_ATTEMPTS 5000
/*
@@ -162,7 +197,6 @@
* Hack -- Dungeon allocation "types"
*/
#define ALLOC_TYP_RUBBLE 1 /* Rubble */
-#define ALLOC_TYP_TRAP 3 /* Trap */
#define ALLOC_TYP_GOLD 4 /* Gold */
#define ALLOC_TYP_OBJECT 5 /* Object */
#define ALLOC_TYP_ALTAR 6 /* Altar */
@@ -273,12 +307,7 @@ typedef struct level_generator_type level_generator_type;
struct level_generator_type
{
cptr name;
- bool_ (*generator)(cptr);
-
- bool_ default_stairs;
- bool_ default_monsters;
- bool_ default_objects;
- bool_ default_miscs;
+ bool_ (*generator)();
struct level_generator_type *next;
};
@@ -288,18 +317,14 @@ static level_generator_type *level_generators = NULL;
/*
* Add a new generator
*/
-void add_level_generator(cptr name, bool_ (*generator)(), bool_ stairs, bool_ monsters, bool_ objects, bool_ miscs)
+void add_level_generator(cptr name, bool_ (*generator)())
{
- level_generator_type *g;
+ assert(name != nullptr);
- MAKE(g, level_generator_type);
- g->name = string_make(name);
- g->generator = generator;
+ level_generator_type *g = new level_generator_type;
- g->default_stairs = stairs;
- g->default_monsters = monsters;
- g->default_objects = objects;
- g->default_miscs = miscs;
+ g->name = strdup(name);
+ g->generator = generator;
g->next = level_generators;
level_generators = g;
@@ -385,7 +410,7 @@ static void place_up_stairs(int y, int x)
cave_type *c_ptr = &cave[y][x];
/* Create up stairs */
- if ((rand_int(3) != 0) || (dungeon_flags2 & DF2_NO_SHAFT))
+ if ((rand_int(3) != 0) || (dungeon_flags & DF_NO_SHAFT))
{
cave_set_feat(y, x, FEAT_LESS);
}
@@ -399,23 +424,12 @@ static void place_up_stairs(int y, int x)
/*
- * Convert existing terrain type to "down stairs" with dungeon changing.
- */
-static void place_magical_stairs(int y, int x, byte next)
-{
- cave_type *c_ptr = &cave[y][x];
-
- /* Create up stairs */
- cave_set_feat(y, x, FEAT_MORE);
- c_ptr->special = next;
-}
-
-
-/*
* Convert existing terrain type to "down stairs"
*/
static void place_down_stairs(int y, int x)
{
+ auto const &d_info = game->edit_data.d_info;
+
cave_type *c_ptr = &cave[y][x];
/*
@@ -423,7 +437,7 @@ static void place_down_stairs(int y, int x)
* All thoses tests are necesary because a shaft can jump up to 4 levels
*/
if ((dun_level + 4 > d_info[dungeon_type].maxdepth) ||
- (rand_int(3) != 0) || (dungeon_flags2 & DF2_NO_SHAFT))
+ (rand_int(3) != 0) || (dungeon_flags & DF_NO_SHAFT))
{
cave_set_feat(y, x, FEAT_MORE);
}
@@ -442,7 +456,9 @@ static void place_down_stairs(int y, int x)
*/
static bool_ is_safe_floor(int y, int x)
{
- dungeon_info_type *d_ptr = &d_info[dungeon_type];
+ auto const &d_info = game->edit_data.d_info;
+
+ auto d_ptr = &d_info[dungeon_type];
byte feat = cave[y][x].feat;
/* One of the legal floor types */
@@ -460,6 +476,8 @@ static bool_ is_safe_floor(int y, int x)
*/
void place_new_way(int *y, int *x)
{
+ auto const &f_info = game->edit_data.f_info;
+
int xx, yy;
int x0, x1, x2;
int y0, y1, y2;
@@ -548,8 +566,8 @@ void place_new_way(int *y, int *x)
if (c_ptr->info & (CAVE_ICKY)) continue;
/* Reject permanent features */
- if ((f_info[c_ptr->feat].flags1 & (FF1_PERMANENT)) &&
- (f_info[c_ptr->feat].flags1 & (FF1_FLOOR))) continue;
+ if ((f_info[c_ptr->feat].flags & FF_PERMANENT) &&
+ (f_info[c_ptr->feat].flags & FF_FLOOR)) continue;
/* Reject room walls */
if ((c_ptr->info & (CAVE_ROOM)) &&
@@ -586,8 +604,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 +611,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;
@@ -715,7 +716,7 @@ bool_ new_player_spot(int branch)
int max_attempts = 5000;
/* Place the player */
- if (dungeon_flags1 & DF1_FLAT)
+ if (dungeon_flags & DF_FLAT)
{
place_new_way(&y, &x);
}
@@ -748,13 +749,13 @@ bool_ new_player_spot(int branch)
p_ptr->px = x;
/* XXX XXX XXX */
- if (dungeon_stair && !(dungeon_flags2 & DF2_NO_STAIR) && dun_level &&
+ if (options->dungeon_stair && !(dungeon_flags & DF_NO_STAIR) && dun_level &&
(!is_quest(dun_level) || (old_dun_level < dun_level)) && !branch)
{
if (old_dun_level < dun_level)
{
place_up_stairs(p_ptr->py , p_ptr->px);
- if (dungeon_flags1 & DF1_FLAT)
+ if (dungeon_flags & DF_FLAT)
{
cave_set_feat(p_ptr->py, p_ptr->px, FEAT_WAY_LESS);
}
@@ -762,7 +763,7 @@ bool_ new_player_spot(int branch)
else
{
place_down_stairs(p_ptr->py , p_ptr->px);
- if (dungeon_flags1 & DF1_FLAT)
+ if (dungeon_flags & DF_FLAT)
{
cave_set_feat(p_ptr->py, p_ptr->px, FEAT_WAY_MORE);
}
@@ -783,12 +784,14 @@ bool_ new_player_spot(int branch)
*/
static int next_to_walls(int y, int x)
{
- int k = 0;
+ auto const &f_info = game->edit_data.f_info;
+
+ int k = 0;
- if (f_info[cave[y + 1][x].feat].flags1 & FF1_WALL) k++;
- if (f_info[cave[y - 1][x].feat].flags1 & FF1_WALL) k++;
- if (f_info[cave[y][x + 1].feat].flags1 & FF1_WALL) k++;
- if (f_info[cave[y][x - 1].feat].flags1 & FF1_WALL) k++;
+ if (f_info[cave[y + 1][x].feat].flags & FF_WALL) k++;
+ if (f_info[cave[y - 1][x].feat].flags & FF_WALL) k++;
+ if (f_info[cave[y][x + 1].feat].flags & FF_WALL) k++;
+ if (f_info[cave[y][x - 1].feat].flags & FF_WALL) k++;
return (k);
}
@@ -820,19 +823,28 @@ static void place_altar(int y, int x)
*/
static void place_fountain(int y, int x)
{
+ auto const &k_info = game->edit_data.k_info;
+
cave_type *c_ptr = &cave[y][x];
- int svals[SV_POTION_LAST + SV_POTION2_LAST + 1], maxsval = 0, k;
+ int svals[SV_POTION_LAST + SV_POTION2_LAST + 1];
+ int maxsval = 0;
/* List of usable svals */
- for (k = 1; k < max_k_idx; k++)
+ for (auto const &k_ref: k_info)
{
- object_kind *k_ptr = &k_info[k];
+ auto k_ptr = &k_ref;
if (((k_ptr->tval == TV_POTION) || (k_ptr->tval == TV_POTION2)) &&
- (k_ptr->level <= dun_level) && (k_ptr->flags4 & TR4_FOUNTAIN))
+ (k_ptr->level <= dun_level) && (k_ptr->flags & TR_FOUNTAIN))
{
- if (k_ptr->tval == TV_POTION2) svals[maxsval] = k_ptr->sval + SV_POTION_LAST;
- else svals[maxsval] = k_ptr->sval;
+ if (k_ptr->tval == TV_POTION2)
+ {
+ svals[maxsval] = k_ptr->sval + SV_POTION_LAST;
+ }
+ else
+ {
+ svals[maxsval] = k_ptr->sval;
+ }
maxsval++;
}
}
@@ -889,6 +901,8 @@ static void place_between(int y, int x)
*/
static void place_random_stairs(int y, int x)
{
+ auto const &d_info = game->edit_data.d_info;
+
/* Paranoia */
if (!cave_clean_bold(y, x)) return;
@@ -903,14 +917,7 @@ static void place_random_stairs(int y, int x)
}
else if (dun_level >= d_info[dungeon_type].maxdepth)
{
- if (d_info[dungeon_type].next)
- {
- place_magical_stairs(y, x, d_info[dungeon_type].next);
- }
- else
- {
- place_up_stairs(y, x);
- }
+ place_up_stairs(y, x);
}
else if (rand_int(100) < 50)
{
@@ -934,45 +941,6 @@ static void place_locked_door(int y, int x)
/*
- * Place a secret door at the given location
- */
-static void place_secret_door(int y, int x)
-{
- cave_type *c_ptr = &cave[y][x];
-
- /* Vaults */
- if (c_ptr->info & CAVE_ICKY)
- {
- c_ptr->mimic = FEAT_WALL_INNER;
- }
-
- /* Ordinary room -- use current outer or inner wall */
- else if (c_ptr->info & CAVE_ROOM)
- {
- /* Determine if it's inner or outer XXX XXX XXX */
- if ((cave[y - 1][x].info & CAVE_ROOM) &&
- (cave[y + 1][x].info & CAVE_ROOM) &&
- (cave[y][x - 1].info & CAVE_ROOM) &&
- (cave[y][x + 1].info & CAVE_ROOM))
- {
- c_ptr->mimic = feat_wall_inner;
- }
- else
- {
- c_ptr->mimic = feat_wall_outer;
- }
- }
- else
- {
- c_ptr->mimic = fill_type[rand_int(100)];
- }
-
- /* Create secret door */
- cave_set_feat(y, x, FEAT_SECRET);
-}
-
-
-/*
* Place a random type of door at the given location
*/
static void place_random_door(int y, int x)
@@ -996,11 +964,11 @@ static void place_random_door(int y, int x)
cave_set_feat(y, x, FEAT_BROKEN);
}
- /* Secret doors (200/1000) */
+ /* Secret doors (200/1000) - now locked instead */
else if (tmp < 600)
{
- /* Create secret door */
- place_secret_door(y, x);
+ /* Create locked door */
+ place_locked_door(y, x);
}
/* Closed doors (300/1000) */
@@ -1021,7 +989,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));
}
}
@@ -1032,6 +1000,8 @@ static void place_random_door(int y, int x)
*/
static void alloc_stairs(int feat, int num, int walls, int branch)
{
+ auto const &d_info = game->edit_data.d_info;
+
int y, x, i, j, cnt;
/* Place "num" stairs */
@@ -1040,7 +1010,7 @@ static void alloc_stairs(int feat, int num, int walls, int branch)
/* Try several times, then decrease "walls" */
for (j = 0; j <= SAFE_MAX_ATTEMPTS; j++)
{
- if (dungeon_flags1 & DF1_FLAT)
+ if (dungeon_flags & DF_FLAT)
{
place_new_way(&y, &x);
}
@@ -1061,11 +1031,11 @@ static void alloc_stairs(int feat, int num, int walls, int branch)
if (!dun_level)
{
/* Clear previous contents, add down stairs */
- if (dungeon_flags1 & DF1_FLAT)
+ if (dungeon_flags & DF_FLAT)
{
cave_set_feat(y, x, FEAT_WAY_MORE);
}
- else if ((rand_int(3) == 0) && (!(dungeon_flags2 & DF2_NO_SHAFT)))
+ else if ((rand_int(3) == 0) && (!(dungeon_flags & DF_NO_SHAFT)))
{
cave_set_feat(y, x, FEAT_SHAFT_DOWN);
}
@@ -1078,14 +1048,14 @@ static void alloc_stairs(int feat, int num, int walls, int branch)
/* Quest -- must go up */
else if ((is_quest(dun_level) && (dun_level >= 1)) ||
((dun_level >= d_info[dungeon_type].maxdepth) &&
- (!(dungeon_flags1 & DF1_FORCE_DOWN))))
+ (!(dungeon_flags & DF_FORCE_DOWN))))
{
/* Clear previous contents, add up stairs */
- if (dungeon_flags1 & DF1_FLAT)
+ if (dungeon_flags & DF_FLAT)
{
cave_set_feat(y, x, FEAT_WAY_LESS);
}
- else if ((rand_int(3) == 0) && (!(dungeon_flags2 & DF2_NO_SHAFT)))
+ else if ((rand_int(3) == 0) && (!(dungeon_flags & DF_NO_SHAFT)))
{
cave_set_feat(y, x, FEAT_SHAFT_UP);
}
@@ -1159,7 +1129,7 @@ static void alloc_object(int set, int typ, int num)
if (dummy >= SAFE_MAX_ATTEMPTS)
{
- if (cheat_room)
+ if (options->cheat_room)
{
msg_format("Warning! Could not place object, type : %d!", typ);
}
@@ -1177,12 +1147,6 @@ static void alloc_object(int set, int typ, int num)
break;
}
- case ALLOC_TYP_TRAP:
- {
- place_trap(y, x);
- break;
- }
-
case ALLOC_TYP_GOLD:
{
place_gold(y, x);
@@ -1423,6 +1387,8 @@ static void add_river(int feat1, int feat2)
*/
static void build_streamer(int feat, int chance)
{
+ auto const &d_info = game->edit_data.d_info;
+
int i, tx, ty;
int y, x, dir;
int dummy = 0;
@@ -1480,7 +1446,7 @@ static void build_streamer(int feat, int chance)
if (dummy >= SAFE_MAX_ATTEMPTS)
{
- if (cheat_room)
+ if (options->cheat_room)
{
msg_print("Warning! Could not place streamer!");
}
@@ -1506,6 +1472,8 @@ static void build_streamer(int feat, int chance)
*/
static void build_streamer2(int feat, int killwall)
{
+ auto const &f_info = game->edit_data.f_info;
+
int i, j, mid, tx, ty;
int y, x, dir;
int poolchance;
@@ -1546,13 +1514,13 @@ static void build_streamer2(int feat, int killwall)
if (c_ptr->info & (CAVE_ICKY)) continue;
/* Reject permanent features */
- if ((f_info[c_ptr->feat].flags1 & (FF1_PERMANENT)) &&
- (f_info[c_ptr->feat].flags1 & (FF1_FLOOR))) continue;
+ if ((f_info[c_ptr->feat].flags & FF_PERMANENT) &&
+ (f_info[c_ptr->feat].flags & FF_FLOOR)) continue;
/* Avoid converting walls when told so */
if (killwall == 0)
{
- if (f_info[c_ptr->feat].flags1 & FF1_WALL) continue;
+ if (f_info[c_ptr->feat].flags & FF_WALL) continue;
}
/* Clear mimic feature to avoid nasty consequences */
@@ -1609,7 +1577,7 @@ static void build_streamer2(int feat, int killwall)
continue;
/* Only convert non-permanent features */
- if (f_info[cave[ty][tx].feat].flags1 & FF1_PERMANENT) continue;
+ if (f_info[cave[ty][tx].feat].flags & FF_PERMANENT) continue;
/* Clear mimic feature to avoid nasty consequences */
cave[ty][tx].mimic = 0;
@@ -1626,14 +1594,14 @@ static void build_streamer2(int feat, int killwall)
/*
* Build a destroyed level
*/
-static void destroy_level(void)
+static void destroy_level()
{
int y1, x1, y, x, k, t, n;
cave_type *c_ptr;
/* Note destroyed levels */
- if ((cheat_room) || (p_ptr->precognition)) msg_print("Destroyed Level");
+ if ((options->cheat_room) || (p_ptr->precognition)) msg_print("Destroyed Level");
/* Drop a few epi-centers (usually about two) */
for (n = 0; n < randint(5); n++)
@@ -1723,11 +1691,13 @@ static void destroy_level(void)
*/
static bool_ get_is_floor(int x, int y)
{
+ auto const &f_info = game->edit_data.f_info;
+
/* Out of bounds */
if (!in_bounds(y, x)) return (FALSE);
/* Do the real check: */
- if (f_info[cave[y][x].feat].flags1 & FF1_FLOOR) return (TRUE);
+ if (f_info[cave[y][x].feat].flags & FF_FLOOR) return (TRUE);
return (FALSE);
}
@@ -1742,7 +1712,7 @@ static void check_room_boundary(int x1, int y1, int x2, int y2)
bool_ old_is_floor, new_is_floor;
/* Avoid doing this in irrelevant places -- pelpel */
- if (!(dungeon_flags1 & DF1_CAVERN)) return;
+ if (!(dungeon_flags & DF_CAVERN)) return;
/* Initialize */
count = 0;
@@ -1843,7 +1813,7 @@ static void vault_objects(int y, int x, int num)
if (dummy >= SAFE_MAX_ATTEMPTS)
{
- if (cheat_room)
+ if (options->cheat_room)
{
msg_print("Warning! Could not place vault object!");
}
@@ -1873,61 +1843,6 @@ static void vault_objects(int y, int x, int num)
/*
- * Place a trap with a given displacement of point
- */
-static void vault_trap_aux(int y, int x, int yd, int xd)
-{
- int count = 0, y1 = y, x1 = x;
- int dummy = 0;
-
- /* Place traps */
- for (count = 0; count <= 5; count++)
- {
- /* Get a location */
- while (dummy < SAFE_MAX_ATTEMPTS)
- {
- y1 = rand_spread(y, yd);
- x1 = rand_spread(x, xd);
- dummy++;
- if (in_bounds(y1, x1)) break;
- }
-
- if (dummy >= SAFE_MAX_ATTEMPTS)
- {
- if (cheat_room)
- {
- msg_print("Warning! Could not place vault trap!");
- }
- }
-
-
- /* Require "naked" floor grids */
- if (!cave_naked_bold(y1, x1)) continue;
-
- /* Place the trap */
- place_trap(y1, x1);
-
- /* Done */
- break;
- }
-}
-
-
-/*
- * Place some traps with a given displacement of given location
- */
-static void vault_traps(int y, int x, int yd, int xd, int num)
-{
- int i;
-
- for (i = 0; i < num; i++)
- {
- vault_trap_aux(y, x, yd, xd);
- }
-}
-
-
-/*
* Hack -- Place some sleeping monsters near the given location
*/
static void vault_monsters(int y1, int x1, int num)
@@ -1950,7 +1865,7 @@ static void vault_monsters(int y1, int x1, int num)
/* Place the monster (allow groups) */
monster_level = dun_level + 2;
- (void)place_monster(y, x, TRUE, TRUE);
+ place_monster(y, x, TRUE, TRUE);
monster_level = dun_level;
}
}
@@ -2273,20 +2188,20 @@ static void build_type3(int by0, int bx0)
/* Build the vault */
build_rectangle(y1b, x1a, y2b, x2a, feat_wall_inner, info);
- /* Place a secret door on the inner room */
+ /* Place a locked door on the inner room */
switch (rand_int(4))
{
case 0:
- place_secret_door(y1b, xval);
+ place_locked_door(y1b, xval);
break;
case 1:
- place_secret_door(y2b, xval);
+ place_locked_door(y2b, xval);
break;
case 2:
- place_secret_door(yval, x1a);
+ place_locked_door(yval, x1a);
break;
case 3:
- place_secret_door(yval, x2a);
+ place_locked_door(yval, x2a);
break;
}
@@ -2296,9 +2211,6 @@ static void build_type3(int by0, int bx0)
/* Let's guard the treasure well */
vault_monsters(yval, xval, rand_int(2) + 3);
- /* Traps naturally */
- vault_traps(yval, xval, 4, 4, rand_int(3) + 2);
-
break;
}
@@ -2324,13 +2236,13 @@ static void build_type3(int by0, int bx0)
cave_set_feat(y2b + 1, x, feat_wall_inner);
}
- /* Sometimes shut using secret doors */
+ /* Sometimes shut using locked doors */
if (rand_int(3) == 0)
{
- place_secret_door(yval, x1a - 1);
- place_secret_door(yval, x2a + 1);
- place_secret_door(y1b - 1, xval);
- place_secret_door(y2b + 1, xval);
+ place_locked_door(yval, x1a - 1);
+ place_locked_door(yval, x2a + 1);
+ place_locked_door(y1b - 1, xval);
+ place_locked_door(y2b + 1, xval);
}
}
@@ -2410,20 +2322,20 @@ static void build_type4(int by0, int bx0)
/* Just an inner room with a monster */
case 1:
{
- /* Place a secret door */
+ /* Place a locked door */
switch (randint(4))
{
case 1:
- place_secret_door(y1 - 1, xval);
+ place_locked_door(y1 - 1, xval);
break;
case 2:
- place_secret_door(y2 + 1, xval);
+ place_locked_door(y2 + 1, xval);
break;
case 3:
- place_secret_door(yval, x1 - 1);
+ place_locked_door(yval, x1 - 1);
break;
case 4:
- place_secret_door(yval, x2 + 1);
+ place_locked_door(yval, x2 + 1);
break;
}
@@ -2436,20 +2348,20 @@ static void build_type4(int by0, int bx0)
/* Treasure Vault (with a door) */
case 2:
{
- /* Place a secret door */
+ /* Place a locked door */
switch (randint(4))
{
case 1:
- place_secret_door(y1 - 1, xval);
+ place_locked_door(y1 - 1, xval);
break;
case 2:
- place_secret_door(y2 + 1, xval);
+ place_locked_door(y2 + 1, xval);
break;
case 3:
- place_secret_door(yval, x1 - 1);
+ place_locked_door(yval, x1 - 1);
break;
case 4:
- place_secret_door(yval, x2 + 1);
+ place_locked_door(yval, x2 + 1);
break;
}
@@ -2489,29 +2401,26 @@ static void build_type4(int by0, int bx0)
place_random_stairs(yval, xval);
}
- /* Traps to protect the treasure */
- vault_traps(yval, xval, 4, 10, 2 + randint(3));
-
break;
}
/* Inner pillar(s). */
case 3:
{
- /* Place a secret door */
+ /* Place a locked door */
switch (randint(4))
{
case 1:
- place_secret_door(y1 - 1, xval);
+ place_locked_door(y1 - 1, xval);
break;
case 2:
- place_secret_door(y2 + 1, xval);
+ place_locked_door(y2 + 1, xval);
break;
case 3:
- place_secret_door(yval, x1 - 1);
+ place_locked_door(yval, x1 - 1);
break;
case 4:
- place_secret_door(yval, x2 + 1);
+ place_locked_door(yval, x2 + 1);
break;
}
@@ -2555,9 +2464,9 @@ static void build_type4(int by0, int bx0)
cave_set_feat(yval, xval - 5, feat_wall_inner);
cave_set_feat(yval, xval + 5, feat_wall_inner);
- /* Secret doors (random top/bottom) */
- place_secret_door(yval - 3 + (randint(2) * 2), xval - 3);
- place_secret_door(yval - 3 + (randint(2) * 2), xval + 3);
+ /* Locked doors (random top/bottom) */
+ place_locked_door(yval - 3 + (randint(2) * 2), xval - 3);
+ place_locked_door(yval - 3 + (randint(2) * 2), xval + 3);
/* Monsters */
vault_monsters(yval, xval - 2, randint(2));
@@ -2574,20 +2483,20 @@ static void build_type4(int by0, int bx0)
/* Maze inside. */
case 4:
{
- /* Place a secret door */
+ /* Place a locked door */
switch (randint(4))
{
case 1:
- place_secret_door(y1 - 1, xval);
+ place_locked_door(y1 - 1, xval);
break;
case 2:
- place_secret_door(y2 + 1, xval);
+ place_locked_door(y2 + 1, xval);
break;
case 3:
- place_secret_door(yval, x1 - 1);
+ place_locked_door(yval, x1 - 1);
break;
case 4:
- place_secret_door(yval, x2 + 1);
+ place_locked_door(yval, x2 + 1);
break;
}
@@ -2607,10 +2516,6 @@ static void build_type4(int by0, int bx0)
vault_monsters(yval, xval - 5, randint(3));
vault_monsters(yval, xval + 5, randint(3));
- /* Traps make them entertaining. */
- vault_traps(yval, xval - 3, 2, 8, randint(3));
- vault_traps(yval, xval + 3, 2, 8, randint(3));
-
/* Mazes should have some treasure too. */
vault_objects(yval, xval, 3);
@@ -2635,18 +2540,18 @@ static void build_type4(int by0, int bx0)
if (rand_int(100) < 50)
{
int i = randint(10);
- place_secret_door(y1 - 1, xval - i);
- place_secret_door(y1 - 1, xval + i);
- place_secret_door(y2 + 1, xval - i);
- place_secret_door(y2 + 1, xval + i);
+ place_locked_door(y1 - 1, xval - i);
+ place_locked_door(y1 - 1, xval + i);
+ place_locked_door(y2 + 1, xval - i);
+ place_locked_door(y2 + 1, xval + i);
}
else
{
int i = randint(3);
- place_secret_door(yval + i, x1 - 1);
- place_secret_door(yval - i, x1 - 1);
- place_secret_door(yval + i, x2 + 1);
- place_secret_door(yval - i, x2 + 1);
+ place_locked_door(yval + i, x1 - 1);
+ place_locked_door(yval - i, x1 - 1);
+ place_locked_door(yval + i, x2 + 1);
+ place_locked_door(yval - i, x2 + 1);
}
/* Treasure, centered at the center of the cross */
@@ -2685,13 +2590,15 @@ static void build_type4(int by0, int bx0)
*/
static bool_ vault_aux_jelly(int r_idx)
{
- monster_race *r_ptr = &r_info[r_idx];
+ auto const &r_info = game->edit_data.r_info;
+
+ auto r_ptr = &r_info[r_idx];
/* Decline unique monsters */
- if (r_ptr->flags1 & (RF1_UNIQUE)) return (FALSE);
+ if (r_ptr->flags & RF_UNIQUE) return (FALSE);
/* Also decline evil jellies (like death molds and shoggoths) */
- if (r_ptr->flags3 & (RF3_EVIL)) return (FALSE);
+ if (r_ptr->flags & RF_EVIL) return (FALSE);
/* Require icky thing, jelly, mold, or mushroom */
if (!strchr("ijm,", r_ptr->d_char)) return (FALSE);
@@ -2706,13 +2613,15 @@ static bool_ vault_aux_jelly(int r_idx)
*/
static bool_ vault_aux_animal(int r_idx)
{
- monster_race *r_ptr = &r_info[r_idx];
+ auto const &r_info = game->edit_data.r_info;
+
+ auto r_ptr = &r_info[r_idx];
/* Decline unique monsters */
- if (r_ptr->flags1 & (RF1_UNIQUE)) return (FALSE);
+ if (r_ptr->flags & RF_UNIQUE) return (FALSE);
/* Require "animal" flag */
- if (!(r_ptr->flags3 & (RF3_ANIMAL))) return (FALSE);
+ if (!(r_ptr->flags & RF_ANIMAL)) return (FALSE);
/* Okay */
return (TRUE);
@@ -2724,13 +2633,15 @@ static bool_ vault_aux_animal(int r_idx)
*/
static bool_ vault_aux_undead(int r_idx)
{
- monster_race *r_ptr = &r_info[r_idx];
+ auto const &r_info = game->edit_data.r_info;
+
+ auto r_ptr = &r_info[r_idx];
/* Decline unique monsters */
- if (r_ptr->flags1 & (RF1_UNIQUE)) return (FALSE);
+ if (r_ptr->flags & RF_UNIQUE) return (FALSE);
/* Require Undead */
- if (!(r_ptr->flags3 & (RF3_UNDEAD))) return (FALSE);
+ if (!(r_ptr->flags & RF_UNDEAD)) return (FALSE);
/* Okay */
return (TRUE);
@@ -2742,14 +2653,15 @@ static bool_ vault_aux_undead(int r_idx)
*/
static bool_ vault_aux_chapel(int r_idx)
{
- monster_race *r_ptr = &r_info[r_idx];
+ auto const &r_info = game->edit_data.r_info;
+
+ auto r_ptr = &r_info[r_idx];
/* Decline unique monsters */
- if (r_ptr->flags1 & (RF1_UNIQUE)) return (FALSE);
+ if (r_ptr->flags & RF_UNIQUE) return (FALSE);
/* Require "priest" or Angel */
- if (!((r_ptr->d_char == 'A') ||
- strstr((r_name + r_ptr->name), "riest")))
+ if (!((r_ptr->d_char == 'A') || strstr(r_ptr->name, "riest")))
{
return (FALSE);
}
@@ -2764,10 +2676,12 @@ static bool_ vault_aux_chapel(int r_idx)
*/
static bool_ vault_aux_kennel(int r_idx)
{
- monster_race *r_ptr = &r_info[r_idx];
+ auto const &r_info = game->edit_data.r_info;
+
+ auto r_ptr = &r_info[r_idx];
/* Decline unique monsters */
- if (r_ptr->flags1 & (RF1_UNIQUE)) return (FALSE);
+ if (r_ptr->flags & RF_UNIQUE) return (FALSE);
/* Require a Zephyr Hound or a dog */
return ((r_ptr->d_char == 'Z') || (r_ptr->d_char == 'C'));
@@ -2780,10 +2694,12 @@ static bool_ vault_aux_kennel(int r_idx)
*/
static bool_ vault_aux_treasure(int r_idx)
{
- monster_race *r_ptr = &r_info[r_idx];
+ auto const &r_info = game->edit_data.r_info;
+
+ auto r_ptr = &r_info[r_idx];
/* Decline unique monsters */
- if (r_ptr->flags1 & (RF1_UNIQUE)) return (FALSE);
+ if (r_ptr->flags & RF_UNIQUE) return (FALSE);
/* Require "priest" or Angel */
if (!((r_ptr->d_char == '!') || (r_ptr->d_char == '|') ||
@@ -2812,8 +2728,10 @@ static bool_ vault_aux_clone(int r_idx)
*/
static bool_ vault_aux_symbol(int r_idx)
{
+ auto const &r_info = game->edit_data.r_info;
+
return ((r_info[r_idx].d_char == (r_info[template_race].d_char))
- && !(r_info[r_idx].flags1 & RF1_UNIQUE));
+ && !(r_info[r_idx].flags & RF_UNIQUE));
}
@@ -2822,10 +2740,12 @@ static bool_ vault_aux_symbol(int r_idx)
*/
static bool_ vault_aux_orc(int r_idx)
{
- monster_race *r_ptr = &r_info[r_idx];
+ auto const &r_info = game->edit_data.r_info;
+
+ auto r_ptr = &r_info[r_idx];
/* Decline unique monsters */
- if (r_ptr->flags1 & (RF1_UNIQUE)) return (FALSE);
+ if (r_ptr->flags & RF_UNIQUE) return (FALSE);
/* Hack -- Require "o" monsters */
if (!strchr("o", r_ptr->d_char)) return (FALSE);
@@ -2841,10 +2761,12 @@ static bool_ vault_aux_orc(int r_idx)
*/
static bool_ vault_aux_troll(int r_idx)
{
- monster_race *r_ptr = &r_info[r_idx];
+ auto const &r_info = game->edit_data.r_info;
+
+ auto r_ptr = &r_info[r_idx];
/* Decline unique monsters */
- if (r_ptr->flags1 & (RF1_UNIQUE)) return (FALSE);
+ if (r_ptr->flags & RF_UNIQUE) return (FALSE);
/* Hack -- Require "T" monsters */
if (!strchr("T", r_ptr->d_char)) return (FALSE);
@@ -2859,10 +2781,12 @@ static bool_ vault_aux_troll(int r_idx)
*/
static bool_ vault_aux_giant(int r_idx)
{
- monster_race *r_ptr = &r_info[r_idx];
+ auto const &r_info = game->edit_data.r_info;
+
+ auto r_ptr = &r_info[r_idx];
/* Decline unique monsters */
- if (r_ptr->flags1 & (RF1_UNIQUE)) return (FALSE);
+ if (r_ptr->flags & RF_UNIQUE) return (FALSE);
/* Hack -- Require "P" monsters */
if (!strchr("P", r_ptr->d_char)) return (FALSE);
@@ -2873,41 +2797,16 @@ static bool_ vault_aux_giant(int r_idx)
/*
- * Hack -- breath type for "vault_aux_dragon()"
- */
-static u32b vault_aux_dragon_mask4;
-
-
-/*
- * Helper function for "monster pit (dragon)"
- */
-static bool_ vault_aux_dragon(int r_idx)
-{
- monster_race *r_ptr = &r_info[r_idx];
-
- /* Decline unique monsters */
- if (r_ptr->flags1 & (RF1_UNIQUE)) return (FALSE);
-
- /* Hack -- Require "d" or "D" monsters */
- if (!strchr("Dd", r_ptr->d_char)) return (FALSE);
-
- /* Hack -- Require correct "breath attack" */
- if (r_ptr->flags4 != vault_aux_dragon_mask4) return (FALSE);
-
- /* Okay */
- return (TRUE);
-}
-
-
-/*
* Helper function for "monster pit (demon)"
*/
static bool_ vault_aux_demon(int r_idx)
{
- monster_race *r_ptr = &r_info[r_idx];
+ auto const &r_info = game->edit_data.r_info;
+
+ auto r_ptr = &r_info[r_idx];
/* Decline unique monsters */
- if (r_ptr->flags1 & (RF1_UNIQUE)) return (FALSE);
+ if (r_ptr->flags & RF_UNIQUE) return (FALSE);
/* Hack -- Require "U" monsters */
if (!strchr("U", r_ptr->d_char)) return (FALSE);
@@ -2943,6 +2842,8 @@ static bool_ vault_aux_demon(int r_idx)
*/
static void build_type5(int by0, int bx0)
{
+ auto const &r_info = game->edit_data.r_info;
+
int y, x, y1, x1, y2, x2, xval, yval;
int tmp, i;
cptr name;
@@ -2981,20 +2882,20 @@ static void build_type5(int by0, int bx0)
/* The inner walls */
build_rectangle(y1 - 1, x1 - 1, y2 + 1, x2 + 1, feat_wall_inner, CAVE_ROOM);
- /* Place a secret door */
+ /* Place a locked door */
switch (randint(4))
{
case 1:
- place_secret_door(y1 - 1, xval);
+ place_locked_door(y1 - 1, xval);
break;
case 2:
- place_secret_door(y2 + 1, xval);
+ place_locked_door(y2 + 1, xval);
break;
case 3:
- place_secret_door(yval, x1 - 1);
+ place_locked_door(yval, x1 - 1);
break;
case 4:
- place_secret_door(yval, x2 + 1);
+ place_locked_door(yval, x2 + 1);
break;
}
@@ -3007,10 +2908,10 @@ static void build_type5(int by0, int bx0)
{
while (1)
{
- template_race = randint(max_r_idx - 2);
+ template_race = rand_int(r_info.size());
/* Reject uniques */
- if (r_info[template_race].flags1 & RF1_UNIQUE) continue;
+ if (r_info[template_race].flags & RF_UNIQUE) continue;
/* Reject OoD monsters in a loose fashion */
if (((r_info[template_race].level) + randint(5)) >
@@ -3106,7 +3007,7 @@ static void build_type5(int by0, int bx0)
if (empty) return;
/* Describe */
- if (cheat_room || p_ptr->precognition)
+ if (options->cheat_room || p_ptr->precognition)
{
/* Room type */
msg_format("Monster nest (%s)", name);
@@ -3129,7 +3030,7 @@ static void build_type5(int by0, int bx0)
int r_idx = what[rand_int(64)];
/* Place that "random" monster (no groups) */
- (void)place_monster_aux(y, x, r_idx, FALSE, FALSE, MSTATUS_ENEMY);
+ place_monster_aux(y, x, r_idx, FALSE, FALSE, MSTATUS_ENEMY);
}
}
}
@@ -3181,6 +3082,8 @@ static void build_type5(int by0, int bx0)
*/
static void build_type6(int by0, int bx0)
{
+ auto const &r_info = game->edit_data.r_info;
+
int tmp, what[16];
int i, j, y, x, y1, x1, y2, x2, xval, yval;
bool_ empty = FALSE;
@@ -3218,20 +3121,20 @@ static void build_type6(int by0, int bx0)
/* The inner walls */
build_rectangle(y1 - 1, x1 - 1, y2 + 1, x2 + 1, feat_wall_outer, CAVE_ROOM);
- /* Place a secret door */
+ /* Place a locked door */
switch (randint(4))
{
case 1:
- place_secret_door(y1 - 1, xval);
+ place_locked_door(y1 - 1, xval);
break;
case 2:
- place_secret_door(y2 + 1, xval);
+ place_locked_door(y2 + 1, xval);
break;
case 3:
- place_secret_door(yval, x1 - 1);
+ place_locked_door(yval, x1 - 1);
break;
case 4:
- place_secret_door(yval, x2 + 1);
+ place_locked_door(yval, x2 + 1);
break;
}
@@ -3279,9 +3182,9 @@ static void build_type6(int by0, int bx0)
do
{
- template_race = randint(max_r_idx - 2);
+ template_race = rand_int(r_info.size() - 1);
}
- while ((r_info[template_race].flags1 & RF1_UNIQUE)
+ while ((r_info[template_race].flags & RF_UNIQUE)
|| (((r_info[template_race].level) + randint(5)) >
(dun_level + randint(5))));
@@ -3299,93 +3202,73 @@ static void build_type6(int by0, int bx0)
/* Dragon pit */
else if (tmp < 80)
{
+ /* Hack - get_mon_num_hook needs a plain function */
+ static monster_spell_flag_set mask;
+
/* Pick dragon type */
switch (rand_int(6))
{
- /* Black */
case 0:
{
- /* Message */
name = "acid dragon";
-
- /* Restrict dragon breath type */
- vault_aux_dragon_mask4 = RF4_BR_ACID;
-
- /* Done */
+ mask = SF_BR_ACID;
break;
}
-
- /* Blue */
case 1:
{
- /* Message */
name = "electric dragon";
-
- /* Restrict dragon breath type */
- vault_aux_dragon_mask4 = RF4_BR_ELEC;
-
- /* Done */
+ mask = SF_BR_ELEC;
break;
}
- /* Red */
case 2:
{
- /* Message */
name = "fire dragon";
-
- /* Restrict dragon breath type */
- vault_aux_dragon_mask4 = RF4_BR_FIRE;
-
- /* Done */
+ mask = SF_BR_FIRE;
break;
}
- /* White */
case 3:
{
- /* Message */
name = "cold dragon";
-
- /* Restrict dragon breath type */
- vault_aux_dragon_mask4 = RF4_BR_COLD;
-
- /* Done */
+ mask = SF_BR_COLD;
break;
}
- /* Green */
case 4:
{
- /* Message */
name = "poison dragon";
-
- /* Restrict dragon breath type */
- vault_aux_dragon_mask4 = RF4_BR_POIS;
-
- /* Done */
+ mask = SF_BR_POIS;
break;
}
- /* Multi-hued */
default:
{
- /* Message */
name = "multi-hued dragon";
-
- /* Restrict dragon breath type */
- vault_aux_dragon_mask4 = (RF4_BR_ACID | RF4_BR_ELEC |
- RF4_BR_FIRE | RF4_BR_COLD |
- RF4_BR_POIS);
-
- /* Done */
+ mask = SF_BR_ACID | SF_BR_ELEC | SF_BR_FIRE | SF_BR_COLD | SF_BR_POIS;
break;
}
}
/* Restrict monster selection */
- get_mon_num_hook = vault_aux_dragon;
+ get_mon_num_hook = [](int r_idx) -> bool_ {
+ auto const &r_info = game->edit_data.r_info;
+
+ auto r_ptr = &r_info[r_idx];
+
+ /* Decline unique monsters */
+ if (r_ptr->flags & RF_UNIQUE) return (FALSE);
+
+ /* Hack -- Require "d" or "D" monsters */
+ if (!strchr("Dd", r_ptr->d_char)) return (FALSE);
+
+ /* Hack -- Require correct "breath attack" */
+ if ((r_ptr->spells & mask) != mask) return (FALSE);
+
+ /* Okay */
+ return (TRUE);
+ };
}
/* Demon pit */
@@ -3451,18 +3334,18 @@ static void build_type6(int by0, int bx0)
}
/* Message */
- if (cheat_room || p_ptr->precognition)
+ if (options->cheat_room || p_ptr->precognition)
{
/* Room type */
msg_format("Monster pit (%s)", name);
- if (cheat_hear || p_ptr->precognition)
+ if (options->cheat_hear || p_ptr->precognition)
{
/* Contents */
for (i = 0; i < 8; i++)
{
/* Message */
- msg_print(r_name + r_info[what[i]].name);
+ msg_print(r_info[what[i]].name);
}
}
}
@@ -3529,264 +3412,270 @@ static void build_type6(int by0, int bx0)
/*
* Hack -- fill in "vault" rooms
*/
-static void build_vault(int yval, int xval, int ymax, int xmax, cptr data)
+static void build_vault(int yval, int xval, int ymax, int xmax, std::string const &data)
{
- int dx, dy, x, y, bwy[8], bwx[8], i;
-
- cptr t;
-
- cave_type *c_ptr;
+ int bwy[8], bwx[8];
/* Clean the between gates arrays */
- for (i = 0; i < 8; i++)
+ for (std::size_t i = 0; i < 8; i++)
{
bwy[i] = bwx[i] = 9999;
}
/* Place dungeon features and objects */
- for (t = data, dy = 0; dy < ymax; dy++)
{
- for (dx = 0; dx < xmax; dx++, t++)
+ std::size_t t = 0;
+ for (int dy = 0; dy < ymax; dy++)
{
- /* Extract the location */
- x = xval - (xmax / 2) + dx;
- y = yval - (ymax / 2) + dy;
+ for (int dx = 0; dx < xmax; dx++, t++)
+ {
+ auto d = data[t];
- /* Hack -- skip "non-grids" */
- if (*t == ' ') continue;
+ /* Hack -- skip "non-grids" */
+ if (d == ' ') continue;
- /* Access the grid */
- c_ptr = &cave[y][x];
+ /* Extract the location */
+ int x = xval - (xmax / 2) + dx;
+ int y = yval - (ymax / 2) + dy;
- /* Lay down a floor */
- place_floor(y, x);
+ /* Access the grid */
+ auto c_ptr = &cave[y][x];
- /* Part of a vault */
- c_ptr->info |= (CAVE_ROOM | CAVE_ICKY);
+ /* Lay down a floor */
+ place_floor(y, x);
- /* Analyze the grid */
- switch (*t)
- {
- /* Granite wall (outer) */
- case '%':
- {
- cave_set_feat(y, x, FEAT_WALL_OUTER);
- break;
- }
+ /* Part of a vault */
+ c_ptr->info |= (CAVE_ROOM | CAVE_ICKY);
- /* Granite wall (inner) */
- case '#':
+ /* Analyze the grid */
+ switch (d)
{
- cave_set_feat(y, x, FEAT_WALL_INNER);
- break;
- }
+ /* Granite wall (outer) */
+ case '%':
+ {
+ cave_set_feat(y, x, FEAT_WALL_OUTER);
+ break;
+ }
- /* Permanent wall (inner) */
- case 'X':
- {
- cave_set_feat(y, x, FEAT_PERM_INNER);
- break;
- }
+ /* Granite wall (inner) */
+ case '#':
+ {
+ cave_set_feat(y, x, FEAT_WALL_INNER);
+ break;
+ }
- /* Treasure/trap */
- case '*':
- {
- if (rand_int(100) < 75)
+ /* Permanent wall (inner) */
+ case 'X':
{
- place_object(y, x, FALSE, FALSE, OBJ_FOUND_VAULT);
+ cave_set_feat(y, x, FEAT_PERM_INNER);
+ break;
}
- else
+
+ /* Treasure/trap */
+ case '*':
{
- place_trap(y, x);
+ if (rand_int(100) < 75)
+ {
+ place_object(y, x, FALSE, FALSE, OBJ_FOUND_VAULT);
+ }
+ else
+ {
+ /* Do nothing */
+ }
+ break;
}
- break;
- }
- /* Secret doors */
- case '+':
- {
- place_secret_door(y, x);
- break;
- }
+ /* locked doors */
+ case '+':
+ {
+ place_locked_door(y, x);
+ break;
+ }
- /* Trap */
- case '^':
- {
- place_trap(y, x);
- break;
- }
+ /* Trap */
+ case '^':
+ {
+ /* Do nothing */
+ break;
+ }
- /* Glass wall */
- case 'G':
- {
- cave_set_feat(y, x, FEAT_GLASS_WALL);
- break;
- }
+ /* Glass wall */
+ case 'G':
+ {
+ cave_set_feat(y, x, FEAT_GLASS_WALL);
+ break;
+ }
- /* Illusion wall */
- case 'I':
- {
- cave_set_feat(y, x, FEAT_ILLUS_WALL);
- break;
+ /* Illusion wall */
+ case 'I':
+ {
+ cave_set_feat(y, x, FEAT_ILLUS_WALL);
+ break;
+ }
}
}
}
}
/* Place dungeon monsters and objects */
- for (t = data, dy = 0; dy < ymax; dy++)
{
- for (dx = 0; dx < xmax; dx++, t++)
+ std::size_t t = 0;
+ for (int dy = 0; dy < ymax; dy++)
{
- /* Extract the grid */
- x = xval - (xmax / 2) + dx;
- y = yval - (ymax / 2) + dy;
-
- /* Hack -- skip "non-grids" */
- if (*t == ' ') continue;
-
- /* Access the grid */
- c_ptr = &cave[y][x];
-
- /* Analyze the symbol */
- switch (*t)
+ for (int dx = 0; dx < xmax; dx++, t++)
{
- /* Monster */
- case '&':
- {
- monster_level = dun_level + 5;
- place_monster(y, x, TRUE, TRUE);
- monster_level = dun_level;
- break;
- }
+ auto d = data[t];
- /* Meaner monster */
- case '@':
- {
- monster_level = dun_level + 11;
- place_monster(y, x, TRUE, TRUE);
- monster_level = dun_level;
- break;
- }
+ /* Hack -- skip "non-grids" */
+ if (d == ' ') continue;
- /* Meaner monster, plus treasure */
- case '9':
- {
- monster_level = dun_level + 9;
- place_monster(y, x, TRUE, TRUE);
- monster_level = dun_level;
- object_level = dun_level + 7;
- place_object(y, x, TRUE, FALSE, OBJ_FOUND_VAULT);
- object_level = dun_level;
- break;
- }
+ /* Extract the grid */
+ int x = xval - (xmax / 2) + dx;
+ int y = yval - (ymax / 2) + dy;
- /* Nasty monster and treasure */
- case '8':
- {
- monster_level = dun_level + 40;
- place_monster(y, x, TRUE, TRUE);
- monster_level = dun_level;
- object_level = dun_level + 20;
- place_object(y, x, TRUE, TRUE, OBJ_FOUND_VAULT);
- object_level = dun_level;
- break;
- }
+ /* Access the grid */
+ auto c_ptr = &cave[y][x];
- /* Monster and/or object */
- case ',':
+ /* Analyze the symbol */
+ switch (d)
{
- if (rand_int(100) < 50)
+ /* Monster */
+ case '&':
{
- monster_level = dun_level + 3;
+ monster_level = dun_level + 5;
place_monster(y, x, TRUE, TRUE);
monster_level = dun_level;
+ break;
}
- if (rand_int(100) < 50)
+
+ /* Meaner monster */
+ case '@':
{
+ monster_level = dun_level + 11;
+ place_monster(y, x, TRUE, TRUE);
+ monster_level = dun_level;
+ break;
+ }
+
+ /* Meaner monster, plus treasure */
+ case '9':
+ {
+ monster_level = dun_level + 9;
+ place_monster(y, x, TRUE, TRUE);
+ monster_level = dun_level;
object_level = dun_level + 7;
- place_object(y, x, FALSE, FALSE, OBJ_FOUND_VAULT);
+ place_object(y, x, TRUE, FALSE, OBJ_FOUND_VAULT);
object_level = dun_level;
+ break;
}
- break;
- }
- case 'p':
- {
- cave_set_feat(y, x, FEAT_PATTERN_START);
- break;
- }
+ /* Nasty monster and treasure */
+ case '8':
+ {
+ monster_level = dun_level + 40;
+ place_monster(y, x, TRUE, TRUE);
+ monster_level = dun_level;
+ object_level = dun_level + 20;
+ place_object(y, x, TRUE, TRUE, OBJ_FOUND_VAULT);
+ object_level = dun_level;
+ break;
+ }
- case 'a':
- {
- cave_set_feat(y, x, FEAT_PATTERN_1);
- break;
- }
+ /* Monster and/or object */
+ case ',':
+ {
+ if (rand_int(100) < 50)
+ {
+ monster_level = dun_level + 3;
+ place_monster(y, x, TRUE, TRUE);
+ monster_level = dun_level;
+ }
+ if (rand_int(100) < 50)
+ {
+ object_level = dun_level + 7;
+ place_object(y, x, FALSE, FALSE, OBJ_FOUND_VAULT);
+ object_level = dun_level;
+ }
+ break;
+ }
- case 'b':
- {
- cave_set_feat(y, x, FEAT_PATTERN_2);
- break;
- }
+ case 'p':
+ {
+ cave_set_feat(y, x, FEAT_PATTERN_START);
+ break;
+ }
- case 'c':
- {
- cave_set_feat(y, x, FEAT_PATTERN_3);
- break;
- }
+ case 'a':
+ {
+ cave_set_feat(y, x, FEAT_PATTERN_1);
+ break;
+ }
- case 'd':
- {
- cave_set_feat(y, x, FEAT_PATTERN_4);
- break;
- }
+ case 'b':
+ {
+ cave_set_feat(y, x, FEAT_PATTERN_2);
+ break;
+ }
- case 'P':
- {
- cave_set_feat(y, x, FEAT_PATTERN_END);
- break;
- }
+ case 'c':
+ {
+ cave_set_feat(y, x, FEAT_PATTERN_3);
+ break;
+ }
- case 'B':
- {
- cave_set_feat(y, x, FEAT_PATTERN_XTRA1);
- break;
- }
+ case 'd':
+ {
+ cave_set_feat(y, x, FEAT_PATTERN_4);
+ break;
+ }
- case 'A':
- {
- object_level = dun_level + 12;
- place_object(y, x, TRUE, FALSE, OBJ_FOUND_VAULT);
- object_level = dun_level;
- break;
- }
+ case 'P':
+ {
+ cave_set_feat(y, x, FEAT_PATTERN_END);
+ break;
+ }
+ case 'B':
+ {
+ cave_set_feat(y, x, FEAT_PATTERN_XTRA1);
+ break;
+ }
- /* Between gates */
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- {
- /* Not found before */
- if (bwy[*t - '0'] == 9999)
+ case 'A':
{
- cave_set_feat(y, x, FEAT_BETWEEN);
- bwy[*t - '0'] = y;
- bwx[*t - '0'] = x;
+ object_level = dun_level + 12;
+ place_object(y, x, TRUE, FALSE, OBJ_FOUND_VAULT);
+ object_level = dun_level;
+ break;
}
- /* The second time */
- else
+
+
+ /* Between gates */
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
{
- cave_set_feat(y, x, FEAT_BETWEEN);
- c_ptr->special = bwx[*t - '0'] + (bwy[*t - '0'] << 8);
- cave[bwy[*t - '0']][bwx[*t - '0']].special = x + (y << 8);
+ /* Not found before */
+ if (bwy[d - '0'] == 9999)
+ {
+ cave_set_feat(y, x, FEAT_BETWEEN);
+ bwy[d - '0'] = y;
+ bwx[d - '0'] = x;
+ }
+ /* The second time */
+ else
+ {
+ cave_set_feat(y, x, FEAT_BETWEEN);
+ c_ptr->special = bwx[d - '0'] + (bwy[d - '0'] << 8);
+ cave[bwy[d - '0']][bwx[d - '0']].special = x + (y << 8);
+ }
+ break;
}
- break;
}
}
}
@@ -3798,8 +3687,10 @@ static void build_vault(int yval, int xval, int ymax, int xmax, cptr data)
*/
static void build_type7(int by0, int bx0)
{
- vault_type *v_ptr = NULL;
- int dummy = 0, xval, yval;
+ auto const &v_info = game->edit_data.v_info;
+
+ auto v_ptr(v_info.end());
+ int dummy = 0;
/* Pick a lesser vault */
while (dummy < SAFE_MAX_ATTEMPTS)
@@ -3807,22 +3698,27 @@ static void build_type7(int by0, int bx0)
dummy++;
/* Access a random vault record */
- v_ptr = &v_info[rand_int(max_v_idx)];
+ v_ptr = uniform_element(v_info);
/* Accept the first lesser vault */
if (v_ptr->typ == 7) break;
}
/* Try to allocate space for room. If fails, exit */
+ int xval;
+ int yval;
if (!room_alloc(v_ptr->wid, v_ptr->hgt, FALSE, by0, bx0, &xval, &yval))
{
- if (cheat_room) msg_print("Could not allocate this vault here");
+ if (options->cheat_room)
+ {
+ msg_print("Could not allocate this vault here");
+ }
return;
}
if (dummy >= SAFE_MAX_ATTEMPTS)
{
- if (cheat_room)
+ if (options->cheat_room)
{
msg_print("Warning! Could not place lesser vault!");
}
@@ -3830,12 +3726,11 @@ 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");
+ if (options->cheat_room || p_ptr->precognition)
+ {
+ msg_print("Lesser Vault");
+ }
/* Boost the rating */
rating += v_ptr->rat;
@@ -3848,7 +3743,7 @@ static void build_type7(int by0, int bx0)
}
/* Hack -- Build the vault */
- build_vault(yval, xval, v_ptr->hgt, v_ptr->wid, v_text + v_ptr->text);
+ build_vault(yval, xval, v_ptr->hgt, v_ptr->wid, v_ptr->data);
}
@@ -3858,8 +3753,10 @@ static void build_type7(int by0, int bx0)
*/
static void build_type8(int by0, int bx0)
{
- vault_type *v_ptr = NULL;
- int dummy = 0, xval, yval;
+ auto const &v_info = game->edit_data.v_info;
+
+ auto v_ptr(v_info.end());
+ int dummy = 0;
/* Pick a lesser vault */
while (dummy < SAFE_MAX_ATTEMPTS)
@@ -3867,22 +3764,27 @@ static void build_type8(int by0, int bx0)
dummy++;
/* Access a random vault record */
- v_ptr = &v_info[rand_int(max_v_idx)];
+ v_ptr = uniform_element(v_info);
/* Accept the first greater vault */
if (v_ptr->typ == 8) break;
}
/* Try to allocate space for room. If fails, exit */
+ int xval;
+ int yval;
if (!room_alloc(v_ptr->wid, v_ptr->hgt, FALSE, by0, bx0, &xval, &yval))
{
- if (cheat_room) msg_print("Could not allocate this vault here");
+ if (options->cheat_room)
+ {
+ msg_print("Could not allocate this vault here");
+ }
return;
}
if (dummy >= SAFE_MAX_ATTEMPTS)
{
- if (cheat_room)
+ if (options->cheat_room)
{
msg_print("Warning! Could not place greater vault!");
}
@@ -3890,12 +3792,11 @@ 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");
+ if (options->cheat_room || p_ptr->precognition)
+ {
+ msg_print("Greater Vault");
+ }
/* Boost the rating */
rating += v_ptr->rat;
@@ -3908,7 +3809,7 @@ static void build_type8(int by0, int bx0)
}
/* Hack -- Build the vault */
- build_vault(yval, xval, v_ptr->hgt, v_ptr->wid, v_text + v_ptr->text);
+ build_vault(yval, xval, v_ptr->hgt, v_ptr->wid, v_ptr->data);
}
/*
@@ -4302,6 +4203,8 @@ static void fill_hack(int y0, int x0, int y, int x, int xsize, int ysize,
bool_ generate_fracave(int y0, int x0, int xsize, int ysize,
int cutoff, bool_ light, bool_ room)
{
+ auto const &f_info = game->edit_data.f_info;
+
int x, y, i, amount, xhsize, yhsize;
cave_type *c_ptr;
@@ -4474,7 +4377,7 @@ bool_ generate_fracave(int y0, int x0, int xsize, int ysize,
c_ptr = &cave[y + y0 - yhsize][x + x0 - xhsize];
/* A floor grid to be converted */
- if ((f_info[c_ptr->feat].flags1 & FF1_FLOOR) &&
+ if ((f_info[c_ptr->feat].flags & FF_FLOOR) &&
(c_ptr->info & CAVE_ICKY))
{
@@ -4532,7 +4435,7 @@ bool_ generate_fracave(int y0, int x0, int xsize, int ysize,
/*
* Makes a cave system in the center of the dungeon
*/
-static void build_cavern(void)
+static void build_cavern()
{
int grd, roug, cutoff, xsize, ysize, x0, y0;
bool_ done, light, room;
@@ -4632,30 +4535,30 @@ static void build_small_room(int x0, int y0)
{
build_rectangle(y0 - 1, x0 - 1, y0 + 1, x0 + 1, feat_wall_inner, CAVE_ROOM);
- /* Place a secret door on one side */
+ /* Place a locked door on one side */
switch (rand_int(4))
{
case 0:
{
- place_secret_door(y0, x0 - 1);
+ place_locked_door(y0, x0 - 1);
break;
}
case 1:
{
- place_secret_door(y0, x0 + 1);
+ place_locked_door(y0, x0 + 1);
break;
}
case 2:
{
- place_secret_door(y0 - 1, x0);
+ place_locked_door(y0 - 1, x0);
break;
}
case 3:
{
- place_secret_door(y0 + 1, x0);
+ place_locked_door(y0 + 1, x0);
break;
}
}
@@ -4691,8 +4594,8 @@ static void add_door(int x, int y)
(cave[y][x - 1].feat == feat_wall_outer) &&
(cave[y][x + 1].feat == feat_wall_outer))
{
- /* secret door */
- place_secret_door(y, x);
+ /* locked door */
+ place_locked_door(y, x);
/* set boundarys so don't get wide doors */
place_filler(y, x - 1);
@@ -4713,8 +4616,8 @@ static void add_door(int x, int y)
(cave[y + 1][x].feat == feat_wall_outer) &&
get_is_floor(x - 1, y) && get_is_floor(x + 1, y))
{
- /* secret door */
- place_secret_door(y, x);
+ /* locked door */
+ place_locked_door(y, x);
/* set boundarys so don't get wide doors */
place_filler(y - 1, x);
@@ -4746,7 +4649,7 @@ static void fill_treasure(int x1, int x2, int y1, int y2, int difficulty)
* Thing added based on distance to center of vault
* Difficulty is 1-easy to 10-hard
*/
- value = (((s32b)distance(cx, cy, x, y) * 100) / size) +
+ value = ((static_cast<s32b>(distance(cx, cy, x, y)) * 100) / size) +
randint(10) - difficulty;
/* Hack -- Empty square part of the time */
@@ -4803,18 +4706,13 @@ static void fill_treasure(int x1, int x2, int y1, int y2, int difficulty)
{
place_object(y, x, FALSE, FALSE, OBJ_FOUND_FLOOR);
}
- else
- {
- place_trap(y, x);
- }
}
else if (value < 30)
{
- /* Monster and trap */
+ /* Monster */
monster_level = dun_level + 5;
place_monster(y, x, TRUE, TRUE);
monster_level = dun_level;
- place_trap(y, x);
}
else if (value < 40)
{
@@ -4834,8 +4732,7 @@ static void fill_treasure(int x1, int x2, int y1, int y2, int difficulty)
}
else if (value < 50)
{
- /* Trap */
- place_trap(y, x);
+ /* Do nothing */
}
else
{
@@ -4848,7 +4745,7 @@ static void fill_treasure(int x1, int x2, int y1, int y2, int difficulty)
}
else if (rand_int(100) < 50)
{
- place_trap(y, x);
+ /* Do nothing */
}
else if (rand_int(100) < 50)
{
@@ -4891,7 +4788,10 @@ static void build_bubble_vault(int x0, int y0, int xsize, int ysize)
int xhsize = xsize / 2;
int yhsize = ysize / 2;
- if (cheat_room) msg_print("Bubble Vault");
+ if (options->cheat_room)
+ {
+ msg_print("Bubble Vault");
+ }
/* Allocate center of bubbles */
center[0].x = randint(xsize - 3) + 1;
@@ -5093,7 +4993,10 @@ static void build_room_vault(int x0, int y0, int xsize, int ysize)
xhsize = xsize / 2;
yhsize = ysize / 2;
- if (cheat_room) msg_print("Room Vault");
+ if (options->cheat_room)
+ {
+ msg_print("Room Vault");
+ }
/* Fill area so don't get problems with arena levels */
for (x1 = 0; x1 <= xsize; x1++)
@@ -5151,7 +5054,10 @@ static void build_cave_vault(int x0, int y0, int xsiz, int ysiz)
xsize = xhsize * 2;
ysize = yhsize * 2;
- if (cheat_room) msg_print("Cave Vault");
+ if (options->cheat_room)
+ {
+ msg_print("Cave Vault");
+ }
light = done = FALSE;
room = TRUE;
@@ -5313,12 +5219,15 @@ static void build_maze_vault(int x0, int y0, int xsize, int ysize)
{
int y, x, dy, dx;
int y1, x1, y2, x2;
- int i, m, n, num_vertices, *visited;
+ int m, n, num_vertices;
bool_ light;
cave_type *c_ptr;
- if (cheat_room) msg_print("Maze Vault");
+ if (options->cheat_room)
+ {
+ msg_print("Maze Vault");
+ }
/* Choose lite or dark */
light = (dun_level <= randint(25));
@@ -5360,22 +5269,13 @@ static void build_maze_vault(int x0, int y0, int xsize, int ysize)
num_vertices = m * n;
/* Allocate an array for visited vertices */
- C_MAKE(visited, num_vertices, int);
-
- /* Initialise array of visited vertices */
- for (i = 0; i < num_vertices; i++)
- {
- visited[i] = 0;
- }
+ std::vector<int> visited(num_vertices, 0);
/* Traverse the graph to create a spaning tree, pick a random root */
- r_visit(y1, x1, y2, x2, rand_int(num_vertices), 0, visited);
+ r_visit(y1, x1, y2, x2, rand_int(num_vertices), 0, visited.data());
/* Fill with monsters and treasure, low difficulty */
fill_treasure(x1, x2, y1, y2, randint(5));
-
- /* Free the array for visited vertices */
- C_FREE(visited, num_vertices, int);
}
@@ -5391,10 +5291,12 @@ static void build_mini_c_vault(int x0, int y0, int xsize, int ysize)
{
int dy, dx;
int y1, x1, y2, x2, y, x, total;
- int i, m, n, num_vertices;
- int *visited;
+ int m, n, num_vertices;
- if (cheat_room) msg_print("Mini Checker Board Vault");
+ if (options->cheat_room)
+ {
+ msg_print("Mini Checker Board Vault");
+ }
/* Pick a random room size */
dy = ysize / 2 - 1;
@@ -5425,16 +5327,10 @@ static void build_mini_c_vault(int x0, int y0, int xsize, int ysize)
num_vertices = m * n;
/* Allocate an array for visited vertices */
- C_MAKE(visited, num_vertices, int);
-
- /* Initialise array of visited vertices */
- for (i = 0; i < num_vertices; i++)
- {
- visited[i] = 0;
- }
+ std::vector<int> visited(num_vertices, 0);
/* Traverse the graph to create a spannng tree, pick a random root */
- r_visit(y1, x1, y2, x2, rand_int(num_vertices), 0, visited);
+ r_visit(y1, x1, y2, x2, rand_int(num_vertices), 0, visited.data());
/* Make it look like a checker board vault */
for (x = x1; x <= x2; x++)
@@ -5469,9 +5365,6 @@ static void build_mini_c_vault(int x0, int y0, int xsize, int ysize)
/* Fill with monsters and treasure, highest difficulty */
fill_treasure(x1, x2, y1, y2, 10);
-
- /* Free the array for visited vertices */
- C_FREE(visited, num_vertices, int);
}
@@ -5709,7 +5602,10 @@ static void build_castle_vault(int x0, int y0, int xsize, int ysize)
y2 = y0 + dy;
x2 = x0 + dx;
- if (cheat_room) msg_print("Castle Vault");
+ if (options->cheat_room)
+ {
+ msg_print("Castle Vault");
+ }
/* Generate the room */
for (y = y1 - 1; y <= y2 + 1; y++)
@@ -5833,7 +5729,10 @@ static void build_target_vault(int x0, int y0, int xsize, int ysize)
h3 = randint(32);
h4 = randint(32) - 16;
- if (cheat_room) msg_print("Target Vault");
+ if (options->cheat_room)
+ {
+ msg_print("Target Vault");
+ }
/* Work out outer radius */
if (xsize > ysize)
@@ -6123,9 +6022,6 @@ static void build_type12(int by0, int bx0)
/* Let's guard the treasure well */
vault_monsters(y0, x0, rand_int(2) + 3);
-
- /* Traps naturally */
- vault_traps(y0, x0, 4, 4, rand_int(3) + 2);
}
}
@@ -6166,6 +6062,8 @@ static void build_type12(int by0, int bx0)
*/
static void build_tunnel(int row1, int col1, int row2, int col2, bool_ water)
{
+ auto const &d_info = game->edit_data.d_info;
+
int i, y, x;
int tmp_row, tmp_col;
int row_dir, col_dir;
@@ -6397,7 +6295,7 @@ static void build_tunnel(int row1, int col1, int row2, int col2, bool_ water)
place_floor(y, x);
/* Occasional doorway */
- if (!(dungeon_flags1 & DF1_NO_DOORS) &&
+ if (!(dungeon_flags & DF_NO_DOORS) &&
(rand_int(100) < DUN_TUN_PEN))
{
/* Place a random door */
@@ -6420,6 +6318,8 @@ static void build_tunnel(int row1, int col1, int row2, int col2, bool_ water)
*/
static int next_to_corr(int y1, int x1)
{
+ auto const &d_info = game->edit_data.d_info;
+
int i, y, x, k = 0;
cave_type *c_ptr;
@@ -6465,19 +6365,21 @@ static int next_to_corr(int y1, int x1)
*/
static bool_ possible_doorway(int y, int x)
{
+ auto const &f_info = game->edit_data.f_info;
+
/* Count the adjacent corridors */
if (next_to_corr(y, x) >= 2)
{
/* Check Vertical */
- if ((f_info[cave[y - 1][x].feat].flags1 & FF1_WALL) &&
- (f_info[cave[y + 1][x].feat].flags1 & FF1_WALL))
+ if ((f_info[cave[y - 1][x].feat].flags & FF_WALL) &&
+ (f_info[cave[y + 1][x].feat].flags & FF_WALL))
{
return (TRUE);
}
/* Check Horizontal */
- if ((f_info[cave[y][x - 1].feat].flags1 & FF1_WALL) &&
- (f_info[cave[y][x + 1].feat].flags1 & FF1_WALL))
+ if ((f_info[cave[y][x - 1].feat].flags & FF_WALL) &&
+ (f_info[cave[y][x + 1].feat].flags & FF_WALL))
{
return (TRUE);
}
@@ -6493,6 +6395,8 @@ static bool_ possible_doorway(int y, int x)
*/
static void try_doors(int y, int x)
{
+ auto const &f_info = game->edit_data.f_info;
+
bool_ dir_ok[4];
int i, k, n;
int yy, xx;
@@ -6501,7 +6405,7 @@ static void try_doors(int y, int x)
/* if (!in_bounds(y, x)) return; */
/* Some dungeons don't have doors at all */
- if (dungeon_flags1 & (DF1_NO_DOORS)) return;
+ if (dungeon_flags & DF_NO_DOORS) return;
/* Reset tally */
n = 0;
@@ -6520,7 +6424,7 @@ static void try_doors(int y, int x)
if (!in_bounds(yy, xx)) continue;
/* Ignore walls */
- if (f_info[cave[yy][xx].feat].flags1 & (FF1_WALL)) continue;
+ if (f_info[cave[yy][xx].feat].flags & FF_WALL) continue;
/* Ignore room grids */
if (cave[yy][xx].info & (CAVE_ROOM)) continue;
@@ -6565,7 +6469,7 @@ static void try_doors(int y, int x)
/* Clear OK flags XXX */
for (i = 0; i < 4; i++) dir_ok[i] = FALSE;
- /* Put one or two secret doors */
+ /* Put one or two locked doors */
dir_ok[rand_int(4)] = TRUE;
dir_ok[rand_int(4)] = TRUE;
}
@@ -6583,7 +6487,7 @@ static void try_doors(int y, int x)
}
}
- /* Place secret door(s) */
+ /* Place locked door(s) */
for (i = 0; i < 4; i++)
{
/* Bad location */
@@ -6593,8 +6497,8 @@ static void try_doors(int y, int x)
yy = y + ddy_ddd[i];
xx = x + ddx_ddd[i];
- /* Place a secret door */
- place_secret_door(yy, xx);
+ /* Place a locked door */
+ place_locked_door(yy, xx);
}
}
}
@@ -6609,7 +6513,7 @@ static void try_doors(int y, int x)
static bool_ room_build(int y, int x, int typ)
{
/* Restrict level */
- if ((dun_level < roomdep[typ]) && !ironman_rooms) return (FALSE);
+ if ((dun_level < roomdep[typ]) && !options->ironman_rooms) return (FALSE);
/* Restrict "crowded" rooms */
if (dun->crowded && ((typ == 5) || (typ == 6))) return (FALSE);
@@ -6667,7 +6571,7 @@ static bool_ room_build(int y, int x, int typ)
/*
* Set level boundaries
*/
-void set_bounders(bool_ empty_level)
+static void set_bounders(bool_ empty_level)
{
int y, x;
@@ -6724,8 +6628,10 @@ static void fill_level(bool_ use_floor, byte smooth);
*/
bool_ level_generate_dungeon()
{
+ auto const &d_info = game->edit_data.d_info;
+
int i, k, y, x, y1, x1, branch = get_branch();
- dungeon_info_type *d_ptr = &d_info[dungeon_type];
+ auto d_ptr = &d_info[dungeon_type];
int max_vault_ok = 2;
@@ -6741,12 +6647,12 @@ bool_ level_generate_dungeon()
}
/* Check for arena level */
- if ((dungeon_flags1 & (DF1_EMPTY)) ||
- (empty_levels && (rand_int(EMPTY_LEVEL) == 0)))
+ if ((dungeon_flags & DF_EMPTY) ||
+ (options->empty_levels && (rand_int(EMPTY_LEVEL) == 0)))
{
empty_level = TRUE;
- if (cheat_room || p_ptr->precognition)
+ if (options->cheat_room || p_ptr->precognition)
{
msg_print("Arena level.");
}
@@ -6756,12 +6662,12 @@ bool_ level_generate_dungeon()
}
/* Possible cavern */
- if ((dungeon_flags1 & DF1_CAVERN) && (rand_int(dun_level / 2) > DUN_CAVERN))
+ if ((dungeon_flags & DF_CAVERN) && (rand_int(dun_level / 2) > DUN_CAVERN))
{
cavern = TRUE;
/* Make a large fractal cave in the middle of the dungeon */
- if (cheat_room)
+ if (options->cheat_room)
{
msg_print("Cavern on level.");
}
@@ -6782,7 +6688,7 @@ bool_ level_generate_dungeon()
if ((cur_wid != MAX_WID) || (cur_hgt != MAX_HGT)) destroyed = FALSE;
/* Hack -- No destroyed levels */
- if (dungeon_flags1 & DF1_NO_DESTROY) destroyed = FALSE;
+ if (dungeon_flags & DF_NO_DESTROY) destroyed = FALSE;
/* Actual maximum number of rooms on this level */
dun->row_rooms = cur_hgt / BLOCK_HGT;
@@ -6809,7 +6715,7 @@ bool_ level_generate_dungeon()
x = rand_int(dun->col_rooms);
/* Align dungeon rooms */
- if (dungeon_align)
+ if (options->dungeon_align)
{
/* Slide some rooms right */
if ((x % 3) == 0) x++;
@@ -6819,7 +6725,10 @@ bool_ level_generate_dungeon()
}
/* Ugly */
- process_hooks(HOOK_BUILD_ROOM1, "(d,d)", y, x);
+ {
+ struct hook_build_room1_in in = { y, x };
+ process_hooks_new(HOOK_BUILD_ROOM1, &in, NULL);
+ }
/* Build some rooms */
for (i = 0; i < DUN_ROOMS; i++)
@@ -6829,7 +6738,7 @@ bool_ level_generate_dungeon()
x = rand_int(dun->col_rooms);
/* Align dungeon rooms */
- if (dungeon_align)
+ if (options->dungeon_align)
{
/* Slide some rooms right */
if ((x % 3) == 0) x++;
@@ -6854,7 +6763,7 @@ bool_ level_generate_dungeon()
else
{
/* Attempt a "trivial" room */
- if ((dungeon_flags1 & DF1_CIRCULAR_ROOMS) &&
+ if ((dungeon_flags & DF_CIRCULAR_ROOMS) &&
room_build(y, x, 9))
{
continue;
@@ -6868,18 +6777,15 @@ bool_ level_generate_dungeon()
/* Attempt an "unusual" room -- no vaults on town levels */
if (!town_level &&
- (ironman_rooms || (rand_int(DUN_UNUSUAL) < dun_level)))
+ (options->ironman_rooms || (rand_int(DUN_UNUSUAL) < dun_level)))
{
/* Roll for room type */
- k = (ironman_rooms ? 0 : rand_int(100));
+ k = (options->ironman_rooms ? 0 : rand_int(100));
/* Attempt a very unusual room */ /* test hack */
- if (ironman_rooms || (rand_int(DUN_UNUSUAL) < dun_level))
+ if (options->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)
@@ -6888,7 +6794,10 @@ bool_ level_generate_dungeon()
}
else
{
- if (cheat_room) msg_print("Refusing a greater vault.");
+ if (options->cheat_room)
+ {
+ msg_print("Refusing a greater vault.");
+ }
}
}
@@ -6901,7 +6810,10 @@ bool_ level_generate_dungeon()
}
else
{
- if (cheat_room) msg_print("Refusing a lesser vault.");
+ if (options->cheat_room)
+ {
+ msg_print("Refusing a lesser vault.");
+ }
}
}
@@ -6914,7 +6826,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%) */
@@ -6933,7 +6844,7 @@ bool_ level_generate_dungeon()
/* Hack - build standard rectangular rooms if needed */
if (k < 90)
{
- if ((dungeon_flags1 & DF1_CIRCULAR_ROOMS) && room_build(y, x, 1)) continue;
+ if ((dungeon_flags & DF_CIRCULAR_ROOMS) && room_build(y, x, 1)) continue;
else if (room_build(y, x, 9)) continue;
}
@@ -6942,13 +6853,13 @@ bool_ level_generate_dungeon()
}
/* Attempt a trivial room */
- if (dungeon_flags1 & DF1_CAVE)
+ if (dungeon_flags & DF_CAVE)
{
if (room_build(y, x, 10)) continue;
}
else
{
- if ((dungeon_flags1 & DF1_CIRCULAR_ROOMS) && room_build(y, x, 9)) continue;
+ if ((dungeon_flags & DF_CIRCULAR_ROOMS) && room_build(y, x, 9)) continue;
else if (room_build(y, x, 1)) continue;
}
}
@@ -6957,7 +6868,7 @@ bool_ level_generate_dungeon()
while (dun->cent_n == 0)
{
/* ...force the creation of a small rectangular room */
- (void)room_build(0, 0, 1);
+ room_build(0, 0, 1);
}
/* Hack -- Scramble the room order */
@@ -7032,9 +6943,12 @@ bool_ level_generate_dungeon()
}
/* Add some sand streamers */
- if ((dungeon_flags1 & DF1_SAND_VEIN) && !rand_int(4))
+ if ((dungeon_flags & DF_SAND_VEIN) && !rand_int(4))
{
- if ((cheat_room) || (p_ptr->precognition)) msg_print("Sand vein.");
+ if (options->cheat_room || p_ptr->precognition)
+ {
+ msg_print("Sand vein.");
+ }
build_streamer(FEAT_SANDWALL, DUN_STR_SC);
}
@@ -7048,18 +6962,24 @@ bool_ level_generate_dungeon()
}
/* Hack -- Add some rivers if requested */
- if ((dungeon_flags1 & DF1_WATER_RIVER) && !rand_int(4))
+ if ((dungeon_flags & DF_WATER_RIVER) && !rand_int(4))
{
- if (cheat_room || p_ptr->precognition) msg_print("River of water.");
+ if (options->cheat_room || p_ptr->precognition)
+ {
+ msg_print("River of water.");
+ }
add_river(FEAT_DEEP_WATER, FEAT_SHAL_WATER);
}
- if ((dungeon_flags1 & DF1_LAVA_RIVER) && !rand_int(4))
+ if ((dungeon_flags & DF_LAVA_RIVER) && !rand_int(4))
{
- if ((cheat_room) || (p_ptr->precognition)) msg_print("River of lava.");
+ if (options->cheat_room || p_ptr->precognition)
+ {
+ msg_print("River of lava.");
+ }
add_river(FEAT_DEEP_LAVA, FEAT_SHAL_LAVA);
}
- if (dungeon_flags1 & DF1_WATER_RIVERS)
+ if (dungeon_flags & DF_WATER_RIVERS)
{
int max = 3 + rand_int(2);
bool_ said = FALSE;
@@ -7069,13 +6989,16 @@ bool_ level_generate_dungeon()
if (rand_int(3) == 0)
{
add_river(FEAT_DEEP_WATER, FEAT_SHAL_WATER);
- if (!said && ((cheat_room) || (p_ptr->precognition))) msg_print("Rivers of water.");
+ if (!said && (options->cheat_room || p_ptr->precognition))
+ {
+ msg_print("Rivers of water.");
+ }
said = TRUE;
}
}
}
- if (dungeon_flags1 & DF1_LAVA_RIVERS)
+ if (dungeon_flags & DF_LAVA_RIVERS)
{
int max = 2 + rand_int(2);
bool_ said = FALSE;
@@ -7085,14 +7008,17 @@ bool_ level_generate_dungeon()
if (rand_int(3) == 0)
{
add_river(FEAT_DEEP_LAVA, FEAT_SHAL_LAVA);
- if (!said && ((cheat_room) || (p_ptr->precognition))) msg_print("Rivers of lava.");
+ if (!said && (options->cheat_room || p_ptr->precognition))
+ {
+ msg_print("Rivers of lava.");
+ }
said = TRUE;
}
}
}
/* Add streamers of trees, water, or lava -KMW- */
- if (!(dungeon_flags1 & DF1_NO_STREAMERS))
+ if (!(dungeon_flags & DF_NO_STREAMERS))
{
int num;
@@ -7101,7 +7027,7 @@ bool_ level_generate_dungeon()
*
* Small trees (penetrate walls)
*/
- if ((dungeon_flags1 & DF1_FLAT) && (randint(20) > 15))
+ if ((dungeon_flags & DF_FLAT) && (randint(20) > 15))
{
num = randint(DUN_STR_QUA);
@@ -7205,34 +7131,34 @@ bool_ level_generate_dungeon()
/*
* Bring the imprinted pets from the old level
*/
-void replace_all_friends()
+static void replace_all_friends()
{
- int i;
-
- if (p_ptr->wild_mode) return;
+ if (p_ptr->wild_mode)
+ {
+ return;
+ }
/* Scan every saved pet */
- for (i = 0; i < max_m_idx; i++)
+ for (int i = 0; i < max_m_idx; i++)
{
if ((km_list[i].r_idx) && (km_list[i].status == MSTATUS_COMPANION))
{
- int y = p_ptr->py, x = p_ptr->px;
- cave_type *c_ptr;
- monster_type *m_ptr;
+ int y = p_ptr->py;
+ int x = p_ptr->px;
/* Find a suitable location */
get_pos_player(5, &y, &x);
- c_ptr = &cave[y][x];
+ cave_type *c_ptr = &cave[y][x];
/* Get a m_idx to use */
c_ptr->m_idx = m_pop();
- m_ptr = &m_list[c_ptr->m_idx];
+ monster_type *m_ptr = &m_list[c_ptr->m_idx];
/* Actualy place the monster */
m_list[c_ptr->m_idx] = km_list[i];
m_ptr->fy = y;
m_ptr->fx = x;
- m_ptr->hold_o_idx = 0;
+ m_ptr->hold_o_idxs.clear(); // Objects have been removed previously by caller
}
}
}
@@ -7240,34 +7166,17 @@ void replace_all_friends()
/*
* Save the imprinted pets from the old level
*/
-void save_all_friends()
+static void save_all_friends()
{
if (p_ptr->old_wild_mode) return;
- C_COPY(km_list, m_list, max_m_idx, monster_type);
-}
-
-
-
-/*
- * Return the dungeon type of the current level(it can only return the
- * principal dungeons)
- */
-byte calc_dungeon_type()
-{
- int i;
-
- for (i = 0; i < max_d_idx; i++)
- {
- if ((dun_level >= d_info[i].mindepth) &&
- (dun_level <= d_info[i].maxdepth) &&
- (d_info[i].flags1 & DF1_PRINCIPAL))
- return (i);
+ for (int i = 0; i < max_m_idx; i++) {
+ km_list[i] = m_list[i];
}
- return (0);
}
+
/*
* Build probability tables for walls and floors and set feat_wall_outer
* and feat_wall_inner according to the current information in d_info.txt
@@ -7275,9 +7184,11 @@ byte calc_dungeon_type()
* *hint* *hint* with this made extern, and we no longer have to
* store fill_type and floor_type in the savefile...
*/
-static void init_feat_info(void)
+static void init_feat_info()
{
- dungeon_info_type *d_ptr = &d_info[dungeon_type];
+ auto const &d_info = game->edit_data.d_info;
+
+ auto d_ptr = &d_info[dungeon_type];
int i;
int cur_depth, max_depth;
int p1, p2;
@@ -7383,6 +7294,8 @@ static void init_feat_info(void)
static void fill_level(bool_ use_floor, byte smooth)
{
+ auto const &d_info = game->edit_data.d_info;
+
int y, x;
int step;
int shift;
@@ -7547,15 +7460,101 @@ static void fill_level(bool_ use_floor, byte smooth)
}
+/**
+ * @brief double a grid tile. Used for the double-size dungeons
+ */
+static void supersize_grid_tile(int sy, int sx, int ty, int tx)
+{
+ /* Displacements for copied grid tiles */
+ constexpr std::size_t n_disp = 4;
+ int disp[n_disp][2] = {
+ { 0, 0 },
+ { 0, +1 },
+ { +1, 0 },
+ { +1, +1 }
+ };
+
+ /* Acquire the grid tile and monster */
+ cave_type *cc_ptr = &cave[sy][sx];
+ monster_type *m_ptr = &m_list[cc_ptr->m_idx];
+
+ /* Save the list of objects */
+ auto const object_idxs(cc_ptr->o_idxs);
+
+ /* Save the monster */
+ auto m_idx = cc_ptr->m_idx;
+
+ /* Create pointers to each of the target grid tiles */
+ cave_type *c_ptr[n_disp];
+ for (std::size_t i = 0; i < n_disp; i++)
+ {
+ c_ptr[i] = &cave[ty + disp[i][0]][tx + disp[i][1]];
+ }
+
+ /* Now we copy around the grid tiles. Objects and
+ monsters are "removed" for now. */
+ for (std::size_t i = 0; i < 4; i++)
+ {
+ c_ptr[i] = &cave[ty + disp[i][0]][tx + disp[i][1]];
+
+ /* Copy grid */
+ *c_ptr[i] = *cc_ptr;
+ c_ptr[i]->o_idxs.clear(); // ... except objects in the tile
+ c_ptr[i]->m_idx = 0; // ... except monsters in the tile
+
+ /* Void gates need special attention */
+ if (cc_ptr->feat == FEAT_BETWEEN)
+ {
+ int xxx = cc_ptr->special & 0xFF;
+ int yyy = cc_ptr->special >> 8;
+
+ xxx *= 2;
+ yyy *= 2;
+ xxx += disp[i][1];
+ yyy += disp[i][0];
+ c_ptr[i]->special = xxx + (yyy << 8);
+ }
+ }
+
+ /* Scatter objects randomly into the destination grid tiles */
+ for (auto const o_idx: object_idxs)
+ {
+ std::size_t i = static_cast<std::size_t>(rand_int(4));
+ /* Put object into grid tile */
+ c_ptr[i]->o_idxs.push_back(o_idx);
+ /* Give object its location */
+ object_type *o_ptr = &o_list[o_idx];
+ o_ptr->iy = ty + disp[i][0];
+ o_ptr->ix = tx + disp[i][1];
+ }
+
+ /* Scatter move monster randomly into one of the destination grid tiles */
+ if (m_idx != 0)
+ {
+ std::size_t i = static_cast<std::size_t>(rand_int(4));
+ /* Place monster into grid tile */
+ c_ptr[i]->m_idx = cc_ptr->m_idx;
+ /* Give the monster its location */
+ m_ptr->fy = ty + disp[i][0];
+ m_ptr->fx = tx + disp[i][1];
+ }
+}
+
+
/*
* Generate a new dungeon level
*
* Note that "dun_body" adds about 4000 bytes of memory to the stack.
*/
-static bool_ cave_gen(void)
+static bool_ cave_gen()
{
- int i, k, y, x, y1, x1, branch;
- dungeon_info_type *d_ptr = &d_info[dungeon_type];
+ auto const &d_info = game->edit_data.d_info;
+ auto const &r_info = game->edit_data.r_info;
+ auto const &a_info = game->edit_data.a_info;
+ auto &k_info = game->edit_data.k_info;
+ auto &alloc = game->alloc;
+
+ auto d_ptr = &d_info[dungeon_type];
int max_vault_ok = 2;
@@ -7568,14 +7567,16 @@ static bool_ cave_gen(void)
char generator_name[100];
if (!get_dungeon_generator(generator_name))
- strnfmt(generator_name, 99, "%s", d_ptr->generator);
+ {
+ strnfmt(generator_name, sizeof(generator_name)-1, "%s", d_ptr->generator.c_str());
+ }
/*
* We generate a double dungeon. First we should halve the desired
* width/height, generate the dungeon normally, then double it
* in both directions
*/
- if (dungeon_flags1 & DF1_DOUBLE)
+ if (dungeon_flags & DF_DOUBLE)
{
cur_wid /= 2;
cur_hgt /= 2;
@@ -7614,7 +7615,7 @@ static bool_ cave_gen(void)
{
if (!strcmp(generator->name, generator_name))
{
- if (!generator->generator(generator->name))
+ if (!generator->generator())
return FALSE;
break;
}
@@ -7622,57 +7623,55 @@ static bool_ cave_gen(void)
generator = generator->next;
}
- /* Only if requested */
- if (generator->default_stairs)
+ /* Generate stairs */
{
/* Is there a dungeon branch ? */
- if ((branch = get_branch()))
+ if (int branch = get_branch())
{
/* Place 5 down stair some walls */
alloc_stairs(FEAT_MORE, 5, 3, branch);
}
/* Is there a father dungeon branch ? */
- if ((branch = get_fbranch()))
+ if (int branch = get_fbranch())
{
/* Place 1 down stair some walls */
alloc_stairs(FEAT_LESS, 5, 3, branch);
}
- if ((dun_level < d_ptr->maxdepth) || ((dun_level == d_ptr->maxdepth) && (dungeon_flags1 & DF1_FORCE_DOWN)))
+ if ((dun_level < d_ptr->maxdepth) || ((dun_level == d_ptr->maxdepth) && (dungeon_flags & DF_FORCE_DOWN)))
{
/* Place 3 or 4 down stairs near some walls */
- alloc_stairs((dungeon_flags1 & DF1_FLAT) ? FEAT_WAY_MORE : FEAT_MORE, rand_range(3, 4), 3, 0);
+ alloc_stairs((dungeon_flags & DF_FLAT) ? FEAT_WAY_MORE : FEAT_MORE, rand_range(3, 4), 3, 0);
/* Place 0 or 1 down shafts near some walls */
- if (!(dungeon_flags2 & DF2_NO_SHAFT)) alloc_stairs((dungeon_flags1 & DF1_FLAT) ? FEAT_WAY_MORE : FEAT_SHAFT_DOWN, rand_range(0, 1), 3, 0);
+ if (!(dungeon_flags & DF_NO_SHAFT)) alloc_stairs((dungeon_flags & DF_FLAT) ? FEAT_WAY_MORE : FEAT_SHAFT_DOWN, rand_range(0, 1), 3, 0);
}
- if ((dun_level > d_ptr->mindepth) || ((dun_level == d_ptr->mindepth) && (!(dungeon_flags1 & DF1_NO_UP))))
+ if ((dun_level > d_ptr->mindepth) || ((dun_level == d_ptr->mindepth) && (!(dungeon_flags & DF_NO_UP))))
{
/* Place 1 or 2 up stairs near some walls */
- alloc_stairs((dungeon_flags1 & DF1_FLAT) ? FEAT_WAY_LESS : FEAT_LESS, rand_range(1, 2), 3, 0);
+ alloc_stairs((dungeon_flags & DF_FLAT) ? FEAT_WAY_LESS : FEAT_LESS, rand_range(1, 2), 3, 0);
/* Place 0 or 1 up shafts near some walls */
- if (!(dungeon_flags2 & DF2_NO_SHAFT)) alloc_stairs((dungeon_flags1 & DF1_FLAT) ? FEAT_WAY_LESS : FEAT_SHAFT_UP, rand_range(0, 1), 3, 0);
+ if (!(dungeon_flags & DF_NO_SHAFT)) alloc_stairs((dungeon_flags & DF_FLAT) ? FEAT_WAY_LESS : FEAT_SHAFT_UP, rand_range(0, 1), 3, 0);
}
}
- process_hooks(HOOK_GEN_LEVEL, "(d)", is_quest(dun_level));
+ process_hooks_new(HOOK_GEN_LEVEL, NULL, NULL);
/* Basic "amount" */
- k = (dun_level / 3);
+ int k = (dun_level / 3);
if (k > 10) k = 10;
if (k < 2) k = 2;
- /* Only if requested */
- if (generator->default_monsters)
+ /* Place monsters */
{
/*
* Pick a base number of monsters
*/
- i = d_ptr->min_m_alloc_level;
+ int i = d_ptr->min_m_alloc_level;
/* To make small levels a bit more playable */
if ((cur_hgt < MAX_HGT) || (cur_wid < MAX_WID))
@@ -7683,8 +7682,11 @@ static bool_ cave_gen(void)
i = (i * cur_wid) / MAX_WID;
i += 1;
- if (i > small_tester) i = small_tester;
- else if (cheat_hear)
+ if (i > small_tester)
+ {
+ i = small_tester;
+ }
+ else if (options->cheat_hear)
{
msg_format("Reduced monsters base from %d to %d", small_tester, i);
}
@@ -7695,12 +7697,12 @@ static bool_ cave_gen(void)
/* Put some monsters in the dungeon */
for (i = i + k; i > 0; i--)
{
- (void)alloc_monster(0, TRUE);
+ alloc_monster(0, TRUE);
}
}
/* Check fates */
- for (i = 0; i < MAX_FATES; i++)
+ for (std::size_t i = 0; i < MAX_FATES; i++)
{
/* Ignore empty slots */
if (fates[i].fate == FATE_NONE) continue;
@@ -7782,7 +7784,7 @@ static bool_ cave_gen(void)
get_obj_num_hook = kind_is_legal;
/* Invalidate the allocation table */
- alloc_kind_table_valid = FALSE;
+ alloc.kind_table_valid = false;
/* Get a local object */
q_ptr = &forge;
@@ -7803,7 +7805,7 @@ static bool_ cave_gen(void)
/* Grant a normal artefact */
else if (a_info[fates[i].a_idx].cur_num == 0)
{
- artifact_type *a_ptr = &a_info[fates[i].a_idx];
+ auto a_ptr = &a_info[fates[i].a_idx];
s16b I_kind;
/* Get local object */
@@ -7833,8 +7835,8 @@ static bool_ cave_gen(void)
}
}
- /* Re scan the list to eliminate the inutile fate */
- for (i = 0; i < MAX_FATES; i++)
+ /* Re-scan the list to eliminate the inutile fate */
+ for (std::size_t i = 0; i < MAX_FATES; i++)
{
switch (fates[i].fate)
{
@@ -7845,24 +7847,16 @@ static bool_ cave_gen(void)
}
case FATE_FIND_R:
{
- if ((r_info[fates[i].r_idx].cur_num == 1) && (r_info[fates[i].r_idx].flags1 & RF1_UNIQUE)) fates[i].icky = TRUE;
+ if ((r_info[fates[i].r_idx].cur_num == 1) && (r_info[fates[i].r_idx].flags & RF_UNIQUE)) fates[i].icky = TRUE;
break;
}
}
}
- /* Only if requested */
- if (generator->default_miscs)
- {
- /* Place some traps in the dungeon */
- alloc_object(ALLOC_SET_BOTH, ALLOC_TYP_TRAP, randint(k * 2));
+ /* Put some rubble in corridors */
+ alloc_object(ALLOC_SET_CORR, ALLOC_TYP_RUBBLE, randint(k));
- /* Put some rubble in corridors */
- alloc_object(ALLOC_SET_CORR, ALLOC_TYP_RUBBLE, randint(k));
- }
-
- /* Only if requested */
- if (generator->default_objects)
+ /* Place objects and treasure */
{
/* Put some objects in rooms */
if (dungeon_type != DUNGEON_DEATH) alloc_object(ALLOC_SET_ROOM, ALLOC_TYP_OBJECT, randnor(DUN_AMT_ROOM, 3));
@@ -7872,8 +7866,7 @@ static bool_ cave_gen(void)
if (dungeon_type != DUNGEON_DEATH) alloc_object(ALLOC_SET_BOTH, ALLOC_TYP_GOLD, randnor(DUN_AMT_GOLD, 3));
}
- /* Only if requested */
- if (generator->default_miscs)
+ /* Place random features such as altars and void gates, etc. */
{
/* Put some altars */
alloc_object(ALLOC_SET_ROOM, ALLOC_TYP_ALTAR, randnor(DUN_AMT_ALTAR, 3));
@@ -7923,7 +7916,7 @@ static bool_ cave_gen(void)
if (m_idx && d_ptr->final_artifact &&
(a_info[d_ptr->final_artifact].cur_num == 0))
{
- artifact_type *a_ptr = &a_info[d_ptr->final_artifact];
+ auto a_ptr = &a_info[d_ptr->final_artifact];
object_type *q_ptr, forge, *o_ptr;
int I_kind, o_idx;
@@ -7969,13 +7962,11 @@ static bool_ cave_gen(void)
object_copy(o_ptr, q_ptr);
/* Build a stack */
- o_ptr->next_o_idx = m_list[m_idx].hold_o_idx;
-
o_ptr->held_m_idx = m_idx;
o_ptr->ix = 0;
o_ptr->iy = 0;
- m_list[m_idx].hold_o_idx = o_idx;
+ m_list[m_idx].hold_o_idxs.push_back(o_idx);
}
}
@@ -8021,13 +8012,11 @@ static bool_ cave_gen(void)
object_copy(o_ptr, q_ptr);
/* Build a stack */
- o_ptr->next_o_idx = m_list[m_idx].hold_o_idx;
-
o_ptr->held_m_idx = m_idx;
o_ptr->ix = 0;
o_ptr->iy = 0;
- m_list[m_idx].hold_o_idx = o_idx;
+ m_list[m_idx].hold_o_idxs.push_back(o_idx);
}
}
}
@@ -8036,66 +8025,26 @@ static bool_ cave_gen(void)
wiz_lite();
/* Now double the generated dungeon */
- if (dungeon_flags1 & DF1_DOUBLE)
+ if (dungeon_flags & DF_DOUBLE)
{
- /* We begin at the bottom-right corner and from there move
- * up/left (this way we don't need another array for the
- * dungeon data) */
- /* Note: we double the border permanent walls, too. It is
- * easier this way and I think it isn't too ugly */
- for (y = cur_hgt - 1, y1 = y * 2; y >= 0; y--, y1 -= 2)
- for (x = cur_wid - 1, x1 = x * 2; x >= 0; x--, x1 -= 2)
+ /*
+ * We begin at the bottom-right corner and move upwards
+ * to the left. This avoids the need for an extra copy of
+ * the cave array.
+ *
+ * We double the border permanent walls, too.
+ */
+ int y = cur_hgt - 1;
+ int y1 = y * 2;
+ for (; y >= 0; y--, y1 -= 2)
+ {
+ int x = cur_wid - 1;
+ int x1 = x * 2;
+ for (; x >= 0; x--, x1 -= 2)
{
- int disp[4][2] = {{0, 0}, {0, + 1}, { + 1, 0}, { + 1, + 1}};
-
- cave_type *c_ptr[4], *cc_ptr = &cave[y][x];
- object_type *o_ptr = &o_list[cc_ptr->o_idx];
- monster_type *m_ptr = &m_list[cc_ptr->m_idx];
-
- /*
- * Now we copy the generated data to the
- * appropriate grids
- */
- for (i = 0; i < 4; i++)
- {
- c_ptr[i] = &cave[y1 + disp[i][0]][x1 + disp[i][1]];
- *c_ptr[i] = *cc_ptr;
- c_ptr[i]->o_idx = 0;
- c_ptr[i]->m_idx = 0;
-
- if (cc_ptr->feat == FEAT_BETWEEN)
- {
- int xxx = cc_ptr->special & 0xFF;
- int yyy = cc_ptr->special >> 8;
-
- xxx *= 2;
- yyy *= 2;
- xxx += disp[i][1];
- yyy += disp[i][0];
- c_ptr[i]->special = xxx + (yyy << 8);
- }
- }
-
- /* Objects should be put only in 1 of the
- * new grids (otherwise we would segfault
- * a lot) ... */
- if (cc_ptr->o_idx != 0)
- {
- i = rand_int(4);
- c_ptr[i]->o_idx = cc_ptr->o_idx;
- o_ptr->iy = y1 + disp[i][0];
- o_ptr->ix = x1 + disp[i][1];
- }
-
- /* ..just like monsters */
- if (cc_ptr->m_idx != 0)
- {
- i = rand_int(4);
- c_ptr[i]->m_idx = cc_ptr->m_idx;
- m_ptr->fy = y1 + disp[i][0];
- m_ptr->fx = x1 + disp[i][1];
- }
+ supersize_grid_tile(y, x, y1, x1);
}
+ }
/* Set the width/height ... */
cur_wid *= 2;
@@ -8110,160 +8059,39 @@ static bool_ cave_gen(void)
}
+
/*
- * Builds the arena after it is entered -KMW-
+ * Creates a special level
*/
-static void build_arena(void)
-{
- int yval, y_height, y_depth, xval, x_left, x_right;
- register int i, j;
- yval = SCREEN_HGT / 2;
- xval = SCREEN_WID / 2;
- y_height = yval - 10 + SCREEN_HGT;
- y_depth = yval + 10 + SCREEN_HGT;
- x_left = xval - 32 + SCREEN_WID;
- x_right = xval + 32 + SCREEN_WID;
+/* Mega-Hack */
+#define REGEN_HACK 0x02
- for (i = y_height; i <= y_height + 5; i++)
- {
- for (j = x_left; j <= x_right; j++)
- {
- cave_set_feat(i, j, FEAT_PERM_EXTRA);
- cave[i][j].info |= (CAVE_GLOW | CAVE_MARK);
- }
- }
- for (i = y_depth; i >= y_depth - 5; i--)
- {
- for (j = x_left; j <= x_right; j++)
- {
- cave_set_feat(i, j, FEAT_PERM_EXTRA);
- cave[i][j].info |= (CAVE_GLOW | CAVE_MARK);
- }
- }
- for (j = x_left; j <= x_left + 17; j++)
- {
- for (i = y_height; i <= y_depth; i++)
- {
- cave_set_feat(i, j, FEAT_PERM_EXTRA);
- cave[i][j].info |= (CAVE_GLOW | CAVE_MARK);
- }
- }
- for (j = x_right; j >= x_right - 17; j--)
+bool_ build_special_level()
+{
+ auto const &d_info = game->edit_data.d_info;
+ auto &level_markers = game->level_markers;
+
+ /* No special levels on the surface */
+ if (!dun_level)
{
- for (i = y_height; i <= y_depth; i++)
- {
- cave_set_feat(i, j, FEAT_PERM_EXTRA);
- cave[i][j].info |= (CAVE_GLOW | CAVE_MARK);
- }
+ return FALSE;
}
- cave_set_feat(y_height + 6, x_left + 18, FEAT_PERM_EXTRA);
- cave[y_height + 6][x_left + 18].info |= (CAVE_GLOW | CAVE_MARK);
- cave_set_feat(y_depth - 6, x_left + 18, FEAT_PERM_EXTRA);
- cave[y_depth - 6][x_left + 18].info |= (CAVE_GLOW | CAVE_MARK);
- cave_set_feat(y_height + 6, x_right - 18, FEAT_PERM_EXTRA);
- cave[y_height + 6][x_right - 18].info |= (CAVE_GLOW | CAVE_MARK);
- cave_set_feat(y_depth - 6, x_right - 18, FEAT_PERM_EXTRA);
- cave[y_depth - 6][x_right - 18].info |= (CAVE_GLOW | CAVE_MARK);
+ auto const level = dun_level - d_info[dungeon_type].mindepth;
- i = y_height + 5;
- j = xval + SCREEN_WID;
- cave_set_feat(i, j, FEAT_SHOP);
- cave[i][j].info |= (CAVE_GLOW | CAVE_MARK);
- player_place(i + 1, j);
-}
-
-
-/*
- * Town logic flow for generation of arena -KMW-
- */
-static void arena_gen(void)
-{
- int y, x;
- int qy = SCREEN_HGT;
- int qx = SCREEN_WID;
- bool_ daytime;
-
- /* Day time */
- if ((turn % (10L * DAY)) < ((10L * DAY) / 2))
- daytime = TRUE;
-
- /* Night time */
- else
- daytime = FALSE;
+ char buf[80];
- /* Start with solid walls */
- for (y = 0; y < MAX_HGT; y++)
+ if ((!get_dungeon_save(buf)) && !is_normal_level(level_markers[level][dungeon_type]))
{
- for (x = 0; x < MAX_WID; x++)
- {
- /* Create "solid" perma-wall */
- cave_set_feat(y, x, FEAT_PERM_SOLID);
-
- /* Illuminate and memorize the walls */
- cave[y][x].info |= (CAVE_GLOW | CAVE_MARK);
- }
+ return FALSE;
}
- /* Then place some floors */
- for (y = qy + 1; y < qy + SCREEN_HGT - 1; y++)
+ if (!get_dungeon_special(buf))
{
- for (x = qx + 1; x < qx + SCREEN_WID - 1; x++)
- {
- /* Create empty floor */
- cave_set_feat(y, x, FEAT_FLOOR);
-
- /* Darken and forget the floors */
- cave[y][x].info &= ~(CAVE_GLOW | CAVE_MARK);
-
- /* Day time */
- if (daytime)
- {
- /* Perma-Lite */
- cave[y][x].info |= (CAVE_GLOW);
-
- /* Memorize */
- if (view_perma_grids) cave[y][x].info |= (CAVE_MARK);
- }
- }
+ return FALSE;
}
- build_arena();
-
- place_monster_aux(p_ptr->py + 5, p_ptr->px, arena_monsters[p_ptr->arena_number],
- FALSE, FALSE, MSTATUS_ENEMY);
-}
-
-
-/*
- * Generate a quest level
- */
-static void quest_gen(void)
-{
- process_hooks(HOOK_GEN_QUEST, "(d)", is_quest(dun_level));
-}
-
-/*
- * Creates a special level
- */
-
-/* Mega-Hack */
-#define REGEN_HACK 0x02
-
-bool_ build_special_level(void)
-{
- char buf[80];
- int y, x, ystart = 2, xstart = 2;
- s16b level;
-
- /* No special levels on the surface */
- if (!dun_level) return FALSE;
-
- level = dun_level - d_info[dungeon_type].mindepth;
- if ((!get_dungeon_save(buf)) && (special_lvl[level][dungeon_type])) return FALSE;
- if (!get_dungeon_special(buf)) return FALSE;
-
/* Big town */
cur_hgt = MAX_HGT;
cur_wid = MAX_WID;
@@ -8277,9 +8105,9 @@ bool_ build_special_level(void)
panel_col_min = max_panel_cols * (SCREEN_WID / 2);
/* Start with perm walls */
- for (y = 0; y < cur_hgt; y++)
+ for (int y = 0; y < cur_hgt; y++)
{
- for (x = 0; x < cur_wid; x++)
+ for (int x = 0; x < cur_wid; x++)
{
cave_set_feat(y, x, FEAT_PERM_SOLID);
}
@@ -8291,10 +8119,12 @@ bool_ build_special_level(void)
get_mon_num_prep();
init_flags = INIT_CREATE_DUNGEON | INIT_POSITION;
+ int ystart = 2;
+ int xstart = 2;
process_dungeon_file(buf, &ystart, &xstart, cur_hgt, cur_wid, TRUE, TRUE);
- special_lvl[level][dungeon_type] = REGEN_HACK;
- generate_special_feeling = TRUE;
+ game->level_markers[level][dungeon_type] = level_marker::REGENERATE;
+ game->generate_special_feeling = true;
/* Special feeling because it's special */
good_item_flag = TRUE;
@@ -8312,59 +8142,83 @@ bool_ build_special_level(void)
* Prepare regeneration of a special level, which should not happen,
* but just in case...
*/
-static void wipe_special_level(void)
+static void wipe_special_level()
{
- s16b level;
- char buf[80];
+ auto const &d_info = game->edit_data.d_info;
+ auto &level_markers = game->level_markers;
/* No special levels on the surface */
- if (!dun_level) return;
+ if (!dun_level)
+ {
+ return;
+ }
- process_hooks(HOOK_LEVEL_REGEN, "()");
+ /* Fire off hooks */
+ process_hooks_new(HOOK_LEVEL_REGEN, NULL, NULL);
/* Calculate relative depth */
- level = dun_level - d_info[dungeon_type].mindepth;
+ auto const level = dun_level - d_info[dungeon_type].mindepth;
- /* No special level at this depth */
- if ((!get_dungeon_save(buf)) &&
- special_lvl[level][dungeon_type]) return;
- if (!get_dungeon_special(buf)) return;
+ /* No special level at this depth? */
+ char buf[80];
+ if ((!get_dungeon_save(buf)) && !is_normal_level(level_markers[level][dungeon_type]))
+ {
+ return;
+ }
+ if (!get_dungeon_special(buf))
+ {
+ return;
+ }
/* Clear the Mega-Hack flag */
- if (special_lvl[level][dungeon_type] == REGEN_HACK)
- special_lvl[level][dungeon_type] = FALSE;
+ if (level_markers[level][dungeon_type] == level_marker::REGENERATE)
+ {
+ level_markers[level][dungeon_type] = level_marker::NORMAL;
+ }
}
/*
* Finalise generation of a special level
*/
-static void finalise_special_level(void)
+static void finalise_special_level()
{
- s16b level;
- char buf[80];
+ auto const &d_info = game->edit_data.d_info;
+ auto &level_markers = game->level_markers;
/* No special levels on the surface */
- if (!dun_level) return;
+ if (!dun_level)
+ {
+ return;
+ }
- process_hooks(HOOK_LEVEL_END_GEN, "()");
+ /* Fire hooks */
+ process_hooks_new(HOOK_LEVEL_END_GEN, NULL, NULL);
/* Calculate relative depth */
- level = dun_level - d_info[dungeon_type].mindepth;
+ auto const level = dun_level - d_info[dungeon_type].mindepth;
- /* No special level at this depth */
- if ((!get_dungeon_save(buf)) &&
- special_lvl[level][dungeon_type]) return;
- if (!get_dungeon_special(buf)) return;
+ /* No special level at this depth? */
+ char buf[80];
+ if ((!get_dungeon_save(buf)) && !is_normal_level(level_markers[level][dungeon_type]))
+ {
+ return;
+ }
+ if (!get_dungeon_special(buf))
+ {
+ return;
+ }
/* Set the "generated" flag */
- if (special_lvl[level][dungeon_type] == REGEN_HACK)
- special_lvl[level][dungeon_type] = TRUE;
+ if (level_markers[level][dungeon_type] == level_marker::REGENERATE)
+ {
+ level_markers[level][dungeon_type] = level_marker::SPECIAL;
+ }
}
/*
* Give some magical energy to the each grid of the level
*/
-void generate_grid_mana()
+static void generate_grid_mana()
{
int y, x, mana, mult;
bool_ xtra_magic = FALSE;
@@ -8373,7 +8227,7 @@ void generate_grid_mana()
{
xtra_magic = TRUE;
- if (cheat_room || p_ptr->precognition)
+ if (options->cheat_room || p_ptr->precognition)
{
msg_print("Magical level");
}
@@ -8408,9 +8262,13 @@ void generate_grid_mana()
*
* Hack -- allow auto-scumming via a gameplay option.
*/
-void generate_cave(void)
+void generate_cave()
{
- dungeon_info_type *d_ptr = &d_info[dungeon_type];
+ auto const &d_info = game->edit_data.d_info;
+ auto &a_info = game->edit_data.a_info;
+ auto const &level_markers = game->level_markers;
+
+ auto d_ptr = &d_info[dungeon_type];
int tester_1, tester_2;
int y, x, num, i;
bool_ loaded = FALSE;
@@ -8419,18 +8277,16 @@ void generate_cave(void)
/* The dungeon is not ready */
character_dungeon = FALSE;
- generate_special_feeling = FALSE;
+ game->generate_special_feeling = false;
/* Initialize the flags with the basic dungeon flags */
if (!dun_level)
{
- dungeon_flags1 = d_info[DUNGEON_WILDERNESS].flags1;
- dungeon_flags2 = d_info[DUNGEON_WILDERNESS].flags2;
+ dungeon_flags = d_info[DUNGEON_WILDERNESS].flags;
}
else
{
- dungeon_flags1 = d_ptr->flags1;
- dungeon_flags2 = d_ptr->flags2;
+ dungeon_flags = d_ptr->flags;
}
/* Is it a town level ? */
@@ -8446,11 +8302,10 @@ void generate_cave(void)
/* Seed the RNG if appropriate */
if (town_level)
{
- Rand_quick = TRUE;
- Rand_value = town_info[town_level].seed;
+ set_quick_rng(town_info[town_level].seed);
}
- process_hooks(HOOK_GEN_LEVEL_BEGIN, "");
+ process_hooks_new(HOOK_GEN_LEVEL_BEGIN, NULL, NULL);
/* Try to load a saved level */
if (get_dungeon_save(buf))
@@ -8466,33 +8321,11 @@ void generate_cave(void)
{
for (x = 0; x < MAX_WID; x++)
{
- /* No flags */
- cave[y][x].info = 0;
+ /* Wipe */
+ cave[y][x].wipe();
/* No features */
cave_set_feat(y, x, FEAT_PERM_INNER);
-
- /* No objects */
- cave[y][x].o_idx = 0;
-
- /* No monsters */
- cave[y][x].m_idx = 0;
-
- /* No traps */
- cave[y][x].t_idx = 0;
-
- /* No mimic */
- cave[y][x].mimic = 0;
-
- /* No effects */
- cave[y][x].effect = 0;
-
- /* No inscription */
- cave[y][x].inscription = 0;
-
- /* No flow */
- cave[y][x].cost = 0;
- cave[y][x].when = 0;
}
}
@@ -8502,8 +8335,8 @@ void generate_cave(void)
/* No saved level -- generate new one */
if (!loaded)
{
- if (!get_dungeon_special(buf) ||
- !special_lvl[dun_level - d_info[dungeon_type].mindepth][dungeon_type])
+ auto const level = dun_level - d_info[dungeon_type].mindepth;
+ if (!get_dungeon_special(buf) || is_normal_level(level_markers[level][dungeon_type]))
{
get_level_flags();
}
@@ -8526,33 +8359,11 @@ void generate_cave(void)
{
for (x = 0; x < MAX_WID; x++)
{
- /* No flags */
- cave[y][x].info = 0;
+ /* Wipe */
+ cave[y][x].wipe();
/* No features */
cave_set_feat(y, x, FEAT_PERM_INNER);
-
- /* No objects */
- cave[y][x].o_idx = 0;
-
- /* No monsters */
- cave[y][x].m_idx = 0;
-
- /* No traps */
- cave[y][x].t_idx = 0;
-
- /* No mimic */
- cave[y][x].mimic = 0;
-
- /* No effect */
- cave[y][x].effect = 0;
-
- /* No inscription */
- cave[y][x].inscription = 0;
-
- /* No flow */
- cave[y][x].cost = 0;
- cave[y][x].when = 0;
}
}
@@ -8591,17 +8402,10 @@ void generate_cave(void)
/* No fated level here yet */
fate_flag = FALSE;
- /* Build the arena -KMW- */
- if (p_ptr->inside_arena)
- {
- /* Small arena */
- arena_gen();
- }
-
/* Quest levels -KMW- */
- else if (p_ptr->inside_quest)
+ if (p_ptr->inside_quest)
{
- quest_gen();
+ process_hooks_new(HOOK_GEN_QUEST, NULL, NULL);
}
/* Special levels */
@@ -8629,7 +8433,7 @@ void generate_cave(void)
if (!p_ptr->wild_mode)
{
/* Make the wilderness */
- wilderness_gen(0);
+ wilderness_gen();
}
/* Small wilderness mode */
@@ -8649,7 +8453,7 @@ void generate_cave(void)
/* Requested size level */
if (d_ptr->size_x != -1)
{
- if (cheat_room || p_ptr->precognition)
+ if (options->cheat_room || p_ptr->precognition)
{
msg_print ("A 'size' dungeon level.");
}
@@ -8665,16 +8469,16 @@ void generate_cave(void)
panel_row_min = max_panel_rows * (SCREEN_HGT / 2);
panel_col_min = max_panel_cols * (SCREEN_WID / 2);
- if (cheat_room)
+ if (options->cheat_room)
{
msg_format("X:%d, Y:%d.", max_panel_cols, max_panel_rows);
}
}
/* Very small (1 x 1 panel) level */
- else if (!(dungeon_flags1 & DF1_BIG) &&
- (dungeon_flags1 & DF1_SMALLEST))
+ else if (!(dungeon_flags & DF_BIG) &&
+ (dungeon_flags & DF_SMALLEST))
{
- if (cheat_room || p_ptr->precognition)
+ if (options->cheat_room || p_ptr->precognition)
{
msg_print ("A 'small' dungeon level.");
}
@@ -8690,19 +8494,19 @@ void generate_cave(void)
panel_row_min = max_panel_rows * (SCREEN_HGT / 2);
panel_col_min = max_panel_cols * (SCREEN_WID / 2);
- if (cheat_room)
+ if (options->cheat_room)
{
msg_format("X:1, Y:1.");
}
}
/* Small level */
- else if (!(dungeon_flags1 & DF1_BIG) &&
- (always_small_level ||
- (dungeon_flags1 & DF1_SMALL) ||
- (small_levels && rand_int(SMALL_LEVEL) == 0)))
+ else if (!(dungeon_flags & DF_BIG) &&
+ (options->always_small_level ||
+ (dungeon_flags & DF_SMALL) ||
+ (options->small_levels && rand_int(SMALL_LEVEL) == 0)))
{
- if (cheat_room || p_ptr->precognition)
+ if (options->cheat_room || p_ptr->precognition)
{
msg_print ("A 'small' dungeon level.");
}
@@ -8721,7 +8525,7 @@ void generate_cave(void)
panel_row_min = max_panel_rows * (SCREEN_HGT / 2);
panel_col_min = max_panel_cols * (SCREEN_WID / 2);
- if (cheat_room)
+ if (options->cheat_room)
{
msg_format("X:%d, Y:%d.", max_panel_cols, max_panel_rows);
}
@@ -8763,7 +8567,7 @@ void generate_cave(void)
else feeling = 10;
/* Hack -- Have a special feeling sometimes */
- if (good_item_flag && !p_ptr->preserve) feeling = 1;
+ if (good_item_flag && !options->preserve) feeling = 1;
/* It takes 1000 game turns for "feelings" to recharge */
if ((turn - old_turn) < 1000) feeling = 0;
@@ -8793,7 +8597,7 @@ void generate_cave(void)
}
/* Mega-Hack -- "auto-scum" */
- if (auto_scum && (num < 100) && !p_ptr->inside_quest && dun_level)
+ if (options->auto_scum && (num < 100) && !p_ptr->inside_quest && dun_level)
{
/* Require "goodness" */
if ((feeling > 9) ||
@@ -8803,8 +8607,8 @@ void generate_cave(void)
((dun_level >= 40) && (feeling > 5)))
{
/* Give message to cheaters */
- if (cheat_room || cheat_hear ||
- cheat_peek || cheat_xtra || p_ptr->precognition)
+ if (options->cheat_room || options->cheat_hear ||
+ options->cheat_peek || options->cheat_xtra || p_ptr->precognition)
{
/* Message */
why = "boring level";
@@ -8842,7 +8646,10 @@ void generate_cave(void)
}
/* Put the kept monsters -- DG */
- if (!p_ptr->wild_mode) replace_all_friends();
+ if (!p_ptr->wild_mode)
+ {
+ replace_all_friends();
+ }
/* Hack -- Clear used up fates */
for (i = 0; i < MAX_FATES; i++)
diff --git a/src/generate.hpp b/src/generate.hpp
new file mode 100644
index 00000000..a21ba069
--- /dev/null
+++ b/src/generate.hpp
@@ -0,0 +1,12 @@
+#pragma once
+
+#include "h-basic.h"
+
+bool_ new_player_spot(int branch);
+void add_level_generator(cptr name, bool_ (*generator)());
+bool_ level_generate_dungeon();
+bool_ generate_fracave(int y0, int x0,int xsize,int ysize,int cutoff,bool_ light,bool_ room);
+void generate_hmap(int y0, int x0,int xsiz,int ysiz,int grd,int roug,int cutoff);
+bool_ room_alloc(int x,int y,bool_ crowded,int by0,int bx0,int *xx,int *yy);
+void generate_cave();
+void build_rectangle(int y1, int x1, int y2, int x2, int feat, int info);
diff --git a/src/gf_name_type.hpp b/src/gf_name_type.hpp
new file mode 100644
index 00000000..0b17bdbf
--- /dev/null
+++ b/src/gf_name_type.hpp
@@ -0,0 +1,10 @@
+#pragma once
+
+/**
+ * GF_XXX descriptor entry.
+ */
+struct gf_name_type
+{
+ int gf;
+ char const *name;
+};
diff --git a/src/gods.c b/src/gods.cc
index b8b8fd3a..82d8d300 100644
--- a/src/gods.c
+++ b/src/gods.cc
@@ -1,7 +1,3 @@
-/* File: gods.c */
-
-/* Purpose: Deities code */
-
/*
* Copyright (c) 2002 DarkGod
*
@@ -9,8 +5,20 @@
* not for profit purposes provided that this copyright and statement are
* included in all such copies.
*/
+#include "gods.hpp"
+
+#include "game.hpp"
+#include "player_type.hpp"
+#include "skills.hpp"
+#include "skill_type.hpp"
+#include "stats.hpp"
+#include "util.hpp"
+#include "util.h"
+#include "variable.h"
+#include "variable.hpp"
+#include "xtra2.hpp"
-#include "angband.h"
+#include <cassert>
/*
* Add amt piety is god is god
@@ -44,10 +52,36 @@ 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
*/
void follow_god(int god, bool_ silent)
{
+ auto &s_info = game->s_info;
+
/* Poor unbelievers, i'm so mean ... BOUHAHAHA */
if (get_skill(SKILL_ANTIMAGIC))
{
@@ -56,7 +90,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)
@@ -64,21 +98,21 @@ void follow_god(int god, bool_ silent)
p_ptr->pgod = god;
/* Melkor offer Udun magic */
- GOD(GOD_MELKOR)
+ if (p_ptr->pgod == GOD_MELKOR)
{
- 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.");
+ 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");
}
}
/*
* Show religious info.
*/
-bool_ show_god_info(bool_ ext)
+bool_ show_god_info()
{
int pgod = p_ptr->pgod;
@@ -125,15 +159,59 @@ 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 < MAX_GODS);
+
+ if (god_idx == 0)
+ {
+ return NULL;
+ }
+
+ return &deity_info[god_idx];
+}
+
+/*
+ * 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;
}
+
+bool praying_to(int god)
+{
+ return (p_ptr->pgod == god) && p_ptr->praying;
+}
diff --git a/src/gods.hpp b/src/gods.hpp
new file mode 100644
index 00000000..2a5f2bb5
--- /dev/null
+++ b/src/gods.hpp
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "h-basic.h"
+
+void inc_piety(int god, s32b amt);
+void abandon_god(int god);
+int wisdom_scale(int max);
+int find_god(cptr name);
+void follow_god(int god, bool_ silent);
+bool_ god_enabled(struct deity_type *deity);
+deity_type *god_at(byte god_idx);
+bool_ show_god_info();
+bool praying_to(int god);
diff --git a/src/grid.hpp b/src/grid.hpp
new file mode 100644
index 00000000..4708811d
--- /dev/null
+++ b/src/grid.hpp
@@ -0,0 +1,72 @@
+#pragma once
+
+#include <boost/multi_array.hpp>
+
+/**
+ * 2D grid of T's.
+ */
+template <typename T>
+struct grid {
+
+private:
+ boost::multi_array<T, 2> impl;
+
+public:
+ /**
+ * Get reference to tile.
+ */
+ T &operator ()(std::size_t x, std::size_t y)
+ {
+ return impl[y][x];
+ }
+
+ /**
+ * Get const reference to tile.
+ */
+ T const &operator ()(std::size_t x, std::size_t y) const
+ {
+ return impl[y][x];
+ }
+
+ /**
+ * Resize grid. There is no guarantee whether
+ * existing elements will be preserved or not.
+ */
+ void resize(std::size_t width, std::size_t height)
+ {
+ impl.resize(boost::extents[height][width]);
+ }
+
+ /**
+ * Get current width.
+ */
+ std::size_t width() const
+ {
+ return impl.shape()[1];
+ }
+
+ /**
+ * Get current height.
+ */
+ std::size_t height() const
+ {
+ return impl.shape()[0];
+ }
+
+ /**
+ * Set width. Same caveats apply as for resize().
+ */
+ void width(std::size_t width)
+ {
+ resize(width, height());
+ }
+
+ /**
+ * Set height. Same caveats apply as for resize().
+ */
+ void height(std::size_t height)
+ {
+ resize(width(), height);
+ }
+
+};
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..09e9bac8 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.
@@ -19,115 +20,12 @@
*/
/*
- * OPTION: Compile on a Macintosh (see "A-mac-h" or "A-mac-pch")
- */
-#ifndef MACINTOSH
-/* #define MACINTOSH */
-#endif
-
-/*
* OPTION: Compile on Windows (automatic)
*/
#ifndef WINDOWS
/* #define WINDOWS */
#endif
-/*
- * OPTION: Compile on a SYS III version of UNIX
- */
-#ifndef SYS_III
-/* #define SYS_III */
-#endif
-
-/*
- * OPTION: Compile on a SYS V version of UNIX (not Solaris)
- */
-#ifndef SYS_V
-/* #define SYS_V */
-#endif
-
-/*
- * OPTION: Compile on a HPUX version of UNIX
- */
-#ifndef HPUX
-/* #define HPUX */
-#endif
-
-/*
- * OPTION: Compile on an SGI running IRIX
- */
-#ifndef SGI
-/* #define SGI */
-#endif
-
-/*
- * OPTION: Compile on a SunOS machine
- */
-#ifndef SUNOS
-/* #define SUNOS */
-#endif
-
-/*
- * OPTION: Compile on a Solaris machine
- */
-#ifndef SOLARIS
-/* #define SOLARIS */
-#endif
-
-/*
- * OPTION: Compile on an ultrix/4.2BSD/Dynix/etc. version of UNIX,
- * Do not define this if you are on any kind of SunOS.
- */
-#ifndef ULTRIX
-/* #define ULTRIX */
-#endif
-
-
-
-/*
- * Extract the "SUNOS" flag from the compiler
- */
-#if defined(sun)
-# ifndef SUNOS
-# define SUNOS
-# endif
-#endif
-
-/*
- * Extract the "ULTRIX" flag from the compiler
- */
-#if defined(ultrix) || defined(Pyramid)
-# ifndef ULTRIX
-# define ULTRIX
-# endif
-#endif
-
-/*
- * Extract the "ATARI" flag from the compiler [cjh]
- */
-#if defined(__atarist) || defined(__atarist__)
-# ifndef ATARI
-# define ATARI
-# endif
-#endif
-
-/*
- * Extract the "SGI" flag from the compiler
- */
-#ifdef sgi
-# ifndef SGI
-# define SGI
-# endif
-#endif
-
-/*
- * Extract the "MSDOS" flag from the compiler
- */
-#ifdef __MSDOS__
-# ifndef MSDOS
-# define MSDOS
-# endif
-#endif
/*
* Extract the "WINDOWS" flag from the compiler
@@ -147,7 +45,7 @@
* The only such platform that angband is ported to is currently
* DEC Alpha AXP running OSF/1 (OpenVMS uses 32-bit longs).
*/
-#if defined(__alpha) && defined(__osf__) || defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(__ia64) || defined(__ia64__) || defined(__mips64) || defined(__ppc64__) || defined(__PPC64__) || defined(__powerpc64__) || defined(__64BIT__) || defined(__sparc64__) || defined(__LP64__)
+#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(__ia64) || defined(__ia64__) || defined(__mips64) || defined(__ppc64__) || defined(__PPC64__) || defined(__powerpc64__) || defined(__64BIT__) || defined(__sparc64__) || defined(__LP64__)
# define L64
#endif
@@ -160,34 +58,14 @@
* and of the "umask()" call for various reasons, and to guess if
* the "kill()" function is available, and for permission to use
* functions to extract user names and expand "tildes" in filenames.
- * It is also used for "locking" and "unlocking" the score file.
- * Basically, SET_UID should *only* be set for "Unix" machines,
- * or for the "Atari" platform which is Unix-like, apparently
+ * Basically, SET_UID should *only* be set for "Unix" machines.
*/
-#if !defined(MACINTOSH) && !defined(WINDOWS) && \
- !defined(MSDOS)
+#if !defined(WINDOWS)
# define SET_UID
#endif
/*
- * OPTION: Set "USG" for "System V" versions of Unix
- * This is used to choose a "lock()" function, and to choose
- * which header files ("string.h" vs "strings.h") to include.
- * It is also used to allow certain other options, such as options
- * involving userid's, or multiple users on a single machine, etc.
- */
-#ifdef SET_UID
-# if defined(SYS_III) || defined(SYS_V) || defined(SOLARIS) || \
- defined(HPUX) || defined(SGI) || defined(ATARI)
-# ifndef USG
-# define USG
-# endif
-# endif
-#endif
-
-
-/*
* Every system seems to use its own symbol as a path separator.
* Default to the standard Unix slash, but attempt to change this
* for various other systems. Note that any system that uses the
@@ -196,79 +74,11 @@
*/
#undef PATH_SEP
#define PATH_SEP "/"
-#ifdef MACINTOSH
-# undef PATH_SEP
-# define PATH_SEP ":"
-#endif
#if defined(WINDOWS) || defined(WINNT)
# undef PATH_SEP
# define PATH_SEP "\\"
#endif
-#if defined(MSDOS) || defined(OS2)
-# undef PATH_SEP
-# define PATH_SEP "\\"
-#endif
-#ifdef __GO32__
-# undef PATH_SEP
-# define PATH_SEP "/"
-#endif
-
-
-/*
- * The Macintosh allows the use of a "file type" when creating a file
- */
-#if defined(MACINTOSH) && !defined(applec) || defined(MACH_O_CARBON)
-# define FILE_TYPE_TEXT 'TEXT'
-# define FILE_TYPE_DATA 'DATA'
-# define FILE_TYPE_SAVE 'SAVE'
-# define FILE_TYPE(X) (_ftype = (X))
-#else
-# define FILE_TYPE(X) ((void)0)
-#endif
-
-
-/*
- * OPTION: Hack -- Make sure "strchr()" and "strrchr()" will work
- */
-#if defined(SYS_III) || defined(SYS_V) || defined(MSDOS)
-# if !defined(__TURBOC__) && !defined(__WATCOMC__)
-# define strchr index
-# define strrchr rindex
-# endif
-#endif
-
-
-/*
- * OPTION: Define "HAS_STRICMP" only if "stricmp()" exists.
- * Note that "stricmp()" is not actually used by Angband.
- */
-/* #define HAS_STRICMP */
-
-/*
- * Linux has "stricmp()" with a different name
- */
-#if defined(linux)
-# define HAS_STRICMP
-# define stricmp strcasecmp
-#endif
-
-
-/*
- * OPTION: Define "HAS_MEMSET" only if "memset()" exists.
- * Note that the "memset()" routines are used in "z-virt.h"
- */
-#define HAS_MEMSET
-
-
-/*
- * OPTION: Define "HAS_USLEEP" only if "usleep()" exists.
- * Note that this is only relevant for "SET_UID" machines
- */
-#ifdef SET_UID
-# if !defined(HPUX) && !defined(ULTRIX) && !defined(SOLARIS) && \
- !defined(SGI) && !defined(ISC)
-# define HAS_USLEEP
-# endif
-#endif
+#ifdef __cplusplus
+} // extern "C"
#endif
diff --git a/src/h-define.h b/src/h-define.h
index cb36b189..76e7e339 100644
--- a/src/h-define.h
+++ b/src/h-define.h
@@ -33,19 +33,6 @@
# define SEEK_END 2
#endif
-/*
- * Hack -- force definitions -- see fd_lock() XXX XXX XXX
- */
-#ifndef F_UNLCK
-# define F_UNLCK 0
-#endif
-#ifndef F_RDLCK
-# define F_RDLCK 1
-#endif
-#ifndef F_WRLCK
-# define F_WRLCK 2
-#endif
-
/*
* The constants "TRUE" and "FALSE"
@@ -87,12 +74,6 @@
#undef ABS
#define ABS(a) (((a) < 0) ? (-(a)) : (a))
-/*
- * Non-typed sign extractor macro
- */
-#undef SGN
-#define SGN(a) (((a) < 0) ? (-1) : ((a) != 0))
-
/*
* Note that all "index" values must be "lowercase letters", while
diff --git a/src/h-system.h b/src/h-system.h
index 50cc0af8..92041742 100644
--- a/src/h-system.h
+++ b/src/h-system.h
@@ -18,27 +18,18 @@
#include <ctype.h>
#include <errno.h>
-#if defined(NeXT)
-# include <libc.h>
-#else
-# include <stdlib.h>
-#endif
+#include <stdlib.h>
#ifdef SET_UID
# include <sys/types.h>
-# if defined(Pyramid) || defined(NeXT) || defined(SUNOS) || \
- defined(NCR3K) || defined(SUNOS) || defined(ibm032) || \
- defined(__osf__) || defined(ISC) || defined(SGI) || \
- defined(linux)
+# if defined(linux)
# include <sys/time.h>
# endif
-# if !defined(SGI) && !defined(ULTRIX)
# include <sys/timeb.h>
-# endif
#endif
@@ -47,35 +38,20 @@
-#ifdef MACINTOSH
-# include <unix.h>
-#endif
-
-#if defined(WINDOWS) || defined(MSDOS)
+#if defined(WINDOWS)
# include <io.h>
#endif
-#if !defined(MACINTOSH) && \
- !defined(__MWERKS__)
-# if defined(__TURBOC__) || defined(__WATCOMC__)
-# include <mem.h>
-# else
-# include <memory.h>
-# endif
-#endif
+#include <memory.h>
-#if !defined(NeXT) && !defined(__MWERKS__)
# include <fcntl.h>
-#endif
#ifdef SET_UID
-# ifndef USG
# include <sys/param.h>
# include <sys/file.h>
-# endif
# ifdef linux
# include <sys/file.h>
@@ -87,32 +63,12 @@
# include <sys/stat.h>
-# if defined(SOLARIS)
-# include <netdb.h>
-# endif
#endif
-#ifdef __DJGPP__
-#include <unistd.h>
-#endif /* __DJGPP__ */
-
#ifdef SET_UID
-#ifdef USG
-# include <string.h>
-#else
# include <strings.h>
-# ifndef strstr
-extern char *strstr();
-# endif
-# ifndef strchr
-extern char *strchr();
-# endif
-# ifndef strrchr
-extern char *strrchr();
-# endif
-#endif
#else
@@ -122,10 +78,6 @@ extern char *strrchr();
-#if !defined(linux) && !defined(__MWERKS__)
-extern long atol();
-#endif
-
#include <stdarg.h>
diff --git a/src/h-type.h b/src/h-type.h
index 5dbb4975..bcf013bb 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".
*
@@ -67,17 +72,11 @@ typedef int errr;
#define uint uint_hack
/*
- * Hack -- prevent problems with MSDOS and WINDOWS
+ * Hack -- prevent problems with WINDOWS
*/
#undef huge
#define huge huge_hack
-/*
- * Hack -- prevent problems with AMIGA
- */
-#undef byte
-#define byte byte_hack
-
/* Note that "signed char" is not always "defined" */
/* So always use "s16b" to hold small signed values */
/* A signed byte of memory */
@@ -109,14 +108,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
@@ -174,5 +179,9 @@ typedef vptr (*func_key)(vptr);
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
#endif
diff --git a/src/help.c b/src/help.c
deleted file mode 100644
index d0bdbedf..00000000
--- a/src/help.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/* 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
- *
- * 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"
-
-/*
- * Driver for the context-sensitive help system
- */
-void ingame_help(bool_ enable)
-{}
diff --git a/src/help.cc b/src/help.cc
new file mode 100644
index 00000000..08956f70
--- /dev/null
+++ b/src/help.cc
@@ -0,0 +1,705 @@
+/*
+ * 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
+ * included in all such copies.
+ */
+
+#include "help.hpp"
+
+#include "cave_type.hpp"
+#include "files.hpp"
+#include "hook_get_in.hpp"
+#include "hook_identify_in.hpp"
+#include "hook_move_in.hpp"
+#include "hooks.hpp"
+#include "object1.hpp"
+#include "object_flag.hpp"
+#include "options.hpp"
+#include "player_type.hpp"
+#include "skills.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+
+#define DESC_MAX 14
+#define TRIGGERED_HELP_MAX 16
+
+#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_ROD 5
+#define HELP_GET_ROD_TIP 6
+#define HELP_GET_DEVICE 7
+#define HELP_WILDERNESS 8
+#define HELP_GAME_TOME 9
+#define HELP_GAME_THEME 10
+#define HELP_1ST_LEVEL 11
+#define HELP_20TH_LEVEL 12
+#define HELP_ID_SPELL_ITM 13
+#define HELP_MELEE_SKILLS 14
+#define HELP_MON_ASK_HELP 15
+
+/**
+ * Game started?
+ */
+static bool_ game_started = FALSE;
+
+/**
+ * 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];
+};
+
+/**
+ * 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 },
+};
+
+/**
+ * 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 },
+};
+
+/**
+ * Class help files
+ */
+context_help_type class_table[] =
+{
+ /* ToME */
+ { "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 },
+ { "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 },
+ { "Wainrider", "c_wainrid.txt", 0 },
+ { "War-mage", "c_warmage.txt", 0 },
+ /* End of list */
+ { 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 },
+};
+
+/**
+ * Skill help files
+ */
+context_help_type skill_table[] =
+{
+ { "Air", "skills.txt", 27 },
+ { "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 },
+ { "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 },
+};
+
+/**
+ * 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 },
+ { "Far reaching attack", "ability.txt", 10 },
+ { "Undead Form", "ability.txt", 12 },
+ { NULL, NULL, 0 },
+};
+
+/**
+ * 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;
+}
+
+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;
+}
+
+static bool_ trigger_found_object(void *in, void *out) {
+ hook_move_in *p = (hook_move_in *) in;
+ return !cave[p->y][p->x].o_idxs.empty();
+}
+
+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));
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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));
+}
+
+static bool_ trigger_end_turn_wilderness(void *in, void *out) {
+ return (((p_ptr->wilderness_x != 34) ||
+ (p_ptr->wilderness_y != 21)) &&
+ (!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);
+}
+
+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);
+}
+
+static bool_ trigger_identify_spell_item(void *in_, void *out) {
+ hook_identify_in *in = (hook_identify_in *) in_;
+
+ if (in->mode == IDENT_FULL)
+ {
+ auto const f = object_flags(in->o_ptr);
+ if (f & TR_SPELL_CONTAIN)
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+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
+ */
+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 }
+ },
+ { 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 }
+ },
+ { 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 }
+ },
+ { 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 }
+ },
+ { 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 }
+ },
+ { 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
+ }
+ },
+ { 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
+ }
+ },
+ { 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
+ }
+ },
+ { 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
+ }
+ },
+ { 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
+ }
+ },
+ { 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
+ }
+ },
+ { 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
+ }
+ },
+ { 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
+ }
+ },
+ { 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
+ }
+ }
+};
+
+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 (options->ingame_help &&
+ (!p_ptr->help.activated[triggered_help->help_index]) &&
+ triggered_help->trigger_func(in,out))
+ {
+ /* Triggered */
+ p_ptr->help.activated[triggered_help->help_index] = true;
+
+ /* Show the description */
+ for (std::size_t 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 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;
+ 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);
+ }
+
+ add_hook_new(HOOK_GAME_START,
+ hook_game_start,
+ "help_game_start",
+ NULL);
+}
+
+/*
+ * Driver for the context-sensitive help system
+ */
+void init_hooks_help()
+{
+ setup_triggered_help_hooks();
+}
+
+/*
+ * Show help file
+ */
+static void show_context_help(context_help_type *context_help)
+{
+ if (context_help == NULL)
+ {
+ return;
+ }
+
+ screen_save();
+
+ show_file(context_help->file_name, 0, -context_help->anchor);
+
+ 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(std::string const &race)
+{
+ show_context_help(find_context_help(race_table, race.c_str()));
+}
+
+void help_subrace(std::string const &subrace)
+{
+ show_context_help(find_context_help(subrace_table, subrace.c_str()));
+}
+
+void help_class(std::string const &klass)
+{
+ show_context_help(find_context_help(class_table, klass.c_str()));
+}
+
+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);
+ }
+}
+
+void help_skill(const std::string &skill)
+{
+ show_context_help(find_context_help(skill_table, skill.c_str()));
+}
+
+void help_ability(std::string const &ability)
+{
+ show_context_help(find_context_help(ability_table, ability.c_str()));
+}
diff --git a/src/help.hpp b/src/help.hpp
new file mode 100644
index 00000000..a805a62b
--- /dev/null
+++ b/src/help.hpp
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "h-basic.h"
+
+#include <string>
+
+void init_hooks_help();
+void help_race(std::string const &race);
+void help_subrace(std::string const &subrace);
+void help_class(std::string const &klass);
+void help_god(cptr god);
+void help_skill(std::string const &skill);
+void help_ability(std::string const &ability);
diff --git a/src/help_info.hpp b/src/help_info.hpp
new file mode 100644
index 00000000..1b4a3757
--- /dev/null
+++ b/src/help_info.hpp
@@ -0,0 +1,17 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * Maximum number of help items.
+ */
+constexpr int HELP_MAX = 64;
+
+/**
+ * Context help runtime data.
+ */
+struct help_info
+{
+ bool enabled = false; /* ingame help enabled */
+ bool activated[HELP_MAX] = { false }; /* help item #i activated? */
+};
diff --git a/src/hiscore.cc b/src/hiscore.cc
new file mode 100644
index 00000000..971b84cd
--- /dev/null
+++ b/src/hiscore.cc
@@ -0,0 +1,85 @@
+#include "hiscore.hpp"
+
+#include "util.hpp"
+
+#include <cassert>
+
+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.hpp b/src/hiscore.hpp
new file mode 100644
index 00000000..990c91aa
--- /dev/null
+++ b/src/hiscore.hpp
@@ -0,0 +1,82 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * Maximum number of high scores in the high score file
+ */
+constexpr int MAX_HISCORES = 100;
+
+/*
+ * 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 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 unused_2[4]; /* Kept for compatibility only */
+ char unused_3[4]; /* Kept for compatibility only */
+ char inside_quest[4]; /* Did the player die in a quest? */
+ char unused_4[4]; /* Kept for compatibility only */
+
+ 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);
diff --git a/src/hook_build_room1_in.hpp b/src/hook_build_room1_in.hpp
new file mode 100644
index 00000000..e9a5d367
--- /dev/null
+++ b/src/hook_build_room1_in.hpp
@@ -0,0 +1,8 @@
+#pragma once
+
+#include "h-basic.h"
+
+struct hook_build_room1_in {
+ s32b y;
+ s32b x;
+};
diff --git a/src/hook_calculate_hp_in.hpp b/src/hook_calculate_hp_in.hpp
new file mode 100644
index 00000000..924add45
--- /dev/null
+++ b/src/hook_calculate_hp_in.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "h-basic.h"
+
+struct hook_calculate_hp_in {
+ s32b mhp;
+};
diff --git a/src/hook_calculate_hp_out.hpp b/src/hook_calculate_hp_out.hpp
new file mode 100644
index 00000000..7923997f
--- /dev/null
+++ b/src/hook_calculate_hp_out.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "h-basic.h"
+
+struct hook_calculate_hp_out {
+ s32b mhp;
+};
diff --git a/src/hook_chardump_in.hpp b/src/hook_chardump_in.hpp
new file mode 100644
index 00000000..c8edea62
--- /dev/null
+++ b/src/hook_chardump_in.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "h-basic.h"
+
+struct hook_chardump_in {
+ FILE *file;
+};
diff --git a/src/hook_chat_in.hpp b/src/hook_chat_in.hpp
new file mode 100644
index 00000000..5062b0e6
--- /dev/null
+++ b/src/hook_chat_in.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "h-basic.h"
+
+struct hook_chat_in {
+ s32b m_idx;
+};
diff --git a/src/hook_drop_in.hpp b/src/hook_drop_in.hpp
new file mode 100644
index 00000000..acaa10ff
--- /dev/null
+++ b/src/hook_drop_in.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+struct hook_drop_in {
+ int o_idx;
+};
diff --git a/src/hook_eat_in.hpp b/src/hook_eat_in.hpp
new file mode 100644
index 00000000..075bb2bf
--- /dev/null
+++ b/src/hook_eat_in.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "object_type_fwd.hpp"
+
+struct hook_eat_in {
+ object_type *o_ptr;
+};
diff --git a/src/hook_eat_out.hpp b/src/hook_eat_out.hpp
new file mode 100644
index 00000000..70bb92a4
--- /dev/null
+++ b/src/hook_eat_out.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "h-basic.h"
+
+struct hook_eat_out {
+ bool_ ident;
+};
diff --git a/src/hook_enter_dungeon_in.hpp b/src/hook_enter_dungeon_in.hpp
new file mode 100644
index 00000000..2f667c78
--- /dev/null
+++ b/src/hook_enter_dungeon_in.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "h-basic.h"
+
+struct hook_enter_dungeon_in {
+ s32b d_idx;
+};
diff --git a/src/hook_get_in.hpp b/src/hook_get_in.hpp
new file mode 100644
index 00000000..9bc4b795
--- /dev/null
+++ b/src/hook_get_in.hpp
@@ -0,0 +1,8 @@
+#pragma once
+
+#include "object_type_fwd.hpp"
+
+struct hook_get_in {
+ object_type *o_ptr;
+ int o_idx;
+};
diff --git a/src/hook_give_in.hpp b/src/hook_give_in.hpp
new file mode 100644
index 00000000..0ef5a11d
--- /dev/null
+++ b/src/hook_give_in.hpp
@@ -0,0 +1,6 @@
+#pragma once
+
+struct hook_give_in {
+ int m_idx;
+ int item;
+};
diff --git a/src/hook_identify_in.hpp b/src/hook_identify_in.hpp
new file mode 100644
index 00000000..40a8fc79
--- /dev/null
+++ b/src/hook_identify_in.hpp
@@ -0,0 +1,9 @@
+#pragma once
+
+#include "object_type_fwd.hpp"
+#include "identify_mode.hpp"
+
+struct hook_identify_in {
+ object_type *o_ptr;
+ identify_mode mode;
+};
diff --git a/src/hook_init_quest_in.hpp b/src/hook_init_quest_in.hpp
new file mode 100644
index 00000000..5d4b274a
--- /dev/null
+++ b/src/hook_init_quest_in.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+struct hook_init_quest_in {
+ int q_idx;
+};
diff --git a/src/hook_mon_speak_in.hpp b/src/hook_mon_speak_in.hpp
new file mode 100644
index 00000000..f3a14338
--- /dev/null
+++ b/src/hook_mon_speak_in.hpp
@@ -0,0 +1,8 @@
+#pragma once
+
+#include "h-basic.h"
+
+struct hook_mon_speak_in {
+ s32b m_idx;
+ cptr m_name;
+};
diff --git a/src/hook_monster_ai_in.hpp b/src/hook_monster_ai_in.hpp
new file mode 100644
index 00000000..492006aa
--- /dev/null
+++ b/src/hook_monster_ai_in.hpp
@@ -0,0 +1,9 @@
+#pragma once
+
+#include "h-basic.h"
+#include "monster_type_fwd.hpp"
+
+struct hook_monster_ai_in {
+ s32b m_idx;
+ monster_type *m_ptr;
+};
diff --git a/src/hook_monster_ai_out.hpp b/src/hook_monster_ai_out.hpp
new file mode 100644
index 00000000..4c5ef28f
--- /dev/null
+++ b/src/hook_monster_ai_out.hpp
@@ -0,0 +1,8 @@
+#pragma once
+
+#include "h-basic.h"
+
+struct hook_monster_ai_out {
+ s32b y;
+ s32b x;
+};
diff --git a/src/hook_monster_death_in.hpp b/src/hook_monster_death_in.hpp
new file mode 100644
index 00000000..354c37d2
--- /dev/null
+++ b/src/hook_monster_death_in.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "h-basic.h"
+
+struct hook_monster_death_in {
+ s32b m_idx;
+};
diff --git a/src/hook_move_in.hpp b/src/hook_move_in.hpp
new file mode 100644
index 00000000..6e299e5b
--- /dev/null
+++ b/src/hook_move_in.hpp
@@ -0,0 +1,6 @@
+#pragma once
+
+struct hook_move_in {
+ int y;
+ int x;
+};
diff --git a/src/hook_new_monster_end_in.hpp b/src/hook_new_monster_end_in.hpp
new file mode 100644
index 00000000..3c5f835b
--- /dev/null
+++ b/src/hook_new_monster_end_in.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "monster_type_fwd.hpp"
+
+struct hook_new_monster_end_in {
+ monster_type *m_ptr;
+};
diff --git a/src/hook_new_monster_in.hpp b/src/hook_new_monster_in.hpp
new file mode 100644
index 00000000..10b0420c
--- /dev/null
+++ b/src/hook_new_monster_in.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "h-basic.h"
+
+struct hook_new_monster_in {
+ s32b r_idx;
+};
diff --git a/src/hook_player_level_in.hpp b/src/hook_player_level_in.hpp
new file mode 100644
index 00000000..90804e27
--- /dev/null
+++ b/src/hook_player_level_in.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+struct hook_player_level_in {
+ int gained_levels;
+};
diff --git a/src/hook_quest_fail_in.hpp b/src/hook_quest_fail_in.hpp
new file mode 100644
index 00000000..2edf86a3
--- /dev/null
+++ b/src/hook_quest_fail_in.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "h-basic.h"
+
+struct hook_quest_fail_in {
+ s16b q_idx;
+};
diff --git a/src/hook_quest_finish_in.hpp b/src/hook_quest_finish_in.hpp
new file mode 100644
index 00000000..55490be4
--- /dev/null
+++ b/src/hook_quest_finish_in.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "h-basic.h"
+
+struct hook_quest_finish_in {
+ s32b q_idx;
+};
diff --git a/src/hook_stair_in.hpp b/src/hook_stair_in.hpp
new file mode 100644
index 00000000..884a187c
--- /dev/null
+++ b/src/hook_stair_in.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "stairs_direction.hpp"
+
+struct hook_stair_in {
+ stairs_direction direction;
+};
diff --git a/src/hook_stair_out.hpp b/src/hook_stair_out.hpp
new file mode 100644
index 00000000..5e3d515a
--- /dev/null
+++ b/src/hook_stair_out.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "h-basic.h"
+
+struct hook_stair_out {
+ bool_ allow;
+};
diff --git a/src/hook_wield_in.hpp b/src/hook_wield_in.hpp
new file mode 100644
index 00000000..036e62da
--- /dev/null
+++ b/src/hook_wield_in.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "object_type_fwd.hpp"
+
+struct hook_wield_in {
+ object_type *o_ptr;
+};
diff --git a/src/hook_wild_gen_in.hpp b/src/hook_wild_gen_in.hpp
new file mode 100644
index 00000000..147a74db
--- /dev/null
+++ b/src/hook_wild_gen_in.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "h-basic.h"
+
+struct hook_wild_gen_in {
+ bool_ small;
+};
diff --git a/src/hooks.cc b/src/hooks.cc
new file mode 100644
index 00000000..bd2ea905
--- /dev/null
+++ b/src/hooks.cc
@@ -0,0 +1,113 @@
+/*
+ * 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.hpp"
+
+#include <algorithm>
+#include <assert.h>
+#include <unordered_map>
+#include <vector>
+
+/******** Hooks stuff *********/
+
+struct hook_data
+{
+private:
+ hook_func_t m_hook_func;
+ void *m_hook_data;
+public:
+ hook_data(hook_func_t hook_func, void *hook_data)
+ : m_hook_func(hook_func)
+ , m_hook_data(hook_data) {
+ }
+
+ hook_data() = delete;
+
+ /**
+ * Check if the given hook points to the given function.
+ */
+ bool is(hook_func_t hook_func) const {
+ return m_hook_func == hook_func;
+ }
+
+ /**
+ * Invoke the hook with the given input and output pointers.
+ */
+ bool_ invoke(void *in, void *out) const {
+ return m_hook_func(m_hook_data, in, out);
+ }
+};
+
+std::unordered_map<size_t, std::vector<hook_data>> &hooks_instance()
+{
+ static auto instance = new std::unordered_map<size_t, std::vector<hook_data>>();
+ return *instance;
+}
+
+
+int process_hooks_restart = FALSE;
+
+static std::vector<hook_data>::iterator find_hook(std::vector<hook_data> &hooks, hook_func_t hook_func)
+{
+ return std::find_if(hooks.begin(),
+ hooks.end(),
+ [&](const hook_data &hook_data) {
+ return hook_data.is(hook_func);
+ });
+}
+
+void add_hook_new(int h_idx, hook_func_t hook_func, cptr name, void *data)
+{
+ auto &hooks = hooks_instance()[h_idx];
+ // Only insert if not already present.
+ if (find_hook(hooks, hook_func) == hooks.end()) {
+ hooks.emplace_back(hook_func, data);
+ }
+}
+
+void del_hook_new(int h_idx, hook_func_t hook_func)
+{
+ auto &hooks = hooks_instance()[h_idx];
+
+ /* Find it */
+ auto found_it = find_hook(hooks, hook_func);
+ if (found_it != hooks.end())
+ {
+ hooks.erase(found_it);
+ }
+}
+
+bool process_hooks_new(int h_idx, void *in, void *out)
+{
+ auto const &hooks = hooks_instance()[h_idx];
+
+ auto hooks_it = hooks.begin();
+ while (hooks_it != hooks.end())
+ {
+ auto &hook_data = *hooks_it;
+
+ /* Invoke hook function; stop processing if the hook
+ returns TRUE */
+ if (hook_data.invoke(in, out))
+ {
+ return true;
+ }
+
+ /* Should we restart processing at the beginning? */
+ if (process_hooks_restart)
+ {
+ hooks_it = hooks.begin();
+ process_hooks_restart = FALSE;
+ }
+ else
+ {
+ hooks_it++;
+ }
+ }
+
+ return false;
+}
diff --git a/src/hooks.hpp b/src/hooks.hpp
new file mode 100644
index 00000000..7cf4285b
--- /dev/null
+++ b/src/hooks.hpp
@@ -0,0 +1,10 @@
+#pragma once
+
+#include "h-basic.h"
+
+typedef bool (*hook_func_t)(void *, void *, void *);
+
+void add_hook_new(int h_idx, hook_func_t hook_func, cptr name, void *data);
+void del_hook_new(int h_idx, hook_func_t hook_func);
+extern int process_hooks_restart;
+bool process_hooks_new(int h_idx, void *in, void *out);
diff --git a/src/identify_mode.hpp b/src/identify_mode.hpp
new file mode 100644
index 00000000..687a1fae
--- /dev/null
+++ b/src/identify_mode.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+typedef enum { IDENT_NORMAL, IDENT_FULL } identify_mode;
diff --git a/src/include/tome/enum_string_map.hpp b/src/include/tome/enum_string_map.hpp
new file mode 100644
index 00000000..814827fe
--- /dev/null
+++ b/src/include/tome/enum_string_map.hpp
@@ -0,0 +1,55 @@
+#pragma once
+
+#include <boost/bimap.hpp>
+#include <boost/noncopyable.hpp>
+#include <string>
+#include <cassert>
+
+/**
+ * Bidirectional mapping between enumerated values
+ * and strings.
+ */
+template <class E>
+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<E, const char *> > 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) const {
+ 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) const {
+ E e;
+ bool result = parse(s, &e);
+ assert(result && "Missing string->enum mapping");
+ return e;
+ }
+
+ bool parse(const char *s, E *e) const {
+ auto i = bimap.right.find(s);
+ if (i == bimap.right.end())
+ {
+ return false;
+ }
+
+ *e = i->second;
+ return true;
+ }
+};
diff --git a/src/include/tome/make_array.hpp b/src/include/tome/make_array.hpp
new file mode 100644
index 00000000..23cb8ac0
--- /dev/null
+++ b/src/include/tome/make_array.hpp
@@ -0,0 +1,13 @@
+#pragma once
+
+#include <type_traits>
+
+/*
+ * Make an array of a POD type.
+ */
+template <typename T> T *make_array(std::size_t n) {
+ static_assert(std::is_pod<T>::value, "Type parameter must be POD type");
+ T *array = new T[n];
+ memset(array, 0, n*sizeof(T));
+ return array;
+}
diff --git a/src/include/tome/pp/global_constexpr.hpp b/src/include/tome/pp/global_constexpr.hpp
new file mode 100644
index 00000000..83168c59
--- /dev/null
+++ b/src/include/tome/pp/global_constexpr.hpp
@@ -0,0 +1,21 @@
+#pragma once
+
+/**
+ * Macro for declaring a global constexpr variable without
+ * violating the ODR and without running into the SIOF.
+ *
+ * Shamelessly cribbed from http://stackoverflow.com/a/20374473
+ */
+#define PP_GLOBAL_CONSTEXPR_CONST(type, var, value) \
+namespace global_constexpr { namespace var { \
+template<class = void> \
+struct wrapper \
+{ \
+ static constexpr type var = value; \
+}; \
+template<class T> \
+constexpr type wrapper<T>::var; \
+} } \
+namespace { \
+auto const& var = global_constexpr::var::wrapper<>::var; \
+}
diff --git a/src/include/tome/squelch/automatizer.hpp b/src/include/tome/squelch/automatizer.hpp
new file mode 100644
index 00000000..833b5648
--- /dev/null
+++ b/src/include/tome/squelch/automatizer.hpp
@@ -0,0 +1,154 @@
+#pragma once
+
+#include <boost/noncopyable.hpp>
+#include <memory>
+#include <jsoncons/json.hpp>
+#include <vector>
+
+#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 "../object_type_fwd.hpp"
+
+namespace squelch {
+
+/**
+ * Automatizer
+ */
+class Automatizer : public boost::noncopyable
+{
+public:
+ Automatizer(std::shared_ptr<TreePrinter> tree_printer,
+ std::shared_ptr<Cursor> 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> 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 document to represent all the rules.
+ */
+ jsoncons::json to_json() const;
+
+ /**
+ * Load rules from a JSON document.
+ */
+ void load_json(jsoncons::json const &);
+
+ /**
+ * 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<std::shared_ptr<Condition> ()> factory);
+
+ /**
+ * Get rule names.
+ */
+ std::vector<std::string> get_rule_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<Rule> current_rule();
+
+private:
+ int m_selected_rule;
+ int m_begin;
+ std::shared_ptr<TreePrinter> m_tree_printer;
+ std::shared_ptr<Cursor> m_cursor;
+ std::vector < std::shared_ptr < Rule > > m_rules;
+};
+
+} // namespace
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..584ecb0e
--- /dev/null
+++ b/src/include/tome/squelch/condition.hpp
@@ -0,0 +1,632 @@
+#pragma once
+
+#include "tome/squelch/condition_fwd.hpp"
+
+#include <boost/noncopyable.hpp>
+#include <cstdint>
+#include <functional>
+#include <memory>
+#include <jsoncons/json.hpp>
+
+#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 "../object_type_fwd.hpp"
+
+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_type> &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> &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:
+ jsoncons::json 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<Condition> first_child() {
+ // No children.
+ return nullptr;
+ }
+
+ virtual std::shared_ptr<Condition> previous_child(Condition *) {
+ // Default no children, so no predecessor.
+ return nullptr;
+ }
+
+ virtual std::shared_ptr<Condition> next_child(Condition *) {
+ // Default no children, so no successor.
+ return nullptr;
+ }
+
+ /**
+ * Parse condition from JSON
+ */
+ static std::shared_ptr<Condition> parse_condition(jsoncons::json const &);
+
+ /**
+ * Convert an (optional) condition to JSON.
+ */
+ static jsoncons::json optional_to_json(std::shared_ptr<Condition> condition);
+
+protected:
+ virtual void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const = 0;
+ virtual void to_json(jsoncons::json &) 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<Condition> from_json(jsoncons::json const &);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(jsoncons::json &) 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<Condition> from_json(jsoncons::json const &);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(jsoncons::json &) 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<Condition> from_json(jsoncons::json const &);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(jsoncons::json &) 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<Condition> from_json(jsoncons::json const &);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(jsoncons::json &) 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<Condition> > conditions = std::vector< std::shared_ptr<Condition> >())
+ : Condition(match)
+ , m_conditions(conditions) {
+ }
+
+ virtual void add_condition(std::shared_ptr<Condition> 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<Condition> first_child() override;
+ virtual std::shared_ptr<Condition> previous_child(Condition *) override;
+ virtual std::shared_ptr<Condition> next_child(Condition *current) override;
+
+ // Parse a list of conditions from JSON property
+ static std::vector< std::shared_ptr<Condition> > parse_conditions(jsoncons::json const &);
+
+protected:
+ void to_json(jsoncons::json &) const override;
+
+protected:
+ std::vector< std::shared_ptr<Condition> > 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<Condition> from_json(jsoncons::json const &);
+
+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<Condition> from_json(jsoncons::json const &);
+
+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<Condition> from_json(jsoncons::json const &);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(jsoncons::json &) 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<Condition> from_json(jsoncons::json const &);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(jsoncons::json &) 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<Condition> from_json(jsoncons::json const &);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(jsoncons::json &) 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<Condition> from_json(jsoncons::json const &);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(jsoncons::json &) 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<Condition> from_json(jsoncons::json const &);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(jsoncons::json &) 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<Condition> from_json(jsoncons::json const &);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(jsoncons::json &) 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<Condition> from_json(jsoncons::json const &);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(jsoncons::json &) 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<Condition> from_json(jsoncons::json const &);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(jsoncons::json &) 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<Condition> from_json(jsoncons::json const &);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(jsoncons::json &) 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<Condition> from_json(jsoncons::json const &);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(jsoncons::json &) 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<Condition> from_json(jsoncons::json const &);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(jsoncons::json &) 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<Condition> subcondition)
+ : Condition(match)
+ , m_subcondition(subcondition) {
+ }
+
+ virtual void add_child(std::function< std::shared_ptr<Condition> () > const &factory) override;
+
+ virtual void remove_child(Condition *c) override;
+
+ virtual std::shared_ptr<Condition> first_child() override;
+
+protected:
+ void to_json(jsoncons::json &) const override;
+
+ static std::shared_ptr<Condition> parse_single_subcondition(
+ jsoncons::json const &condition_json);
+
+protected:
+ std::shared_ptr<Condition> m_subcondition;
+};
+
+/**
+ * Condition which negates another condition
+ */
+class NotCondition : public SingleSubconditionCondition
+{
+public:
+ NotCondition(std::shared_ptr<Condition> subcondition = nullptr)
+ : SingleSubconditionCondition(match_type::NOT, subcondition) {
+ }
+
+ bool is_match(object_type *) const override;
+
+ static std::shared_ptr<Condition> from_json(jsoncons::json const &);
+
+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<Condition> subcondition = nullptr)
+ : SingleSubconditionCondition(match_type::INVENTORY, subcondition) {
+ }
+
+ bool is_match(object_type *) const override;
+
+ static std::shared_ptr<Condition> from_json(jsoncons::json const &);
+
+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<Condition> subcondition = nullptr)
+ : SingleSubconditionCondition(match_type::EQUIPMENT, subcondition) {
+ }
+
+ bool is_match(object_type *) const override;
+
+ static std::shared_ptr<Condition> from_json(jsoncons::json const &);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+};
+
+} // namespace
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 <functional>
+#include <memory>
+
+namespace squelch {
+
+enum class match_type : int;
+class Condition;
+typedef std::function< std::shared_ptr<Condition> () > 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<Condition> 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 <memory>
+
+namespace squelch {
+
+std::shared_ptr<Condition> 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 <boost/noncopyable.hpp>
+#include <deque>
+
+#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<Condition *> 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_type> &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..361ea2fe
--- /dev/null
+++ b/src/include/tome/squelch/object_status_fwd.hpp
@@ -0,0 +1,12 @@
+#pragma once
+
+#include "../object_type_fwd.hpp"
+#include "tome/enum_string_map.hpp"
+
+namespace squelch {
+
+enum class status_type;
+EnumStringMap<status_type> &status_mapping();
+status_type object_status(object_type *o_ptr);
+
+} // namespace
diff --git a/src/include/tome/squelch/rule.hpp b/src/include/tome/squelch/rule.hpp
new file mode 100644
index 00000000..af86dfc8
--- /dev/null
+++ b/src/include/tome/squelch/rule.hpp
@@ -0,0 +1,162 @@
+#pragma once
+
+#include <memory>
+#include <jsoncons/json.hpp>
+
+#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 "../object_type_fwd.hpp"
+
+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_type> &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> 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 std::string &new_name);
+
+ /**
+ * Get the name of the rule
+ */
+ std::string get_name() const;
+
+ /**
+ * Get condition
+ */
+ std::shared_ptr<Condition> 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 jsoncons::json to_json() const;
+
+ /**
+ * Parse rule from JSON
+ */
+ static std::shared_ptr<Rule> parse_rule(jsoncons::json const &);
+
+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<Condition> m_condition;
+};
+
+/**
+ * Rule for destroying matching objects
+ */
+class DestroyRule : public Rule
+{
+public:
+ DestroyRule(std::string name,
+ int module_idx,
+ std::shared_ptr<Condition> 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> 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> condition,
+ std::string inscription)
+ : Rule(name, action_type::AUTO_INSCRIBE, module_idx, condition)
+ , m_inscription(inscription) {
+ }
+
+ jsoncons::json to_json() const override;
+
+protected:
+ virtual void do_write_tree(TreePrinter *p) const override;
+ virtual bool do_apply_rule(object_type *o_ptr, int) const override;
+
+private:
+ // Inscription to use for inscription rules.
+ std::string m_inscription;
+};
+
+} // namespace
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_type> &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..c9e79af2
--- /dev/null
+++ b/src/include/tome/squelch/tree_printer.hpp
@@ -0,0 +1,51 @@
+#ifndef H_3d6cc652_c674_4a84_911d_e8ec35cc992a
+#define H_3d6cc652_c674_4a84_911d_e8ec35cc992a
+
+#include <boost/noncopyable.hpp>
+#include <cstdint>
+#include <string>
+
+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 *);
+ void write(uint8_t color, std::string const &);
+
+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/init1.c b/src/init1.c
deleted file mode 100644
index 9715831d..00000000
--- a/src/init1.c
+++ /dev/null
@@ -1,11819 +0,0 @@
-/* File: init1.c */
-
-/* Purpose: Initialization (part 1) -BEN- */
-
-#include "angband.h"
-
-
-/*
- * This file is used to initialize various variables and arrays for the
- * Angband game. Note the use of "fd_read()" and "fd_write()" to bypass
- * the common limitation of "read()" and "write()" to only 32767 bytes
- * at a time.
- *
- * Several of the arrays for Angband are built from "template" files in
- * the "lib/file" directory, from which quick-load binary "image" files
- * are constructed whenever they are not present in the "lib/data"
- * directory, or if those files become obsolete, if we are allowed.
- *
- * Warning -- the "ascii" file parsers use a minor hack to collect the
- * name and text information in a single pass. Thus, the game will not
- * be able to load any template file with more than 20K of names or 60K
- * of text, even though technically, up to 64K should be legal.
- */
-
-
-/*** Helper arrays for parsing ascii template files ***/
-
-/*
- * Monster Blow Methods
- */
-static cptr r_info_blow_method[] =
-{
- "*",
- "HIT",
- "TOUCH",
- "PUNCH",
- "KICK",
- "CLAW",
- "BITE",
- "STING",
- "XXX1",
- "BUTT",
- "CRUSH",
- "ENGULF",
- "CHARGE",
- "CRAWL",
- "DROOL",
- "SPIT",
- "EXPLODE",
- "GAZE",
- "WAIL",
- "SPORE",
- "XXX4",
- "BEG",
- "INSULT",
- "MOAN",
- "SHOW",
- NULL
-};
-
-
-/*
- * Monster Blow Effects
- */
-static cptr r_info_blow_effect[] =
-{
- "*",
- "HURT",
- "POISON",
- "UN_BONUS",
- "UN_POWER",
- "EAT_GOLD",
- "EAT_ITEM",
- "EAT_FOOD",
- "EAT_LITE",
- "ACID",
- "ELEC",
- "FIRE",
- "COLD",
- "BLIND",
- "CONFUSE",
- "TERRIFY",
- "PARALYZE",
- "LOSE_STR",
- "LOSE_INT",
- "LOSE_WIS",
- "LOSE_DEX",
- "LOSE_CON",
- "LOSE_CHR",
- "LOSE_ALL",
- "SHATTER",
- "EXP_10",
- "EXP_20",
- "EXP_40",
- "EXP_80",
- "DISEASE",
- "TIME",
- "INSANITY",
- "HALLU",
- "PARASITE",
- "ABOMINATION",
- NULL
-};
-
-
-/*
- * Monster race flags
- */
-static cptr r_info_flags1[] =
-{
- "UNIQUE",
- "QUESTOR",
- "MALE",
- "FEMALE",
- "CHAR_CLEAR",
- "CHAR_MULTI",
- "ATTR_CLEAR",
- "ATTR_MULTI",
- "FORCE_DEPTH",
- "FORCE_MAXHP",
- "FORCE_SLEEP",
- "FORCE_EXTRA",
- "FRIEND",
- "FRIENDS",
- "ESCORT",
- "ESCORTS",
- "NEVER_BLOW",
- "NEVER_MOVE",
- "RAND_25",
- "RAND_50",
- "ONLY_GOLD",
- "ONLY_ITEM",
- "DROP_60",
- "DROP_90",
- "DROP_1D2",
- "DROP_2D2",
- "DROP_3D2",
- "DROP_4D2",
- "DROP_GOOD",
- "DROP_GREAT",
- "DROP_USEFUL",
- "DROP_CHOSEN"
-};
-
-/*
- * Monster race flags
- */
-static cptr r_info_flags2[] =
-{
- "STUPID",
- "SMART",
- "CAN_SPEAK",
- "REFLECTING",
- "INVISIBLE",
- "COLD_BLOOD",
- "EMPTY_MIND",
- "WEIRD_MIND",
- "DEATH_ORB",
- "REGENERATE",
- "SHAPECHANGER",
- "ATTR_ANY",
- "POWERFUL",
- "ELDRITCH_HORROR",
- "AURA_FIRE",
- "AURA_ELEC",
- "OPEN_DOOR",
- "BASH_DOOR",
- "PASS_WALL",
- "KILL_WALL",
- "MOVE_BODY",
- "KILL_BODY",
- "TAKE_ITEM",
- "KILL_ITEM",
- "BRAIN_1",
- "BRAIN_2",
- "BRAIN_3",
- "BRAIN_4",
- "BRAIN_5",
- "BRAIN_6",
- "BRAIN_7",
- "BRAIN_8"
-};
-
-/*
- * Monster race flags
- */
-static cptr r_info_flags3[] =
-{
- "ORC",
- "TROLL",
- "GIANT",
- "DRAGON",
- "DEMON",
- "UNDEAD",
- "EVIL",
- "ANIMAL",
- "THUNDERLORD",
- "GOOD",
- "AURA_COLD", /* TODO: Implement aura_cold */
- "NONLIVING",
- "HURT_LITE",
- "HURT_ROCK",
- "SUSCEP_FIRE",
- "SUSCEP_COLD",
- "IM_ACID",
- "IM_ELEC",
- "IM_FIRE",
- "IM_COLD",
- "IM_POIS",
- "RES_TELE",
- "RES_NETH",
- "RES_WATE",
- "RES_PLAS",
- "RES_NEXU",
- "RES_DISE",
- "UNIQUE_4",
- "NO_FEAR",
- "NO_STUN",
- "NO_CONF",
- "NO_SLEEP"
-};
-
-/*
- * Monster race flags
- */
-static cptr r_info_flags4[] =
-{
- "SHRIEK",
- "MULTIPLY",
- "S_ANIMAL",
- "ROCKET",
- "ARROW_1",
- "ARROW_2",
- "ARROW_3",
- "ARROW_4",
- "BR_ACID",
- "BR_ELEC",
- "BR_FIRE",
- "BR_COLD",
- "BR_POIS",
- "BR_NETH",
- "BR_LITE",
- "BR_DARK",
- "BR_CONF",
- "BR_SOUN",
- "BR_CHAO",
- "BR_DISE",
- "BR_NEXU",
- "BR_TIME",
- "BR_INER",
- "BR_GRAV",
- "BR_SHAR",
- "BR_PLAS",
- "BR_WALL",
- "BR_MANA",
- "BA_NUKE",
- "BR_NUKE",
- "BA_CHAO",
- "BR_DISI",
-};
-
-/*
- * Monster race flags
- */
-static cptr r_info_flags5[] =
-{
- "BA_ACID",
- "BA_ELEC",
- "BA_FIRE",
- "BA_COLD",
- "BA_POIS",
- "BA_NETH",
- "BA_WATE",
- "BA_MANA",
- "BA_DARK",
- "DRAIN_MANA",
- "MIND_BLAST",
- "BRAIN_SMASH",
- "CAUSE_1",
- "CAUSE_2",
- "CAUSE_3",
- "CAUSE_4",
- "BO_ACID",
- "BO_ELEC",
- "BO_FIRE",
- "BO_COLD",
- "BO_POIS",
- "BO_NETH",
- "BO_WATE",
- "BO_MANA",
- "BO_PLAS",
- "BO_ICEE",
- "MISSILE",
- "SCARE",
- "BLIND",
- "CONF",
- "SLOW",
- "HOLD"
-};
-
-/*
- * Monster race flags
- */
-static cptr r_info_flags6[] =
-{
- "HASTE",
- "HAND_DOOM",
- "HEAL",
- "S_ANIMALS",
- "BLINK",
- "TPORT",
- "TELE_TO",
- "TELE_AWAY",
- "TELE_LEVEL",
- "DARKNESS",
- "TRAPS",
- "FORGET",
- "ANIM_DEAD", /* ToDo: Implement ANIM_DEAD */
- "S_BUG",
- "S_RNG",
- "S_THUNDERLORD", /* DG : Summon Thunderlord */
- "S_KIN",
- "S_HI_DEMON",
- "S_MONSTER",
- "S_MONSTERS",
- "S_ANT",
- "S_SPIDER",
- "S_HOUND",
- "S_HYDRA",
- "S_ANGEL",
- "S_DEMON",
- "S_UNDEAD",
- "S_DRAGON",
- "S_HI_UNDEAD",
- "S_HI_DRAGON",
- "S_WRAITH",
- "S_UNIQUE"
-};
-
-
-/*
- * Monster race flags
- */
-static cptr r_info_flags7[] =
-{
- "AQUATIC",
- "CAN_SWIM",
- "CAN_FLY",
- "FRIENDLY",
- "PET",
- "MORTAL",
- "SPIDER",
- "NAZGUL",
- "DG_CURSE",
- "POSSESSOR",
- "NO_DEATH",
- "NO_TARGET",
- "AI_ANNOY",
- "AI_SPECIAL",
- "NEUTRAL",
- "DROP_ART",
- "DROP_RANDART",
- "AI_PLAYER",
- "NO_THEFT",
- "SPIRIT",
- "IM_MELEE",
- "XXX7X21",
- "XXX7X22",
- "XXX7X23",
- "XXX7X24",
- "XXX7X25",
- "XXX7X26",
- "XXX7X27",
- "XXX7X28",
- "XXX7X29",
- "XXX7X30",
- "XXX7X31",
-};
-
-/*
- * Monster race flags
- */
-static cptr r_info_flags8[] =
-{
- "WILD_ONLY",
- "WILD_TOWN",
- "XXX8X02",
- "WILD_SHORE",
- "WILD_OCEAN",
- "WILD_WASTE",
- "WILD_WOOD",
- "WILD_VOLCANO",
- "XXX8X08",
- "WILD_MOUNTAIN",
- "WILD_GRASS",
- "NO_CUT",
- "CTHANGBAND",
- "XXX8X13",
- "ZANGBAND",
- "JOKEANGBAND",
- "BASEANGBAND",
- "XXX8X17",
- "XXX8X18",
- "XXX8X19",
- "XXX8X20",
- "XXX8X21",
- "XXX8X22",
- "XXX8X23",
- "XXX8X24",
- "XXX8X25",
- "XXX8X26",
- "XXX8X27",
- "XXX8X28",
- "XXX8X29",
- "WILD_SWAMP", /* ToDo: Implement Swamp */
- "WILD_TOO",
-};
-
-
-/*
- * Monster race flags - Drops
- */
-static cptr r_info_flags9[] =
-{
- "DROP_CORPSE",
- "DROP_SKELETON",
- "HAS_LITE",
- "MIMIC",
- "HAS_EGG",
- "IMPRESED",
- "SUSCEP_ACID",
- "SUSCEP_ELEC",
- "SUSCEP_POIS",
- "KILL_TREES",
- "WYRM_PROTECT",
- "DOPPLEGANGER",
- "ONLY_DEPTH",
- "SPECIAL_GENE",
- "NEVER_GENE",
- "XXX9X15",
- "XXX9X16",
- "XXX9X17",
- "XXX9X18",
- "XXX9X19",
- "XXX9X20",
- "XXX9X21",
- "XXX9X22",
- "XXX9X23",
- "XXX9X24",
- "XXX9X25",
- "XXX9X26",
- "XXX9X27",
- "XXX9X28",
- "XXX9X29",
- "XXX9X30",
- "XXX9X31",
-};
-
-
-/*
- * Object flags
- */
-cptr k_info_flags1[] =
-{
- "STR",
- "INT",
- "WIS",
- "DEX",
- "CON",
- "CHR",
- "MANA",
- "SPELL",
- "STEALTH",
- "SEARCH",
- "INFRA",
- "TUNNEL",
- "SPEED",
- "BLOWS",
- "CHAOTIC",
- "VAMPIRIC",
- "SLAY_ANIMAL",
- "SLAY_EVIL",
- "SLAY_UNDEAD",
- "SLAY_DEMON",
- "SLAY_ORC",
- "SLAY_TROLL",
- "SLAY_GIANT",
- "SLAY_DRAGON",
- "KILL_DRAGON",
- "VORPAL",
- "IMPACT",
- "BRAND_POIS",
- "BRAND_ACID",
- "BRAND_ELEC",
- "BRAND_FIRE",
- "BRAND_COLD"
-};
-
-/*
- * Object flags
- */
-cptr k_info_flags2[] =
-{
- "SUST_STR",
- "SUST_INT",
- "SUST_WIS",
- "SUST_DEX",
- "SUST_CON",
- "SUST_CHR",
- "INVIS",
- "LIFE",
- "IM_ACID",
- "IM_ELEC",
- "IM_FIRE",
- "IM_COLD",
- "SENS_FIRE",
- "REFLECT",
- "FREE_ACT",
- "HOLD_LIFE",
- "RES_ACID",
- "RES_ELEC",
- "RES_FIRE",
- "RES_COLD",
- "RES_POIS",
- "RES_FEAR",
- "RES_LITE",
- "RES_DARK",
- "RES_BLIND",
- "RES_CONF",
- "RES_SOUND",
- "RES_SHARDS",
- "RES_NETHER",
- "RES_NEXUS",
- "RES_CHAOS",
- "RES_DISEN"
-};
-
-/*
- * Trap flags
- */
-cptr k_info_flags2_trap[] =
-{
- "AUTOMATIC_5",
- "AUTOMATIC_99",
- "KILL_GHOST",
- "TELEPORT_TO",
- "ONLY_DRAGON",
- "ONLY_DEMON",
- "XXX3",
- "XXX3",
- "ONLY_ANIMAL",
- "ONLY_UNDEAD",
- "ONLY_EVIL",
- "XXX3",
- "XXX3",
- "XXX3",
- "XXX3",
- "XXX3",
- "XXX3",
- "XXX3",
- "XXX3",
- "XXX3",
- "XXX3",
- "XXX3",
- "XXX3",
- "XXX3",
- "XXX3",
- "XXX3",
- "XXX3",
- "XXX3",
- "XXX3",
- "XXX3",
- "XXX3",
- "XXX3",
-};
-
-
-/*
- * Object flags
- */
-cptr k_info_flags3[] =
-{
- "SH_FIRE",
- "SH_ELEC",
- "AUTO_CURSE",
- "DECAY",
- "NO_TELE",
- "NO_MAGIC",
- "WRAITH",
- "TY_CURSE",
- "EASY_KNOW",
- "HIDE_TYPE",
- "SHOW_MODS",
- "INSTA_ART",
- "FEATHER",
- "LITE1",
- "SEE_INVIS",
- "NORM_ART",
- "SLOW_DIGEST",
- "REGEN",
- "XTRA_MIGHT",
- "XTRA_SHOTS",
- "IGNORE_ACID",
- "IGNORE_ELEC",
- "IGNORE_FIRE",
- "IGNORE_COLD",
- "ACTIVATE",
- "DRAIN_EXP",
- "TELEPORT",
- "AGGRAVATE",
- "BLESSED",
- "CURSED",
- "HEAVY_CURSE",
- "PERMA_CURSE"
-};
-
-/*
- * Object flags
- */
-cptr k_info_flags4[] =
-{
- "NEVER_BLOW",
- "PRECOGNITION",
- "BLACK_BREATH",
- "RECHARGE",
- "FLY",
- "DG_CURSE",
- "COULD2H",
- "MUST2H",
- "LEVELS",
- "CLONE",
- "SPECIAL_GENE",
- "CLIMB",
- "FAST_CAST",
- "CAPACITY",
- "CHARGING",
- "CHEAPNESS",
- "FOUNTAIN",
- "ANTIMAGIC_50",
- "ANTIMAGIC_30",
- "ANTIMAGIC_20",
- "ANTIMAGIC_10",
- "EASY_USE",
- "IM_NETHER",
- "RECHARGED",
- "ULTIMATE",
- "AUTO_ID",
- "LITE2",
- "LITE3",
- "FUEL_LITE",
- "ART_EXP",
- "CURSE_NO_DROP",
- "NO_RECHARGE"
-};
-
-/*
- * Object flags
- */
-cptr k_info_flags5[] =
-{
- "TEMPORARY",
- "DRAIN_MANA",
- "DRAIN_HP",
- "KILL_DEMON",
- "KILL_UNDEAD",
- "CRIT",
- "ATTR_MULTI",
- "WOUNDING",
- "FULL_NAME",
- "LUCK",
- "IMMOVABLE",
- "SPELL_CONTAIN",
- "RES_MORGUL",
- "ACTIVATE_NO_WIELD",
- "MAGIC_BREATH",
- "WATER_BREATH",
- "WIELD_CAST",
- "XXX8X17",
- "XXX8X18",
- "XXX8X19",
- "XXX8X20",
- "XXX8X21",
- "XXX8X22",
- "XXX8X23",
- "XXX8X24",
- "XXX8X25",
- "XXX8X26",
- "XXX8X27",
- "XXX8X28",
- "XXX8X29",
- "XXX8X02",
- "XXX8X22",
-};
-
-/*
- * ESP flags
- */
-cptr esp_flags[] =
-{
- "ESP_ORC",
- "ESP_TROLL",
- "ESP_DRAGON",
- "ESP_GIANT",
- "ESP_DEMON",
- "ESP_UNDEAD",
- "ESP_EVIL",
- "ESP_ANIMAL",
- "ESP_THUNDERLORD",
- "ESP_GOOD",
- "ESP_NONLIVING",
- "ESP_UNIQUE",
- "ESP_SPIDER",
- "XXX8X02",
- "XXX8X02",
- "XXX8X02",
- "XXX8X02",
- "XXX8X17",
- "XXX8X18",
- "XXX8X19",
- "XXX8X20",
- "XXX8X21",
- "XXX8X22",
- "XXX8X23",
- "XXX8X24",
- "XXX8X25",
- "XXX8X26",
- "XXX8X27",
- "XXX8X28",
- "XXX8X29",
- "XXX8X02",
- "ESP_ALL",
-};
-
-/* Specially handled properties for ego-items */
-
-static cptr ego_flags[] =
-{
- "SUSTAIN",
- "OLD_RESIST",
- "ABILITY",
- "R_ELEM",
- "R_LOW",
- "R_HIGH",
- "R_ANY",
- "R_DRAGON",
- "SLAY_WEAP",
- "DAM_DIE",
- "DAM_SIZE",
- "PVAL_M1",
- "PVAL_M2",
- "PVAL_M3",
- "PVAL_M5",
- "AC_M1",
- "AC_M2",
- "AC_M3",
- "AC_M5",
- "TH_M1",
- "TH_M2",
- "TH_M3",
- "TH_M5",
- "TD_M1",
- "TD_M2",
- "TD_M3",
- "TD_M5",
- "R_P_ABILITY",
- "R_STAT",
- "R_STAT_SUST",
- "R_IMMUNITY",
- "LIMIT_BLOWS"
-};
-
-/*
- * Feature flags
- */
-static cptr f_info_flags1[] =
-{
- "NO_WALK",
- "NO_VISION",
- "CAN_LEVITATE",
- "CAN_PASS",
- "FLOOR",
- "WALL",
- "PERMANENT",
- "CAN_FLY",
- "REMEMBER",
- "NOTICE",
- "DONT_NOTICE_RUNNING",
- "CAN_RUN",
- "DOOR",
- "SUPPORT_LIGHT",
- "CAN_CLIMB",
- "TUNNELABLE",
- "WEB",
- "ATTR_MULTI",
- "SUPPORT_GROWTH",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1"
-};
-
-/*
- * Dungeon flags
- */
-static cptr d_info_flags1[] =
-{
- "PRINCIPAL",
- "MAZE",
- "SMALLEST",
- "SMALL",
- "BIG",
- "NO_DOORS",
- "WATER_RIVER",
- "LAVA_RIVER",
- "WATER_RIVERS",
- "LAVA_RIVERS",
- "CAVE",
- "CAVERN",
- "NO_UP",
- "HOT",
- "COLD",
- "FORCE_DOWN",
- "FORGET",
- "NO_DESTROY",
- "SAND_VEIN",
- "CIRCULAR_ROOMS",
- "EMPTY",
- "DAMAGE_FEAT",
- "FLAT",
- "TOWER",
- "RANDOM_TOWNS",
- "DOUBLE",
- "LIFE_LEVEL",
- "EVOLVE",
- "ADJUST_LEVEL_1",
- "ADJUST_LEVEL_2",
- "NO_RECALL",
- "NO_STREAMERS"
-};
-
-static cptr d_info_flags2[] =
-{
- "ADJUST_LEVEL_1_2",
- "NO_SHAFT",
- "ADJUST_LEVEL_PLAYER",
- "NO_TELEPORT",
- "ASK_LEAVE",
- "NO_STAIR",
- "SPECIAL",
- "NO_NEW_MONSTER",
- "DESC",
- "NO_GENO",
- "NO_BREATH",
- "WATER_BREATH",
- "ELVEN",
- "DWARVEN",
- "NO_EASY_MOVE",
- "NO_RECALL_OUT",
- "DESC_ALWAYS",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1"
-};
-
-/*
- * Trap flags
- */
-static cptr t_info_flags[] =
-{
- "CHEST",
- "DOOR",
- "FLOOR",
- "XXX4",
- "XXX5",
- "XXX6",
- "XXX7",
- "XXX8",
- "XXX9",
- "XXX10",
- "XXX11",
- "XXX12",
- "XXX13",
- "XXX14",
- "XXX15",
- "XXX16",
- "LEVEL1",
- "LEVEL2",
- "LEVEL3",
- "LEVEL4",
- "XXX21",
- "XXX22",
- "XXX23",
- "XXX24",
- "XXX25",
- "XXX26",
- "XXX27",
- "XXX28",
- "XXX29",
- "XXX30",
- "XXX31",
- "XXX32"
-};
-
-/*
- * Wilderness feature flags
- */
-static cptr wf_info_flags1[] =
-{
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1"
-};
-
-/*
- * Stores flags
- */
-static cptr st_info_flags1[] =
-{
- "DEPEND_LEVEL",
- "SHALLOW_LEVEL",
- "MEDIUM_LEVEL",
- "DEEP_LEVEL",
- "RARE",
- "VERY_RARE",
- "COMMON",
- "ALL_ITEM",
- "RANDOM",
- "FORCE_LEVEL",
- "MUSEUM",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1"
-};
-
-/*
- * Race flags
- */
-cptr rp_info_flags1[] =
-{
- "EXPERIMENTAL",
- "XXX",
- "RESIST_BLACK_BREATH",
- "NO_STUN",
- "XTRA_MIGHT_BOW",
- "XTRA_MIGHT_XBOW",
- "XTRA_MIGHT_SLING",
- "AC_LEVEL",
- "HURT_LITE",
- "VAMPIRE",
- "UNDEAD",
- "NO_CUT",
- "CORRUPT",
- "NO_FOOD",
- "NO_GOD",
- "XXX",
- "ELF",
- "SEMI_WRAITH",
- "NO_SUBRACE_CHANGE",
- "XXX",
- "XXX",
- "MOLD_FRIEND",
- "GOD_FRIEND",
- "XXX",
- "INNATE_SPELLS",
- "XXX",
- "XXX",
- "EASE_STEAL",
- "XXX",
- "XXX",
- "XXX",
- "XXX"
-};
-
-/*
- * Race flags
- */
-cptr rp_info_flags2[] =
-{
- "XXX",
- "ASTRAL",
- "XXX",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1"
-};
-
-/* Skill flags */
-static cptr s_info_flags1[] =
-{
- "HIDDEN",
- "AUTO_HIDE",
- "RANDOM_GAIN",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1",
- "XXX1"
-};
-
-/*
- * Dungeon effect types (used in E:damage:frequency:type entry in d_info.txt)
- */
-static struct
-{
-cptr name;
-int feat;
-}
-d_info_dtypes[] =
-{
- {"ELEC", GF_ELEC},
- {"POISON", GF_POIS},
- {"ACID", GF_ACID},
- {"COLD", GF_COLD},
- {"FIRE", GF_FIRE},
- {"MISSILE", GF_MISSILE},
- {"ARROW", GF_ARROW},
- {"PLASMA", GF_PLASMA},
- {"WATER", GF_WATER},
- {"LITE", GF_LITE},
- {"DARK", GF_DARK},
- {"LITE_WEAK", GF_LITE_WEAK},
- {"LITE_DARK", GF_DARK_WEAK},
- {"SHARDS", GF_SHARDS},
- {"SOUND", GF_SOUND},
- {"CONFUSION", GF_CONFUSION},
- {"FORCE", GF_FORCE},
- {"INERTIA", GF_INERTIA},
- {"MANA", GF_MANA},
- {"METEOR", GF_METEOR},
- {"ICE", GF_ICE},
- {"CHAOS", GF_CHAOS},
- {"NETHER", GF_NETHER},
- {"DISENCHANT", GF_DISENCHANT},
- {"NEXUS", GF_NEXUS},
- {"TIME", GF_TIME},
- {"GRAVITY", GF_GRAVITY},
- {"ROCKET", GF_ROCKET},
- {"NUKE", GF_NUKE},
- {"HOLY_FIRE", GF_HOLY_FIRE},
- {"HELL_FIRE", GF_HELL_FIRE},
- {"DISINTEGRATE", GF_DISINTEGRATE},
- {"DESTRUCTION", GF_DESTRUCTION},
- {"RAISE", GF_RAISE},
- {NULL, 0}
-};
-
-/* Essence names for al_info.txt */
-static const char *essence_names[] =
-{
- "No name here", /* can't be matched, sscanf stops at spaces */
- "POISON",
- "EXPLOSION",
- "TELEPORT",
- "COLD",
- "FIRE",
- "ACID",
- "LIFE",
- "CONFUSION",
- "LITE",
- "CHAOS",
- "TIME",
- "MAGIC",
- "EXTRALIFE",
- "DARKNESS",
- "KNOWLEDGE",
- "FORCE",
- "LIGHTNING",
- "MANA",
- ""
-};
-static const char *activation_names[] =
-{
- "NO_ACTIVATION", /* 0*/
- "SUNLIGHT", /* 1*/
- "BO_MISS_1", /* 2*/
- "BA_POIS_1", /* 3*/
- "BO_ELEC_1", /* 4*/
- "BO_ACID_1", /* 5*/
- "BO_COLD_1", /* 6*/
- "BO_FIRE_1", /* 7*/
- "BA_COLD_1", /* 8*/
- "BA_FIRE_1", /* 9*/
- "DRAIN_1", /* 10*/
- "BA_COLD_2", /* 11*/
- "BA_ELEC_2", /* 12*/
- "DRAIN_2", /* 13*/
- "VAMPIRE_1", /* 14*/
- "BO_MISS_2", /* 15*/
- "BA_FIRE_2", /* 16*/
- "BA_COLD_3", /* 17*/
- "BA_ELEC_3", /* 18*/
- "WHIRLWIND", /* 19*/
- "VAMPIRE_2", /* 20*/
- "CALL_CHAOS", /* 21*/
- "ROCKET", /* 22*/
- "DISP_EVIL", /* 23*/
- "BA_MISS_3", /* 24*/
- "DISP_GOOD", /* 25*/
- "GILGALAD", /* 26*/
- "CELEBRIMBOR", /* 27*/
- "SKULLCLEAVER", /* 28*/
- "HARADRIM", /* 29*/
- "FUNDIN", /* 30*/
- "EOL", /* 31*/
- "UMBAR", /* 32*/
- "NUMENOR", /* 33*/
- "KNOWLEDGE", /* 34*/
- "UNDEATH", /* 35*/
- "THRAIN", /* 36*/
- "BARAHIR", /* 37*/
- "TULKAS", /* 38*/
- "NARYA", /* 39*/
- "NENYA", /* 40*/
- "VILYA", /* 41*/
- "POWER", /* 42*/
- "STONE_LORE", /* 43*/
- "RAZORBACK", /* 44*/
- "BLADETURNER", /* 45*/
- "MEDIATOR", /* 46*/
- "BELEGENNON", /* 47*/
- "GORLIM", /* 48*/
- "COLLUIN", /* 49*/
- "BELANGIL", /* 50*/
- "CONFUSE", /* 51*/
- "SLEEP", /* 52*/
- "QUAKE", /* 53*/
- "TERROR", /* 54*/
- "TELE_AWAY", /* 55*/
- "BANISH_EVIL", /* 56*/
- "GENOCIDE", /* 57*/
- "MASS_GENO", /* 58*/
- "ANGUIREL", /* 59*/
- "ERU", /* 60*/
- "DAWN", /* 61*/
- "FIRESTAR", /* 62*/
- "TURMIL", /* 63*/
- "CUBRAGOL", /* 64*/
- "CHARM_ANIMAL", /* 65*/
- "CHARM_UNDEAD", /* 66*/
- "CHARM_OTHER", /* 67*/
- "CHARM_ANIMALS", /* 68*/
- "CHARM_OTHERS", /* 69*/
- "SUMMON_ANIMAL", /* 70*/
- "SUMMON_PHANTOM", /* 71*/
- "SUMMON_ELEMENTAL", /* 72*/
- "SUMMON_DEMON", /* 73*/
- "SUMMON_UNDEAD", /* 74*/
- "ELESSAR", /* 75*/
- "GANDALF", /* 76*/
- "MARDA", /* 77*/
- "PALANTIR", /* 78*/
- "XXX79",
- "XXX80",
- "CURE_LW", /* 81*/
- "CURE_MW", /* 82*/
- "CURE_POISON", /* 83*/
- "REST_LIFE", /* 84*/
- "REST_ALL", /* 85*/
- "CURE_700", /* 86*/
- "CURE_1000", /* 87*/
- "XXX88",
- "EREBOR", /* 89*/
- "DRUEDAIN", /* 90*/
- "ESP", /* 91*/
- "BERSERK", /* 92*/
- "PROT_EVIL", /* 93*/
- "RESIST_ALL", /* 94*/
- "SPEED", /* 95*/
- "XTRA_SPEED", /* 96*/
- "WRAITH", /* 97*/
- "INVULN", /* 98*/
- "ROHAN", /* 99*/
- "HELM", /* 100*/
- "BOROMIR", /* 101*/
- "HURIN", /* 102*/
- "AXE_GOTHMOG", /* 103*/
- "MELKOR", /* 104*/
- "GROND", /* 105*/
- "NATUREBANE", /* 106*/
- "NIGHT", /* 107*/
- "ORCHAST", /* 108*/
- "XXX109",
- "XXX110",
- "LIGHT", /* 111*/
- "MAP_LIGHT", /* 112*/
- "DETECT_ALL", /* 113*/
- "DETECT_XTRA", /* 114*/
- "ID_FULL", /* 115*/
- "ID_PLAIN", /* 116*/
- "RUNE_EXPLO", /* 117*/
- "RUNE_PROT", /* 118*/
- "SATIATE", /* 119*/
- "DEST_DOOR", /* 120*/
- "STONE_MUD", /* 121*/
- "RECHARGE", /* 122*/
- "ALCHEMY", /* 123*/
- "DIM_DOOR", /* 124*/
- "TELEPORT", /* 125*/
- "RECALL", /* 126*/
- "DEATH", /* 127*/
- "RUINATION", /* 128*/
- "DESTRUC", /* 129*/
- "UNINT", /* 130*/
- "UNSTR", /* 131*/
- "UNCON", /* 132*/
- "UNCHR", /* 133*/
- "UNDEX", /* 134*/
- "UNWIS", /* 135*/
- "STATLOSS", /* 136*/
- "HISTATLOSS", /* 137*/
- "EXPLOSS", /* 138*/
- "HIEXPLOSS", /* 139*/
- "SUMMON_MONST", /* 140*/
- "PARALYZE", /* 141*/
- "HALLU", /* 142*/
- "POISON", /* 143*/
- "HUNGER", /* 144*/
- "STUN", /* 145*/
- "CUTS", /* 146*/
- "PARANO", /* 147*/
- "CONFUSION", /* 148*/
- "BLIND", /* 149*/
- "PET_SUMMON", /* 150*/
- "CURE_PARA", /* 151*/
- "CURE_HALLU", /* 152*/
- "CURE_POIS", /* 153*/
- "CURE_HUNGER", /* 154*/
- "CURE_STUN", /* 155*/
- "CURE_CUTS", /* 156*/
- "CURE_FEAR", /* 157*/
- "CURE_CONF", /* 158*/
- "CURE_BLIND", /* 159*/
- "CURING", /* 160*/
- "DARKNESS", /* 161*/
- "LEV_TELE", /* 162*/
- "ACQUIREMENT", /* 163*/
- "WEIRD", /* 164*/
- "AGGRAVATE", /* 165*/
- "MUT", /* 166*/
- "CURE_INSANITY", /* 167*/
- "CURE_MUT", /* 168*/
- "LIGHT_ABSORBTION", /* 169*/
- "BA_FIRE_H", /* 170*/
- "BA_COLD_H", /* 171*/
- "BA_ELEC_H", /* 172*/
- "BA_ACID_H", /* 173*/
- "SPIN", /* 174*/
- "NOLDOR", /* 175*/
- "SPECTRAL", /* 176*/
- "JUMP", /* 177*/
- "DEST_TELE", /* 178*/
- "BA_POIS_4", /* 179*/
- "BA_COLD_4", /* 180*/
- "BA_FIRE_4", /* 181*/
- "BA_ACID_4", /* 182*/
- "BA_ELEC_4", /* 183*/
- "BR_ELEC", /* 184*/
- "BR_COLD", /* 185*/
- "BR_FIRE", /* 186*/
- "BR_ACID", /* 187*/
- "BR_POIS", /* 188*/
- "BR_MANY", /* 189*/
- "BR_CONF", /* 190*/
- "BR_SOUND", /* 191*/
- "BR_CHAOS", /* 192*/
- "BR_SHARD", /* 193*/
- "BR_BALANCE", /* 194*/
- "BR_LIGHT", /* 195*/
- "BR_POWER", /* 196*/
- "GROW_MOLD", /* 197*/
- "XXX198",
- "XXX199",
- "MUSIC", /* 200*/
- ""
-};
-
-/*
- * Convert a "color letter" into an "actual" color
- * The colors are: dwsorgbuDWvyRGBU, as shown below
- */
-int color_char_to_attr(char c)
-{
- switch (c)
- {
- case 'd':
- return (TERM_DARK);
- case 'w':
- return (TERM_WHITE);
- case 's':
- return (TERM_SLATE);
- case 'o':
- return (TERM_ORANGE);
- case 'r':
- return (TERM_RED);
- case 'g':
- return (TERM_GREEN);
- case 'b':
- return (TERM_BLUE);
- case 'u':
- return (TERM_UMBER);
-
- case 'D':
- return (TERM_L_DARK);
- case 'W':
- return (TERM_L_WHITE);
- case 'v':
- return (TERM_VIOLET);
- case 'y':
- return (TERM_YELLOW);
- case 'R':
- return (TERM_L_RED);
- case 'G':
- return (TERM_L_GREEN);
- case 'B':
- return (TERM_L_BLUE);
- case 'U':
- return (TERM_L_UMBER);
- }
-
- return ( -1);
-}
-
-/*
- * Attr value-to-char convertion table
- */
-byte conv_color[16] =
-{
- 'd',
- 'w',
- 's',
- 'o',
- 'r',
- 'g',
- 'b',
- 'u',
- 'D',
- 'W',
- 'v',
- 'y',
- 'R',
- 'G',
- 'B',
- 'U',
-};
-
-
-/* Values in re_info can be fixed, added, substracted or percented */
-static byte monster_ego_modify(char c)
-{
- switch (c)
- {
- case '+':
- return MEGO_ADD;
- case '-':
- return MEGO_SUB;
- case '=':
- return MEGO_FIX;
- case '%':
- return MEGO_PRC;
- default:
- {
- msg_format("Unknown mego value modifier %c.", c);
- return MEGO_ADD;
- }
- }
-}
-
-/*
- * Implements fp stacks, for included files
- */
-static FILE *fp_stack[10];
-static int fp_stack_idx = 0;
-
-/*
- * Must be caleld before the main loop
- */
-static void fp_stack_init(FILE *fp)
-{
- fp_stack[0] = fp;
- fp_stack_idx = 0;
-}
-
-static void fp_stack_push(cptr name)
-{
- if (fp_stack_idx < 9)
- {
- char buf[1024];
- FILE *fp;
-
- /* Build the filename */
- path_build(buf, 1024, ANGBAND_DIR_EDIT, name);
-
- /* Open the file */
- fp = my_fopen(buf, "r");
-
- /* Parse it */
- if (!fp) quit(format("Cannot open '%s' file.", name));
-
- printf("ibncluding %s\n", name);
-
- fp_stack[++fp_stack_idx] = fp;
- }
-}
-
-static bool_ fp_stack_pop()
-{
- if (fp_stack_idx > 0)
- {
- FILE *fp = fp_stack[fp_stack_idx--];
- my_fclose(fp);
- return TRUE;
- }
- else
- return FALSE;
-}
-
-/*
- * Must be used instead of my_fgets for teh main loop
- */
-static int my_fgets_dostack(char *buf, int len)
-{
- // End of a file
- if (0 != my_fgets(fp_stack[fp_stack_idx], buf, len))
- {
- // If any left, use them
- if (fp_stack_pop())
- return my_fgets_dostack(buf, len);
- // If not, this is the end
- else
- return 1;
- }
- else
- {
- return 0;
- }
-}
-
-
-/*** Initialize from ascii template files ***/
-
-/*
- * Grab one race flag from a textual string
- */
-static bool_ unknown_shut_up = FALSE;
-static errr grab_one_class_flag(u32b *choice, cptr what)
-{
- int i;
- cptr s;
-
- /* Scan classes flags */
- for (i = 0; i < max_c_idx && (s = class_info[i].title + c_name); i++)
- {
- if (streq(what, s))
- {
- (choice[i / 32]) |= (1L << i);
- return (0);
- }
- }
-
- /* Oops */
- if (!unknown_shut_up) msg_format("Unknown class flag '%s'.", what);
-
- /* Failure */
- return (1);
-}
-static errr grab_one_race_allow_flag(u32b *choice, cptr what)
-{
- int i;
- cptr s;
-
- /* Scan classes flags */
- for (i = 0; i < max_rp_idx && (s = race_info[i].title + rp_name); i++)
- {
- if (streq(what, s))
- {
- (choice[i / 32]) |= (1L << i);
- return (0);
- }
- }
-
- /* Oops */
- if (!unknown_shut_up) msg_format("(1)Unknown race flag '%s'.", what);
-
- /* Failure */
- return (1);
-}
-
-/*
- * Grab one flag from a textual string
- */
-static errr grab_one_skill_flag(u32b *f1, cptr what)
-{
- int i;
-
- /* Check flags1 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, s_info_flags1[i]))
- {
- (*f1) |= (1L << i);
- return (0);
- }
- }
-
- /* Oops */
- msg_format("(2)Unknown skill flag '%s'.", what);
-
- /* Error */
- return (1);
-}
-/*
- * Grab one flag from a textual string
- */
-static errr grab_one_player_race_flag(u32b *f1, u32b *f2, cptr what)
-{
- int i;
-
- /* Check flags1 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, rp_info_flags1[i]))
- {
- (*f1) |= (1L << i);
- return (0);
- }
- }
-
- /* Check flags2 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, rp_info_flags2[i]))
- {
- (*f2) |= (1L << i);
- return (0);
- }
- }
-
- /* Oops */
- msg_format("(2)Unknown race flag '%s'.", what);
-
- /* Error */
- return (1);
-}
-
-/* Get an activation number (good for artifacts, recipes, egos, and object kinds) */
-int get_activation(char *activation)
-{
- int i;
- for ( i = 0 ; activation_names[i][0] ; i++)
- if (!strncmp(activation_names[i], activation, 19))
- {
- return i;
- }
- return -1;
-}
-
-/*
- * Grab one flag in an object_kind from a textual string
- */
-static errr grab_one_race_kind_flag(u32b *f1, u32b *f2, u32b *f3, u32b *f4, u32b *f5, u32b *esp, cptr what)
-{
- int i;
-
- /* Check flags1 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, k_info_flags1[i]))
- {
- (*f1) |= (1L << i);
- return (0);
- }
- }
-
- /* Check flags2 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, k_info_flags2[i]))
- {
- (*f2) |= (1L << i);
- return (0);
- }
- }
-
- /* Check flags2 -- traps*/
- for (i = 0; i < 32; i++)
- {
- if (streq(what, k_info_flags2_trap[i]))
- {
- (*f3) |= (1L << i);
- return (0);
- }
- }
-
- /* Check flags3 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, k_info_flags3[i]))
- {
- (*f3) |= (1L << i);
- return (0);
- }
- }
-
- /* Check flags4 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, k_info_flags4[i]))
- {
- (*f4) |= (1L << i);
- return (0);
- }
- }
-
- /* Check flags5 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, k_info_flags5[i]))
- {
- (*f5) |= (1L << i);
- return (0);
- }
- }
-
- /* Check esp_flags */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, esp_flags[i]))
- {
- (*esp) |= (1L << i);
- return (0);
- }
- }
-
- /* Oops */
- msg_format("Unknown object flag '%s'.", what);
-
- /* Error */
- return (1);
-}
-
-/*
- * Initialize the "player" arrays, by parsing an ascii "template" file
- */
-errr init_player_info_txt(FILE *fp, char *buf)
-{
- int i = 0, z;
- int powers = 0;
- int lev = 1;
- int tit_idx = 0;
- int spec_idx = 0;
- int cur_ab = -1;
-
- char *s, *t;
-
- /* Not ready yet */
- bool_ okay = FALSE;
-
- /* Current entry */
- player_race *rp_ptr = NULL;
- player_race_mod *rmp_ptr = NULL;
- player_class *c_ptr = NULL;
- player_spec *s_ptr = NULL;
- meta_class_type *mc_ptr = NULL;
-
-
- /* Just before the first record */
- error_idx = -1;
-
- /* Just before the first line */
- error_line = -1;
-
-
- /* Start the "fake" stuff */
- rp_head->name_size = 0;
- rp_head->text_size = 0;
- rmp_head->name_size = 0;
- rmp_head->text_size = 0;
- c_head->name_size = 0;
- c_head->text_size = 0;
-
- /* Init general skills */
- for (z = 0; z < MAX_SKILLS; z++)
- {
- gen_skill_basem[z] = 0;
- gen_skill_base[z] = 0;
- gen_skill_modm[z] = 0;
- gen_skill_mod[z] = 0;
- }
-
- /* Parse */
- fp_stack_init(fp);
- while (0 == my_fgets_dostack(buf, 1024))
- {
- /* Advance the line number */
- error_line++;
-
- /* Skip comments and blank lines */
- if (!buf[0] || (buf[0] == '#')) continue;
-
- /* Verify correct "colon" format */
- if (buf[1] != ':') return (1);
-
-
- /* Hack -- Process 'V' for "Version" */
- if (buf[0] == 'V')
- {
- int v1, v2, v3;
-
- /* Scan for the values */
- if (3 != sscanf(buf + 2, "%d.%d.%d", &v1, &v2, &v3)) return (2);
-
- /* Okay to proceed */
- okay = TRUE;
-
- /* Continue */
- continue;
- }
-
- /* No version yet */
- if (!okay) return (2);
-
- /* Included file */
- if (buf[0] == '<')
- {
- fp_stack_push(buf + 2);
- continue;
- }
-
- /* Reinit error_idx */
- if (buf[0] == 'I')
- {
- error_idx = -1;
- continue;
- }
-
- /* Process 'H' for "History" */
- if (buf[0] == 'H')
- {
- int idx;
- char *zz[6];
-
- /* Scan for the values */
- if (tokenize(buf + 2, 6, zz, ':', ':') != 6) return (1);
-
- idx = atoi(zz[0]);
- bg[idx].roll = atoi(zz[1]);
- bg[idx].chart = atoi(zz[2]);
- bg[idx].next = atoi(zz[3]);
- bg[idx].bonus = atoi(zz[4]);
-
- bg[idx].info = ++rp_head->text_size;
-
- /* Append chars to the name */
- strcpy(rp_text + rp_head->text_size, zz[5]);
-
- /* Advance the index */
- rp_head->text_size += strlen(zz[5]);
-
- /* Next... */
- continue;
- }
-
- /* Process 'G:k' for "General skills" */
- if ((buf[0] == 'G') && (buf[2] == 'k'))
- {
- long val, mod, i;
- char name[200], v, m;
-
- /* Scan for the values */
- if (5 != sscanf(buf + 4, "%c%ld:%c%ld:%s",
- &v, &val, &m, &mod, name)) return (1);
-
- if ((i = find_skill(name)) == -1) return (1);
- gen_skill_basem[i] = monster_ego_modify(v);
- gen_skill_base[i] = val;
- gen_skill_modm[i] = monster_ego_modify(m);
- gen_skill_mod[i] = mod;
-
- /* Next... */
- continue;
- }
-
- /* Process 'N' for "New/Number/Name" */
- if ((buf[0] == 'R') && (buf[2] == 'N'))
- {
- /* Find the colon before the name */
- s = strchr(buf + 4, ':');
-
- /* Verify that colon */
- if (!s) return (1);
-
- /* Nuke the colon, advance to the name */
- *s++ = '\0';
-
- /* Paranoia -- require a name */
- if (!*s) return (1);
-
- /* Get the index */
- i = atoi(buf + 4);
-
- /* Verify information */
- if (i < error_idx) return (4);
-
- /* Verify information */
- if (i >= rp_head->info_num) return (2);
-
- /* Save the index */
- error_idx = i;
-
- /* Point at the "info" */
- rp_ptr = &race_info[i];
-
- /* Hack -- Verify space */
- 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;
-
- /* Append chars to the name */
- strcpy(rp_name + rp_head->name_size, s);
-
- /* Advance the index */
- rp_head->name_size += strlen(s);
-
- rp_ptr->powers[0] = rp_ptr->powers[1] = rp_ptr->powers[2] = rp_ptr->powers[3] = -1;
- powers = 0;
- lev = 1;
- cur_ab = 0;
- for (z = 0; z < 10; z++)
- rp_ptr->abilities[z].level = -1;
-
- /* Next... */
- continue;
- }
-
- /* Process 'D' for "Description" */
- if ((buf[0] == 'R') && (buf[2] == 'D'))
- {
- /* Acquire the text */
- s = buf + 4;
-
- /* Hack -- Verify space */
- if (rp_head->text_size + strlen(s) + 8 > fake_text_size) return (7);
-
- /* Advance and Save the text index */
- if (!rp_ptr->desc)
- {
- rp_ptr->desc = ++rp_head->text_size;
-
- /* Append chars to the name */
- strcpy(rp_text + rp_head->text_size, s);
-
- /* Advance the index */
- rp_head->text_size += strlen(s);
- }
- else
- {
- /* Append chars to the name */
- strcpy(rp_text + rp_head->text_size, format("\n%s", s));
-
- /* Advance the index */
- rp_head->text_size += strlen(s) + 1;
- }
-
- /* Next... */
- continue;
- }
-
- /* Process 'E' for "body parts" */
- if ((buf[0] == 'R') && (buf[2] == 'E'))
- {
- int s[BODY_MAX], z;
-
- /* Scan for the values */
- if (BODY_MAX != sscanf(buf + 4, "%d:%d:%d:%d:%d:%d",
- &s[0], &s[1], &s[2], &s[3], &s[4], &s[5])) return (1);
-
- for (z = 0; z < BODY_MAX; z++)
- rp_ptr->body_parts[z] = s[z];
-
- /* Next... */
- continue;
- }
-
- /* Process 'R' for "flag level" */
- if ((buf[0] == 'R') && (buf[2] == 'R'))
- {
- int s[2];
-
- /* Scan for the values */
- if (2 != sscanf(buf + 4, "%d:%d",
- &s[0], &s[1])) return (1);
-
- lev = s[0];
- rp_ptr->opval[lev] = s[1];
-
- /* Next... */
- continue;
- }
-
- /* Process 'S' for "Stats" */
- if ((buf[0] == 'R') && (buf[2] == 'S'))
- {
- int s[7], z;
-
- /* Scan for the values */
- if (7 != sscanf(buf + 4, "%d:%d:%d:%d:%d:%d:%d",
- &s[0], &s[1], &s[2], &s[3], &s[4], &s[5], &s[6])) return (1);
-
- rp_ptr->luck = s[6];
- for (z = 0; z < 6; z++)
- rp_ptr->r_adj[z] = s[z];
-
- /* Next... */
- continue;
- }
-
- /* Process 'Z' for "powers" */
- if ((buf[0] == 'R') && (buf[2] == 'Z'))
- {
- int i;
-
- /* Acquire the text */
- s = buf + 4;
-
- /* Find it in the list */
- for (i = 0; i < power_max; i++)
- {
- if (!stricmp(s, powers_type[i].name)) break;
- }
-
- if (i == power_max) return (6);
-
- rp_ptr->powers[powers++] = i;
-
- /* Next... */
- continue;
- }
-
- /* Process 'K' for "sKills" */
- if ((buf[0] == 'R') && (buf[2] == 'K'))
- {
- int s[8];
-
- /* Scan for the values */
- if (8 != sscanf(buf + 4, "%d:%d:%d:%d:%d:%d:%d:%d",
- &s[0], &s[1], &s[2], &s[3], &s[4], &s[5], &s[6], &s[7])) return (1);
-
- rp_ptr->r_dis = s[0];
- rp_ptr->r_dev = s[1];
- rp_ptr->r_sav = s[2];
- rp_ptr->r_stl = s[3];
- rp_ptr->r_srh = s[4];
- rp_ptr->r_fos = s[5];
- rp_ptr->r_thn = s[6];
- rp_ptr->r_thb = s[7];
-
- /* Next... */
- continue;
- }
-
- /* Process 'k' for "skills" */
- if ((buf[0] == 'R') && (buf[2] == 'k'))
- {
- long val, mod, i;
- char name[200], v, m;
-
- /* Scan for the values */
- if (5 != sscanf(buf + 4, "%c%ld:%c%ld:%s",
- &v, &val, &m, &mod, name)) return (1);
-
- if ((i = find_skill(name)) == -1) return (1);
- rp_ptr->skill_basem[i] = monster_ego_modify(v);
- rp_ptr->skill_base[i] = val;
- rp_ptr->skill_modm[i] = monster_ego_modify(m);
- rp_ptr->skill_mod[i] = mod;
-
- /* Next... */
- continue;
- }
-
- /* Process 'b' for "abilities" */
- if ((buf[0] == 'R') && (buf[2] == 'b'))
- {
- char *sec;
-
- /* Scan for the values */
- if (NULL == (sec = strchr(buf + 4, ':')))
- {
- return (1);
- }
- *sec = '\0';
- sec++;
- if (!*sec) return (1);
-
- if ((i = find_ability(sec)) == -1) return (1);
-
- rp_ptr->abilities[cur_ab].ability = i;
- rp_ptr->abilities[cur_ab].level = atoi(buf + 4);
- cur_ab++;
-
- /* Next... */
- continue;
- }
-
- /* Process 'M' for "Mods" */
- if ((buf[0] == 'R') && (buf[2] == 'M'))
- {
- int s[10];
-
- /* Scan for the values */
- if (10 != sscanf(buf + 4, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
- &s[0], &s[1], &s[2], &s[3], &s[4], &s[5], &s[6], &s[7], &s[8], &s[9])) return (1);
-
- rp_ptr->b_age = s[0];
- rp_ptr->m_age = s[1];
- rp_ptr->m_b_ht = s[2];
- rp_ptr->m_m_ht = s[3];
- rp_ptr->m_b_wt = s[4];
- rp_ptr->m_m_wt = s[5];
- rp_ptr->f_b_ht = s[6];
- rp_ptr->f_m_ht = s[7];
- rp_ptr->f_b_wt = s[8];
- rp_ptr->f_m_wt = s[9];
-
- /* Next... */
- continue;
- }
-
- /* Process 'P' for "xtra" */
- if ((buf[0] == 'R') && (buf[2] == 'P'))
- {
- int s[4];
-
- /* Scan for the values */
- if (4 != sscanf(buf + 4, "%d:%d:%d:%d",
- &s[0], &s[1], &s[2], &s[3])) return (1);
-
- rp_ptr->r_mhp = s[0];
- rp_ptr->r_exp = s[1];
- rp_ptr->infra = s[2];
- rp_ptr->chart = s[3];
-
- /* Next... */
- continue;
- }
-
- /* Process 'G' for "Player flags" (multiple lines) */
- if ((buf[0] == 'R') && (buf[2] == 'G'))
- {
- /* Parse every entry */
- for (s = buf + 4; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while (*t == ' ' || *t == '|') t++;
- }
-
- /* Parse this entry */
- if (0 != grab_one_player_race_flag(&rp_ptr->flags1, &rp_ptr->flags2, s)) return (5);
-
- /* Start the next entry */
- s = t;
- }
-
- /* Next... */
- continue;
- }
-
- /* Process 'F' for "level Flags" (multiple lines) */
- if ((buf[0] == 'R') && (buf[2] == 'F'))
- {
- /* Parse every entry */
- for (s = buf + 4; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while (*t == ' ' || *t == '|') t++;
- }
-
- /* Parse this entry */
- if (0 != grab_one_race_kind_flag(&rp_ptr->oflags1[lev], &rp_ptr->oflags2[lev], &rp_ptr->oflags3[lev], &rp_ptr->oflags4[lev], &rp_ptr->oflags5[lev], &rp_ptr->oesp[lev], s)) return (5);
-
- /* Start the next entry */
- s = t;
- }
-
- /* Next... */
- continue;
- }
-
- /* Process 'O' for "Object birth" */
- if ((buf[0] == 'R') && (buf[2] == 'O'))
- {
- int s[5];
-
- /* Scan for the values */
- if (5 != sscanf(buf + 4, "%d:%d:%d:%dd%d",
- &s[0], &s[1], &s[4], &s[2], &s[3]))
- {
- s[4] = 0;
-
- if (4 != sscanf(buf + 4, "%d:%d:%dd%d",
- &s[0], &s[1], &s[2], &s[3]))
- {
- return (1);
- }
- }
-
- rp_ptr->obj_pval[rp_ptr->obj_num] = s[4];
- rp_ptr->obj_tval[rp_ptr->obj_num] = s[0];
- rp_ptr->obj_sval[rp_ptr->obj_num] = s[1];
- rp_ptr->obj_dd[rp_ptr->obj_num] = s[2];
- rp_ptr->obj_ds[rp_ptr->obj_num++] = s[3];
-
- /* Next... */
- continue;
- }
-
- /* Process 'C' for "Class choice flags" (multiple lines) */
- if ((buf[0] == 'R') && (buf[2] == 'C'))
- {
- /* Parse every entry */
- for (s = buf + 4; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while (*t == ' ' || *t == '|') t++;
- }
-
- /* Parse this entry */
- if (0 != grab_one_class_flag(rp_ptr->choice, s)) return (5);
-
- /* Start the next entry */
- s = t;
- }
-
- /* Next... */
- continue;
- }
-
- /* Process 'N' for "New/Number/Name" */
- if ((buf[0] == 'S') && (buf[2] == 'N'))
- {
- /* Find the colon before the name */
- s = strchr(buf + 4, ':');
-
- /* Verify that colon */
- if (!s) return (1);
-
- /* Nuke the colon, advance to the name */
- *s++ = '\0';
-
- /* Paranoia -- require a name */
- if (!*s) return (1);
-
- /* Get the index */
- i = atoi(buf + 4);
-
- /* Verify information */
- if (i < error_idx) return (4);
-
- /* Verify information */
- if (i >= rmp_head->info_num) return (2);
-
- /* Save the index */
- error_idx = i;
-
- /* Point at the "info" */
- rmp_ptr = &race_mod_info[i];
-
- /* Hack -- Verify space */
- 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;
-
- /* Append chars to the name */
- strcpy(rmp_name + rmp_head->name_size, s);
-
- /* Advance the index */
- rmp_head->name_size += strlen(s);
-
- rmp_ptr->powers[0] = rmp_ptr->powers[1] = rmp_ptr->powers[2] = rmp_ptr->powers[3] = -1;
- powers = 0;
- lev = 1;
- cur_ab = 0;
- for (z = 0; z < 10; z++)
- rmp_ptr->abilities[z].level = -1;
-
- /* Next... */
- continue;
- }
-
- /* Process 'D' for "Description" */
- if ((buf[0] == 'S') && (buf[2] == 'D'))
- {
- /* Acquire the text */
- s = buf + 6;
-
- if (buf[4] == 'A') rmp_ptr->place = TRUE;
- else rmp_ptr->place = FALSE;
-
- /* Hack -- Verify space */
- if (rmp_head->text_size + strlen(s) + 8 > fake_text_size) return (7);
-
- /* Advance and Save the text index */
- if (!rmp_ptr->desc)
- {
- rmp_ptr->desc = ++rmp_head->text_size;
-
- /* Append chars to the name */
- strcpy(rmp_text + rmp_head->text_size, s);
-
- /* Advance the index */
- rmp_head->text_size += strlen(s);
- }
- else
- {
- /* Append chars to the name */
- strcpy(rmp_text + rmp_head->text_size, format("\n%s", s));
-
- /* Advance the index */
- rmp_head->text_size += strlen(s) + 1;
- }
-
- /* Next... */
- continue;
- }
-
- /* Process 'E' for "body parts" */
- if ((buf[0] == 'S') && (buf[2] == 'E'))
- {
- int s[BODY_MAX], z;
-
- /* Scan for the values */
- if (BODY_MAX != sscanf(buf + 4, "%d:%d:%d:%d:%d:%d",
- &s[0], &s[1], &s[2], &s[3], &s[4], &s[5])) return (1);
-
- for (z = 0; z < BODY_MAX; z++)
- rmp_ptr->body_parts[z] = s[z];
-
- /* Next... */
- continue;
- }
-
- /* Process 'R' for "flag level" */
- if ((buf[0] == 'S') && (buf[2] == 'R'))
- {
- int s[2];
-
- /* Scan for the values */
- if (2 != sscanf(buf + 4, "%d:%d",
- &s[0], &s[1])) return (1);
-
- lev = s[0];
- rmp_ptr->opval[lev] = s[1];
-
- /* Next... */
- continue;
- }
-
- /* Process 'S' for "Stats" */
- if ((buf[0] == 'S') && (buf[2] == 'S'))
- {
- int s[8], z;
-
- /* Scan for the values */
- if (8 != sscanf(buf + 4, "%d:%d:%d:%d:%d:%d:%d:%d",
- &s[0], &s[1], &s[2], &s[3], &s[4], &s[5], &s[6], &s[7])) return (1);
-
- rmp_ptr->mana = s[7];
- rmp_ptr->luck = s[6];
- for (z = 0; z < 6; z++)
- rmp_ptr->r_adj[z] = s[z];
-
- /* Next... */
- continue;
- }
-
- /* Process 'Z' for "powers" */
- if ((buf[0] == 'S') && (buf[2] == 'Z'))
- {
- int i;
-
- /* Acquire the text */
- s = buf + 4;
-
- /* Find it in the list */
- for (i = 0; i < power_max; i++)
- {
- if (!stricmp(s, powers_type[i].name)) break;
- }
-
- if (i == power_max) return (6);
-
- rmp_ptr->powers[powers++] = i;
-
- /* Next... */
- continue;
- }
-
- /* Process 'k' for "skills" */
- if ((buf[0] == 'S') && (buf[2] == 'k'))
- {
- long val, mod, i;
- char name[200], v, m;
-
- /* Scan for the values */
- if (5 != sscanf(buf + 4, "%c%ld:%c%ld:%s",
- &v, &val, &m, &mod, name)) return (1);
-
- if ((i = find_skill(name)) == -1) return (1);
- rmp_ptr->skill_basem[i] = monster_ego_modify(v);
- rmp_ptr->skill_base[i] = val;
- rmp_ptr->skill_modm[i] = monster_ego_modify(m);
- rmp_ptr->skill_mod[i] = mod;
-
- /* Next... */
- continue;
- }
-
- /* Process 'b' for "abilities" */
- if ((buf[0] == 'S') && (buf[2] == 'b'))
- {
- char *sec;
-
- /* Scan for the values */
- if (NULL == (sec = strchr(buf + 4, ':')))
- {
- return (1);
- }
- *sec = '\0';
- sec++;
- if (!*sec) return (1);
-
- if ((i = find_ability(sec)) == -1) return (1);
-
- rmp_ptr->abilities[cur_ab].ability = i;
- rmp_ptr->abilities[cur_ab].level = atoi(buf + 4);
- cur_ab++;
-
- /* Next... */
- continue;
- }
-
- /* Process 'K' for "sKills" */
- if ((buf[0] == 'S') && (buf[2] == 'K'))
- {
- int s[8];
-
- /* Scan for the values */
- if (8 != sscanf(buf + 4, "%d:%d:%d:%d:%d:%d:%d:%d",
- &s[0], &s[1], &s[2], &s[3], &s[4], &s[5], &s[6], &s[7])) return (1);
-
- rmp_ptr->r_dis = s[0];
- rmp_ptr->r_dev = s[1];
- rmp_ptr->r_sav = s[2];
- rmp_ptr->r_stl = s[3];
- rmp_ptr->r_srh = s[4];
- rmp_ptr->r_fos = s[5];
- rmp_ptr->r_thn = s[6];
- rmp_ptr->r_thb = s[7];
-
- /* Next... */
- continue;
- }
-
- /* Process 'M' for "Mods" */
- if ((buf[0] == 'S') && (buf[2] == 'M'))
- {
- int s[10];
-
- /* Scan for the values */
- if (10 != sscanf(buf + 4, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
- &s[0], &s[1], &s[2], &s[3], &s[4], &s[5], &s[6], &s[7], &s[8], &s[9])) return (1);
-
- rmp_ptr->b_age = s[0];
- rmp_ptr->m_age = s[1];
- rmp_ptr->m_b_ht = s[2];
- rmp_ptr->m_m_ht = s[3];
- rmp_ptr->m_b_wt = s[4];
- rmp_ptr->m_m_wt = s[5];
- rmp_ptr->f_b_ht = s[6];
- rmp_ptr->f_m_ht = s[7];
- rmp_ptr->f_b_wt = s[8];
- rmp_ptr->f_m_wt = s[9];
-
- /* Next... */
- continue;
- }
-
- /* Process 'P' for "xtra" */
- if ((buf[0] == 'S') && (buf[2] == 'P'))
- {
- int s[3];
-
- /* Scan for the values */
- if (3 != sscanf(buf + 4, "%d:%d:%d",
- &s[0], &s[1], &s[2])) return (1);
-
- rmp_ptr->r_mhp = s[0];
- rmp_ptr->r_exp = s[1];
- rmp_ptr->infra = s[2];
-
- /* Next... */
- continue;
- }
-
- /* Process 'G' for "Player flags" (multiple lines) */
- if ((buf[0] == 'S') && (buf[2] == 'G'))
- {
- /* Parse every entry */
- for (s = buf + 4; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while (*t == ' ' || *t == '|') t++;
- }
-
- /* Parse this entry */
- if (0 != grab_one_player_race_flag(&rmp_ptr->flags1, &rmp_ptr->flags2, s)) return (5);
-
- /* Start the next entry */
- s = t;
- }
-
- /* Next... */
- continue;
- }
-
- /* Process 'F' for "level Flags" (multiple lines) */
- if ((buf[0] == 'S') && (buf[2] == 'F'))
- {
- /* Parse every entry */
- for (s = buf + 4; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while (*t == ' ' || *t == '|') t++;
- }
-
- /* Parse this entry */
- if (0 != grab_one_race_kind_flag(&rmp_ptr->oflags1[lev], &rmp_ptr->oflags2[lev], &rmp_ptr->oflags3[lev], &rmp_ptr->oflags4[lev], &rmp_ptr->oflags5[lev], &rmp_ptr->oesp[lev], s)) return (5);
-
- /* Start the next entry */
- s = t;
- }
-
- /* Next... */
- continue;
- }
-
- /* Process 'O' for "Object birth" */
- if ((buf[0] == 'S') && (buf[2] == 'O'))
- {
- int s[5];
-
- /* Scan for the values */
- if (5 != sscanf(buf + 4, "%d:%d:%d:%dd%d",
- &s[0], &s[1], &s[4], &s[2], &s[3]))
- {
- s[4] = 0;
-
- if (4 != sscanf(buf + 4, "%d:%d:%dd%d",
- &s[0], &s[1], &s[2], &s[3]))
- {
- return (1);
- }
- }
-
- rmp_ptr->obj_pval[rmp_ptr->obj_num] = s[4];
- rmp_ptr->obj_tval[rmp_ptr->obj_num] = s[0];
- rmp_ptr->obj_sval[rmp_ptr->obj_num] = s[1];
- rmp_ptr->obj_dd[rmp_ptr->obj_num] = s[2];
- rmp_ptr->obj_ds[rmp_ptr->obj_num++] = s[3];
-
- /* Next... */
- continue;
- }
-
- /* Process 'A' for "Allowed races" (multiple lines) */
- if ((buf[0] == 'S') && (buf[2] == 'A'))
- {
- /* Parse every entry */
- for (s = buf + 4; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while (*t == ' ' || *t == '|') t++;
- }
-
- /* Parse this entry */
- if (0 != grab_one_race_allow_flag(rmp_ptr->choice, s)) return (5);
-
- /* Start the next entry */
- s = t;
- }
-
- /* Next... */
- continue;
- }
-
- /* Process 'C' for "Class choice flags" (multiple lines) */
- if ((buf[0] == 'S') && (buf[2] == 'C'))
- {
- u32b choice[2] = {0, 0}, z;
-
- /* Parse every entry */
- for (s = buf + 6; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while (*t == ' ' || *t == '|') t++;
- }
-
- /* Parse this entry */
- if (0 != grab_one_class_flag(choice, s)) return (5);
-
- /* Start the next entry */
- s = t;
- }
-
- for (z = 0; z < 2; z++)
- {
- if (buf[4] == 'A') rmp_ptr->pclass[z] |= choice[z];
- else rmp_ptr->mclass[z] |= choice[z];
- }
-
- /* Next... */
- continue;
- }
-
- /* Process 'N' for "New/Number/Name" */
- if ((buf[0] == 'C') && (buf[2] == 'N'))
- {
- int z;
-
- /* Find the colon before the name */
- s = strchr(buf + 4, ':');
-
- /* Verify that colon */
- if (!s) return (1);
-
- /* Nuke the colon, advance to the name */
- *s++ = '\0';
-
- /* Paranoia -- require a name */
- if (!*s) return (1);
-
- /* Get the index */
- i = atoi(buf + 4);
-
- /* Verify information */
- if (i < error_idx) return (4);
-
- /* Verify information */
- if (i >= c_head->info_num) return (2);
-
- /* Save the index */
- error_idx = i;
-
- /* Point at the "info" */
- c_ptr = &class_info[i];
-
- /* Hack -- Verify space */
- 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;
-
- /* Append chars to the name */
- strcpy(c_name + c_head->name_size, s);
-
- /* Advance the index */
- c_head->name_size += strlen(s);
-
- c_ptr->powers[0] = c_ptr->powers[1] = c_ptr->powers[2] = c_ptr->powers[3] = -1;
- powers = 0;
- lev = 1;
- for (z = 0; z < 10; z++)
- c_ptr->abilities[z].level = -1;
- cur_ab = 0;
- c_ptr->obj_num = 0;
- tit_idx = 0;
- spec_idx = -1;
- for (z = 0; z < MAX_SPEC; z++)
- c_ptr->spec[z].title = 0;
-
- /* Next... */
- continue;
- }
-
- /* Process 'D' for "Description" */
- if ((buf[0] == 'C') && (buf[2] == 'D'))
- {
- /* Acquire the text */
- s = buf + 6;
-
- /* Hack -- Verify space */
- if (c_head->text_size + strlen(s) + 8 > fake_text_size) return (7);
-
- switch (buf[4])
- {
- case '0':
- /* Advance and Save the text index */
- if (!c_ptr->desc)
- {
- c_ptr->desc = ++c_head->text_size;
-
- /* Append chars to the name */
- strcpy(c_text + c_head->text_size, s);
-
- /* Advance the index */
- c_head->text_size += strlen(s);
- }
- else
- {
- /* Append chars to the name */
- strcpy(c_text + c_head->text_size, format("\n%s", s));
-
- /* Advance the index */
- c_head->text_size += strlen(s) + 1;
- }
- break;
- case '1':
- /* Advance and Save the text index */
- c_ptr->titles[tit_idx++] = ++c_head->text_size;
-
- /* Append chars to the name */
- strcpy(c_text + c_head->text_size, s);
-
- /* Advance the index */
- c_head->text_size += strlen(s);
- break;
- default:
- return (6);
- break;
- }
-
- /* Next... */
- continue;
- }
-
- /* Process 'O' for "Object birth" */
- if ((buf[0] == 'C') && (buf[2] == 'O'))
- {
- int s[5];
-
- /* Scan for the values */
- if (5 != sscanf(buf + 4, "%d:%d:%d:%dd%d",
- &s[0], &s[1], &s[4], &s[2], &s[3]))
- {
- s[4] = 0;
-
- if (4 != sscanf(buf + 4, "%d:%d:%dd%d",
- &s[0], &s[1], &s[2], &s[3]))
- {
- return (1);
- }
- }
-
- c_ptr->obj_pval[c_ptr->obj_num] = s[4];
- c_ptr->obj_tval[c_ptr->obj_num] = s[0];
- c_ptr->obj_sval[c_ptr->obj_num] = s[1];
- c_ptr->obj_dd[c_ptr->obj_num] = s[2];
- c_ptr->obj_ds[c_ptr->obj_num++] = s[3];
-
- /* Next... */
- continue;
- }
-
- /* Process 'E' for "body parts" */
- if ((buf[0] == 'C') && (buf[2] == 'E'))
- {
- int s[BODY_MAX], z;
-
- /* Scan for the values */
- if (BODY_MAX != sscanf(buf + 4, "%d:%d:%d:%d:%d:%d",
- &s[0], &s[1], &s[2], &s[3], &s[4], &s[5])) return (1);
-
- for (z = 0; z < BODY_MAX; z++)
- c_ptr->body_parts[z] = s[z];
-
- /* Next... */
- continue;
- }
-
- /* Process 'R' for "flag level" */
- if ((buf[0] == 'C') && (buf[2] == 'R'))
- {
- int s[2];
-
- /* Scan for the values */
- if (2 != sscanf(buf + 4, "%d:%d",
- &s[0], &s[1])) return (1);
-
- lev = s[0];
- c_ptr->opval[lev] = s[1];
-
- /* Next... */
- continue;
- }
-
- /* Process 'C' for "Stats" */
- if ((buf[0] == 'C') && (buf[2] == 'S'))
- {
- int s[8], z;
-
- /* Scan for the values */
- if (8 != sscanf(buf + 4, "%d:%d:%d:%d:%d:%d:%d:%d",
- &s[0], &s[1], &s[2], &s[3], &s[4], &s[5], &s[6], &s[7])) return (1);
-
- c_ptr->mana = s[6];
- c_ptr->extra_blows = s[7];
- for (z = 0; z < 6; z++)
- c_ptr->c_adj[z] = s[z];
-
- /* Next... */
- continue;
- }
-
- /* Process 'k' for "skills" */
- if ((buf[0] == 'C') && (buf[2] == 'k'))
- {
- long val, mod, i;
- char name[200], v, m;
-
- /* Scan for the values */
- if (5 != sscanf(buf + 4, "%c%ld:%c%ld:%s",
- &v, &val, &m, &mod, name)) return (1);
-
- if ((i = find_skill(name)) == -1) return (1);
- c_ptr->skill_basem[i] = monster_ego_modify(v);
- c_ptr->skill_base[i] = val;
- c_ptr->skill_modm[i] = monster_ego_modify(m);
- c_ptr->skill_mod[i] = mod;
-
- /* Next... */
- continue;
- }
-
- /* Process 'b' for "abilities" */
- if ((buf[0] == 'C') && (buf[2] == 'b'))
- {
- char *sec;
-
- /* Scan for the values */
- if (NULL == (sec = strchr(buf + 4, ':')))
- {
- return (1);
- }
- *sec = '\0';
- sec++;
- if (!*sec) return (1);
-
- if ((i = find_ability(sec)) == -1) return (1);
-
- c_ptr->abilities[cur_ab].ability = i;
- c_ptr->abilities[cur_ab].level = atoi(buf + 4);
- cur_ab++;
-
- /* Next... */
- continue;
- }
-
- /* Process 'g' for "gods" */
- if ((buf[0] == 'C') && (buf[2] == 'g'))
- {
- int i;
-
- if (streq(buf + 4, "All Gods"))
- c_ptr->gods = 0xFFFFFFFF;
- else
- {
- if ((i = find_god(buf + 4)) == -1) return (1);
- c_ptr->gods |= BIT(i);
- }
-
- /* Next... */
- continue;
- }
-
- /* Process 'Z' for "powers" */
- if ((buf[0] == 'C') && (buf[2] == 'Z'))
- {
- int i;
-
- /* Acquire the text */
- s = buf + 4;
-
- /* Find it in the list */
- for (i = 0; i < power_max; i++)
- {
- if (!stricmp(s, powers_type[i].name)) break;
- }
-
- if (i == power_max) return (6);
-
- c_ptr->powers[powers++] = i;
-
- /* Next... */
- continue;
- }
-
- /* Process 'K' for "sKills" */
- if ((buf[0] == 'C') && (buf[2] == 'K'))
- {
- int s[8];
-
- /* Scan for the values */
- if (8 != sscanf(buf + 4, "%d:%d:%d:%d:%d:%d:%d:%d",
- &s[0], &s[1], &s[2], &s[3], &s[4], &s[5], &s[6], &s[7])) return (1);
-
- c_ptr->c_dis = s[0];
- c_ptr->c_dev = s[1];
- c_ptr->c_sav = s[2];
- c_ptr->c_stl = s[3];
- c_ptr->c_srh = s[4];
- c_ptr->c_fos = s[5];
- c_ptr->c_thn = s[6];
- c_ptr->c_thb = s[7];
-
- /* Next... */
- continue;
- }
-
- /* Process 'x' for "Xtra skills" */
- if ((buf[0] == 'C') && (buf[2] == 'X'))
- {
- int s[8];
-
- /* Scan for the values */
- if (8 != sscanf(buf + 4, "%d:%d:%d:%d:%d:%d:%d:%d",
- &s[0], &s[1], &s[2], &s[3], &s[4], &s[5], &s[6], &s[7])) return (1);
-
- c_ptr->x_dis = s[0];
- c_ptr->x_dev = s[1];
- c_ptr->x_sav = s[2];
- c_ptr->x_stl = s[3];
- c_ptr->x_srh = s[4];
- c_ptr->x_fos = s[5];
- c_ptr->x_thn = s[6];
- c_ptr->x_thb = s[7];
-
- /* Next... */
- continue;
- }
-
- /* Process 'P' for "xtra" */
- if ((buf[0] == 'C') && (buf[2] == 'P'))
- {
- int s[2];
-
- /* Scan for the values */
- if (2 != sscanf(buf + 4, "%d:%d",
- &s[0], &s[1])) return (1);
-
- c_ptr->c_mhp = s[0];
- c_ptr->c_exp = s[1];
-
- /* Next... */
- continue;
- }
-
- /* Process 'C' for "sensing" */
- if ((buf[0] == 'C') && (buf[2] == 'C'))
- {
- long int s[3];
- char h, m;
-
- /* Scan for the values */
- if (5 != sscanf(buf + 4, "%c:%c:%ld:%ld:%ld",
- &h, &m, &s[0], &s[1], &s[2])) return (1);
-
- c_ptr->sense_heavy = (h == 'H') ? TRUE : FALSE;
- c_ptr->sense_heavy_magic = (m == 'H') ? TRUE : FALSE;
- c_ptr->sense_base = s[0];
- c_ptr->sense_pl = s[1];
- c_ptr->sense_plus = s[2];
-
- /* Next... */
- continue;
- }
-
- /* Process 'B' for "blows" */
- if ((buf[0] == 'C') && (buf[2] == 'B'))
- {
- int s[3];
-
- /* Scan for the values */
- if (3 != sscanf(buf + 4, "%d:%d:%d",
- &s[0], &s[1], &s[2])) return (1);
-
- c_ptr->blow_num = s[0];
- c_ptr->blow_wgt = s[1];
- c_ptr->blow_mul = s[2];
-
- /* Next... */
- continue;
- }
-
- /* Process 'G' for "Player flags" (multiple lines) */
- if ((buf[0] == 'C') && (buf[2] == 'G'))
- {
- /* Parse every entry */
- for (s = buf + 4; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while (*t == ' ' || *t == '|') t++;
- }
-
- /* Parse this entry */
- if (0 != grab_one_player_race_flag(&c_ptr->flags1, &c_ptr->flags2, s)) return (5);
-
- /* Start the next entry */
- s = t;
- }
-
- /* Next... */
- continue;
- }
-
- /* Process 'F' for "level Flags" (multiple lines) */
- if ((buf[0] == 'C') && (buf[2] == 'F'))
- {
- /* Parse every entry */
- for (s = buf + 4; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while (*t == ' ' || *t == '|') t++;
- }
-
- /* Parse this entry */
- if (0 != grab_one_race_kind_flag(&c_ptr->oflags1[lev], &c_ptr->oflags2[lev], &c_ptr->oflags3[lev], &c_ptr->oflags4[lev], &c_ptr->oflags5[lev], &c_ptr->oesp[lev], s)) return (5);
-
- /* Start the next entry */
- s = t;
- }
-
- /* Next... */
- continue;
- }
-
- /* Specialities */
- if ((buf[0] == 'C') && (buf[2] == 'a'))
- {
- /* Process 'N' for "New/Number/Name" */
- if (buf[4] == 'N')
- {
- /* Find the colon before the name */
- s = buf + 6;
-
- /* Paranoia -- require a name */
- if (!*s) return (1);
- /* Get the index */
- spec_idx++;
-
- /* Verify information */
- if (spec_idx >= MAX_SPEC) return (2);
-
- /* Point at the "info" */
- s_ptr = &c_ptr->spec[spec_idx];
-
- /* Hack -- Verify space */
- 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;
-
- /* Append chars to the name */
- strcpy(c_name + c_head->name_size, s);
-
- /* Advance the index */
- c_head->name_size += strlen(s);
-
- s_ptr->obj_num = 0;
- cur_ab = 0;
- for (z = 0; z < 10; z++)
- s_ptr->abilities[z].level = -1;
-
- /* Next... */
- continue;
- }
-
- /* Process 'D' for "Description" */
- if (buf[4] == 'D')
- {
- /* Acquire the text */
- s = buf + 6;
-
- /* Hack -- Verify space */
- if (c_head->text_size + strlen(s) + 8 > fake_text_size) return (7);
-
- /* Advance and Save the text index */
- if (!s_ptr->desc)
- {
- s_ptr->desc = ++c_head->text_size;
-
- /* Append chars to the name */
- strcpy(c_text + c_head->text_size, s);
-
- /* Advance the index */
- c_head->text_size += strlen(s);
- }
- else
- {
- /* Append chars to the name */
- strcpy(c_text + c_head->text_size, format("\n%s", s));
-
- /* Advance the index */
- c_head->text_size += strlen(s) + 1;
- }
-
- /* Next... */
- continue;
- }
-
- /* Process 'O' for "Object birth" */
- if (buf[4] == 'O')
- {
- int s[5];
-
- /* Scan for the values */
- if (5 != sscanf(buf + 6, "%d:%d:%d:%dd%d",
- &s[0], &s[1], &s[4], &s[2], &s[3]))
- {
- s[4] = 0;
-
- if (4 != sscanf(buf + 6, "%d:%d:%dd%d",
- &s[0], &s[1], &s[2], &s[3]))
- {
- return (1);
- }
- }
-
- s_ptr->obj_pval[s_ptr->obj_num] = s[4];
- s_ptr->obj_tval[s_ptr->obj_num] = s[0];
- s_ptr->obj_sval[s_ptr->obj_num] = s[1];
- s_ptr->obj_dd[s_ptr->obj_num] = s[2];
- s_ptr->obj_ds[s_ptr->obj_num++] = s[3];
-
- /* Next... */
- continue;
- }
-
- /* Process 'g' for "gods" */
- if (buf[4] == 'g')
- {
- int i;
-
- if (streq(buf + 6, "All Gods"))
- s_ptr->gods = 0xFFFFFFFF;
- else
- {
- if ((i = find_god(buf + 6)) == -1) return (1);
- s_ptr->gods |= BIT(i);
- }
-
- /* Next... */
- continue;
- }
-
- /* Process 'k' for "skills" */
- if (buf[4] == 'k')
- {
- long val, mod, i;
- char name[200], v, m;
-
- /* Scan for the values */
- if (5 != sscanf(buf + 6, "%c%ld:%c%ld:%s",
- &v, &val, &m, &mod, name)) return (1);
-
- if ((i = find_skill(name)) == -1) return (1);
- s_ptr->skill_basem[i] = monster_ego_modify(v);
- s_ptr->skill_base[i] = val;
- s_ptr->skill_modm[i] = monster_ego_modify(m);
- s_ptr->skill_mod[i] = mod;
-
- /* Next... */
- continue;
- }
-
- /* Process 'b' for "abilities" */
- if (buf[4] == 'b')
- {
- char *sec;
-
- /* Scan for the values */
- if (NULL == (sec = strchr(buf + 6, ':')))
- {
- return (1);
- }
- *sec = '\0';
- sec++;
- if (!*sec) return (1);
-
- if ((i = find_ability(sec)) == -1) return (1);
-
- s_ptr->abilities[cur_ab].ability = i;
- s_ptr->abilities[cur_ab].level = atoi(buf + 6);
- cur_ab++;
-
- /* Next... */
- continue;
- }
-
- /* Process 'G' for "Player flags" (multiple lines) */
- if (buf[4] == 'G')
- {
- /* Parse every entry */
- for (s = buf + 6; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while (*t == ' ' || *t == '|') t++;
- }
-
- /* Parse this entry */
- if (0 != grab_one_player_race_flag(&s_ptr->flags1, &s_ptr->flags2, s)) return (5);
-
- /* Start the next entry */
- s = t;
- }
-
- /* Next... */
- continue;
- }
-
-
- /* Process 'K' for "desired skills" */
- if (buf[4] == 'K')
- {
- long val;
- char name[200];
-
- /* Scan for the values */
- if (2 != sscanf(buf + 6, "%ld:%s",
- &val, name)) return (1);
-
- if ((i = find_skill(name)) == -1) return (1);
- s_ptr->skill_ideal[i] = val;
-
- /* Next... */
- continue;
- }
- }
-
- /* Process 'N' for "New/Number/Name" */
- if ((buf[0] == 'M') && (buf[2] == 'N'))
- {
- /* Find the colon before the name */
- s = strchr(buf + 4, ':');
-
- /* Verify that colon */
- if (!s) return (1);
-
- /* Nuke the colon, advance to the name */
- *s++ = '\0';
-
- /* Paranoia -- require a name */
- if (!*s) return (1);
-
- /* Get the index */
- i = atoi(buf + 4);
-
- /* Verify information */
- if (i < error_idx) return (4);
-
- /* Verify information */
- if (i >= max_mc_idx) return (2);
-
- /* Save the index */
- error_idx = i;
-
- /* Point at the "info" */
- mc_ptr = &meta_class_info[i];
-
- /* Append chars to the name */
- strcpy(mc_ptr->name, s + 2);
- mc_ptr->color = color_char_to_attr(s[0]);
- for (powers = 0; powers < max_c_idx; powers++)
- mc_ptr->classes[powers] = -1;
- powers = 0;
-
- /* Next... */
- continue;
- }
-
- /* Process 'C' for "Classes" */
- if ((buf[0] == 'M') && (buf[2] == 'C'))
- {
- int i;
-
- /* Acquire the text */
- s = buf + 4;
-
- /* Find it in the list */
- for (i = 0; i < max_c_idx; i++)
- {
- if (!stricmp(s, class_info[i].title + c_name)) break;
- }
-
- if (i == max_c_idx) return (6);
-
- mc_ptr->classes[powers++] = i;
-
- /* Next... */
- continue;
- }
-
- /* Oops */
- return (6);
- }
-
- /* Complete the "name" and "text" sizes */
- ++rp_head->name_size;
- ++rp_head->text_size;
- ++rmp_head->name_size;
- ++rmp_head->text_size;
- ++c_head->name_size;
- ++c_head->text_size;
- /* No version yet */
- if (!okay) return (2);
-
- /* Success */
- return (0);
-}
-
-
-/*
- * Initialize the "v_info" array, by parsing an ascii "template" file
- */
-errr init_v_info_txt(FILE *fp, char *buf, bool_ start)
-{
- int i;
- char *s;
-
- /* Not ready yet */
- bool_ okay = FALSE;
-
- /* Current entry */
- vault_type *v_ptr = NULL;
-
- if (start)
- {
- /* Just before the first record */
- error_idx = -1;
-
- /* Just before the first line */
- error_line = -1;
-
- /* Prepare the "fake" stuff */
- v_head->name_size = 0;
- v_head->text_size = 0;
- }
-
- /* Parse */
- fp_stack_init(fp);
- while (0 == my_fgets_dostack(buf, 1024))
- {
- /* Advance the line number */
- error_line++;
-
- /* Skip comments and blank lines */
- if (!buf[0] || (buf[0] == '#')) continue;
- if ((buf[0] == 'Q') || (buf[0] == 'T')) continue;
-
- /* Verify correct "colon" format */
- if (buf[1] != ':') return (1);
-
-
- /* Hack -- Process 'V' for "Version" */
- if (buf[0] == 'V')
- {
- int v1, v2, v3;
-
- /* Scan for the values */
- if (3 != sscanf(buf, "V:%d.%d.%d", &v1, &v2, &v3)) return (2);
-
- /* Okay to proceed */
- okay = TRUE;
-
- /* Continue */
- continue;
- }
-
- /* No version yet */
- if (!okay) return (2);
-
- /* Included file */
- if (buf[0] == '<')
- {
- fp_stack_push(buf + 2);
- continue;
- }
-
- /* Process 'N' for "New/Number/Name" */
- if (buf[0] == 'N')
- {
- /* Find the colon before the name */
- s = strchr(buf + 2, ':');
-
- /* Verify that colon */
- if (!s) return (1);
-
- /* Nuke the colon, advance to the name */
- *s++ = '\0';
-
- /* Paranoia -- require a name */
- if (!*s) return (1);
-
- /* Get the index */
- i = atoi(buf + 2);
-
- /* Verify information */
- if (i <= error_idx) return (4);
-
- /* Verify information */
- if (i >= v_head->info_num) return (2);
-
- /* Save the index */
- error_idx = i;
-
- /* Point at the "info" */
- v_ptr = &v_info[i];
-
- /* Hack -- Verify space */
- 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;
-
- /* Append chars to the name */
- strcpy(v_name + v_head->name_size, s);
-
- /* Advance the index */
- v_head->name_size += strlen(s);
-
- /* Next... */
- continue;
- }
-
- /* There better be a current v_ptr */
- if (!v_ptr) return (3);
-
- /* Process 'D' for "Description" */
- if (buf[0] == 'D')
- {
- /* Acquire the text */
- s = buf + 2;
-
- /* Hack -- Verify space */
- 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;
-
- /* Append chars to the name */
- strcpy(v_text + v_head->text_size, s);
-
- /* Advance the index */
- v_head->text_size += strlen(s);
-
- /* Next... */
- continue;
- }
-
-
- /* Process 'X' for "Extra info" (one line only) */
- if (buf[0] == 'X')
- {
- int typ, rat, hgt, wid;
-
- /* Scan for the values */
- if (4 != sscanf(buf + 2, "%d:%d:%d:%d",
- &typ, &rat, &hgt, &wid)) return (1);
-
- /* Save the values */
- v_ptr->typ = typ;
- v_ptr->rat = rat;
- v_ptr->hgt = hgt;
- v_ptr->wid = wid;
-
- /* Next... */
- continue;
- }
-
- /* There better be a current v_ptr */
- if (!v_ptr) return (3);
-
- /* Process monster, item and level info for special levels */
- if (buf[0] == 'Y')
- {
-
- int mon1, mon2, mon3, mon4, mon5, mon6, mon7, mon8, mon9;
- int mon10, item1, item2, item3, lvl, dun_type;
-
- /* Scan for the values */
- if (15 != sscanf(buf + 2, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
- &mon1, &mon2, &mon3, &mon4, &mon5, &mon6, &mon7, &mon8, &mon9, &mon10, &item1, &item2, &item3, &lvl, &dun_type)) return (1);
-
- /* Save the values */
- v_ptr->mon[0] = mon1;
- v_ptr->mon[1] = mon2;
- v_ptr->mon[2] = mon3;
- v_ptr->mon[3] = mon4;
- v_ptr->mon[4] = mon5;
- v_ptr->mon[5] = mon6;
- v_ptr->mon[6] = mon7;
- v_ptr->mon[7] = mon8;
- v_ptr->mon[8] = mon9;
- v_ptr->mon[9] = mon10;
- v_ptr->item[0] = item1;
- v_ptr->item[1] = item2;
- v_ptr->item[2] = item3;
- v_ptr->lvl = lvl;
- v_ptr->dun_type = dun_type;
-
- /* Next... */
- continue;
- }
-
-
- /* Oops */
- return (6);
- }
-
-
- /* Complete the "name" and "text" sizes */
- if (!start)
- {
- ++v_head->name_size;
- ++v_head->text_size;
- }
-
-
- /* No version yet */
- if (!okay) return (2);
-
-
- /* Success */
- return (0);
-}
-
-
-/*
- * Grab one flag in an feature_type from a textual string
- */
-static errr grab_one_feature_flag(feature_type *f_ptr, cptr what)
-{
- int i;
-
- /* Check flags1 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, f_info_flags1[i]))
- {
- f_ptr->flags1 |= (1L << i);
- return (0);
- }
- }
-
- /* Oops */
- msg_format("Unknown object flag '%s'.", what);
-
- /* Error */
- return (1);
-}
-
-
-/*
- * Initialize the "f_info" array, by parsing an ascii "template" file
- */
-errr init_f_info_txt(FILE *fp, char *buf)
-{
- int i;
-
- char *s, *t;
-
- /* Not ready yet */
- bool_ okay = FALSE;
- u32b default_desc = 0, default_tunnel = 0, default_block = 0;
-
- /* Current entry */
- feature_type *f_ptr = NULL;
-
-
- /* Just before the first record */
- error_idx = -1;
-
- /* Just before the first line */
- error_line = -1;
-
-
- /* Prepare the "fake" stuff */
- f_head->name_size = 0;
- f_head->text_size = 0;
-
- /* Add some fake descs */
- default_desc = ++f_head->text_size;
- strcpy(f_text + f_head->text_size, "a wall blocking your way");
- f_head->text_size += strlen("a wall blocking your way");
-
- default_tunnel = ++f_head->text_size;
- strcpy(f_text + f_head->text_size, "You cannot tunnel through that.");
- f_head->text_size += strlen("You cannot tunnel through that.");
-
- default_block = ++f_head->text_size;
- strcpy(f_text + f_head->text_size, "a wall blocking your way");
- f_head->text_size += strlen("a wall blocking your way");
-
- /* Parse */
- fp_stack_init(fp);
- while (0 == my_fgets_dostack(buf, 1024))
- {
- /* Advance the line number */
- error_line++;
-
- /* Skip comments and blank lines */
- if (!buf[0] || (buf[0] == '#')) continue;
-
- /* Verify correct "colon" format */
- if (buf[1] != ':') return (1);
-
-
- /* Hack -- Process 'V' for "Version" */
- if (buf[0] == 'V')
- {
- int v1, v2, v3;
-
- /* Scan for the values */
- if (3 != sscanf(buf + 2, "%d.%d.%d", &v1, &v2, &v3)) return (2);
-
- /* Okay to proceed */
- okay = TRUE;
-
- /* Continue */
- continue;
- }
-
- /* No version yet */
- if (!okay) return (2);
-
- /* Included file */
- if (buf[0] == '<')
- {
- fp_stack_push(buf + 2);
- continue;
- }
-
- /* Process 'N' for "New/Number/Name" */
- if (buf[0] == 'N')
- {
- /* Find the colon before the name */
- s = strchr(buf + 2, ':');
-
- /* Verify that colon */
- if (!s) return (1);
-
- /* Nuke the colon, advance to the name */
- *s++ = '\0';
-
- /* Paranoia -- require a name */
- if (!*s) return (1);
-
- /* Get the index */
- i = atoi(buf + 2);
-
- /* Verify information */
- if (i <= error_idx) return (4);
-
- /* Verify information */
- if (i >= f_head->info_num) return (2);
-
- /* Save the index */
- error_idx = i;
-
- /* Point at the "info" */
- f_ptr = &f_info[i];
-
- /* Hack -- Verify space */
- 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;
-
- /* Append chars to the name */
- strcpy(f_name + f_head->name_size, s);
-
- /* Advance the index */
- f_head->name_size += strlen(s);
-
- /* Default "mimic" */
- f_ptr->mimic = i;
- f_ptr->text = default_desc;
- f_ptr->block = default_desc;
- f_ptr->tunnel = default_tunnel;
- f_ptr->block = default_block;
-
- /* Next... */
- continue;
- }
-
- /* There better be a current f_ptr */
- if (!f_ptr) return (3);
-
-
- /* Process 'D' for "Descriptions" */
- if (buf[0] == 'D')
- {
- /* Acquire the text */
- s = buf + 4;
-
- /* Hack -- Verify space */
- if (f_head->text_size + strlen(s) + 8 > fake_text_size) return (7);
-
- switch (buf[2])
- {
- case '0':
- /* Advance and Save the text index */
- f_ptr->text = ++f_head->text_size;
- break;
- case '1':
- /* Advance and Save the text index */
- f_ptr->tunnel = ++f_head->text_size;
- break;
- case '2':
- /* Advance and Save the text index */
- f_ptr->block = ++f_head->text_size;
- break;
- default:
- return (6);
- break;
- }
-
- /* Append chars to the name */
- strcpy(f_text + f_head->text_size, s);
-
- /* Advance the index */
- f_head->text_size += strlen(s);
-
- /* Next... */
- continue;
- }
-
-
- /* Process 'M' for "Mimic" (one line only) */
- if (buf[0] == 'M')
- {
- int mimic;
-
- /* Scan for the values */
- if (1 != sscanf(buf + 2, "%d",
- &mimic)) return (1);
-
- /* Save the values */
- f_ptr->mimic = mimic;
-
- /* Next... */
- continue;
- }
-
- /* Process 'S' for "Shimmer" (one line only) */
- if (buf[0] == 'S')
- {
- char s0, s1, s2, s3, s4, s5, s6;
-
- /* Scan for the values */
- if (7 != sscanf(buf + 2, "%c:%c:%c:%c:%c:%c:%c",
- &s0, &s1, &s2, &s3, &s4, &s5, &s6)) return (1);
-
- /* Save the values */
- f_ptr->shimmer[0] = color_char_to_attr(s0);
- f_ptr->shimmer[1] = color_char_to_attr(s1);
- f_ptr->shimmer[2] = color_char_to_attr(s2);
- f_ptr->shimmer[3] = color_char_to_attr(s3);
- f_ptr->shimmer[4] = color_char_to_attr(s4);
- f_ptr->shimmer[5] = color_char_to_attr(s5);
- f_ptr->shimmer[6] = color_char_to_attr(s6);
-
- /* Next... */
- continue;
- }
-
-
- /* Process 'G' for "Graphics" (one line only) */
- if (buf[0] == 'G')
- {
- int tmp;
-
- /* Paranoia */
- if (!buf[2]) return (1);
- if (!buf[3]) return (1);
- if (!buf[4]) return (1);
-
- /* Extract the color */
- tmp = color_char_to_attr(buf[4]);
-
- /* Paranoia */
- if (tmp < 0) return (1);
-
- /* Save the values */
- f_ptr->d_attr = tmp;
- f_ptr->d_char = buf[2];
-
- /* Next... */
- continue;
- }
-
- /* Process 'E' for "Effects" (up to four lines) -SC- */
- if (buf[0] == 'E')
- {
- int side, dice, freq, type;
- cptr tmp;
-
- /* Find the next empty blow slot (if any) */
- for (i = 0; i < 4; i++) if ((!f_ptr->d_side[i]) &&
- (!f_ptr->d_dice[i])) break;
-
- /* Oops, no more slots */
- if (i == 4) return (1);
-
- /* Scan for the values */
- if (4 != sscanf(buf + 2, "%dd%d:%d:%d",
- &dice, &side, &freq, &type))
- {
- int j;
-
- if (3 != sscanf(buf + 2, "%dd%d:%d",
- &dice, &side, &freq)) return (1);
-
- tmp = buf + 2;
- for (j = 0; j < 2; j++)
- {
- tmp = strchr(tmp, ':');
- if (tmp == NULL) return (1);
- tmp++;
- }
-
- j = 0;
-
- while (d_info_dtypes[j].name != NULL)
- if (strcmp(d_info_dtypes[j].name, tmp) == 0)
- {
- f_ptr->d_type[i] = d_info_dtypes[j].feat;
- break;
- }
- else j++;
-
- if (d_info_dtypes[j].name == NULL) return (1);
- }
- else
- f_ptr->d_type[i] = type;
-
- freq *= 10;
- /* Save the values */
- f_ptr->d_side[i] = side;
- f_ptr->d_dice[i] = dice;
- f_ptr->d_frequency[i] = freq;
-
- /* Next... */
- continue;
- }
-
- /* Hack -- Process 'F' for flags */
- if (buf[0] == 'F')
- {
- /* Parse every entry textually */
- for (s = buf + 2; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while (*t == ' ' || *t == '|') t++;
- }
-
- /* Parse this entry */
- if (0 != grab_one_feature_flag(f_ptr, s)) return (5);
-
- /* Start the next entry */
- s = t;
- }
-
- /* Next... */
- continue;
- }
-
-
-
- /* Oops */
- return (6);
- }
-
-
- /* Complete the "name" and "text" sizes */
- ++f_head->name_size;
- ++f_head->text_size;
-
-
- /* No version yet */
- if (!okay) return (2);
-
-
- /* Success */
- return (0);
-}
-
-
-/*
- * Grab one flag in an object_kind from a textual string
- */
-static errr grab_one_kind_flag(object_kind *k_ptr, cptr what, bool_ obvious)
-{
- int i;
-
- /* Check flags1 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, k_info_flags1[i]))
- {
- if (obvious)
- k_ptr->oflags1 |= (1L << i);
- else
- k_ptr->flags1 |= (1L << i);
- return (0);
- }
- }
-
- /* Check flags2 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, k_info_flags2[i]))
- {
- if (obvious)
- k_ptr->oflags2 |= (1L << i);
- else
- k_ptr->flags2 |= (1L << i);
- return (0);
- }
- }
-
- /* Check flags2 -- traps*/
- for (i = 0; i < 32; i++)
- {
- if (streq(what, k_info_flags2_trap[i]))
- {
- if (obvious)
- k_ptr->oflags2 |= (1L << i);
- else
- k_ptr->flags2 |= (1L << i);
- return (0);
- }
- }
-
- /* Check flags3 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, k_info_flags3[i]))
- {
- if (obvious)
- k_ptr->oflags3 |= (1L << i);
- else
- k_ptr->flags3 |= (1L << i);
- return (0);
- }
- }
-
- /* Check flags4 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, k_info_flags4[i]))
- {
- if (obvious)
- k_ptr->oflags4 |= (1L << i);
- else
- k_ptr->flags4 |= (1L << i);
- return (0);
- }
- }
-
- /* Check flags5 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, k_info_flags5[i]))
- {
- if (obvious)
- k_ptr->oflags5 |= (1L << i);
- else
- k_ptr->flags5 |= (1L << i);
- return (0);
- }
- }
-
- /* Check esp_flags */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, esp_flags[i]))
- {
- if (obvious)
- k_ptr->oesp |= (1L << i);
- else
- k_ptr->esp |= (1L << i);
- return (0);
- }
- }
-
- /* Oops */
- msg_format("Unknown object flag '%s'.", what);
-
- /* Error */
- return (1);
-}
-
-/*
- * Initialize the "k_info" array, by parsing an ascii "template" file
- */
-errr init_k_info_txt(FILE *fp, char *buf)
-{
- int i;
-
- char *s, *t;
-
- /* Not ready yet */
- bool_ okay = FALSE;
-
- /* Current entry */
- object_kind *k_ptr = NULL;
-
-
- /* Just before the first record */
- error_idx = -1;
-
- /* Just before the first line */
- error_line = -1;
-
-
- /* Prepare the "fake" stuff */
- k_head->name_size = 0;
- k_head->text_size = 0;
-
- /* Parse */
- fp_stack_init(fp);
- while (0 == my_fgets_dostack(buf, 1024))
- {
- /* Advance the line number */
- error_line++;
-
- /* Skip comments and blank lines */
- if (!buf[0] || (buf[0] == '#')) continue;
-
- /* Verify correct "colon" format */
- if (buf[1] != ':') return (1);
-
-
- /* Hack -- Process 'V' for "Version" */
- if (buf[0] == 'V')
- {
- int v1, v2, v3;
-
- /* Scan for the values */
- if (3 != sscanf(buf + 2, "%d.%d.%d", &v1, &v2, &v3)) return (2);
-
- /* Okay to proceed */
- okay = TRUE;
-
- /* Continue */
- continue;
- }
-
- /* No version yet */
- if (!okay) return (2);
-
- /* Included file */
- if (buf[0] == '<')
- {
- fp_stack_push(buf + 2);
- continue;
- }
-
- /* Process 'N' for "New/Number/Name" */
- if (buf[0] == 'N')
- {
- /* Find the colon before the name */
- s = strchr(buf + 2, ':');
-
- /* Verify that colon */
- if (!s) return (1);
-
- /* Nuke the colon, advance to the name */
- *s++ = '\0';
-
- /* Paranoia -- require a name */
- if (!*s) return (1);
-
- /* Get the index */
- i = atoi(buf + 2);
-
- /* Verify information */
- if (i <= error_idx) return (4);
-
- /* Verify information */
- if (i >= k_head->info_num) return (2);
-
- /* Save the index */
- error_idx = i;
-
- /* Point at the "info" */
- k_ptr = &k_info[i];
-
- /* Hack -- Verify space */
- 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;
-
- /* Append chars to the name */
- strcpy(k_name + k_head->name_size, s);
-
- /* Advance the index */
- k_head->name_size += strlen(s);
-
- /* Needed hack */
- k_ptr->esp = 0;
- k_ptr->power = -1;
-
- /* Next... */
- continue;
- }
-
- /* There better be a current k_ptr */
- if (!k_ptr) return (3);
-
- /* Process 'D' for "Description" */
- if (buf[0] == 'D')
- {
- /* Acquire the text */
- s = buf + 2;
-
- /* Hack -- Verify space */
- 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;
-
- /* Append a space if needed */
- else if (k_text[k_head->text_size - 1] != ' ')
- {
- /* Append chars to the name */
- strcpy(k_text + k_head->text_size, " ");
-
- /* Advance the index */
- k_head->text_size += 1;
- }
-
- /* Append chars to the name */
- strcpy(k_text + k_head->text_size, s);
-
- /* Advance the index */
- k_head->text_size += strlen(s);
-
- /* Next... */
- continue;
- }
-
- /* Process 'G' for "Graphics" (one line only) */
- if (buf[0] == 'G')
- {
- char sym;
- int tmp;
-
- /* Paranoia */
- if (!buf[2]) return (1);
- if (!buf[3]) return (1);
- if (!buf[4]) return (1);
-
- /* Extract the char */
- sym = buf[2];
-
- /* Extract the attr */
- tmp = color_char_to_attr(buf[4]);
-
- /* Paranoia */
- if (tmp < 0) return (1);
-
- /* Save the values */
- k_ptr->d_attr = tmp;
- k_ptr->d_char = sym;
-
- /* Next... */
- continue;
- }
-
- /* Process 'I' for "Info" (one line only) */
- if (buf[0] == 'I')
- {
- int tval, sval, pval, pval2 = 0;
-
- /* Scan for the values */
- if (4 != sscanf(buf + 2, "%d:%d:%d:%d",
- &tval, &sval, &pval, &pval2))
- {
- char spl[70];
-
- if (4 != sscanf(buf + 2, "%d:%d:%d:SPELL=%s",
- &tval, &sval, &pval, spl))
- {
- if (3 != sscanf(buf + 2, "%d:%d:%d",
- &tval, &sval, &pval))
- return (1);
- }
- else
- {
- char *spl = strchr(buf + 2, '=') + 1;
-
- pval2 = find_spell(spl);
- }
- }
-
- /* Save the values */
- k_ptr->tval = tval;
- k_ptr->sval = sval;
- k_ptr->pval = pval;
- k_ptr->pval2 = pval2;
-
- /* Next... */
- continue;
- }
-
- /* Process 'W' for "More Info" (one line only) */
- if (buf[0] == 'W')
- {
- int level, extra, wgt;
- long cost;
-
- /* Scan for the values */
- if (4 != sscanf(buf + 2, "%d:%d:%d:%ld",
- &level, &extra, &wgt, &cost)) return (1);
-
- /* Save the values */
- k_ptr->level = level;
- k_ptr->extra = extra;
- k_ptr->weight = wgt;
- k_ptr->cost = cost;
-
- /* Next... */
- continue;
- }
-
- /* Process 'T' for "arTifact Info" (one line only) */
- if (buf[0] == 'T')
- {
- int btval, bsval;
-
- /* Scan for the values */
- if (2 != sscanf(buf + 2, "%d:%d",
- &btval, &bsval)) return (1);
-
- /* Save the values */
- k_ptr->btval = btval;
- k_ptr->bsval = bsval;
-
- /* Next... */
- continue;
- }
-
- /* Process 'Z' for "Granted power" */
- if (buf[0] == 'Z')
- {
- int i;
-
- /* Acquire the text */
- s = buf + 2;
-
- /* Find it in the list */
- for (i = 0; i < power_max; i++)
- {
- if (!stricmp(s, powers_type[i].name)) break;
- }
-
- if (i == power_max) return (6);
-
- k_ptr->power = i;
-
- /* Next... */
- continue;
- }
-
- /* Process 'a' for Activation */
- if ( buf[0] == 'a')
- {
- if (prefix(buf + 2, "HARDCORE="))
- {
- k_ptr->activate = get_activation(buf + 11);
- if (k_ptr->activate == -1)
- return 1;
- }
- else if (prefix(buf + 2, "SPELL="))
- {
- k_ptr->activate = -find_spell(buf + 8);
- if (k_ptr->activate == -( -1))
- return 1;
- }
-
- /* Next... */
- continue;
- }
-
- /* Process 'A' for "Allocation" (one line only) */
- if (buf[0] == 'A')
- {
- int i;
-
- /* XXX XXX XXX Simply read each number following a colon */
- for (i = 0, s = buf + 1; s && (s[0] == ':') && s[1]; ++i)
- {
- /* Default chance */
- k_ptr->chance[i] = 1;
-
- /* Store the level */
- k_ptr->locale[i] = atoi(s + 1);
-
- /* Find the slash */
- t = strchr(s + 1, '/');
-
- /* Find the next colon */
- s = strchr(s + 1, ':');
-
- /* If the slash is "nearby", use it */
- if (t && (!s || t < s))
- {
- int chance = atoi(t + 1);
- if (chance > 0) k_ptr->chance[i] = chance;
- }
- }
-
- /* Next... */
- continue;
- }
-
- /* Hack -- Process 'P' for "power" and such */
- if (buf[0] == 'P')
- {
- int ac, hd1, hd2, th, td, ta;
-
- /* Scan for the values */
- if (6 != sscanf(buf + 2, "%d:%dd%d:%d:%d:%d",
- &ac, &hd1, &hd2, &th, &td, &ta)) return (1);
-
- k_ptr->ac = ac;
- k_ptr->dd = hd1;
- k_ptr->ds = hd2;
- k_ptr->to_h = th;
- k_ptr->to_d = td;
- k_ptr->to_a = ta;
-
- /* Next... */
- continue;
- }
-
- /* Hack -- Process 'F' for flags */
- if (buf[0] == 'F')
- {
- /* Parse every entry textually */
- for (s = buf + 2; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while (*t == ' ' || *t == '|') t++;
- }
-
- /* Parse this entry */
- if (0 != grab_one_kind_flag(k_ptr, s, FALSE)) return (5);
-
- /* Start the next entry */
- s = t;
- }
-
- /* Next... */
- continue;
- }
-
- /* Hack -- Process 'f' for obvious flags */
- if (buf[0] == 'f')
- {
- /* Parse every entry textually */
- for (s = buf + 2; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while (*t == ' ' || *t == '|') t++;
- }
-
- /* Parse this entry */
- if (0 != grab_one_kind_flag(k_ptr, s, TRUE)) return (5);
-
- /* Start the next entry */
- s = t;
- }
-
- /* Next... */
- continue;
- }
-
-
- /* Oops */
- return (6);
- }
-
-
- /* Complete the "name" and "text" sizes */
- ++k_head->name_size;
- ++k_head->text_size;
-
-
- /* No version yet */
- if (!okay) return (2);
-
-
- /* Success */
- return (0);
-}
-
-/*Get a kind flag, return flag*32+bit number or -1 for unknown*/
-
-int get_k_flag(char *what)
-{
- int i;
-
- /* Check flags1 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, k_info_flags1[i]))
- return i;
- if (streq(what, k_info_flags2[i]))
- return 1*32 + i;
- if (streq(what, k_info_flags2_trap[i]))
- return 1*32 + i;
- if (streq(what, k_info_flags3[i]))
- return 2*32 + i;
- if (streq(what, k_info_flags4[i]))
- return 3*32 + i;
- if (streq(what, k_info_flags5[i]))
- return 4*32 + i;
- if (streq(what, esp_flags[i]))
- return 5*32 + i;
- }
-
- /* Oops */
- msg_format("Unknown object flag '%s'.", what);
-
- /* Error */
- return ( -1);
-
-}
-
-int get_r_flag(char *what)
-{
- int i;
-
- /* Check flags */
- /* this processes all r_info_flag arrays in parallel.
- Seemed like a good idea at the time..
- */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, r_info_flags1[i]))
- return i;
- if (streq(what, r_info_flags2[i]))
- return 1*32 + i;
- if (streq(what, r_info_flags3[i]))
- return 2*32 + i;
- if (streq(what, r_info_flags4[i]))
- return 3*32 + i;
- if (streq(what, r_info_flags5[i]))
- return 4*32 + i;
- if (streq(what, r_info_flags6[i]))
- return 5*32 + i;
- if (streq(what, r_info_flags7[i]))
- return 6*32 + i;
- if (streq(what, r_info_flags8[i]))
- return 7*32 + i;
- if (streq(what, r_info_flags9[i]))
- return 8*32 + i;
- }
-
- /* Oops */
- msg_format("Unknown race flag '%s'.", what);
-
- /* Error */
- return ( -1);
-}
-int init_al_info_essence(char *essence)
-{
- int i;
- for ( i = 0 ; essence_names[i][0] ; i++)
- if (!strncmp(essence_names[i], essence, 9))
- {
- return i;
- }
- return -1;
-}
-/*
- * Initialize the "al_info" array, by parsing an ascii "template" file
- */
-errr init_al_info_txt(FILE *fp, char *buf)
-{
- int al_idx = 0, a_idx = 0;
- char *s, *t;
- struct artifact_select_flag *a_ptr = NULL;
-
- /* Not ready yet */
- bool_ okay = FALSE;
-
- /* Just before the first record */
- error_idx = -1;
-
- /* Just before the first line */
- error_line = -1;
-
- /* Fun! */
- al_head->name_size = 0;
- *al_name = 0;
-
- /* Parse */
- fp_stack_init(fp);
- while (0 == my_fgets_dostack(buf, 1024))
- {
- /* Advance the line number */
- error_line++;
-
- /* Skip comments and blank lines */
- if (!buf[0] || (buf[0] == '#')) continue;
-
- /* Verify correct "colon" format */
- if (buf[1] != ':') return (1);
-
- /* Hack -- Process 'V' for "Version" */
- if (buf[0] == 'V')
- {
- int v1, v2, v3;
-
- /* Scan for the values */
- if (3 != sscanf(buf + 2, "%d.%d.%d", &v1, &v2, &v3)) return (2);
-
- /* Okay to proceed */
- okay = TRUE;
-
- /* Continue */
- continue;
- }
-
- /* No version yet */
- if (!okay) return (2);
-
- /* Included file */
- if (buf[0] == '<')
- {
- fp_stack_push(buf + 2);
- continue;
- }
-
- /* Process 'I' for "Info" (one line only) */
- if (buf[0] == 'I')
- {
- int tval, sval, qty;
-
- /* Scan for the values */
- if (3 != sscanf(buf + 2, "%d:%d:%d",
- &tval, &sval, &qty))
- {
- return (1);
- }
-
- /* ignore everything after the first space. */
- s = strchr(buf, ' ');
- if (s != NULL)
- *s = 0;
-
- /* Save the values */
- alchemist_recipes[al_idx].tval = tval;
- alchemist_recipes[al_idx].sval = sval;
- alchemist_recipes[al_idx].qty = qty;
- alchemist_recipes[al_idx].sval_essence = init_al_info_essence(strrchr(buf, ':') + 1);
- if (alchemist_recipes[al_idx].sval_essence < 0)
- return 5;
-
- al_idx++;
- if (al_idx >= max_al_idx)
- return 7;
- /* Next... */
- continue;
- }
- if (buf[0] == 'a')
- {
- int qty;
- if ( 1 != sscanf(buf + 2, "%d", &qty))
- {
- return (1);
- }
- s = strrchr(buf, ':');
- *(s++) = 0;
- t = strchr(s, ' ');
- *(t++) = 0;
- alchemist_recipes[al_idx].tval = 0;
- alchemist_recipes[al_idx].sval = get_k_flag(s);
- alchemist_recipes[al_idx].qty = qty;
- alchemist_recipes[al_idx].sval_essence = init_al_info_essence(t);
- if (alchemist_recipes[al_idx].sval_essence < 0)
- return 1;
-
- al_idx++;
- if (al_idx >= max_al_idx)
- return 7; /* 7 is an 'out of memory' error */
-
- continue;
- }
- if (buf[0] == 'A')
- {
- int group, level, pval, rtval, rsval, rpval;
- long xp;
- /*Verify that complete description information is
- Recorded for previous Artifact flag
- */
- if (a_ptr
- && (!a_ptr->group || !a_ptr->desc || !a_ptr->item_desc != !a_ptr->rtval)
- )
- return (1);
-
- a_ptr = &a_select_flags[a_idx++];
-
- if ( 7 != sscanf(buf + 2, "%d:%d:%d:%d:%d:%d:%ld",
- &group, &rtval, &rsval, &rpval, &pval, &level, &xp))
- return (1);
- a_ptr->group = group;
- a_ptr->rtval = rtval;
- a_ptr->rsval = rsval;
- a_ptr->rpval = rpval;
- a_ptr->pval = pval;
- a_ptr->level = level;
- a_ptr->xp = xp;
- continue;
- }
-
- /*Anything else here MUST be a artifact flag line*/
- if ( !a_ptr)
- return (3);
-
- if (buf[0] == 'F')
- {
- /* Get the Item flag associated with this */
- a_ptr->flag = get_k_flag(buf + 2);
- if (a_ptr->flag == -1)
- return (1);
- continue;
- }
- if (buf[0] == 'x')
- {
- /* Get the activation name associated with this */
- a_ptr->flag = -get_activation(buf + 2);
- if (a_ptr->flag == 1)
- return (1);
- a_ptr->group = 88;
- a_ptr->pval = 0;
- continue;
- }
- /* Get the race flags associated with this */
- if (buf[0] == 'f')
- {
- char *s, *t;
- int idx = 0;
-
- if ( a_ptr->rflag[0] )
- {
- msg_print("duplicate f: entries for one corpse");
- return (5);
- }
-
- if ( a_ptr->rtval != TV_CORPSE )
- {
- msg_print("f: section for corpse flags only");
- return (5);
- }
- if ( a_ptr->rpval )
- {
- msg_print("Can't specify r_info.txt index with f: section");
- return (5);
- }
-
- /* Parse every entry textually */
- for (s = buf + 2; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while ((*t == ' ') || (*t == '|')) t++;
- }
-
- if ( idx > 5 )
- {
- msg_print("Limit on race flags is currently 6");
- return (5);
- }
-
- /* Parse this entry */
- a_ptr->rflag[idx] = get_r_flag(s);
- if (a_ptr->rflag[idx++] == -1)
- return (5);
-
- /* Start the next entry */
- s = t;
- }
-
- /* Next... */
- continue;
- }
-
- /* Process 'p' for "Plural Description" */
- /* Only valid for flag which depend on pval */
- if (buf[0] == 'p')
- {
- /* Reject if doesn't depend on pval */
-
- if (!a_ptr->pval)
- return (1);
-
- /* Acquire the description */
- s = buf + 2;
-
- /* Hack -- Verify space */
- 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;
-
- /* Append chars to the name */
- strcpy(al_name + al_head->name_size, s);
-
- /* Advance the index */
- al_head->name_size += strlen(s);
-
- /* Next... */
- continue;
- }
-
- /* Process 'D' for "Description" */
- if (buf[0] == 'D')
- {
- /* Acquire the description */
- s = buf + 2;
-
- /* Hack -- Verify space */
- 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;
-
- /* Append chars to the name */
- strcpy(al_name + al_head->name_size, s);
-
- /* Advance the index */
- al_head->name_size += strlen(s);
-
- /* Next... */
- continue;
- }
-
- /* Process 'd' for "Item Description" */
- if (buf[0] == 'd')
- {
- /* Acquire the name */
- s = buf + 2;
-
- /* Hack -- Verify space */
- if (al_head->name_size + strlen(s) + 8 > fake_name_size) return (7);
-
- if (a_ptr->item_desc)
- return (7);
-
- /* Advance and Save the name index */
- a_ptr->item_desc = ++al_head->name_size;
-
- /* Append chars to the name */
- strcpy(al_name + al_head->name_size, s);
-
- /* Advance the index */
- al_head->name_size += strlen(s);
-
- /* Next... */
- continue;
- }
-
- /* Oops */
- return (6);
- }
-
- /* No version yet */
- if (!okay) return (2);
-
- /* Hack - set the al_head->text_size to byte size of array */
- al_head->text_size = (a_idx + 1) * sizeof(artifact_select_flag);
-
- /* Success */
- return (0);
-}
-
-/*
- * Grab one flag in an artifact_type from a textual string
- */
-static errr grab_one_artifact_flag(artifact_type *a_ptr, cptr what, bool_ obvious)
-{
- int i;
-
- /* Check flags1 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, k_info_flags1[i]))
- {
- if (obvious)
- a_ptr->oflags1 |= (1L << i);
- else
- a_ptr->flags1 |= (1L << i);
- return (0);
- }
- }
-
- /* Check flags2 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, k_info_flags2[i]))
- {
- if (obvious)
- a_ptr->oflags2 |= (1L << i);
- else
- a_ptr->flags2 |= (1L << i);
- return (0);
- }
- }
-
- /* Check flags2 -- traps*/
- for (i = 0; i < 32; i++)
- {
- if (streq(what, k_info_flags2_trap[i]))
- {
- if (obvious)
- a_ptr->oflags2 |= (1L << i);
- else
- a_ptr->flags2 |= (1L << i);
- return (0);
- }
- }
-
- /* Check flags3 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, k_info_flags3[i]))
- {
- if (obvious)
- a_ptr->oflags3 |= (1L << i);
- else
- a_ptr->flags3 |= (1L << i);
- return (0);
- }
- }
-
- /* Check flags4 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, k_info_flags4[i]))
- {
- if (obvious)
- a_ptr->oflags4 |= (1L << i);
- else
- a_ptr->flags4 |= (1L << i);
- return (0);
- }
- }
-
- /* Check flags5 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, k_info_flags5[i]))
- {
- if (obvious)
- a_ptr->oflags5 |= (1L << i);
- else
- a_ptr->flags5 |= (1L << i);
- return (0);
- }
- }
-
- /* Check esp_flags */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, esp_flags[i]))
- {
- if (obvious)
- a_ptr->oesp |= (1L << i);
- else
- a_ptr->esp |= (1L << i);
- return (0);
- }
- }
-
- /* Oops */
- msg_format("Unknown artifact flag '%s'.", what);
-
- /* Error */
- return (1);
-}
-
-
-
-
-/*
- * Initialize the "a_info" array, by parsing an ascii "template" file
- */
-errr init_a_info_txt(FILE *fp, char *buf)
-{
- int i;
-
- char *s, *t;
-
- /* Not ready yet */
- bool_ okay = FALSE;
-
- /* Current entry */
- artifact_type *a_ptr = NULL;
-
-
- /* Just before the first record */
- error_idx = -1;
-
- /* Just before the first line */
- error_line = -1;
-
-
- /* Parse */
- fp_stack_init(fp);
- while (0 == my_fgets_dostack(buf, 1024))
- {
- /* Advance the line number */
- error_line++;
-
- /* Skip comments and blank lines */
- if (!buf[0] || (buf[0] == '#')) continue;
-
- /* Verify correct "colon" format */
- if (buf[1] != ':') return (1);
-
-
- /* Hack -- Process 'V' for "Version" */
- if (buf[0] == 'V')
- {
- int v1, v2, v3;
-
- /* Scan for the values */
- if (3 != sscanf(buf + 2, "%d.%d.%d", &v1, &v2, &v3)) return (2);
-
- /* Okay to proceed */
- okay = TRUE;
-
- /* Continue */
- continue;
- }
-
- /* No version yet */
- if (!okay) return (2);
-
- /* Included file */
- if (buf[0] == '<')
- {
- fp_stack_push(buf + 2);
- continue;
- }
-
- /* Process 'N' for "New/Number/Name" */
- if (buf[0] == 'N')
- {
- /* Find the colon before the name */
- s = strchr(buf + 2, ':');
-
- /* Verify that colon */
- if (!s) return (1);
-
- /* Nuke the colon, advance to the name */
- *s++ = '\0';
-
- /* Paranoia -- require a name */
- if (!*s) return (1);
-
- /* Get the index */
- i = atoi(buf + 2);
-
- /* Verify information */
- if (i < error_idx) return (4);
-
- /* Verify information */
- if (i >= a_head->info_num) return (2);
-
- /* Save the index */
- error_idx = i;
-
- /* Point at the "info" */
- a_ptr = &a_info[i];
-
- /* Hack -- Verify space */
- 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;
-
- /* Append chars to the name */
- strcpy(a_name + a_head->name_size, s);
-
- /* Advance the index */
- a_head->name_size += strlen(s);
-
- /* Ignore everything */
- a_ptr->flags3 |= (TR3_IGNORE_ACID);
- a_ptr->flags3 |= (TR3_IGNORE_ELEC);
- a_ptr->flags3 |= (TR3_IGNORE_FIRE);
- a_ptr->flags3 |= (TR3_IGNORE_COLD);
-
- /* Needed hack */
- a_ptr->esp = 0;
- a_ptr->power = -1;
-
- /*Require activating artifacts to have a activation type */
- if (a_ptr && a_ptr->flags3 & TR3_ACTIVATE && !a_ptr->activate)
- {
- msg_print("Activate flag without activate type");
- return 1;
- }
-
- /* Next... */
- continue;
- }
-
- /* There better be a current a_ptr */
- if (!a_ptr) return (3);
-
- /* Process 'D' for "Description" */
- if (buf[0] == 'D')
- {
- /* Acquire the text */
- s = buf + 2;
-
- /* Hack -- Verify space */
- 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;
-
- /* Append a space at the end of the line, if needed */
- else if (a_text[a_head->text_size - 1] != ' ')
- {
- /* Append the space */
- strcpy(a_text + a_head->text_size, " ");
-
- /* Advance the index */
- a_head->text_size += 1;
- }
-
- /* Append chars to the name */
- strcpy(a_text + a_head->text_size, s);
-
- /* Advance the index */
- a_head->text_size += strlen(s);
-
- /* Next... */
- continue;
- }
-
- /* Process 'I' for "Info" (one line only) */
- if (buf[0] == 'I')
- {
- int tval, sval, pval;
-
- /* Scan for the values */
- if (3 != sscanf(buf + 2, "%d:%d:%d",
- &tval, &sval, &pval))
- {
- return (1);
- }
-
- /* Save the values */
- a_ptr->tval = tval;
- a_ptr->sval = sval;
- a_ptr->pval = pval;
-
- /* Verify */
- if (!lookup_kind(tval, sval)) return (6);
-
- /* Next... */
- continue;
- }
-
- /* Process 'W' for "More Info" (one line only) */
- if (buf[0] == 'W')
- {
- int level, rarity, wgt;
- long cost;
-
- /* Scan for the values */
- if (4 != sscanf(buf + 2, "%d:%d:%d:%ld",
- &level, &rarity, &wgt, &cost)) return (1);
-
- /* Save the values */
- a_ptr->level = level;
- a_ptr->rarity = rarity;
- a_ptr->weight = wgt;
- a_ptr->cost = cost;
-
- /* Next... */
- continue;
- }
-
- /* Hack -- Process 'P' for "power" and such */
- if (buf[0] == 'P')
- {
- int ac, hd1, hd2, th, td, ta;
-
- /* Scan for the values */
- if (6 != sscanf(buf + 2, "%d:%dd%d:%d:%d:%d",
- &ac, &hd1, &hd2, &th, &td, &ta)) return (1);
-
- a_ptr->ac = ac;
- a_ptr->dd = hd1;
- a_ptr->ds = hd2;
- a_ptr->to_h = th;
- a_ptr->to_d = td;
- a_ptr->to_a = ta;
-
- /* Next... */
- continue;
- }
-
- /* Process 'Z' for "Granted power" */
- if (buf[0] == 'Z')
- {
- int i;
-
- /* Acquire the text */
- s = buf + 2;
-
- /* Find it in the list */
- for (i = 0; i < power_max; i++)
- {
- if (!stricmp(s, powers_type[i].name)) break;
- }
-
- if (i == power_max) return (6);
-
- a_ptr->power = i;
-
- /* Next... */
- continue;
- }
-
- /* Hack -- Process 'F' for flags */
- if (buf[0] == 'F')
- {
- /* Parse every entry textually */
- for (s = buf + 2; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while ((*t == ' ') || (*t == '|')) t++;
- }
-
- /* Parse this entry */
- if (0 != grab_one_artifact_flag(a_ptr, s, FALSE)) return (5);
-
- /* Start the next entry */
- s = t;
- }
-
- /* Next... */
- continue;
- }
-
- /* Hack -- Process 'f' for obvious flags */
- if (buf[0] == 'f')
- {
- /* Parse every entry textually */
- for (s = buf + 2; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while (*t == ' ' || *t == '|') t++;
- }
-
- /* Parse this entry */
- if (0 != grab_one_artifact_flag(a_ptr, s, TRUE)) return (5);
-
- /* Start the next entry */
- s = t;
- }
-
- /* Next... */
- continue;
- }
-
- /* Read activation type. */
- if (buf[0] == 'a')
- {
- if (prefix(buf + 2, "HARDCORE="))
- {
- a_ptr->activate = get_activation(buf + 11);
- if (a_ptr->activate == -1)
- return 1;
- }
- else if (prefix(buf + 2, "SPELL="))
- {
- a_ptr->activate = -find_spell(buf + 8);
- if (a_ptr->activate == -( -1))
- return 1;
- }
-
- /* Next... */
- continue;
- }
-
-
- /* Oops */
- return (6);
- }
-
-
- /* Complete the "name" and "text" sizes */
- ++a_head->name_size;
- ++a_head->text_size;
-
-
- /* No version yet */
- if (!okay) return (2);
-
-
- /* Success */
- return (0);
-}
-
-/*
-* Initialize the "set_info" array, by parsing an ascii "template" file
-*/
-errr init_set_info_txt(FILE *fp, char *buf)
-{
- int i;
- int cur_art = 0, cur_num = 0;
-
- char *s, *t;
-
- /* Not ready yet */
- bool_ okay = FALSE;
-
- /* Current entry */
- set_type *set_ptr = NULL;
-
-
- /* Just before the first record */
- error_idx = -1;
-
- /* Just before the first line */
- error_line = -1;
-
-
- /* Parse */
- fp_stack_init(fp);
- while (0 == my_fgets_dostack(buf, 1024))
- {
- /* Advance the line number */
- error_line++;
-
- /* Skip comments and blank lines */
- if (!buf[0] || (buf[0] == '#')) continue;
-
- /* Verify correct "colon" format */
- if (buf[1] != ':') return (1);
-
-
- /* Hack -- Process 'V' for "Version" */
- if (buf[0] == 'V')
- {
- int v1, v2, v3;
-
- /* Scan for the values */
- if (3 != sscanf(buf + 2, "%d.%d.%d", &v1, &v2, &v3)) return (2);
-
- /* Okay to proceed */
- okay = TRUE;
-
- /* Continue */
- continue;
- }
-
- /* No version yet */
- if (!okay) return (2);
-
- /* Included file */
- if (buf[0] == '<')
- {
- fp_stack_push(buf + 2);
- continue;
- }
-
- /* Process 'N' for "New/Number/Name" */
- if (buf[0] == 'N')
- {
- int z, y;
-
- /* Find the colon before the name */
- s = strchr(buf + 2, ':');
-
- /* Verify that colon */
- if (!s) return (1);
-
- /* Nuke the colon, advance to the name */
- *s++ = '\0';
-
- /* Paranoia -- require a name */
- if (!*s) return (1);
-
- /* Get the index */
- i = atoi(buf + 2);
-
- /* Verify information */
- if (i < error_idx) return (4);
-
- /* Verify information */
- if (i >= set_head->info_num) return (2);
-
- /* Save the index */
- error_idx = i;
-
- /* Point at the "info" */
- set_ptr = &set_info[i];
-
- /* Hack -- Verify space */
- 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;
-
- /* Append chars to the name */
- strcpy(set_name + set_head->name_size, s);
-
- /* Advance the index */
- set_head->name_size += strlen(s);
-
- /* Needed hack */
- set_ptr->num = 0;
- set_ptr->num_use = 0;
- for (z = 0; z < 6; z++)
- {
- set_ptr->arts[z].a_idx = 0;
- set_ptr->arts[z].present = FALSE;
- for (y = 0; y < 6; y++)
- {
- set_ptr->arts[z].flags1[y] = 0;
- set_ptr->arts[z].flags2[y] = 0;
- set_ptr->arts[z].flags3[y] = 0;
- set_ptr->arts[z].flags4[y] = 0;
- set_ptr->arts[z].flags5[y] = 0;
- set_ptr->arts[z].esp[y] = 0;
- set_ptr->arts[z].pval[y] = 0;
- }
- }
-
- /* Next... */
- continue;
- }
-
- /* There better be a current set_ptr */
- if (!set_ptr) return (3);
-
- /* Process 'D' for "Description" */
- if (buf[0] == 'D')
- {
- /* Acquire the text */
- s = buf + 2;
-
- /* Hack -- Verify space */
- 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;
-
- /* Append chars to the name */
- strcpy(set_text + set_head->text_size, s);
-
- /* Advance the index */
- set_head->text_size += strlen(s);
-
- /* Next... */
- continue;
- }
-
- /* Process 'P' for "Power" (up to 6) */
- if (buf[0] == 'P')
- {
- int a_idx, num, pval;
- int z;
-
- /* Scan for the values */
- if (3 != sscanf(buf + 2, "%d:%d:%d",
- &a_idx, &num, &pval))
- {
- return (1);
- }
-
- for (z = 0; z < set_ptr->num; z++)
- if (set_ptr->arts[z].a_idx == a_idx) break;
- if (z == set_ptr->num)
- {
- set_ptr->num++;
- set_ptr->arts[z].a_idx = a_idx;
- }
-
- /* Save the values */
- set_ptr->arts[z].pval[num - 1] = pval;
- cur_art = z;
- cur_num = num - 1;
-
- /* Next... */
- continue;
- }
-
- /* Process 'F' for flags */
- if (buf[0] == 'F')
- {
- /* Parse every entry textually */
- for (s = buf + 2; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while ((*t == ' ') || (*t == '|')) t++;
- }
-
- /* Parse this entry */
- if (0 != grab_one_race_kind_flag(&set_ptr->arts[cur_art].flags1[cur_num],
- &set_ptr->arts[cur_art].flags2[cur_num],
- &set_ptr->arts[cur_art].flags3[cur_num],
- &set_ptr->arts[cur_art].flags4[cur_num],
- &set_ptr->arts[cur_art].flags5[cur_num],
- &set_ptr->arts[cur_art].esp[cur_num],
- s)) return (5);
-
- /* Start the next entry */
- s = t;
- }
-
- /* Next... */
- continue;
- }
-
-
- /* Oops */
- return (6);
- }
-
-
- /* Complete the "name" and "text" sizes */
- ++set_head->name_size;
- ++set_head->text_size;
-
-
- /* No version yet */
- if (!okay) return (2);
-
-
- /* Success */
- return (0);
-}
-
-
-/*
- * Initialize the "s_info" array, by parsing an ascii "template" file
- */
-errr init_s_info_txt(FILE *fp, char *buf)
-{
- int i, z, order = 1;
-
- char *s;
-
- /* Not ready yet */
- bool_ okay = FALSE;
-
- /* Current entry */
- skill_type *s_ptr = NULL;
-
-
- /* Just before the first record */
- error_idx = -1;
-
- /* Just before the first line */
- error_line = -1;
-
-
- /* Parse */
- fp_stack_init(fp);
- while (0 == my_fgets_dostack(buf, 1024))
- {
- /* Advance the line number */
- error_line++;
-
- /* Skip comments and blank lines */
- if (!buf[0] || (buf[0] == '#')) continue;
-
- /* Verify correct "colon" format */
- if (buf[1] != ':') return (1);
-
-
- /* Hack -- Process 'V' for "Version" */
- if (buf[0] == 'V')
- {
- int v1, v2, v3;
-
- /* Scan for the values */
- if (3 != sscanf(buf + 2, "%d.%d.%d", &v1, &v2, &v3)) return (2);
-
- /* Okay to proceed */
- okay = TRUE;
-
- /* Continue */
- continue;
- }
-
- /* No version yet */
- if (!okay) return (2);
-
- /* Included file */
- if (buf[0] == '<')
- {
- fp_stack_push(buf + 2);
- continue;
- }
-
- /* Process 'T' for "skill Tree" */
- if (buf[0] == 'T')
- {
- char *sec;
- s16b s1, s2;
-
- /* Scan for the values */
- if (NULL == (sec = strchr(buf + 2, ':')))
- {
- return (1);
- }
- *sec = '\0';
- sec++;
- if (!*sec) return (1);
-
- s1 = find_skill(buf + 2);
- s2 = find_skill(sec);
- if (s2 == -1) return (1);
-
- s_info[s2].father = s1;
- s_info[s2].order = order++;
-
- /* Next... */
- continue;
- }
-
- /* Process 'E' for "Exclusive" */
- if (buf[0] == 'E')
- {
- char *sec;
- s16b s1, s2;
-
- /* Scan for the values */
- if (NULL == (sec = strchr(buf + 2, ':')))
- {
- return (1);
- }
- *sec = '\0';
- sec++;
- if (!*sec) return (1);
-
- s1 = find_skill(buf + 2);
- s2 = find_skill(sec);
- if ((s1 == -1) || (s2 == -1)) return (1);
-
- s_info[s1].action[s2] = SKILL_EXCLUSIVE;
- s_info[s2].action[s1] = SKILL_EXCLUSIVE;
-
- /* Next... */
- continue;
- }
-
-
- /* Process 'O' for "Opposite" */
- if (buf[0] == 'O')
- {
- char *sec, *cval;
- s16b s1, s2;
-
- /* Scan for the values */
- if (NULL == (sec = strchr(buf + 2, ':')))
- {
- return (1);
- }
- *sec = '\0';
- sec++;
- if (!*sec) return (1);
- if (NULL == (cval = strchr(sec, '%')))
- {
- return (1);
- }
- *cval = '\0';
- cval++;
- if (!*cval) return (1);
-
- s1 = find_skill(buf + 2);
- s2 = find_skill(sec);
- if ((s1 == -1) || (s2 == -1)) return (1);
-
- s_info[s1].action[s2] = -atoi(cval);
-
- /* Next... */
- continue;
- }
-
- /* Process 'A' for "Amical/friendly" */
- if (buf[0] == 'f')
- {
- char *sec, *cval;
- s16b s1, s2;
-
- /* Scan for the values */
- if (NULL == (sec = strchr(buf + 2, ':')))
- {
- return (1);
- }
- *sec = '\0';
- sec++;
- if (!*sec) return (1);
- if (NULL == (cval = strchr(sec, '%')))
- {
- return (1);
- }
- *cval = '\0';
- cval++;
- if (!*cval) return (1);
-
- s1 = find_skill(buf + 2);
- s2 = find_skill(sec);
- if ((s1 == -1) || (s2 == -1)) return (1);
-
- s_info[s1].action[s2] = atoi(cval);
-
- /* Next... */
- continue;
- }
-
- /* Process 'N' for "New/Number/Name" */
- if (buf[0] == 'N')
- {
- /* Find the colon before the name */
- s = strchr(buf + 2, ':');
-
- /* Verify that colon */
- if (!s) return (1);
-
- /* Nuke the colon, advance to the name */
- *s++ = '\0';
-
- /* Paranoia -- require a name */
- if (!*s) return (1);
-
- /* Get the index */
- i = atoi(buf + 2);
-
- /* Verify information */
- if (i >= s_head->info_num) return (2);
-
- /* Save the index */
- error_idx = i;
-
- /* Point at the "info" */
- s_ptr = &s_info[i];
-
- /* Hack -- Verify space */
- 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;
-
- /* Append chars to the name */
- strcpy(s_name + s_head->name_size, s);
-
- /* Advance the index */
- s_head->name_size += strlen(s);
-
- /* Init */
- s_ptr->action_mkey = 0;
- s_ptr->dev = FALSE;
- s_ptr->random_gain_chance = 100;
- for (z = 0; z < max_s_idx; z++)
- {
- s_ptr->action[z] = 0;
- }
-
- /* Next... */
- continue;
- }
-
- /* There better be a current s_ptr */
- if (!s_ptr) return (3);
-
- /* Process 'D' for "Description" */
- if (buf[0] == 'D')
- {
- /* Acquire the text */
- s = buf + 2;
-
- /* Hack -- Verify space */
- if (s_head->text_size + strlen(s) + 8 > fake_text_size) return (7);
-
- /* Advance and Save the text index */
- if (!s_ptr->desc)
- {
- s_ptr->desc = ++s_head->text_size;
-
- /* Append chars to the name */
- strcpy(s_text + s_head->text_size, s);
-
- /* Advance the index */
- s_head->text_size += strlen(s);
- }
- else
- {
- /* Append chars to the name */
- strcpy(s_text + s_head->text_size, format("\n%s", s));
-
- /* Advance the index */
- s_head->text_size += strlen(s) + 1;
- }
-
- /* Next... */
- continue;
- }
-
- /* Process 'A' for "Activation Description" */
- if (buf[0] == 'A')
- {
- char *txt;
-
- /* Acquire the text */
- s = buf + 2;
-
- if (NULL == (txt = strchr(s, ':'))) return (1);
- *txt = '\0';
- txt++;
-
- /* Hack -- Verify space */
- 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;
-
- /* Append chars to the name */
- strcpy(s_text + s_head->text_size, txt);
- s_ptr->action_mkey = atoi(s);
-
- /* Advance the index */
- s_head->text_size += strlen(txt);
-
- /* Next... */
- continue;
- }
-
- /* Process 'I' for "Info" (one line only) */
- if (buf[0] == 'I')
- {
- int rate;
-
- /* Scan for the values */
- if (1 != sscanf(buf + 2, "%d", &rate))
- {
- return (1);
- }
-
- /* Save the values */
- s_ptr->rate = rate;
-
- /* Next... */
- continue;
- }
-
- /* Process 'G' for "random Gain" (one line only) */
- if (buf[0] == 'G')
- {
- int chance;
-
- /* Scan for the values */
- if (1 != sscanf(buf + 2, "%d", &chance))
- {
- return (1);
- }
-
- /* Save the values */
- s_ptr->random_gain_chance = chance;
-
- /* Next... */
- continue;
- }
-
- /* Process 'F' for flags */
- if (buf[0] == 'F')
- {
- char *t;
-
- /* Parse every entry textually */
- for (s = buf + 2; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while ((*t == ' ') || (*t == '|')) t++;
- }
-
- /* Parse this entry */
- if (0 != grab_one_skill_flag(&(s_ptr->flags1), s)) return (5);
-
- /* Start the next entry */
- s = t;
- }
-
- /* Next... */
- continue;
- }
-
- /* Oops */
- return (6);
- }
-
-
- /* Complete the "name" and "text" sizes */
- ++s_head->name_size;
- ++s_head->text_size;
-
-
- /* No version yet */
- if (!okay) return (2);
-
-
- /* Success */
- return (0);
-}
-
-/*
- * Initialize the "ab_info" array, by parsing an ascii "template" file
- */
-errr init_ab_info_txt(FILE *fp, char *buf)
-{
- int i, z;
-
- char *s;
-
- /* Not ready yet */
- bool_ okay = FALSE;
-
- /* Current entry */
- ability_type *ab_ptr = NULL;
-
-
- /* Just before the first record */
- error_idx = -1;
-
- /* Just before the first line */
- error_line = -1;
-
-
- /* Parse */
- fp_stack_init(fp);
- while (0 == my_fgets_dostack(buf, 1024))
- {
- /* Advance the line number */
- error_line++;
-
- /* Skip comments and blank lines */
- if (!buf[0] || (buf[0] == '#')) continue;
-
- /* Verify correct "colon" format */
- if (buf[1] != ':') return (1);
-
-
- /* Hack -- Process 'V' for "Version" */
- if (buf[0] == 'V')
- {
- int v1, v2, v3;
-
- /* Scan for the values */
- if (3 != sscanf(buf + 2, "%d.%d.%d", &v1, &v2, &v3)) return (2);
-
- /* Okay to proceed */
- okay = TRUE;
-
- /* Continue */
- continue;
- }
-
- /* No version yet */
- if (!okay) return (2);
-
- /* Included file */
- if (buf[0] == '<')
- {
- fp_stack_push(buf + 2);
- continue;
- }
-
- /* Process 'N' for "New/Number/Name" */
- if (buf[0] == 'N')
- {
- /* Find the colon before the name */
- s = strchr(buf + 2, ':');
-
- /* Verify that colon */
- if (!s) return (1);
-
- /* Nuke the colon, advance to the name */
- *s++ = '\0';
-
- /* Paranoia -- require a name */
- if (!*s) return (1);
-
- /* Get the index */
- i = atoi(buf + 2);
-
- /* Verify information */
- if (i >= ab_head->info_num) return (2);
-
- /* Save the index */
- error_idx = i;
-
- /* Point at the "info" */
- ab_ptr = &ab_info[i];
-
- /* Hack -- Verify space */
- 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;
-
- /* Append chars to the name */
- strcpy(ab_name + ab_head->name_size, s);
-
- /* Advance the index */
- ab_head->name_size += strlen(s);
-
- /* Init */
- ab_ptr->action_mkey = 0;
- ab_ptr->acquired = FALSE;
- for (z = 0; z < 10; z++)
- {
- ab_ptr->skills[z] = -1;
- ab_ptr->need_abilities[z] = -1;
- ab_ptr->forbid_abilities[z] = -1;
- }
- for (z = 0; z < 6; z++)
- {
- ab_ptr->stat[z] = -1;
- }
-
- /* Next... */
- continue;
- }
-
- /* There better be a current ab_ptr */
- if (!ab_ptr) return (3);
-
- /* Process 'D' for "Description" */
- if (buf[0] == 'D')
- {
- /* Acquire the text */
- s = buf + 2;
-
- /* Hack -- Verify space */
- if (ab_head->text_size + strlen(s) + 8 > fake_text_size) return (7);
-
- /* Advance and Save the text index */
- if (!ab_ptr->desc)
- {
- ab_ptr->desc = ++ab_head->text_size;
-
- /* Append chars to the name */
- strcpy(ab_text + ab_head->text_size, s);
-
- /* Advance the index */
- ab_head->text_size += strlen(s);
- }
- else
- {
- /* Append chars to the name */
- strcpy(ab_text + ab_head->text_size, format("\n%s", s));
-
- /* Advance the index */
- ab_head->text_size += strlen(s) + 1;
- }
-
- /* Next... */
- continue;
- }
-
- /* Process 'A' for "Activation Description" */
- if (buf[0] == 'A')
- {
- char *txt;
-
- /* Acquire the text */
- s = buf + 2;
-
- if (NULL == (txt = strchr(s, ':'))) return (1);
- *txt = '\0';
- txt++;
-
- /* Hack -- Verify space */
- 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;
-
- /* Append chars to the name */
- strcpy(ab_text + ab_head->text_size, txt);
- ab_ptr->action_mkey = atoi(s);
-
- /* Advance the index */
- ab_head->text_size += strlen(txt);
-
- /* Next... */
- continue;
- }
-
- /* Process 'I' for "Info" (one line only) */
- if (buf[0] == 'I')
- {
- int cost;
-
- /* Scan for the values */
- if (1 != sscanf(buf + 2, "%d", &cost))
- {
- return (1);
- }
-
- /* Save the values */
- ab_ptr->cost = cost;
-
- /* Next... */
- continue;
- }
-
- /* Process 'k' for "Skill" */
- if (buf[0] == 'k')
- {
- char *sec;
- s16b level, skill;
-
- /* Scan for the values */
- if (NULL == (sec = strchr(buf + 2, ':')))
- {
- return (1);
- }
- *sec = '\0';
- sec++;
- if (!*sec) return (1);
-
- level = atoi(buf + 2);
- skill = find_skill(sec);
-
- if (skill == -1) return (1);
-
- for (z = 0; z < 10; z++)
- if (ab_ptr->skills[z] == -1) break;
-
- if (z < 10)
- {
- ab_ptr->skills[z] = skill;
- ab_ptr->skill_levels[z] = level;
- }
-
- /* Next... */
- continue;
- }
-
- /* Process 'a' for "needed ability" */
- if (buf[0] == 'a')
- {
- s16b ab;
-
- ab = find_ability(buf + 2);
-
- if (ab == -1) return (1);
-
- for (z = 0; z < 10; z++)
- if (ab_ptr->need_abilities[z] == -1) break;
-
- if (z < 10)
- {
- ab_ptr->need_abilities[z] = ab;
- }
-
- /* Next... */
- continue;
- }
-
- /* Process 'S' for "Stat" */
- if (buf[0] == 'S')
- {
- char *sec;
- s16b stat;
-
- /* Scan for the values */
- if (NULL == (sec = strchr(buf + 2, ':')))
- {
- return (1);
- }
- *sec = '\0';
- sec++;
- if (!*sec) return (1);
-
- for (stat = 0; stat < 6; stat++)
- {
- if (!strcmp(stat_names[stat], sec))
- break;
- }
-
- if (stat == 6) return (1);
-
- ab_ptr->stat[stat] = atoi(buf + 2);
-
- /* Next... */
- continue;
- }
-
- /* Process 'E' for "Excluding ability" */
- if (buf[0] == 'E')
- {
- char *sec;
- s16b ab1, ab2;
-
- /* Scan for the values */
- if (NULL == (sec = strchr(buf + 2, ':')))
- {
- return (1);
- }
- *sec = '\0';
- sec++;
- if (!*sec) return (1);
-
- ab1 = find_ability(buf + 2);
- ab2 = find_ability(sec);
-
- if ((ab1 == -1) || (ab2 == -1)) return (1);
-
- for (z = 0; z < 10; z++)
- if (ab_info[ab1].forbid_abilities[z] == -1) break;
- if (z < 10)
- {
- ab_info[ab1].forbid_abilities[z] = ab2;
- }
-
- for (z = 0; z < 10; z++)
- if (ab_info[ab2].forbid_abilities[z] == -1) break;
- if (z < 10)
- {
- ab_info[ab2].forbid_abilities[z] = ab1;
- }
-
- /* Next... */
- continue;
- }
-
- /* Oops */
- return (6);
- }
-
-
- /* Complete the "name" and "text" sizes */
- ++ab_head->name_size;
- ++ab_head->text_size;
-
-
- /* No version yet */
- if (!okay) return (2);
-
-
- /* Success */
- return (0);
-}
-
-
-/*
- * Grab one flag in a ego-item_type from a textual string
- */
-static bool_ grab_one_ego_item_flag(ego_item_type *e_ptr, cptr what, int n, bool_ obvious)
-{
- int i;
-
- /* Check flags1 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, k_info_flags1[i]))
- {
- if (obvious)
- e_ptr->oflags1[n] |= (1L << i);
- else
- e_ptr->flags1[n] |= (1L << i);
- return (0);
- }
- }
-
- /* Check flags2 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, k_info_flags2[i]))
- {
- if (obvious)
- e_ptr->oflags2[n] |= (1L << i);
- else
- e_ptr->flags2[n] |= (1L << i);
- return (0);
- }
- }
-
- /* Check flags2 -- traps */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, k_info_flags2_trap[i]))
- {
- if (obvious)
- e_ptr->oflags2[n] |= (1L << i);
- else
- e_ptr->flags2[n] |= (1L << i);
- return (0);
- }
- }
-
- /* Check flags3 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, k_info_flags3[i]))
- {
- if (obvious)
- e_ptr->oflags3[n] |= (1L << i);
- else
- e_ptr->flags3[n] |= (1L << i);
- return (0);
- }
- }
-
- /* Check flags4 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, k_info_flags4[i]))
- {
- if (obvious)
- e_ptr->oflags4[n] |= (1L << i);
- else
- e_ptr->flags4[n] |= (1L << i);
- return (0);
- }
- }
-
- /* Check flags5 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, k_info_flags5[i]))
- {
- if (obvious)
- e_ptr->oflags5[n] |= (1L << i);
- else
- e_ptr->flags5[n] |= (1L << i);
- return (0);
- }
- }
-
- /* Check esp_flags */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, esp_flags[i]))
- {
- if (obvious)
- e_ptr->oesp[n] |= (1L << i);
- else
- e_ptr->esp[n] |= (1L << i);
- return (0);
- }
- }
-
- /* Check ego_flags */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, ego_flags[i]))
- {
- e_ptr->fego[n] |= (1L << i);
- return (0);
- }
- }
-
- /* Oops */
- msg_format("Unknown ego-item flag '%s'.", what);
-
- /* Error */
- return (1);
-}
-
-static bool_ grab_one_ego_item_flag_restrict(ego_item_type *e_ptr, cptr what, bool_ need)
-{
- int i;
-
- /* Check flags1 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, k_info_flags1[i]))
- {
- if (need)
- e_ptr->need_flags1 |= (1L << i);
- else
- e_ptr->forbid_flags1 |= (1L << i);
- return (0);
- }
- }
-
- /* Check flags2 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, k_info_flags2[i]))
- {
- if (need)
- e_ptr->need_flags2 |= (1L << i);
- else
- e_ptr->forbid_flags2 |= (1L << i);
- return (0);
- }
- }
-
- /* Check flags2 -- traps */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, k_info_flags2_trap[i]))
- {
- if (need)
- e_ptr->need_flags2 |= (1L << i);
- else
- e_ptr->forbid_flags2 |= (1L << i);
- return (0);
- }
- }
-
- /* Check flags3 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, k_info_flags3[i]))
- {
- if (need)
- e_ptr->need_flags3 |= (1L << i);
- else
- e_ptr->forbid_flags3 |= (1L << i);
- return (0);
- }
- }
-
- /* Check flags4 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, k_info_flags4[i]))
- {
- if (need)
- e_ptr->need_flags4 |= (1L << i);
- else
- e_ptr->forbid_flags4 |= (1L << i);
- return (0);
- }
- }
-
- /* Check flags5 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, k_info_flags5[i]))
- {
- if (need)
- e_ptr->need_flags5 |= (1L << i);
- else
- e_ptr->forbid_flags5 |= (1L << i);
- return (0);
- }
- }
-
- /* Check esp_flags */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, esp_flags[i]))
- {
- if (need)
- e_ptr->need_esp |= (1L << i);
- else
- e_ptr->forbid_esp |= (1L << i);
- return (0);
- }
- }
-
- /* Oops */
- msg_format("Unknown ego-item restrict flag '%s'.", what);
-
- /* Error */
- return (1);
-}
-
-
-
-
-/*
- * Initialize the "e_info" array, by parsing an ascii "template" file
- */
-errr init_e_info_txt(FILE *fp, char *buf)
-{
- int i, cur_r = -1, cur_t = 0, j;
-
- char *s, *t;
-
- /* Not ready yet */
- bool_ okay = FALSE;
-
- /* Current entry */
- ego_item_type *e_ptr = NULL;
-
-
- /* Just before the first record */
- error_idx = -1;
-
- /* Just before the first line */
- error_line = -1;
-
-
- /* Parse */
- fp_stack_init(fp);
- while (0 == my_fgets_dostack(buf, 1024))
- {
- /* Advance the line number */
- error_line++;
-
- /* Skip comments and blank lines */
- if (!buf[0] || (buf[0] == '#')) continue;
-
- /* Verify correct "colon" format */
- if (buf[1] != ':') return (1);
-
-
- /* Hack -- Process 'V' for "Version" */
- if (buf[0] == 'V')
- {
- int v1, v2, v3;
-
- /* Scan for the values */
- if (3 != sscanf(buf + 2, "%d.%d.%d", &v1, &v2, &v3)) return (2);
-
- /* Okay to proceed */
- okay = TRUE;
-
- /* Continue */
- continue;
- }
-
- /* No version yet */
- if (!okay) return (2);
-
- /* Included file */
- if (buf[0] == '<')
- {
- fp_stack_push(buf + 2);
- continue;
- }
-
- /* Process 'N' for "New/Number/Name" */
- if (buf[0] == 'N')
- {
- /* Find the colon before the name */
- s = strchr(buf + 2, ':');
-
- /* Verify that colon */
- if (!s) return (1);
-
- /* Nuke the colon, advance to the name */
- *s++ = '\0';
-
- /* Paranoia -- require a name */
- if (!*s) return (1);
-
- /* Get the index */
- i = atoi(buf + 2);
-
- /* Verify information */
- if (i < error_idx) return (4);
-
- /* Verify information */
- if (i >= e_head->info_num) return (2);
-
- /* Save the index */
- error_idx = i;
-
- /* Point at the "info" */
- e_ptr = &e_info[i];
-
- /* Hack -- Verify space */
- 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;
-
- /* Append chars to the name */
- strcpy(e_name + e_head->name_size, s);
-
- /* Advance the index */
- e_head->name_size += strlen(s);
-
- /* Needed hack */
- e_ptr->power = -1;
- cur_r = -1;
- cur_t = 0;
-
- for (j = 0; j < 10; j++)
- {
- e_ptr->tval[j] = 255;
- }
- for (j = 0; j < 5; j++)
- {
- e_ptr->rar[j] = 0;
- e_ptr->flags1[j] = 0;
- e_ptr->flags2[j] = 0;
- e_ptr->flags3[j] = 0;
- e_ptr->flags4[j] = 0;
- e_ptr->flags5[j] = 0;
- e_ptr->esp[j] = 0;
- }
-
- /* Next... */
- continue;
- }
-
- /* There better be a current e_ptr */
- if (!e_ptr) return (3);
-
-
- /* Process 'T' for "Tval/Sval" (up to 5 lines) */
- if (buf[0] == 'T')
- {
- int tv, minsv, maxsv;
-
- if (cur_t == 10) return 1;
-
- /* Scan for the values */
- if (3 != sscanf(buf + 2, "%d:%d:%d",
- &tv, &minsv, &maxsv)) return (1);
-
- /* Save the values */
- e_ptr->tval[cur_t] = tv;
- e_ptr->min_sval[cur_t] = minsv;
- e_ptr->max_sval[cur_t] = maxsv;
-
- cur_t++;
-
- /* Next... */
- continue;
- }
-
- /* Process 'R' for "flags rarity" (up to 5 lines) */
- if (buf[0] == 'R')
- {
- int rar;
-
- if (cur_r == 5) return 1;
-
- /* Scan for the values */
- if (1 != sscanf(buf + 2, "%d",
- &rar)) return (1);
-
- cur_r++;
-
- /* Save the values */
- e_ptr->rar[cur_r] = rar;
-
- /* Next... */
- continue;
- }
-
- /* Process 'X' for "Xtra" (one line only) */
- if (buf[0] == 'X')
- {
- int slot, rating;
- char pos;
-
- /* Scan for the values */
- if (3 != sscanf(buf + 2, "%c:%d:%d",
- &pos, &slot, &rating)) return (1);
-
- /* Save the values */
- /* e_ptr->slot = slot; */
- e_ptr->rating = rating;
- e_ptr->before = (pos == 'B') ? TRUE : FALSE;
-
- /* Next... */
- continue;
- }
-
- /* Process 'W' for "More Info" (one line only) */
- if (buf[0] == 'W')
- {
- int level, rarity, rarity2;
- long cost;
-
- /* Scan for the values */
- if (4 != sscanf(buf + 2, "%d:%d:%d:%ld",
- &level, &rarity, &rarity2, &cost)) return (1);
-
- /* Save the values */
- e_ptr->level = level;
- e_ptr->rarity = rarity;
- e_ptr->mrarity = rarity2;
- e_ptr->cost = cost;
-
- /* Next... */
- continue;
- }
-
- /* Hack -- Process 'C' for "creation" */
- if (buf[0] == 'C')
- {
- int th, td, ta, pv;
-
- /* Scan for the values */
- if (4 != sscanf(buf + 2, "%d:%d:%d:%d",
- &th, &td, &ta, &pv)) return (1);
-
- e_ptr->max_to_h = th;
- e_ptr->max_to_d = td;
- e_ptr->max_to_a = ta;
- e_ptr->max_pval = pv;
-
- /* Next... */
- continue;
- }
-
- /* Process 'Z' for "Granted power" */
- if (buf[0] == 'Z')
- {
- int i;
-
- /* Acquire the text */
- s = buf + 2;
-
- /* Find it in the list */
- for (i = 0; i < power_max; i++)
- {
- if (!stricmp(s, powers_type[i].name)) break;
- }
-
- if (i == power_max) return (6);
-
- e_ptr->power = i;
-
- /* Next... */
- continue;
- }
-
- if (buf[0] == 'a')
- {
- if (prefix(buf + 2, "HARDCORE="))
- {
- e_ptr->activate = get_activation(buf + 11);
- if (e_ptr->activate == -1)
- return 1;
- }
- else if (prefix(buf + 2, "SPELL="))
- {
- e_ptr->activate = -find_spell(buf + 8);
- if (e_ptr->activate == -( -1))
- return 1;
- }
-
- /* Next... */
- continue;
- }
-
- /* Hack -- Process 'r:N' for needed flags */
- if ((buf[0] == 'r') && (buf[2] == 'N'))
- {
- /* Parse every entry textually */
- for (s = buf + 4; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while ((*t == ' ') || (*t == '|')) t++;
- }
-
- /* Parse this entry */
- if (0 != grab_one_ego_item_flag_restrict(e_ptr, s, TRUE)) return (5);
-
- /* Start the next entry */
- s = t;
- }
-
- /* Next... */
- continue;
- }
-
- /* Hack -- Process 'r:F' for forbidden flags */
- if ((buf[0] == 'r') && (buf[2] == 'F'))
- {
- /* Parse every entry textually */
- for (s = buf + 4; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while ((*t == ' ') || (*t == '|')) t++;
- }
-
- /* Parse this entry */
- if (0 != grab_one_ego_item_flag_restrict(e_ptr, s, FALSE)) return (5);
-
- /* Start the next entry */
- s = t;
- }
-
- /* Next... */
- continue;
- }
-
- /* Hack -- Process 'F' for flags */
- if (buf[0] == 'F')
- {
- if (cur_r == -1) return (6);
-
- /* Parse every entry textually */
- for (s = buf + 2; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while ((*t == ' ') || (*t == '|')) t++;
- }
-
- /* Parse this entry */
- if (0 != grab_one_ego_item_flag(e_ptr, s, cur_r, FALSE)) return (5);
-
- /* Start the next entry */
- s = t;
- }
-
- /* Next... */
- continue;
- }
-
- /* Hack -- Process 'f' for obvious flags */
- if (buf[0] == 'f')
- {
- if (cur_r == -1) return (6);
-
- /* Parse every entry textually */
- for (s = buf + 2; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while ((*t == ' ') || (*t == '|')) t++;
- }
-
- /* Parse this entry */
- if (0 != grab_one_ego_item_flag(e_ptr, s, cur_r, TRUE)) return (5);
-
- /* Start the next entry */
- s = t;
- }
-
- /* Next... */
- continue;
- }
-
- /* Oops */
- return (6);
- }
-
-
- /* Complete the "name" and "text" sizes */
- ++e_head->name_size;
- ++e_head->text_size;
-
-
- /* No version yet */
- if (!okay) return (2);
-
-
- /* Success */
- return (0);
-}
-
-/*
- * Grab one flag in a randart_part_type from a textual string
- */
-static bool_ grab_one_randart_item_flag(randart_part_type *ra_ptr, cptr what, char c)
-{
- int i;
- u32b *f1, *f2, *f3, *f4, *f5, *esp;
-
- if (c == 'F')
- {
- f1 = &ra_ptr->flags1;
- f2 = &ra_ptr->flags2;
- f3 = &ra_ptr->flags3;
- f4 = &ra_ptr->flags4;
- f5 = &ra_ptr->flags5;
- esp = &ra_ptr->esp;
- }
- else
- {
- f1 = &ra_ptr->aflags1;
- f2 = &ra_ptr->aflags2;
- f3 = &ra_ptr->aflags3;
- f4 = &ra_ptr->aflags4;
- f5 = &ra_ptr->aflags5;
- esp = &ra_ptr->aesp;
- }
-
- /* Check flags1 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, k_info_flags1[i]))
- {
- *f1 |= (1L << i);
- return (0);
- }
- }
-
- /* Check flags2 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, k_info_flags2[i]))
- {
- *f2 |= (1L << i);
- return (0);
- }
- }
-
- /* Check flags2 -- traps */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, k_info_flags2_trap[i]))
- {
- *f2 |= (1L << i);
- return (0);
- }
- }
-
- /* Check flags3 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, k_info_flags3[i]))
- {
- *f3 |= (1L << i);
- return (0);
- }
- }
-
- /* Check flags4 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, k_info_flags4[i]))
- {
- *f4 |= (1L << i);
- return (0);
- }
- }
-
- /* Check flags5 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, k_info_flags5[i]))
- {
- *f5 |= (1L << i);
- return (0);
- }
- }
-
- /* Check esp_flags */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, esp_flags[i]))
- {
- *esp |= (1L << i);
- return (0);
- }
- }
-
- /* Check ego_flags */
- if (c == 'F')
- {
- for (i = 0; i < 32; i++)
- {
- if (streq(what, ego_flags[i]))
- {
- ra_ptr->fego |= (1L << i);
- return (0);
- }
- }
- }
-
- /* Oops */
- msg_format("Unknown ego-item flag '%s'.", what);
-
- /* Error */
- return (1);
-}
-
-
-
-
-/*
- * Initialize the "ra_info" array, by parsing an ascii "template" file
- */
-errr init_ra_info_txt(FILE *fp, char *buf)
-{
- int i, cur_t = 0, j, cur_g = 0;
-
- char *s, *t;
-
- /* Not ready yet */
- bool_ okay = FALSE;
-
- /* Current entry */
- randart_part_type *ra_ptr = NULL;
-
-
- /* Just before the first record */
- error_idx = -1;
-
- /* Just before the first line */
- error_line = -1;
-
-
- /* Parse */
- fp_stack_init(fp);
- while (0 == my_fgets_dostack(buf, 1024))
- {
- /* Advance the line number */
- error_line++;
-
- /* Skip comments and blank lines */
- if (!buf[0] || (buf[0] == '#')) continue;
-
- /* Verify correct "colon" format */
- if (buf[1] != ':') return (1);
-
-
- /* Hack -- Process 'V' for "Version" */
- if (buf[0] == 'V')
- {
- int v1, v2, v3;
-
- /* Scan for the values */
- if (3 != sscanf(buf + 2, "%d.%d.%d", &v1, &v2, &v3)) return (2);
-
- /* Okay to proceed */
- okay = TRUE;
-
- /* Continue */
- continue;
- }
-
- /* No version yet */
- if (!okay) return (2);
-
- /* Included file */
- if (buf[0] == '<')
- {
- fp_stack_push(buf + 2);
- continue;
- }
-
- /* Process 'G' for "General" (up to 30 lines) */
- if (buf[0] == 'G')
- {
- int chance, dd, ds, plus;
-
- /* Scan for the values */
- if (4 != sscanf(buf + 2, "%d:%dd%d:%d",
- &chance, &dd, &ds, &plus)) return (1);
-
- /* Save the values */
- ra_gen[cur_g].chance = chance;
- ra_gen[cur_g].dd = dd;
- ra_gen[cur_g].ds = ds;
- ra_gen[cur_g].plus = plus;
- cur_g++;
-
- /* Next... */
- continue;
- }
-
- /* Process 'N' for "New/Number" */
- if (buf[0] == 'N')
- {
- /* Get the index */
- i = atoi(buf + 2);
-
- /* Verify information */
- if (i < error_idx) return (4);
-
- /* Verify information */
- if (i >= ra_head->info_num) return (2);
-
- /* Save the index */
- error_idx = i;
-
- /* Point at the "info" */
- ra_ptr = &ra_info[i];
-
- /* Needed hack */
- ra_ptr->power = -1;
- cur_t = 0;
-
- for (j = 0; j < 20; j++)
- {
- ra_ptr->tval[j] = 255;
- }
- ra_ptr->flags1 = 0;
- ra_ptr->flags2 = 0;
- ra_ptr->flags3 = 0;
- ra_ptr->flags4 = 0;
- ra_ptr->flags5 = 0;
- ra_ptr->esp = 0;
- ra_ptr->fego = 0;
-
- /* Next... */
- continue;
- }
-
- /* There better be a current ra_ptr */
- if (!ra_ptr) return (3);
-
- /* Process 'T' for "Tval/Sval" (up to 5 lines) */
- if (buf[0] == 'T')
- {
- int tv, minsv, maxsv;
-
- if (cur_t == 20) return 1;
-
- /* Scan for the values */
- if (3 != sscanf(buf + 2, "%d:%d:%d",
- &tv, &minsv, &maxsv)) return (1);
-
- /* Save the values */
- ra_ptr->tval[cur_t] = tv;
- ra_ptr->min_sval[cur_t] = minsv;
- ra_ptr->max_sval[cur_t] = maxsv;
-
- cur_t++;
-
- /* Next... */
- continue;
- }
-
- /* Process 'X' for "Xtra" (one line only) */
- if (buf[0] == 'X')
- {
- int power, max;
-
- /* Scan for the values */
- if (2 != sscanf(buf + 2, "%d:%d",
- &power, &max)) return (1);
-
- /* Save the values */
- ra_ptr->value = power;
- ra_ptr->max = max;
-
- /* Next... */
- continue;
- }
-
- /* Process 'W' for "More Info" (one line only) */
- if (buf[0] == 'W')
- {
- int level, rarity, rarity2;
-
- /* Scan for the values */
- if (3 != sscanf(buf + 2, "%d:%d:%d",
- &level, &rarity, &rarity2)) return (1);
-
- /* Save the values */
- ra_ptr->level = level;
- ra_ptr->rarity = rarity;
- ra_ptr->mrarity = rarity2;
-
- /* Next... */
- continue;
- }
-
- /* Hack -- Process 'C' for "creation" */
- if (buf[0] == 'C')
- {
- int th, td, ta, pv;
-
- /* Scan for the values */
- if (4 != sscanf(buf + 2, "%d:%d:%d:%d",
- &th, &td, &ta, &pv)) return (1);
-
- ra_ptr->max_to_h = th;
- ra_ptr->max_to_d = td;
- ra_ptr->max_to_a = ta;
- ra_ptr->max_pval = pv;
-
- /* Next... */
- continue;
- }
-
- /* Process 'Z' for "Granted power" */
- if (buf[0] == 'Z')
- {
- int i;
-
- /* Acquire the text */
- s = buf + 2;
-
- /* Find it in the list */
- for (i = 0; i < power_max; i++)
- {
- if (!stricmp(s, powers_type[i].name)) break;
- }
-
- if (i == power_max) return (6);
-
- ra_ptr->power = i;
-
- /* Next... */
- continue;
- }
-
- /* Hack -- Process 'F' for flags */
- if (buf[0] == 'F')
- {
- /* Parse every entry textually */
- for (s = buf + 2; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while ((*t == ' ') || (*t == '|')) t++;
- }
-
- /* Parse this entry */
- if (0 != grab_one_randart_item_flag(ra_ptr, s, 'F')) return (5);
-
- /* Start the next entry */
- s = t;
- }
-
- /* Next... */
- continue;
- }
-
- /* Hack -- Process 'A' for antagonic flags */
- if (buf[0] == 'A')
- {
- /* Parse every entry textually */
- for (s = buf + 2; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while ((*t == ' ') || (*t == '|')) t++;
- }
-
- /* Parse this entry */
- if (0 != grab_one_randart_item_flag(ra_ptr, s, 'A')) return (5);
-
- /* Start the next entry */
- s = t;
- }
-
- /* Next... */
- continue;
- }
-
- /* Oops */
- return (6);
- }
-
-
- /* No version yet */
- if (!okay) return (2);
-
-
- /* Success */
- return (0);
-}
-
-/*
- * Grab one (basic) flag in a monster_race from a textual string
- */
-static errr grab_one_basic_flag(monster_race *r_ptr, cptr what)
-{
- int i;
-
- /* Scan flags1 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, r_info_flags1[i]))
- {
- r_ptr->flags1 |= (1L << i);
- return (0);
- }
- }
-
- /* Scan flags2 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, r_info_flags2[i]))
- {
- r_ptr->flags2 |= (1L << i);
- return (0);
- }
- }
-
- /* Scan flags3 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, r_info_flags3[i]))
- {
- r_ptr->flags3 |= (1L << i);
- return (0);
- }
- }
-
- /* Scan flags7 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, r_info_flags7[i]))
- {
- r_ptr->flags7 |= (1L << i);
- return (0);
- }
- }
-
- /* Scan flags8 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, r_info_flags8[i]))
- {
- r_ptr->flags8 |= (1L << i);
- return (0);
- }
- }
-
- /* Scan flags9 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, r_info_flags9[i]))
- {
- r_ptr->flags9 |= (1L << i);
- return (0);
- }
- }
-
- /* Oops */
- msg_format("Unknown monster flag '%s'.", what);
-
- /* Failure */
- return (1);
-}
-
-
-/*
- * Grab one (spell) flag in a monster_race from a textual string
- */
-static errr grab_one_spell_flag(monster_race *r_ptr, cptr what)
-{
- int i;
-
- /* Scan flags4 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, r_info_flags4[i]))
- {
- r_ptr->flags4 |= (1L << i);
- return (0);
- }
- }
-
- /* Scan flags5 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, r_info_flags5[i]))
- {
- r_ptr->flags5 |= (1L << i);
- return (0);
- }
- }
-
- /* Scan flags6 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, r_info_flags6[i]))
- {
- r_ptr->flags6 |= (1L << i);
- return (0);
- }
- }
-
- /* Oops */
- msg_format("Unknown monster flag '%s'.", what);
-
- /* Failure */
- return (1);
-}
-
-
-/*
- * Initialize the "r_info" array, by parsing an ascii "template" file
- */
-errr init_r_info_txt(FILE *fp, char *buf)
-{
- int i;
-
- char *s, *t;
-
- /* Not ready yet */
- bool_ okay = FALSE;
-
- /* Current entry */
- monster_race *r_ptr = NULL;
-
-
- /* Just before the first record */
- error_idx = -1;
-
- /* Just before the first line */
- error_line = -1;
-
-
- /* Start the "fake" stuff */
- r_head->name_size = 0;
- r_head->text_size = 0;
-
- /* Parse */
- fp_stack_init(fp);
- while (0 == my_fgets_dostack(buf, 1024))
- {
- /* Advance the line number */
- error_line++;
-
- /* Skip comments and blank lines */
- if (!buf[0] || (buf[0] == '#')) continue;
-
- /* Verify correct "colon" format */
- if (buf[1] != ':') return (1);
-
-
- /* Hack -- Process 'V' for "Version" */
- if (buf[0] == 'V')
- {
- int v1, v2, v3;
-
- /* Scan for the values */
- if (3 != sscanf(buf + 2, "%d.%d.%d", &v1, &v2, &v3)) return (2);
-
- /* Okay to proceed */
- okay = TRUE;
-
- /* Continue */
- continue;
- }
-
- /* No version yet */
- if (!okay) return (2);
-
- /* Included file */
- if (buf[0] == '<')
- {
- fp_stack_push(buf + 2);
- continue;
- }
-
- /* Process 'N' for "New/Number/Name" */
- if (buf[0] == 'N')
- {
- /* Find the colon before the name */
- s = strchr(buf + 2, ':');
-
- /* Verify that colon */
- if (!s) return (1);
-
- /* Nuke the colon, advance to the name */
- *s++ = '\0';
-
- /* Paranoia -- require a name */
- if (!*s) return (1);
-
- /* Get the index */
- i = atoi(buf + 2);
-
- /* Verify information */
- if (i < error_idx) return (4);
-
- /* Verify information */
- if (i >= r_head->info_num) return (2);
-
- /* Save the index */
- error_idx = i;
-
- /* Point at the "info" */
- r_ptr = &r_info[i];
-
- /* Hack -- Verify space */
- 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;
-
- /* Append chars to the name */
- strcpy(r_name + r_head->name_size, s);
-
- /* Advance the index */
- r_head->name_size += strlen(s);
-
- /* HACK -- Those ones HAVE to have a set default value */
- r_ptr->drops.treasure = OBJ_GENE_TREASURE;
- r_ptr->drops.combat = OBJ_GENE_COMBAT;
- r_ptr->drops.magic = OBJ_GENE_MAGIC;
- r_ptr->drops.tools = OBJ_GENE_TOOL;
- r_ptr->freq_inate = r_ptr->freq_spell = 0;
-
- /* Next... */
- continue;
- }
-
- /* There better be a current r_ptr */
- if (!r_ptr) return (3);
-
-
- /* Process 'D' for "Description" */
- if (buf[0] == 'D')
- {
- /* Acquire the text */
- s = buf + 2;
-
- /* Hack -- Verify space */
- 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;
-
- /* Append chars to the name */
- strcpy(r_text + r_head->text_size, s);
-
- /* Advance the index */
- r_head->text_size += strlen(s);
-
- /* Next... */
- continue;
- }
-
- /* Process 'G' for "Graphics" (one line only) */
- if (buf[0] == 'G')
- {
- char sym;
- int tmp;
-
- /* Paranoia */
- if (!buf[2]) return (1);
- if (!buf[3]) return (1);
- if (!buf[4]) return (1);
-
- /* Extract the char */
- sym = buf[2];
-
- /* Extract the attr */
- tmp = color_char_to_attr(buf[4]);
-
- /* Paranoia */
- if (tmp < 0) return (1);
-
- /* Save the values */
- r_ptr->d_char = sym;
- r_ptr->d_attr = tmp;
-
- /* Next... */
- continue;
- }
-
- /* Process 'I' for "Info" (one line only) */
- if (buf[0] == 'I')
- {
- int spd, hp1, hp2, aaf, ac, slp;
-
- /* Scan for the other values */
- if (6 != sscanf(buf + 2, "%d:%dd%d:%d:%d:%d",
- &spd, &hp1, &hp2, &aaf, &ac, &slp)) return (1);
-
- /* Save the values */
- r_ptr->speed = spd;
- r_ptr->hdice = hp1;
- r_ptr->hside = hp2;
- r_ptr->aaf = aaf;
- r_ptr->ac = ac;
- r_ptr->sleep = slp;
-
- /* Next... */
- continue;
- }
-
- /* Process 'E' for "Body Parts" (one line only) */
- if (buf[0] == 'E')
- {
- int weap, tors, fing, head, arms, legs;
-
- /* Scan for the other values */
- if (BODY_MAX != sscanf(buf + 2, "%d:%d:%d:%d:%d:%d",
- &weap, &tors, &arms, &fing, &head, &legs)) return (1);
-
- /* Save the values */
- r_ptr->body_parts[BODY_WEAPON] = weap;
- r_ptr->body_parts[BODY_TORSO] = tors;
- r_ptr->body_parts[BODY_ARMS] = arms;
- r_ptr->body_parts[BODY_FINGER] = fing;
- r_ptr->body_parts[BODY_HEAD] = head;
- r_ptr->body_parts[BODY_LEGS] = legs;
-
- /* Mega debugging hack */
- if (weap > arms) quit(format("monster %d, %d weapon(s), %d arm(s) !", error_idx, weap, arms));
-
- /* Next... */
- continue;
- }
-
- /* Process 'O' for "Object type" (one line only) */
- if (buf[0] == 'O')
- {
- int treasure, combat, magic, tools;
-
- /* Scan for the values */
- if (4 != sscanf(buf + 2, "%d:%d:%d:%d",
- &treasure, &combat, &magic, &tools)) return (1);
-
- /* Save the values */
- r_ptr->drops.treasure = treasure;
- r_ptr->drops.combat = combat;
- r_ptr->drops.magic = magic;
- r_ptr->drops.tools = tools;
-
- /* Next... */
- continue;
- }
-
- /* Process 'W' for "More Info" (one line only) */
- if (buf[0] == 'W')
- {
- int lev, rar, wt;
- long exp;
-
- /* Scan for the values */
- if (4 != sscanf(buf + 2, "%d:%d:%d:%ld",
- &lev, &rar, &wt, &exp)) return (1);
-
- /* Save the values */
- r_ptr->level = lev;
- r_ptr->rarity = rar;
- /* MEGA HACK */
- if (!wt) wt = 100;
- r_ptr->weight = wt;
- r_ptr->mexp = exp;
-
- /* Next... */
- continue;
- }
-
- /* Process 'B' for "Blows" (up to four lines) */
- if (buf[0] == 'B')
- {
- int n1, n2;
-
- /* Find the next empty blow slot (if any) */
- for (i = 0; i < 4; i++) if (!r_ptr->blow[i].method) break;
-
- /* Oops, no more slots */
- if (i == 4) return (1);
-
- /* Analyze the first field */
- for (s = t = buf + 2; *t && (*t != ':'); t++) /* loop */;
-
- /* Terminate the field (if necessary) */
- if (*t == ':') *t++ = '\0';
-
- /* Analyze the method */
- for (n1 = 0; r_info_blow_method[n1]; n1++)
- {
- if (streq(s, r_info_blow_method[n1])) break;
- }
-
- /* Invalid method */
- if (!r_info_blow_method[n1]) return (1);
-
- /* Analyze the second field */
- for (s = t; *t && (*t != ':'); t++) /* loop */;
-
- /* Terminate the field (if necessary) */
- if (*t == ':') *t++ = '\0';
-
- /* Analyze effect */
- for (n2 = 0; r_info_blow_effect[n2]; n2++)
- {
- if (streq(s, r_info_blow_effect[n2])) break;
- }
-
- /* Invalid effect */
- if (!r_info_blow_effect[n2]) return (1);
-
- /* Analyze the third field */
- for (s = t; *t && (*t != 'd'); t++) /* loop */;
-
- /* Terminate the field (if necessary) */
- if (*t == 'd') *t++ = '\0';
-
- /* Save the method */
- r_ptr->blow[i].method = n1;
-
- /* Save the effect */
- r_ptr->blow[i].effect = n2;
-
- /* Extract the damage dice and sides */
- r_ptr->blow[i].d_dice = atoi(s);
- r_ptr->blow[i].d_side = atoi(t);
-
- /* Next... */
- continue;
- }
-
- /* Process 'F' for "Basic Flags" (multiple lines) */
- if (buf[0] == 'F')
- {
- /* Parse every entry */
- for (s = buf + 2; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while (*t == ' ' || *t == '|') t++;
- }
-
- /* Parse this entry */
- if (0 != grab_one_basic_flag(r_ptr, s)) return (5);
-
- /* Start the next entry */
- s = t;
- }
-
- /* Next... */
- continue;
- }
-
- /* Process 'S' for "Spell Flags" (multiple lines) */
- if (buf[0] == 'S')
- {
- /* Parse every entry */
- for (s = buf + 2; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while ((*t == ' ') || (*t == '|')) t++;
- }
-
- /* XXX XXX XXX Hack -- Read spell frequency */
- if (1 == sscanf(s, "1_IN_%d", &i))
- {
- /* Extract a "frequency" */
- r_ptr->freq_spell = r_ptr->freq_inate = 100 / i;
-
- /* Start at next entry */
- s = t;
-
- /* Continue */
- continue;
- }
-
- /* Parse this entry */
- if (0 != grab_one_spell_flag(r_ptr, s)) return (5);
-
- /* Start the next entry */
- s = t;
- }
-
- /* Next... */
- continue;
- }
-
- /* Oops */
- return (6);
- }
-
-
- /* Complete the "name" and "text" sizes */
- ++r_head->name_size;
- ++r_head->text_size;
-
- for (i = 1; i < max_r_idx; i++)
- {
- /* Invert flag WILD_ONLY <-> RF8_DUNGEON */
- r_info[i].flags8 ^= 1L;
-
- /* WILD_TOO without any other wilderness flags enables all flags */
- if ((r_info[i].flags8 & RF8_WILD_TOO) && !(r_info[i].flags8 & 0x7FFFFFFE))
- r_info[i].flags8 = 0x0463;
- }
-
- /* No version yet */
- if (!okay) return (2);
-
- /* Success */
- return (0);
-}
-
-
-/*
- * Grab one (basic) flag in a monster_race from a textual string
- */
-static errr grab_one_basic_ego_flag(monster_ego *re_ptr, cptr what, bool_ add)
-{
- int i;
-
- /* Scan flags1 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, r_info_flags1[i]))
- {
- if (add)
- re_ptr->mflags1 |= (1L << i);
- else
- re_ptr->nflags1 |= (1L << i);
- return (0);
- }
- }
-
- /* Scan flags2 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, r_info_flags2[i]))
- {
- if (add)
- re_ptr->mflags2 |= (1L << i);
- else
- re_ptr->nflags2 |= (1L << i);
- return (0);
- }
- }
-
- /* Scan flags3 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, r_info_flags3[i]))
- {
- if (add)
- re_ptr->mflags3 |= (1L << i);
- else
- re_ptr->nflags3 |= (1L << i);
- return (0);
- }
- }
-
- /* Scan flags7 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, r_info_flags7[i]))
- {
- if (add)
- re_ptr->mflags7 |= (1L << i);
- else
- re_ptr->nflags7 |= (1L << i);
- return (0);
- }
- }
-
- /* Scan flags8 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, r_info_flags8[i]))
- {
- if (add)
- re_ptr->mflags8 |= (1L << i);
- else
- re_ptr->nflags8 |= (1L << i);
- return (0);
- }
- }
-
- /* Scan flags9 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, r_info_flags9[i]))
- {
- if (add)
- re_ptr->mflags9 |= (1L << i);
- else
- re_ptr->nflags9 |= (1L << i);
- return (0);
- }
- }
-
- /* Oops */
- msg_format("Unknown monster flag '%s'.", what);
-
- /* Failure */
- return (1);
-}
-
-
-/*
- * Grab one (spell) flag in a monster_race from a textual string
- */
-static errr grab_one_spell_ego_flag(monster_ego *re_ptr, cptr what, bool_ add)
-{
- int i;
-
- /* Scan flags4 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, r_info_flags4[i]))
- {
- if (add)
- re_ptr->mflags4 |= (1L << i);
- else
- re_ptr->nflags4 |= (1L << i);
- return (0);
- }
- }
-
- /* Scan flags5 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, r_info_flags5[i]))
- {
- if (add)
- re_ptr->mflags5 |= (1L << i);
- else
- re_ptr->nflags5 |= (1L << i);
- return (0);
- }
- }
-
- /* Scan flags6 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, r_info_flags6[i]))
- {
- if (add)
- re_ptr->mflags6 |= (1L << i);
- else
- re_ptr->nflags6 |= (1L << i);
- return (0);
- }
- }
-
- /* Oops */
- msg_format("Unknown monster flag '%s'.", what);
-
- /* Failure */
- return (1);
-}
-
-/*
- * Grab one (basic) flag in a monster_race from a textual string
- */
-static errr grab_one_ego_flag(monster_ego *re_ptr, cptr what, bool_ must)
-{
- int i;
-
- /* Scan flags1 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, r_info_flags1[i]))
- {
- if (must) re_ptr->flags1 |= (1L << i);
- else re_ptr->hflags1 |= (1L << i);
- return (0);
- }
- }
-
- /* Scan flags2 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, r_info_flags2[i]))
- {
- if (must) re_ptr->flags2 |= (1L << i);
- else re_ptr->hflags2 |= (1L << i);
- return (0);
- }
- }
-
- /* Scan flags3 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, r_info_flags3[i]))
- {
- if (must) re_ptr->flags3 |= (1L << i);
- else re_ptr->hflags3 |= (1L << i);
- return (0);
- }
- }
-
- /* Scan flags7 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, r_info_flags7[i]))
- {
- if (must) re_ptr->flags7 |= (1L << i);
- else re_ptr->hflags7 |= (1L << i);
- return (0);
- }
- }
-
- /* Scan flags8 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, r_info_flags8[i]))
- {
- if (must) re_ptr->flags8 |= (1L << i);
- else re_ptr->hflags8 |= (1L << i);
- return (0);
- }
- }
-
- /* Scan flags9 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, r_info_flags9[i]))
- {
- if (must) re_ptr->flags9 |= (1L << i);
- else re_ptr->hflags9 |= (1L << i);
- return (0);
- }
- }
-
- /* Oops */
- msg_format("Unknown monster flag '%s'.", what);
-
- /* Failure */
- return (1);
-}
-
-/*
- * Initialize the "re_info" array, by parsing an ascii "template" file
- */
-errr init_re_info_txt(FILE *fp, char *buf)
-{
- int i, j;
-
- byte blow_num = 0;
- int r_char_number = 0, nr_char_number = 0;
-
- char *s, *t;
-
- /* Not ready yet */
- bool_ okay = FALSE;
-
- /* Current entry */
- monster_ego *re_ptr = NULL;
-
-
- /* Just before the first record */
- error_idx = -1;
-
- /* Just before the first line */
- error_line = -1;
-
-
- /* Start the "fake" stuff */
- re_head->name_size = 0;
- re_head->text_size = 0;
-
- /* Parse */
- fp_stack_init(fp);
- while (0 == my_fgets_dostack(buf, 1024))
- {
- /* Advance the line number */
- error_line++;
-
- /* Skip comments and blank lines */
- if (!buf[0] || (buf[0] == '#')) continue;
-
- /* Verify correct "colon" format */
- if (buf[1] != ':') return (1);
-
-
- /* Hack -- Process 'V' for "Version" */
- if (buf[0] == 'V')
- {
- int v1, v2, v3;
-
- /* Scan for the values */
- if (3 != sscanf(buf + 2, "%d.%d.%d", &v1, &v2, &v3)) return (2);
-
- /* Okay to proceed */
- okay = TRUE;
-
- /* Continue */
- continue;
- }
-
- /* No version yet */
- if (!okay) return (2);
-
- /* Included file */
- if (buf[0] == '<')
- {
- fp_stack_push(buf + 2);
- continue;
- }
-
- /* Process 'N' for "New/Number/Name" */
- if (buf[0] == 'N')
- {
- /* Find the colon before the name */
- s = strchr(buf + 2, ':');
-
- /* Verify that colon */
- if (!s) return (1);
-
- /* Nuke the colon, advance to the name */
- *s++ = '\0';
-
- /* Paranoia -- require a name */
- if (!*s) return (1);
-
- /* Get the index */
- i = atoi(buf + 2);
-
- /* Verify information */
- if (i < error_idx) return (4);
-
- /* Verify information */
- if (i >= re_head->info_num) return (2);
-
- /* Save the index */
- error_idx = i;
-
- /* Point at the "info" */
- re_ptr = &re_info[i];
-
- /* Hack -- Verify space */
- 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;
-
- /* Append chars to the name */
- strcpy(re_name + re_head->name_size, s);
-
- /* Advance the index */
- re_head->name_size += strlen(s);
-
- /* Some inits */
- blow_num = 0;
- r_char_number = 0;
- nr_char_number = 0;
- for (j = 0; j < 5; j++) re_ptr->r_char[j] = 0;
- for (j = 0; j < 5; j++) re_ptr->nr_char[j] = 0;
- for (j = 0; j < 4; j++)
- {
- re_ptr->blow[j].method = 0;
- re_ptr->blow[j].effect = 0;
- re_ptr->blow[j].d_dice = 0;
- re_ptr->blow[j].d_side = 0;
- re_ptr->blowm[j][0] = MEGO_ADD;
- re_ptr->blowm[j][1] = MEGO_ADD;
- }
-
- /* Next... */
- continue;
- }
-
- /* There better be a current re_ptr */
- if (!re_ptr) return (3);
-
- /* Process 'G' for "Graphics" (one line only) */
- if (buf[0] == 'G')
- {
- char sym;
- int tmp;
-
- /* Paranoia */
- if (!buf[2]) return (1);
- if (!buf[3]) return (1);
- if (!buf[4]) return (1);
-
- /* Extract the char */
- if (buf[2] != '*') sym = buf[2];
- else sym = MEGO_CHAR_ANY;
-
- /* Extract the attr */
- if (buf[4] != '*') tmp = color_char_to_attr(buf[4]);
- else tmp = MEGO_CHAR_ANY;
-
- /* Paranoia */
- if (tmp < 0) return (1);
-
- /* Save the values */
- re_ptr->d_char = sym;
- re_ptr->d_attr = tmp;
-
- /* Next... */
- continue;
- }
-
- /* Process 'I' for "Info" (one line only) */
- if (buf[0] == 'I')
- {
- int spd, hp1, hp2, aaf, ac, slp;
- char mspd, mhp1, mhp2, maaf, mac, mslp;
-
- /* Scan for the other values */
- if (12 != sscanf(buf + 2, "%c%d:%c%dd%c%d:%c%d:%c%d:%c%d",
- &mspd, &spd, &mhp1, &hp1, &mhp2, &hp2, &maaf, &aaf, &mac, &ac, &mslp, &slp)) return (1);
-
- /* Save the values */
- re_ptr->speed = (spd << 2) + monster_ego_modify(mspd);
- re_ptr->hdice = (hp1 << 2) + monster_ego_modify(mhp1);
- re_ptr->hside = (hp2 << 2) + monster_ego_modify(mhp2);
- re_ptr->aaf = (aaf << 2) + monster_ego_modify(maaf);
- re_ptr->ac = (ac << 2) + monster_ego_modify(mac);
- re_ptr->sleep = (slp << 2) + monster_ego_modify(mslp);
-
- /* Next... */
- continue;
- }
-
- /* Process 'W' for "More Info" (one line only) */
- if (buf[0] == 'W')
- {
- int lev, rar, wt;
- char mlev, mwt, mexp, pos;
- long exp;
-
- /* Scan for the values */
- if (8 != sscanf(buf + 2, "%c%d:%d:%c%d:%c%ld:%c",
- &mlev, &lev, &rar, &mwt, &wt, &mexp, &exp, &pos)) return (1);
-
- /* Save the values */
- re_ptr->level = (lev << 2) + monster_ego_modify(mlev);
- re_ptr->rarity = rar;
- re_ptr->weight = (wt << 2) + monster_ego_modify(mwt);
- re_ptr->mexp = (exp << 2) + monster_ego_modify(mexp);
- re_ptr->before = (pos == 'B') ? TRUE : FALSE;
-
- /* Next... */
- continue;
- }
-
- /* Process 'B' for "Blows" (up to four lines) */
- if (buf[0] == 'B')
- {
- int n1, n2, dice, side;
- char mdice, mside;
-
- /* Oops, no more slots */
- if (blow_num == 4) return (1);
-
- /* Analyze the first field */
- for (s = t = buf + 2; *t && (*t != ':'); t++) /* loop */;
-
- /* Terminate the field (if necessary) */
- if (*t == ':') *t++ = '\0';
-
- /* Analyze the method */
- for (n1 = 0; r_info_blow_method[n1]; n1++)
- {
- if (streq(s, r_info_blow_method[n1])) break;
- }
-
- /* Invalid method */
- if (!r_info_blow_method[n1]) return (1);
-
- /* Analyze the second field */
- for (s = t; *t && (*t != ':'); t++) /* loop */;
-
- /* Terminate the field (if necessary) */
- if (*t == ':') *t++ = '\0';
-
- /* Analyze effect */
- for (n2 = 0; r_info_blow_effect[n2]; n2++)
- {
- if (streq(s, r_info_blow_effect[n2])) break;
- }
-
- /* Invalid effect */
- if (!r_info_blow_effect[n2]) return (1);
-
- /* Save the method */
- re_ptr->blow[blow_num].method = n1;
-
- /* Save the effect */
- re_ptr->blow[blow_num].effect = n2;
-
- /* Extract the damage dice and sides */
- if (4 != sscanf(t, "%c%dd%c%d",
- &mdice, &dice, &mside, &side)) return (1);
-
- re_ptr->blow[blow_num].d_dice = dice;
- re_ptr->blow[blow_num].d_side = side;
- re_ptr->blowm[blow_num][0] = monster_ego_modify(mdice);
- re_ptr->blowm[blow_num][1] = monster_ego_modify(mside);
- blow_num++;
-
- /* Next... */
- continue;
- }
-
- /* Process 'F' for "Flags monster must have" (multiple lines) */
- if (buf[0] == 'F')
- {
- char r_char;
-
- /* Parse every entry */
- for (s = buf + 2; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while (*t == ' ' || *t == '|') t++;
- }
-
- /* XXX XXX XXX Hack -- Read monster symbols */
- if (1 == sscanf(s, "R_CHAR_%c", &r_char))
- {
- /* Limited to 5 races */
- if (r_char_number >= 5) continue;
-
- /* Extract a "frequency" */
- re_ptr->r_char[r_char_number++] = r_char;
-
- /* Start at next entry */
- s = t;
-
- /* Continue */
- continue;
- }
-
- /* Parse this entry */
- if (0 != grab_one_ego_flag(re_ptr, s, TRUE)) return (5);
-
- /* Start the next entry */
- s = t;
- }
-
- /* Next... */
- continue;
- }
-
- /* Process 'H' for "Flags monster must not have" (multiple lines) */
- if (buf[0] == 'H')
- {
- char r_char;
-
- /* Parse every entry */
- for (s = buf + 2; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while (*t == ' ' || *t == '|') t++;
- }
-
- /* XXX XXX XXX Hack -- Read monster symbols */
- if (1 == sscanf(s, "R_CHAR_%c", &r_char))
- {
- /* Limited to 5 races */
- if (nr_char_number >= 5) continue;
-
- /* Extract a "frequency" */
- re_ptr->nr_char[nr_char_number++] = r_char;
-
- /* Start at next entry */
- s = t;
-
- /* Continue */
- continue;
- }
-
- /* Parse this entry */
- if (0 != grab_one_ego_flag(re_ptr, s, FALSE)) return (5);
-
- /* Start the next entry */
- s = t;
- }
-
- /* Next... */
- continue;
- }
-
- /* Process 'M' for "Basic Monster Flags" (multiple lines) */
- if (buf[0] == 'M')
- {
- /* Parse every entry */
- for (s = buf + 2; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while (*t == ' ' || *t == '|') t++;
- }
-
- /* Parse this entry */
- if (0 != grab_one_basic_ego_flag(re_ptr, s, TRUE)) return (5);
-
- /* Start the next entry */
- s = t;
- }
-
- /* Next... */
- continue;
- }
-
- /* Process 'O' for "Basic Monster -Flags" (multiple lines) */
- if (buf[0] == 'O')
- {
- /* Parse every entry */
- for (s = buf + 2; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while (*t == ' ' || *t == '|') t++;
- }
-
- /* XXX XXX XXX Hack -- Read no flags */
- if (!strcmp(s, "MF_ALL"))
- {
- /* No flags */
- re_ptr->nflags1 = re_ptr->nflags2 = re_ptr->nflags3 = re_ptr->nflags7 = re_ptr->nflags8 = re_ptr->nflags9 = 0xFFFFFFFF;
-
- /* Start at next entry */
- s = t;
-
- /* Continue */
- continue;
- }
-
- /* Parse this entry */
- if (0 != grab_one_basic_ego_flag(re_ptr, s, FALSE)) return (5);
-
- /* Start the next entry */
- s = t;
- }
-
- /* Next... */
- continue;
- }
-
- /* Process 'S' for "Spell Flags" (multiple lines) */
- if (buf[0] == 'S')
- {
- /* Parse every entry */
- for (s = buf + 2; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while ((*t == ' ') || (*t == '|')) t++;
- }
-
- /* XXX XXX XXX Hack -- Read spell frequency */
- if (1 == sscanf(s, "1_IN_%d", &i))
- {
- /* Extract a "frequency" */
- re_ptr->freq_spell = re_ptr->freq_inate = 100 / i;
-
- /* Start at next entry */
- s = t;
-
- /* Continue */
- continue;
- }
-
- /* Parse this entry */
- if (0 != grab_one_spell_ego_flag(re_ptr, s, TRUE)) return (5);
-
- /* Start the next entry */
- s = t;
- }
-
- /* Next... */
- continue;
- }
-
- /* Process 'T' for "Spell -Flags" (multiple lines) */
- if (buf[0] == 'T')
- {
- /* Parse every entry */
- for (s = buf + 2; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while ((*t == ' ') || (*t == '|')) t++;
- }
-
- /* XXX XXX XXX Hack -- Read no flags */
- if (!strcmp(s, "MF_ALL"))
- {
- /* No flags */
- re_ptr->nflags4 = re_ptr->nflags5 = re_ptr->nflags6 = 0xFFFFFFFF;
-
- /* Start at next entry */
- s = t;
-
- /* Continue */
- continue;
- }
-
- /* Parse this entry */
- if (0 != grab_one_spell_ego_flag(re_ptr, s, FALSE)) return (5);
-
- /* Start the next entry */
- s = t;
- }
-
- /* Next... */
- continue;
- }
-
- /* Oops */
- return (6);
- }
-
-
- /* Complete the "name" and "text" sizes */
- ++re_head->name_size;
-
- /* No version yet */
- if (!okay) return (2);
-
- /* Success */
- return (0);
-}
-
-
-/*
- * Grab one flag in an trap_type from a textual string
- */
-static errr grab_one_trap_type_flag(trap_type *t_ptr, cptr what)
-{
- s16b i;
-
- /* Check flags1 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, t_info_flags[i]))
- {
- t_ptr->flags |= (1L << i);
- return (0);
- }
- }
- /* Oops */
- msg_format("Unknown trap_type flag '%s'.", what);
-
- /* Error */
- return (1);
-}
-
-
-/*
- * Initialize the "tr_info" array, by parsing an ascii "template" file
- */
-errr init_t_info_txt(FILE *fp, char *buf)
-{
- int i;
-
- char *s, *t;
-
- /* Not ready yet */
- bool_ okay = FALSE;
-
- /* Current entry */
- trap_type *t_ptr = NULL;
-
-
- /* Just before the first record */
- error_idx = -1;
-
- /* Just before the first line */
- error_line = -1;
-
-
- /* Prepare the "fake" stuff */
- t_head->name_size = 0;
- t_head->text_size = 0;
-
- /* Parse */
- fp_stack_init(fp);
- while (0 == my_fgets_dostack(buf, 1024))
- {
- /* Advance the line number */
- error_line++;
-
- /* Skip comments and blank lines */
- if (!buf[0] || (buf[0] == '#')) continue;
-
- /* Verify correct "colon" format */
- if (buf[1] != ':') return (1);
-
-
- /* Hack -- Process 'V' for "Version" */
- if (buf[0] == 'V')
- {
- int v1, v2, v3;
-
- /* Scan for the values */
- if (3 != sscanf(buf + 2, "%d.%d.%d", &v1, &v2, &v3)) return (2);
-
- /* Okay to proceed */
- okay = TRUE;
-
- /* Continue */
- continue;
- }
-
- /* No version yet */
- if (!okay) return (2);
-
- /* Included file */
- if (buf[0] == '<')
- {
- fp_stack_push(buf + 2);
- continue;
- }
-
- /* Process 'N' for "New/Number/Name" */
- if (buf[0] == 'N')
- {
- /* Find the colon before the name */
- s = strchr(buf + 2, ':');
-
- /* Verify that colon */
- if (!s) return (1);
-
- /* Nuke the colon, advance to the name */
- *s++ = '\0';
-
- /* Paranoia -- require a name */
- if (!*s) return (1);
-
- /* Get the index */
- i = atoi(buf + 2);
-
- /* Verify information */
- if (i <= error_idx) return (4);
-
- /* Verify information */
- if (i >= t_head->info_num) return (2);
-
- /* Save the index */
- error_idx = i;
-
- /* Point at the "info" */
- t_ptr = &t_info[i];
-
- /* Hack -- Verify space */
- 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;
-
- /* Append chars to the name */
- strcpy(t_name + t_head->name_size, s);
-
- /* Advance the index */
- t_head->name_size += strlen(s);
-
- /* Next... */
- continue;
- }
-
- /* There better be a current t_ptr */
- if (!t_ptr) return (3);
-
-
- /* Process 'I' for "Information" */
- if (buf[0] == 'I')
- {
- int probability, another, p1valinc, difficulty;
- int minlevel;
- int dd, ds;
- char color;
-
- /* Scan for the values */
- if (8 != sscanf(buf + 2, "%d:%d:%d:%d:%d:%dd%d:%c",
- &difficulty, &probability, &another,
- &p1valinc, &minlevel, &dd, &ds,
- &color)) return (1);
-
- t_ptr->difficulty = (byte)difficulty;
- t_ptr->probability = (s16b)probability;
- t_ptr->another = (s16b)another;
- t_ptr->p1valinc = (s16b)p1valinc;
- t_ptr->minlevel = (byte)minlevel;
- t_ptr->dd = (s16b)dd;
- t_ptr->ds = (s16b)ds;
- t_ptr->color = color_char_to_attr(color);
-
- /* Next... */
- continue;
- }
-
-
- /* Process 'D' for "Description" */
- if (buf[0] == 'D')
- {
- /* Acquire the text */
- s = buf + 2;
-
- /* Hack -- Verify space */
- 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;
-
- /* Append chars to the name */
- strcpy(t_text + t_head->text_size, s);
-
- /* Advance the index */
- t_head->text_size += strlen(s);
-
- /* Next... */
- continue;
- }
-
-
- /* Hack -- Process 'F' for flags */
- if (buf[0] == 'F')
- {
-
- t_ptr->flags = 0;
-
- /* Parse every entry textually */
- for (s = buf + 2; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while (*t == ' ' || *t == '|') t++;
- }
-
- /* Parse this entry */
- if (0 != grab_one_trap_type_flag(t_ptr, s)) return (5);
-
- /* Start the next entry */
- s = t;
- }
-
- /* Next... */
- continue;
- }
-
-
- /* Oops */
- return (6);
- }
-
-
- /* Complete the "name" and "text" sizes */
- ++t_head->name_size;
- ++t_head->text_size;
-
-
- /* No version yet */
- if (!okay) return (2);
-
-
- /* Success */
- return (0);
-}
-
-/*
- * Grab one flag for a dungeon type from a textual string
- */
-errr grab_one_dungeon_flag(u32b *flags1, u32b *flags2, cptr what)
-{
- int i;
-
- /* Scan flags1 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, d_info_flags1[i]))
- {
- *flags1 |= (1L << i);
- return (0);
- }
- }
-
- /* Scan flags2 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, d_info_flags2[i]))
- {
- *flags2 |= (1L << i);
- return (0);
- }
- }
-
- /* Oops */
- msg_format("Unknown dungeon type flag '%s'.", what);
-
- /* Failure */
- return (1);
-}
-
-/*
- * Grab one (basic) flag in a monster_race from a textual string
- */
-static errr grab_one_basic_monster_flag(dungeon_info_type *d_ptr, cptr what, byte rule)
-{
- int i;
-
- /* Scan flags1 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, r_info_flags1[i]))
- {
- d_ptr->rules[rule].mflags1 |= (1L << i);
- return (0);
- }
- }
-
- /* Scan flags2 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, r_info_flags2[i]))
- {
- d_ptr->rules[rule].mflags2 |= (1L << i);
- return (0);
- }
- }
-
- /* Scan flags3 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, r_info_flags3[i]))
- {
- d_ptr->rules[rule].mflags3 |= (1L << i);
- return (0);
- }
- }
-
- /* Scan flags7 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, r_info_flags7[i]))
- {
- d_ptr->rules[rule].mflags7 |= (1L << i);
- return (0);
- }
- }
-
- /* Scan flags8 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, r_info_flags8[i]))
- {
- d_ptr->rules[rule].mflags8 |= (1L << i);
- return (0);
- }
- }
-
- /* Scan flags9 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, r_info_flags9[i]))
- {
- d_ptr->rules[rule].mflags9 |= (1L << i);
- return (0);
- }
- }
-
- /* Oops */
- msg_format("Unknown monster flag '%s'.", what);
-
- /* Failure */
- return (1);
-}
-
-
-/*
- * Grab one (spell) flag in a monster_race from a textual string
- */
-static errr grab_one_spell_monster_flag(dungeon_info_type *d_ptr, cptr what, byte rule)
-{
- int i;
-
- /* Scan flags4 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, r_info_flags4[i]))
- {
- d_ptr->rules[rule].mflags4 |= (1L << i);
- return (0);
- }
- }
-
- /* Scan flags5 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, r_info_flags5[i]))
- {
- d_ptr->rules[rule].mflags5 |= (1L << i);
- return (0);
- }
- }
-
- /* Scan flags6 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, r_info_flags6[i]))
- {
- d_ptr->rules[rule].mflags6 |= (1L << i);
- return (0);
- }
- }
-
- /* Oops */
- msg_format("Unknown monster flag '%s'.", what);
-
- /* Failure */
- return (1);
-}
-
-/*
- * Initialize the "d_info" array, by parsing an ascii "template" file
- */
-errr init_d_info_txt(FILE *fp, char *buf)
-{
- int i, j;
-
- s16b rule_num = 0;
-
- byte r_char_number = 0;
-
- char *s, *t;
-
- /* Not ready yet */
- bool_ okay = FALSE;
-
- /* Current entry */
- dungeon_info_type *d_ptr = NULL;
-
-
- /* Just before the first record */
- error_idx = -1;
-
- /* Just before the first line */
- error_line = -1;
-
-
- /* Start the "fake" stuff */
- d_head->name_size = 0;
- d_head->text_size = 0;
-
- /* Parse */
- fp_stack_init(fp);
- while (0 == my_fgets_dostack(buf, 1024))
- {
- /* Advance the line number */
- error_line++;
-
- /* Skip comments and blank lines */
- if (!buf[0] || (buf[0] == '#')) continue;
-
- /* Verify correct "colon" format */
- if (buf[1] != ':') return (1);
-
-
- /* Hack -- Process 'V' for "Version" */
- if (buf[0] == 'V')
- {
- int v1, v2, v3;
-
- /* Scan for the values */
- if (3 != sscanf(buf + 2, "%d.%d.%d", &v1, &v2, &v3)) return (2);
-
- /* Okay to proceed */
- okay = TRUE;
-
- /* Continue */
- continue;
- }
-
- /* No version yet */
- if (!okay) return (2);
-
- /* Included file */
- if (buf[0] == '<')
- {
- fp_stack_push(buf + 2);
- continue;
- }
-
- /* Process 'N' for "New/Number/Name" */
- if (buf[0] == 'N')
- {
- /* Find the colon before the name */
- s = strchr(buf + 2, ':');
-
- /* Verify that colon */
- if (!s) return (1);
-
- /* Nuke the colon, advance to the name */
- *s++ = '\0';
-
- /* Paranoia -- require a name */
- if (!*s) return (1);
-
- /* Get the index */
- i = atoi(buf + 2);
-
- /* Verify information */
- if (i < error_idx) return (4);
-
- /* Verify information */
- if (i >= d_head->info_num) return (2);
-
- /* Save the index */
- error_idx = i;
-
- /* Point at the "info" */
- d_ptr = &d_info[i];
-
- /* Hack -- Verify space */
- 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;
-
- /* Append chars to the name */
- strcpy(d_name + d_head->name_size, s);
-
- /* Advance the index */
- d_head->name_size += strlen(s);
-
- /* HACK -- Those ones HAVE to have a set default value */
- d_ptr->size_x = -1;
- d_ptr->size_y = -1;
- d_ptr->ix = -1;
- d_ptr->iy = -1;
- d_ptr->ox = -1;
- d_ptr->oy = -1;
- d_ptr->fill_method = 1;
- rule_num = -1;
- r_char_number = 0;
- for (j = 0; j < 5; j++)
- {
- int k;
-
- d_ptr->rules[j].mode = DUNGEON_MODE_NONE;
- d_ptr->rules[j].percent = 0;
-
- for (k = 0; k < 5; k++) d_ptr->rules[j].r_char[k] = 0;
- }
-
- /* HACK -- Those ones HAVE to have a set default value */
- d_ptr->objs.treasure = OBJ_GENE_TREASURE;
- d_ptr->objs.combat = OBJ_GENE_COMBAT;
- d_ptr->objs.magic = OBJ_GENE_MAGIC;
- d_ptr->objs.tools = OBJ_GENE_TOOL;
-
- /* The default generator */
- strcpy(d_ptr->generator, "dungeon");
-
- /* Next... */
- continue;
- }
-
- /* There better be a current d_ptr */
- if (!d_ptr) return (3);
-
- /* Process 'D' for "Description */
- if (buf[0] == 'D')
- {
- /* Acquire short name */
- d_ptr->short_name[0] = buf[2];
- d_ptr->short_name[1] = buf[3];
- d_ptr->short_name[2] = buf[4];
-
- /* Acquire the text */
- s = buf + 6;
-
- /* Hack -- Verify space */
- 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;
-
- /* Append chars to the name */
- strcpy(d_text + d_head->text_size, s);
-
- /* Advance the index */
- d_head->text_size += strlen(s);
-
- /* Next... */
- continue;
- }
-
- /* Process 'W' for "More Info" (one line only) */
- if (buf[0] == 'W')
- {
- int min_lev, max_lev;
- int min_plev, next;
- int min_alloc, max_chance;
-
- /* Scan for the values */
- if (6 != sscanf(buf + 2, "%d:%d:%d:%d:%d:%d",
- &min_lev, &max_lev, &min_plev, &next, &min_alloc, &max_chance)) return (1);
-
- /* Save the values */
- d_ptr->mindepth = min_lev;
- d_ptr->maxdepth = max_lev;
- d_ptr->min_plev = min_plev;
- d_ptr->next = next;
- d_ptr->min_m_alloc_level = min_alloc;
- d_ptr->max_m_alloc_chance = max_chance;
-
- /* Next... */
- continue;
- }
-
- /* Process 'L' for "fLoor type" (one line only) */
- if (buf[0] == 'L')
- {
- int f1, f2, f3;
- int p1, p2, p3;
- int i;
-
- /* Scan for the values */
- if (6 != sscanf(buf + 2, "%d:%d:%d:%d:%d:%d",
- &f1, &p1, &f2, &p2, &f3, &p3))
- {
- /* Scan for the values - part ii*/
- if (3 != sscanf(buf + 2, "%d:%d:%d", &p1, &p2,
- &p3)) return (1);
-
- /* Save the values */
- d_ptr->floor_percent1[1] = p1;
- d_ptr->floor_percent2[1] = p2;
- d_ptr->floor_percent3[1] = p3;
-
- continue;
- }
-
- /* Save the values */
- d_ptr->floor1 = f1;
- d_ptr->floor2 = f2;
- d_ptr->floor3 = f3;
-
- for (i = 0; i < 2; i++)
- {
- d_ptr->floor_percent1[i] = p1;
- d_ptr->floor_percent2[i] = p2;
- d_ptr->floor_percent3[i] = p3;
- }
-
- /* Next... */
- continue;
- }
-
- /* Process 'O' for "Object type" (one line only) */
- if (buf[0] == 'O')
- {
- int treasure, combat, magic, tools;
-
- /* Scan for the values */
- if (4 != sscanf(buf + 2, "%d:%d:%d:%d",
- &treasure, &combat, &magic, &tools)) return (1);
-
- /* Save the values */
- d_ptr->objs.treasure = treasure;
- d_ptr->objs.combat = combat;
- d_ptr->objs.magic = magic;
- d_ptr->objs.tools = tools;
-
- /* Next... */
- continue;
- }
-
- /* Process 'G' for "Generator" (one line only) */
- if (buf[0] == 'G')
- {
- strnfmt(d_ptr->generator, 30, "%s", buf + 2);
-
- /* Next... */
- continue;
- }
-
- /* Process 'A' for "wAll type" (one line only) */
- if (buf[0] == 'A')
- {
- int w1, w2, w3, outer, inner;
- int p1, p2, p3;
- int i;
-
- /* Scan for the values */
- if (8 != sscanf(buf + 2, "%d:%d:%d:%d:%d:%d:%d:%d",
- &w1, &p1, &w2, &p2, &w3, &p3, &outer, &inner))
- {
- /* Scan for the values - part ii*/
- if (3 != sscanf(buf + 2, "%d:%d:%d", &p1, &p2,
- &p3)) return (1);
-
- /* Save the values */
- d_ptr->fill_percent1[1] = p1;
- d_ptr->fill_percent2[1] = p2;
- d_ptr->fill_percent3[1] = p3;
- continue;
- }
-
- /* Save the values */
- d_ptr->fill_type1 = w1;
- d_ptr->fill_type2 = w2;
- d_ptr->fill_type3 = w3;
-
- for (i = 0; i < 2; i++)
- {
- d_ptr->fill_percent1[i] = p1;
- d_ptr->fill_percent2[i] = p2;
- d_ptr->fill_percent3[i] = p3;
- }
-
- d_ptr->outer_wall = outer;
- d_ptr->inner_wall = inner;
-
- /* Next... */
- continue;
- }
-
- /* Process 'E' for "Effects" (up to four lines) -SC- */
- if (buf[0] == 'E')
- {
- int side, dice, freq, type;
- cptr tmp;
-
- /* Find the next empty blow slot (if any) */
- for (i = 0; i < 4; i++) if ((!d_ptr->d_side[i]) &&
- (!d_ptr->d_dice[i])) break;
-
- /* Oops, no more slots */
- if (i == 4) return (1);
-
- /* Scan for the values */
- if (4 != sscanf(buf + 2, "%dd%d:%d:%d",
- &dice, &side, &freq, &type))
- {
- int j;
-
- if (3 != sscanf(buf + 2, "%dd%d:%d",
- &dice, &side, &freq)) return (1);
-
- tmp = buf + 2;
- for (j = 0; j < 2; j++)
- {
- tmp = strchr(tmp, ':');
- if (tmp == NULL) return (1);
- tmp++;
- }
-
- j = 0;
-
- while (d_info_dtypes[j].name != NULL)
- if (strcmp(d_info_dtypes[j].name, tmp) == 0)
- {
- d_ptr->d_type[i] = d_info_dtypes[j].feat;
- break;
- }
- else j++;
-
- if (d_info_dtypes[j].name == NULL) return (1);
- }
- else
- d_ptr->d_type[i] = type;
-
- freq *= 10;
- /* Save the values */
- d_ptr->d_side[i] = side;
- d_ptr->d_dice[i] = dice;
- d_ptr->d_frequency[i] = freq;
-
- /* Next... */
- continue;
- }
-
- /* Process 'F' for "Dungeon Flags" (multiple lines) */
- if (buf[0] == 'F')
- {
- int artif = 0, monst = 0, obj = 0;
- int ix = -1, iy = -1, ox = -1, oy = -1;
- int fill_method;
-
- /* Parse every entry */
- for (s = buf + 2; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while (*t == ' ' || *t == '|') t++;
- }
-
- /* Read dungeon in/out coords */
- if (4 == sscanf(s, "WILD_%d_%d__%d_%d", &ix, &iy, &ox, &oy))
- {
- d_ptr->ix = ix;
- d_ptr->iy = iy;
- d_ptr->ox = ox;
- d_ptr->oy = oy;
-
- /* Start at next entry */
- s = t;
-
- /* Continue */
- continue;
- }
-
- /* Read dungeon size */
- if (2 == sscanf(s, "SIZE_%d_%d", &ix, &iy))
- {
- d_ptr->size_x = ix;
- d_ptr->size_y = iy;
-
- /* Start at next entry */
- s = t;
-
- /* Continue */
- continue;
- }
-
- /* Read dungeon fill method */
- if (1 == sscanf(s, "FILL_METHOD_%d", &fill_method))
- {
- d_ptr->fill_method = fill_method;
-
- /* Start at next entry */
- s = t;
-
- /* Continue */
- continue;
- }
-
- /* Read Final Object */
- if (1 == sscanf(s, "FINAL_OBJECT_%d", &obj))
- {
- /* Extract a "Final Artifact" */
- d_ptr->final_object = obj;
-
- /* Start at next entry */
- s = t;
-
- /* Continue */
- continue;
- }
-
- /* Read Final Artifact */
- if (1 == sscanf(s, "FINAL_ARTIFACT_%d", &artif ))
- {
- /* Extract a "Final Artifact" */
- d_ptr->final_artifact = artif ;
-
- /* Start at next entry */
- s = t;
-
- /* Continue */
- continue;
- }
-
- /* Read Artifact Guardian */
- if (1 == sscanf(s, "FINAL_GUARDIAN_%d", &monst))
- {
- /* Extract a "Artifact Guardian" */
- d_ptr->final_guardian = monst;
-
- /* Start at next entry */
- s = t;
-
- /* Continue */
- continue;
- }
-
- /* Parse this entry */
- if (0 != grab_one_dungeon_flag(&(d_ptr->flags1), &(d_ptr->flags2), s)) return (5);
-
- /* Start the next entry */
- s = t;
- }
-
- /* Next... */
- continue;
- }
-
- /* Process 'R' for "monster generation Rule" (up to 5 lines) */
- if (buf[0] == 'R')
- {
- int percent, mode;
- int z, y, lims[5];
-
- /* Scan for the values */
- if (2 != sscanf(buf + 2, "%d:%d",
- &percent, &mode)) return (1);
-
- /* Save the values */
- r_char_number = 0;
- rule_num++;
-
- d_ptr->rules[rule_num].percent = percent;
- d_ptr->rules[rule_num].mode = mode;
-
- /* Lets remap the flat percents */
- lims[0] = d_ptr->rules[0].percent;
- for (y = 1; y <= rule_num; y++)
- {
- lims[y] = lims[y - 1] + d_ptr->rules[y].percent;
- }
- for (z = 0; z < 100; z++)
- {
- for (y = rule_num; y >= 0; y--)
- {
- if (z < lims[y]) d_ptr->rule_percents[z] = y;
- }
- }
-
- /* Next... */
- continue;
- }
-
- /* Process 'M' for "Basic Flags" (multiple lines) */
- if (buf[0] == 'M')
- {
- byte r_char;
-
- /* Parse every entry */
- for (s = buf + 2; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while (*t == ' ' || *t == '|') t++;
- }
-
- /* Read monster symbols */
- if (1 == sscanf(s, "R_CHAR_%c", &r_char))
- {
- /* Limited to 5 races */
- if (r_char_number >= 5) continue;
-
- /* Extract a "frequency" */
- d_ptr->rules[rule_num].r_char[r_char_number++] = r_char;
-
- /* Start at next entry */
- s = t;
-
- /* Continue */
- continue;
- }
-
- /* Parse this entry */
- if (0 != grab_one_basic_monster_flag(d_ptr, s, rule_num)) return (5);
-
- /* Start the next entry */
- s = t;
- }
-
- /* Next... */
- continue;
- }
-
- /* Process 'S' for "Spell Flags" (multiple lines) */
- if (buf[0] == 'S')
- {
- /* Parse every entry */
- for (s = buf + 2; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while ((*t == ' ') || (*t == '|')) t++;
- }
-
- /* Parse this entry */
- if (0 != grab_one_spell_monster_flag(d_ptr, s, rule_num)) return (5);
-
- /* Start the next entry */
- s = t;
- }
-
- /* Next... */
- continue;
- }
-
- /* Oops */
- return (6);
- }
-
-
- /* Complete the "name" and "text" sizes */
- ++d_head->name_size;
- ++d_head->text_size;
-
- /* No version yet */
- if (!okay) return (2);
-
- /* Success */
- return (0);
-}
-
-/*
- * Grab one race flag from a textual string
- */
-static errr grab_one_race_flag(owner_type *ow_ptr, int state, cptr what)
-{
- /* int i;
- cptr s; */
-
- /* Scan race flags */
- unknown_shut_up = TRUE;
- if (!grab_one_race_allow_flag(ow_ptr->races[state], what))
- {
- unknown_shut_up = FALSE;
- return (0);
- }
-
- /* Scan classes flags */
- if (!grab_one_class_flag(ow_ptr->classes[state], what))
- {
- unknown_shut_up = FALSE;
- return (0);
- }
-
- /* Oops */
- unknown_shut_up = FALSE;
- msg_format("Unknown race/class flag '%s'.", what);
-
- /* Failure */
- return (1);
-}
-
-/*
- * Grab one store flag from a textual string
- */
-static errr grab_one_store_flag(store_info_type *st_ptr, cptr what)
-{
- int i;
-
- /* Scan store flags */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, st_info_flags1[i]))
- {
- st_ptr->flags1 |= (1L << i);
- return (0);
- }
- }
-
- /* Oops */
- msg_format("Unknown store flag '%s'.", what);
-
- /* Failure */
- return (1);
-}
-
-/*
- * Initialize the "st_info" array, by parsing an ascii "template" file
- */
-errr init_st_info_txt(FILE *fp, char *buf)
-{
- int i = 0, item_idx = 0;
-
- char *s, *t;
-
- /* Not ready yet */
- bool_ okay = FALSE;
-
- /* Current entry */
- store_info_type *st_ptr = NULL;
-
-
- /* Just before the first record */
- error_idx = -1;
-
- /* Just before the first line */
- error_line = -1;
-
-
- /* Start the "fake" stuff */
- st_head->name_size = 0;
- st_head->text_size = 0;
-
- /* Parse */
- fp_stack_init(fp);
- while (0 == my_fgets_dostack(buf, 1024))
- {
- /* Advance the line number */
- error_line++;
-
- /* Skip comments and blank lines */
- if (!buf[0] || (buf[0] == '#')) continue;
-
- /* Verify correct "colon" format */
- if (buf[1] != ':') return (1);
-
-
- /* Hack -- Process 'V' for "Version" */
- if (buf[0] == 'V')
- {
- int v1, v2, v3;
-
- /* Scan for the values */
- if (3 != sscanf(buf + 2, "%d.%d.%d", &v1, &v2, &v3)) return (2);
-
- /* Okay to proceed */
- okay = TRUE;
-
- /* Continue */
- continue;
- }
-
- /* No version yet */
- if (!okay) return (2);
-
- /* Included file */
- if (buf[0] == '<')
- {
- fp_stack_push(buf + 2);
- continue;
- }
-
- /* Process 'N' for "New/Number/Name" */
- if (buf[0] == 'N')
- {
- /* Find the colon before the name */
- s = strchr(buf + 2, ':');
-
- /* Verify that colon */
- if (!s) return (1);
-
- /* Nuke the colon, advance to the name */
- *s++ = '\0';
-
- /* Paranoia -- require a name */
- if (!*s) return (1);
-
- /* Get the index */
- i = atoi(buf + 2);
-
- /* Verify information */
- if (i < error_idx) return (4);
-
- /* Verify information */
- if (i >= st_head->info_num) return (2);
-
- /* Save the index */
- error_idx = i;
-
- /* Point at the "info" */
- st_ptr = &st_info[i];
-
- /* Hack -- Verify space */
- 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;
-
- /* Append chars to the name */
- strcpy(st_name + st_head->name_size, s);
-
- /* Advance the index */
- st_head->name_size += strlen(s);
-
- /* We are ready for a new set of objects */
- item_idx = 0;
-
- /* Next... */
- continue;
- }
-
- /* There better be a current st_ptr */
- if (!st_ptr) return (3);
-
- /* Process 'I' for "Items" (multiple lines) */
- if (buf[0] == 'I')
- {
- /* Find the colon before the name */
- s = strchr(buf + 2, ':');
-
- /* Verify that colon */
- if (!s) return (1);
-
- /* Nuke the colon, advance to the name */
- *s++ = '\0';
-
- /* Paranoia -- require a name */
- if (!*s) return (1);
-
- /* Get the index */
- st_ptr->table[item_idx][1] = atoi(buf + 2);
-
- /* Append chars to the name */
- st_ptr->table[item_idx++][0] = test_item_name(s);
-
- st_ptr->table_num = item_idx;
-
- /* Next... */
- continue;
- }
-
- /* Process 'T' for "Tval/sval" */
- if (buf[0] == 'T')
- {
- int tv1, sv1, rar1;
-
- /* Scan for the values */
- if (3 != sscanf(buf + 2, "%d:%d:%d",
- &rar1, &tv1, &sv1)) return (1);
-
- /* Get the index */
- st_ptr->table[item_idx][1] = rar1;
- /* Hack -- 256 as a sval means all possible items */
- st_ptr->table[item_idx++][0] = (sv1 < 256) ? lookup_kind(tv1, sv1) : tv1 + 10000;
-
- st_ptr->table_num = item_idx;
-
- /* Next... */
- continue;
- }
-
- /* Process 'G' for "Graphics" one line only) */
- if (buf[0] == 'G')
- {
- char c, a;
- int attr;
-
- /* Scan for the values */
- if (2 != sscanf(buf + 2, "%c:%c",
- &c, &a)) return (1);
-
- /* Extract the color */
- attr = color_char_to_attr(a);
-
- /* Paranoia */
- if (attr < 0) return (1);
-
- /* Save the values */
- st_ptr->d_char = c;
- st_ptr->d_attr = attr;
-
- /* Next... */
- continue;
- }
-
- /* Process 'A' for "Actions" (one line only) */
- if (buf[0] == 'A')
- {
- int a1, a2, a3, a4, a5, a6;
-
- /* Scan for the values */
- if (6 != sscanf(buf + 2, "%d:%d:%d:%d:%d:%d",
- &a1, &a2, &a3, &a4, &a5, &a6)) return (1);
-
- /* Save the values */
- st_ptr->actions[0] = a1;
- st_ptr->actions[1] = a2;
- st_ptr->actions[2] = a3;
- st_ptr->actions[3] = a4;
- st_ptr->actions[4] = a5;
- st_ptr->actions[5] = a6;
-
- /* Next... */
- continue;
- }
-
- /* Process 'F' for "store Flags" (multiple lines) */
- if (buf[0] == 'F')
- {
- /* Parse every entry */
- for (s = buf + 2; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while (*t == ' ' || *t == '|') t++;
- }
-
- /* Parse this entry */
- if (0 != grab_one_store_flag(st_ptr, s)) return (5);
-
- /* Start the next entry */
- s = t;
- }
-
- /* Next... */
- continue;
- }
-
- /* Process 'O' for "Owners" (one line only) */
- if (buf[0] == 'O')
- {
- int a1, a2, a3, a4;
-
- /* Scan for the values */
- if (4 != sscanf(buf + 2, "%d:%d:%d:%d",
- &a1, &a2, &a3, &a4)) return (1);
-
- /* Save the values */
- st_ptr->owners[0] = a1;
- st_ptr->owners[1] = a2;
- st_ptr->owners[2] = a3;
- st_ptr->owners[3] = a4;
-
- /* Next... */
- continue;
- }
-
- /* Process 'W' for "Extra info" (one line only) */
- if (buf[0] == 'W')
- {
- int max_obj;
-
- /* Scan for the values */
- if (1 != sscanf(buf + 2, "%d",
- &max_obj)) return (1);
-
- /* Save the values */
- if (max_obj > STORE_INVEN_MAX) max_obj = STORE_INVEN_MAX;
- st_ptr->max_obj = max_obj;
-
- /* Next... */
- continue;
- }
-
- /* Oops */
- return (6);
- }
-
-
- /* Complete the "name" and "text" sizes */
- ++st_head->name_size;
- ++st_head->text_size;
-
- /* No version yet */
- if (!okay) return (2);
-
- /* Success */
- return (0);
-}
-
-/*
- * Initialize the "ba_info" array, by parsing an ascii "template" file
- */
-errr init_ba_info_txt(FILE *fp, char *buf)
-{
- int i = 0;
-
- char *s;
-
- /* Not ready yet */
- bool_ okay = FALSE;
-
- /* Current entry */
- store_action_type *ba_ptr = NULL;
-
-
- /* Just before the first record */
- error_idx = -1;
-
- /* Just before the first line */
- error_line = -1;
-
-
- /* Start the "fake" stuff */
- ba_head->name_size = 0;
- ba_head->text_size = 0;
-
- /* Parse */
- fp_stack_init(fp);
- while (0 == my_fgets_dostack(buf, 1024))
- {
- /* Advance the line number */
- error_line++;
-
- /* Skip comments and blank lines */
- if (!buf[0] || (buf[0] == '#')) continue;
-
- /* Verify correct "colon" format */
- if (buf[1] != ':') return (1);
-
-
- /* Hack -- Process 'V' for "Version" */
- if (buf[0] == 'V')
- {
- int v1, v2, v3;
-
- /* Scan for the values */
- if (3 != sscanf(buf + 2, "%d.%d.%d", &v1, &v2, &v3)) return (2);
-
- /* Okay to proceed */
- okay = TRUE;
-
- /* Continue */
- continue;
- }
-
- /* No version yet */
- if (!okay) return (2);
-
- /* Included file */
- if (buf[0] == '<')
- {
- fp_stack_push(buf + 2);
- continue;
- }
-
- /* Process 'N' for "New/Number/Name" */
- if (buf[0] == 'N')
- {
- /* Find the colon before the name */
- s = strchr(buf + 2, ':');
-
- /* Verify that colon */
- if (!s) return (1);
-
- /* Nuke the colon, advance to the name */
- *s++ = '\0';
-
- /* Paranoia -- require a name */
- if (!*s) return (1);
-
- /* Get the index */
- i = atoi(buf + 2);
-
- /* Verify information */
- if (i < error_idx) return (4);
-
- /* Verify information */
- if (i >= ba_head->info_num) return (2);
-
- /* Save the index */
- error_idx = i;
-
- /* Point at the "info" */
- ba_ptr = &ba_info[i];
-
- /* Hack -- Verify space */
- 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;
-
- /* Append chars to the name */
- strcpy(ba_name + ba_head->name_size, s);
-
- /* Advance the index */
- ba_head->name_size += strlen(s);
-
- /* Next... */
- continue;
- }
-
- /* There better be a current ba_ptr */
- if (!ba_ptr) return (3);
-
- /* Process 'C' for "Costs" (one line only) */
- if (buf[0] == 'C')
- {
- int ch, cn, cl;
-
- /* Scan for the values */
- if (3 != sscanf(buf + 2, "%d:%d:%d",
- &ch, &cn, &cl)) return (1);
-
- /* Save the values */
- ba_ptr->costs[STORE_HATED] = ch;
- ba_ptr->costs[STORE_NORMAL] = cn;
- ba_ptr->costs[STORE_LIKED] = cl;
-
- /* Next... */
- continue;
- }
-
- /* Process 'I' for "Infos" (one line only) */
- if (buf[0] == 'I')
- {
- int act, act_res;
- char letter, letter_aux = 0;
-
- /* Scan for the values */
- if (4 != sscanf(buf + 2, "%d:%d:%c:%c", &act, &act_res, &letter, &letter_aux))
- if (3 != sscanf(buf + 2, "%d:%d:%c", &act, &act_res, &letter))
- return (1);
-
- /* Save the values */
- ba_ptr->action = act;
- ba_ptr->action_restr = act_res;
- ba_ptr->letter = letter;
- ba_ptr->letter_aux = letter_aux;
-
- /* Next... */
- continue;
- }
-
- /* Oops */
- return (6);
- }
-
-
- /* Complete the "name" and "text" sizes */
- ++ba_head->name_size;
- ++ba_head->text_size;
-
- /* No version yet */
- if (!okay) return (2);
-
- /* Success */
- return (0);
-}
-
-/*
- * Initialize the "ow_info" array, by parsing an ascii "template" file
- */
-errr init_ow_info_txt(FILE *fp, char *buf)
-{
- int i;
-
- char *s, *t;
-
- /* Not ready yet */
- bool_ okay = FALSE;
-
- /* Current entry */
- owner_type *ow_ptr = NULL;
-
-
- /* Just before the first record */
- error_idx = -1;
-
- /* Just before the first line */
- error_line = -1;
-
-
- /* Start the "fake" stuff */
- ow_head->name_size = 0;
- ow_head->text_size = 0;
-
- /* Parse */
- fp_stack_init(fp);
- while (0 == my_fgets_dostack(buf, 1024))
- {
- /* Advance the line number */
- error_line++;
-
- /* Skip comments and blank lines */
- if (!buf[0] || (buf[0] == '#')) continue;
-
- /* Verify correct "colon" format */
- if (buf[1] != ':') return (1);
-
-
- /* Hack -- Process 'V' for "Version" */
- if (buf[0] == 'V')
- {
- int v1, v2, v3;
-
- /* Scan for the values */
- if (3 != sscanf(buf + 2, "%d.%d.%d", &v1, &v2, &v3)) return (2);
-
- /* Okay to proceed */
- okay = TRUE;
-
- /* Continue */
- continue;
- }
-
- /* No version yet */
- if (!okay) return (2);
-
- /* Included file */
- if (buf[0] == '<')
- {
- fp_stack_push(buf + 2);
- continue;
- }
-
- /* Process 'N' for "New/Number/Name" */
- if (buf[0] == 'N')
- {
- /* Find the colon before the name */
- s = strchr(buf + 2, ':');
-
- /* Verify that colon */
- if (!s) return (1);
-
- /* Nuke the colon, advance to the name */
- *s++ = '\0';
-
- /* Paranoia -- require a name */
- if (!*s) return (1);
-
- /* Get the index */
- i = atoi(buf + 2);
-
- /* Verify information */
- if (i < error_idx) return (4);
-
- /* Verify information */
- if (i >= ow_head->info_num) return (2);
-
- /* Save the index */
- error_idx = i;
-
- /* Point at the "info" */
- ow_ptr = &ow_info[i];
-
- /* Hack -- Verify space */
- 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;
-
- /* Append chars to the name */
- strcpy(ow_name + ow_head->name_size, s);
-
- /* Advance the index */
- ow_head->name_size += strlen(s);
-
- /* Next... */
- continue;
- }
-
- /* There better be a current ow_ptr */
- if (!ow_ptr) return (3);
-
-
- /* Process 'C' for "Costs" (one line only) */
- if (buf[0] == 'C')
- {
- int ch, cn, cl;
-
- /* Scan for the values */
- if (3 != sscanf(buf + 2, "%d:%d:%d",
- &ch, &cn, &cl)) return (1);
-
- /* Save the values */
- ow_ptr->costs[STORE_HATED] = ch;
- ow_ptr->costs[STORE_NORMAL] = cn;
- ow_ptr->costs[STORE_LIKED] = cl;
-
- /* Next... */
- continue;
- }
-
- /* Process 'I' for "Info" (multiple lines line only) */
- if (buf[0] == 'I')
- {
- int cost, max_inf, min_inf, haggle, insult;
-
- /* Scan for the values */
- if (5 != sscanf(buf + 2, "%d:%d:%d:%d:%d",
- &cost, &max_inf, &min_inf, &haggle, &insult)) 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;
-
- /* Next... */
- continue;
- }
-
- /* Process 'L' for "Liked races/classes" (multiple lines) */
- if (buf[0] == 'L')
- {
- /* Parse every entry */
- for (s = buf + 2; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while (*t == ' ' || *t == '|') t++;
- }
-
- /* Parse this entry */
- if (0 != grab_one_race_flag(ow_ptr, STORE_LIKED, s)) return (5);
-
- /* Start the next entry */
- s = t;
- }
-
- /* Next... */
- continue;
- }
- /* Process 'H' for "Hated races/classes" (multiple lines) */
- if (buf[0] == 'H')
- {
- /* Parse every entry */
- for (s = buf + 2; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while (*t == ' ' || *t == '|') t++;
- }
-
- /* Parse this entry */
- if (0 != grab_one_race_flag(ow_ptr, STORE_HATED, s)) return (5);
-
- /* Start the next entry */
- s = t;
- }
-
- /* Next... */
- continue;
- }
-
- /* Oops */
- return (6);
- }
-
-
- /* Complete the "name" and "text" sizes */
- ++ow_head->name_size;
- ++ow_head->text_size;
-
- /* No version yet */
- if (!okay) return (2);
-
- /* Success */
- return (0);
-}
-
-/*
- * Grab one flag for a dungeon type from a textual string
- */
-static errr grab_one_wf_info_flag(wilderness_type_info *wf_ptr, cptr what)
-{
- int i;
-
- /* Scan flags1 */
- for (i = 0; i < 32; i++)
- {
- if (streq(what, wf_info_flags1[i]))
- {
- wf_ptr->flags1 |= (1L << i);
- return (0);
- }
- }
-
- /* Oops */
- msg_format("Unknown monster flag '%s'.", what);
-
- /* Failure */
- return (1);
-}
-
-/*
- * Initialize the "wf_info" array, by parsing an ascii "template" file
- */
-errr init_wf_info_txt(FILE *fp, char *buf)
-{
- int i;
-
- char *s, *t;
-
- /* Not ready yet */
- bool_ okay = FALSE;
-
- /* Current entry */
- wilderness_type_info *wf_ptr = NULL;
-
-
- /* Just before the first record */
- error_idx = -1;
-
- /* Just before the first line */
- error_line = -1;
-
-
- /* Start the "fake" stuff */
- wf_head->name_size = 0;
- wf_head->text_size = 0;
-
- /* Parse */
- fp_stack_init(fp);
- while (0 == my_fgets_dostack(buf, 1024))
- {
- /* Advance the line number */
- error_line++;
-
- /* Skip comments and blank lines */
- if (!buf[0] || (buf[0] == '#')) continue;
-
- /* Verify correct "colon" format */
- if (buf[1] != ':') return (1);
-
-
- /* Hack -- Process 'V' for "Version" */
- if (buf[0] == 'V')
- {
- int v1, v2, v3;
-
- /* Scan for the values */
- if (3 != sscanf(buf + 2, "%d.%d.%d", &v1, &v2, &v3)) return (2);
-
- /* Okay to proceed */
- okay = TRUE;
-
- /* Continue */
- continue;
- }
-
- /* No version yet */
- if (!okay) return (2);
-
- /* Included file */
- if (buf[0] == '<')
- {
- fp_stack_push(buf + 2);
- continue;
- }
-
- /* Process 'N' for "New/Number/Name" */
- if (buf[0] == 'N')
- {
- /* Find the colon before the name */
- s = strchr(buf + 2, ':');
-
- /* Verify that colon */
- if (!s) return (1);
-
- /* Nuke the colon, advance to the name */
- *s++ = '\0';
-
- /* Paranoia -- require a name */
- if (!*s) return (1);
-
- /* Get the index */
- i = atoi(buf + 2);
-
- /* Verify information */
- if (i < error_idx) return (4);
-
- /* Verify information */
- if (i >= wf_head->info_num) return (2);
-
- /* Save the index */
- error_idx = i;
-
- /* Point at the "info" */
- wf_ptr = &wf_info[i];
-
- /* Hack -- Verify space */
- 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;
-
- /* Append chars to the name */
- strcpy(wf_name + wf_head->name_size, s);
-
- /* Advance the index */
- wf_head->name_size += strlen(s);
-
- /* Next... */
- continue;
- }
-
- /* There better be a current wf_ptr */
- if (!wf_ptr) return (3);
-
- /* Process 'D' for "Description */
- if (buf[0] == 'D')
- {
- /* Acquire the text */
- s = buf + 2;
-
- /* Hack -- Verify space */
- 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;
-
- /* Append chars to the name */
- strcpy(wf_text + wf_head->text_size, s);
-
- /* Advance the index */
- wf_head->text_size += strlen(s);
-
- /* Next... */
- continue;
- }
-
- /* Process 'W' for "More Info" (one line only) */
- if (buf[0] == 'W')
- {
- int entrance, level;
- int road, feat, ter_idx;
- char car;
-
- /* Scan for the values */
- if (6 != sscanf(buf + 2, "%d:%d:%d:%d:%d:%c",
- &level, &entrance, &road, &feat, &ter_idx, &car)) return (1);
-
- /* Save the values */
- wf_ptr->level = level;
- wf_ptr->entrance = entrance;
- wf_ptr->road = road;
- wf_ptr->feat = feat;
- wf_ptr->terrain_idx = ter_idx;
-
- /* To acces it easily from the map structure */
- wildc2i[(int)car] = error_idx;
-
- /* Next... */
- continue;
- }
-
- /* Process 'X' for "More Info" (one line only) */
- if (buf[0] == 'X')
- {
- int terrain[MAX_WILD_TERRAIN], i;
-
- /* Scan for the values */
- if (MAX_WILD_TERRAIN != sscanf(buf + 2, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
- &terrain[0], &terrain[1], &terrain[2],
- &terrain[3], &terrain[4], &terrain[5],
- &terrain[6], &terrain[7], &terrain[8],
- &terrain[9], &terrain[10], &terrain[11],
- &terrain[12], &terrain[13], &terrain[14],
- &terrain[15], &terrain[16], &terrain[17])) return (1);
-
- /* Save the values */
- for (i = 0; i < MAX_WILD_TERRAIN; i++)
- {
- wf_ptr->terrain[i] = terrain[i];
- }
-
- /* Next... */
- continue;
- }
-
- /* Process 'F' for "Wilderness feature Flags" (multiple lines) */
- if (buf[0] == 'F')
- {
- /* Parse every entry */
- for (s = buf + 2; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while (*t == ' ' || *t == '|') t++;
- }
-
- /* Parse this entry */
- if (0 != grab_one_wf_info_flag(wf_ptr, s)) return (5);
-
- /* Start the next entry */
- s = t;
- }
-
- /* Next... */
- continue;
- }
-
- /* Oops */
- return (6);
- }
-
-
- /* Complete the "name" and "text" sizes */
- ++wf_head->name_size;
- ++wf_head->text_size;
-
- /* No version yet */
- if (!okay) return (2);
-
- /* Success */
- return (0);
-}
-
-
-/* Random dungeon grid effects */
-#define RANDOM_NONE 0x00
-#define RANDOM_FEATURE 0x01
-#define RANDOM_MONSTER 0x02
-#define RANDOM_OBJECT 0x04
-#define RANDOM_EGO 0x08
-#define RANDOM_ARTIFACT 0x10
-#define RANDOM_TRAP 0x20
-
-
-typedef struct dungeon_grid dungeon_grid;
-
-struct dungeon_grid
-{
- int feature; /* Terrain feature */
- int monster; /* Monster */
- int object; /* Object */
- int ego; /* Ego-Item */
- int artifact; /* Artifact */
- int trap; /* Trap */
- int cave_info; /* Flags for CAVE_MARK, CAVE_GLOW, CAVE_ICKY, CAVE_ROOM */
- int special; /* Reserved for special terrain info */
- int random; /* Number of the random effect */
- int bx, by; /* For between gates */
- int mimic; /* Mimiced features */
- s32b mflag; /* monster's mflag */
- bool_ ok;
- bool_ defined;
-};
-static bool_ meta_sleep = TRUE;
-
-static dungeon_grid letter[255];
-
-/*
- * Parse a sub-file of the "extra info"
- */
-static errr process_dungeon_file_aux(char *buf, int *yval, int *xval, int xvalstart, int ymax, int xmax, bool_ full)
-{
- int i;
-
- char *zz[33];
-
-
- /* 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 "%:<fname>" */
- if (buf[0] == '%')
- {
- /* Attempt to Process the given file */
- return (process_dungeon_file(buf + 2, yval, xval, ymax, xmax, FALSE, full));
- }
-
- /* Process "N:<sleep>" */
- if (buf[0] == 'N')
- {
- int num;
-
- if ((num = tokenize(buf + 2, 1, zz, ':', '/')) > 0)
- {
- meta_sleep = atoi(zz[0]);
- }
-
- return (0);
- }
-
- /* Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>:<mimic>:<mflag>" -- info for dungeon grid */
- if (buf[0] == 'F')
- {
- int num;
-
- if ((num = tokenize(buf + 2, 11, zz, ':', '/')) > 1)
- {
- int index = zz[0][0];
-
- /* Reset the feature */
- letter[index].feature = 0;
- letter[index].monster = 0;
- letter[index].object = 0;
- letter[index].ego = 0;
- letter[index].artifact = 0;
- letter[index].trap = 0;
- letter[index].cave_info = 0;
- letter[index].special = 0;
- letter[index].random = 0;
- letter[index].mimic = 0;
- letter[index].mflag = 0;
- letter[index].ok = TRUE;
- letter[index].defined = TRUE;
-
- if (num > 1)
- {
- if (zz[1][0] == '*')
- {
- letter[index].random |= RANDOM_FEATURE;
- if (zz[1][1])
- {
- zz[1]++;
- letter[index].feature = atoi(zz[1]);
- }
- }
- else
- {
- letter[index].feature = atoi(zz[1]);
- }
- }
-
- if (num > 2)
- letter[index].cave_info = atoi(zz[2]);
-
- /* Monster */
- if (num > 3)
- {
- if (zz[3][0] == '*')
- {
- letter[index].random |= RANDOM_MONSTER;
- if (zz[3][1])
- {
- zz[3]++;
- letter[index].monster = atoi(zz[3]);
- }
- }
- else
- {
- letter[index].monster = atoi(zz[3]);
- }
- }
-
- /* Object */
- if (num > 4)
- {
- if (zz[4][0] == '*')
- {
- letter[index].random |= RANDOM_OBJECT;
-
- if (zz[4][1])
- {
- zz[4]++;
- letter[index].object = atoi(zz[4]);
- }
- }
- else
- {
- letter[index].object = atoi(zz[4]);
- }
- }
-
- /* Ego-Item */
- if (num > 5)
- {
- if (zz[5][0] == '*')
- {
- letter[index].random |= RANDOM_EGO;
-
- if (zz[5][1])
- {
- zz[5]++;
- letter[index].ego = atoi(zz[5]);
- }
- }
- else
- {
- letter[index].ego = atoi(zz[5]);
- }
- }
-
- /* Artifact */
- if (num > 6)
- {
- if (zz[6][0] == '*')
- {
- letter[index].random |= RANDOM_ARTIFACT;
-
- if (zz[6][1])
- {
- zz[6]++;
- letter[index].artifact = atoi(zz[6]);
- }
- }
- else
- {
- letter[index].artifact = atoi(zz[6]);
- }
- }
-
- if (num > 7)
- {
- if (zz[7][0] == '*')
- {
- letter[index].random |= RANDOM_TRAP;
-
- if (zz[7][1])
- {
- zz[7]++;
- letter[index].trap = atoi(zz[7]);
- }
- }
- else
- letter[index].trap = atoi(zz[7]);
- }
-
- if (num > 8)
- {
- /* Quests can be defined by name only */
- if (zz[8][0] == '"')
- {
- int i;
-
- /* Hunt & shoot the ending " */
- 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++)
- {
- if (!strcmp(&zz[8][1], quest[i].name))
- {
- letter[index].special = i;
- break;
- }
- }
- }
- else
- letter[index].special = atoi(zz[8]);
- }
-
- if (num > 9)
- {
- letter[index].mimic = atoi(zz[9]);
- }
-
- if (num > 10)
- {
- letter[index].mflag = atoi(zz[10]);
- }
-
- return (0);
- }
- }
-
- /* Process "f:flags" -- level flags */
- else if (buf[0] == 'f')
- {
- char *s, *t;
-
- /* Parse every entry textually */
- for (s = buf + 2; *s; )
- {
- /* Find the end of this entry */
- for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
-
- /* Nuke and skip any dividers */
- if (*t)
- {
- *t++ = '\0';
- while (*t == ' ' || *t == '|') t++;
- }
-
- /* Parse this entry */
- if (0 != grab_one_dungeon_flag(&dungeon_flags1, &dungeon_flags2, s)) return 1;
-
- /* Start the next entry */
- s = t;
- }
-
- return 0;
- }
-
- /* Process "D:<dungeon>" -- info for the cave grids */
- else if (buf[0] == 'D')
- {
- int x, m_idx = 0;
-
- object_type object_type_body;
-
- /* Acquire the text */
- char *s = buf + 2;
-
- /* Length of the text */
- int len = strlen(s);
-
- int y = *yval;
- *xval = xvalstart;
- for (x = *xval, i = 0; ((x < xmax) && (i < len)); x++, s++, i++)
- {
- /* Access the grid */
- cave_type *c_ptr = &cave[y][x];
-
- int idx = s[0];
-
- int object_index = letter[idx].object;
- int monster_index = letter[idx].monster;
- int random = letter[idx].random;
- int artifact_index = letter[idx].artifact;
-
- if (!letter[idx].ok) msg_format("Warning '%c' not defined but used.", idx);
-
- if (init_flags & INIT_GET_SIZE) continue;
-
- /* use the plasma generator wilderness */
- if (((!dun_level) || (!letter[idx].defined)) && (idx == ' ')) continue;
-
- /* Clear some info */
- c_ptr->info = 0;
-
- /* Lay down a floor */
- c_ptr->mimic = letter[idx].mimic;
- cave_set_feat(y, x, letter[idx].feature);
-
- /* Cave info */
- c_ptr->info |= letter[idx].cave_info;
-
- /* Create a monster */
- if (random & RANDOM_MONSTER)
- {
- int level = monster_level;
-
- monster_level = quest[p_ptr->inside_quest].level + monster_index;
-
- m_idx = place_monster(y, x, meta_sleep, FALSE);
-
- monster_level = level;
- }
- else if (monster_index)
- {
- /* Place it */
- m_allow_special[monster_index] = TRUE;
- m_idx = place_monster_aux(y, x, monster_index, meta_sleep, FALSE, MSTATUS_ENEMY);
- m_allow_special[monster_index] = FALSE;
- }
-
- /* Set the mflag of the monster */
- if (m_idx) m_list[m_idx].mflag |= letter[idx].mflag;
-
- /* Object (and possible trap) */
- if ((random & RANDOM_OBJECT) && (random & RANDOM_TRAP))
- {
- int level = object_level;
-
- object_level = quest[p_ptr->inside_quest].level;
-
- /*
- * Random trap and random treasure defined
- * 25% chance for trap and 75% chance for object
- */
- if (rand_int(100) < 75)
- {
- place_object(y, x, FALSE, FALSE, OBJ_FOUND_SPECIAL);
- }
- else
- {
- place_trap(y, x);
- }
-
- object_level = level;
- }
- else if (random & RANDOM_OBJECT)
- {
- /* Create an out of deep object */
- if (object_index)
- {
- int level = object_level;
-
- object_level = quest[p_ptr->inside_quest].level + object_index;
- if (rand_int(100) < 75)
- place_object(y, x, FALSE, FALSE, OBJ_FOUND_SPECIAL);
- else if (rand_int(100) < 80)
- place_object(y, x, TRUE, FALSE, OBJ_FOUND_SPECIAL);
- else
- place_object(y, x, TRUE, TRUE, OBJ_FOUND_SPECIAL);
-
- object_level = level;
- }
- else if (rand_int(100) < 75)
- {
- place_object(y, x, FALSE, FALSE, OBJ_FOUND_SPECIAL);
- }
- else if (rand_int(100) < 80)
- {
- place_object(y, x, TRUE, FALSE, OBJ_FOUND_SPECIAL);
- }
- else
- {
- place_object(y, x, TRUE, TRUE, OBJ_FOUND_SPECIAL);
- }
- }
- /* Random trap */
- else if (random & RANDOM_TRAP)
- {
- place_trap(y, x);
- }
- else if (object_index)
- {
- /* Get local object */
- object_type *o_ptr = &object_type_body;
-
- k_allow_special[object_index] = TRUE;
-
- /* Create the item */
- object_prep(o_ptr, object_index);
-
- /* Apply magic (no messages, no artifacts) */
- apply_magic(o_ptr, dun_level, FALSE, TRUE, FALSE);
-
- o_ptr->found = OBJ_FOUND_SPECIAL;
-
- k_allow_special[object_index] = FALSE;
-
- drop_near(o_ptr, -1, y, x);
- }
-
- /* Artifact */
- if (artifact_index)
- {
- int I_kind = 0;
-
- artifact_type *a_ptr = &a_info[artifact_index];
-
- object_type forge;
-
- /* Get local object */
- object_type *q_ptr = &forge;
-
- a_allow_special[artifact_index] = TRUE;
-
- /* Wipe the object */
- object_wipe(q_ptr);
-
- /* Acquire the "kind" index */
- I_kind = lookup_kind(a_ptr->tval, a_ptr->sval);
-
- /* Create the artifact */
- object_prep(q_ptr, I_kind);
-
- /* Save the name */
- q_ptr->name1 = artifact_index;
-
- /* Extract the fields */
- q_ptr->pval = a_ptr->pval;
- q_ptr->ac = a_ptr->ac;
- q_ptr->dd = a_ptr->dd;
- q_ptr->ds = a_ptr->ds;
- q_ptr->to_a = a_ptr->to_a;
- q_ptr->to_h = a_ptr->to_h;
- q_ptr->to_d = a_ptr->to_d;
- q_ptr->weight = a_ptr->weight;
- q_ptr->found = OBJ_FOUND_SPECIAL;
-
- random_artifact_resistance(q_ptr);
-
- a_info[artifact_index].cur_num = 1;
-
- a_allow_special[artifact_index] = FALSE;
-
- /* It's amazing that this "creating objects anywhere"
- junk ever worked.
- Let's just HACK around one observed bug: Shadow Cloak
- of Luthien [Globe of Light] */
- {
- u32b f1, f2, f3, f4, f5, esp;
- object_flags(q_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
- if (f5 & TR5_SPELL_CONTAIN)
- q_ptr->pval2 = -1;
- }
-
- /* Drop the artifact */
- drop_near(q_ptr, -1, y, x);
-
- }
-
- /* Terrain special */
- if (letter[idx].special == -1)
- {
- if (!letter[idx].bx)
- {
- letter[idx].bx = x;
- letter[idx].by = y;
- }
- else
- {
- c_ptr->special = (letter[idx].by << 8) + letter[idx].bx;
- cave[letter[idx].by][letter[idx].bx].special = (y << 8) + x;
- }
- }
- else
- {
- c_ptr->special = letter[idx].special;
- }
- }
- if (full && (*xval < x)) *xval = x;
- (*yval)++;
-
- return (0);
- }
-
- /* Process "W:<command>: ..." -- info for the wilderness */
- else if (buf[0] == 'W')
- {
- /* Process "W:D:<layout> */
- /* Layout of the wilderness */
- if (buf[2] == 'D')
- {
- int x;
- char i;
-
- /* Acquire the text */
- char *s = buf + 4;
-
- int y = *yval;
-
- for (x = 0; x < max_wild_x; x++)
- {
- if (1 != sscanf(s + x, "%c", &i)) return (1);
- wild_map[y][x].feat = wildc2i[(int)i];
-
- /*
- * If this is a town/dungeon entrance, note
- * its coordinates. (Have to check for
- * duplicate Morias...)
- */
- if (wf_info[wildc2i[(int)i]].entrance &&
- wf_info[wildc2i[(int)i]].wild_x == 0)
- {
- wf_info[wildc2i[(int)i]].wild_x = x;
- wf_info[wildc2i[(int)i]].wild_y = y;
- }
- }
-
- (*yval)++;
-
- return (0);
- }
- /* Process "M:<plus>:<line>" -- move line lines */
- else if (buf[2] == 'M')
- {
- if (tokenize(buf + 4, 2, zz, ':', '/') == 2)
- {
- if (atoi(zz[0]))
- {
- (*yval) += atoi(zz[1]);
- }
- else
- {
- (*yval) -= atoi(zz[1]);
- }
- }
- else
- {
- return (1);
- }
- return (0);
- }
- /* Process "W:P:<x>:<y> - starting position in the wilderness */
- else if (buf[2] == 'P')
- {
- if ((p_ptr->wilderness_x == 0) &&
- (p_ptr->wilderness_y == 0))
- {
- if (tokenize(buf + 4, 2, zz, ':', '/') == 2)
- {
- p_ptr->wilderness_x = atoi(zz[0]);
- p_ptr->wilderness_y = atoi(zz[1]);
- }
- else
- {
- return (1);
- }
- }
-
- return (0);
- }
- /* Process "W:E:<dungeon>:<y>:<x> - entrance to the dungeon <dungeon> */
- else if (buf[2] == 'E')
- {
- if (tokenize(buf + 4, 3, zz, ':', '/') == 3)
- {
- wild_map[atoi(zz[1])][atoi(zz[2])].entrance = 1000 + atoi(zz[0]);
- }
- else
- {
- return (1);
- }
-
- return (0);
- }
- }
-
- /* Process "P:<y>:<x>" -- player position */
- else if (buf[0] == 'P')
- {
- if (init_flags & INIT_CREATE_DUNGEON)
- {
- if (tokenize(buf + 2, 2, zz, ':', '/') == 2)
- {
- /* Place player in a quest level */
- if (p_ptr->inside_quest || (init_flags & INIT_POSITION))
- {
- p_ptr->py = atoi(zz[0]);
- p_ptr->px = atoi(zz[1]);
- }
- /* Place player in the town */
- else if ((p_ptr->oldpx == 0) && (p_ptr->oldpy == 0))
- {
- p_ptr->oldpy = atoi(zz[0]);
- p_ptr->oldpx = atoi(zz[1]);
- }
- }
- }
-
- return (0);
- }
-
- /* Process "M:<type>:<maximum>" -- set maximum values */
- else if (buf[0] == 'M')
- {
- if (tokenize(buf + 2, 3, zz, ':', '/') >= 2)
- {
- /* Maximum towns */
- if (zz[0][0] == 'T')
- {
- max_towns = atoi(zz[1]);
- }
-
- /* Maximum real towns */
- if (zz[0][0] == 't')
- {
- max_real_towns = atoi(zz[1]);
- }
-
- /* Maximum r_idx */
- else if (zz[0][0] == 'R')
- {
- max_r_idx = atoi(zz[1]);
- }
-
- /* Maximum re_idx */
- else if (zz[0][0] == 'r')
- {
- max_re_idx = atoi(zz[1]);
- }
-
- /* Maximum s_idx */
- else if (zz[0][0] == 'k')
- {
- max_s_idx = atoi(zz[1]);
- if (max_s_idx > MAX_SKILLS) return (1);
- }
-
- /* Maximum ab_idx */
- else if (zz[0][0] == 'b')
- {
- max_ab_idx = atoi(zz[1]);
- }
-
- /* Maximum k_idx */
- else if (zz[0][0] == 'K')
- {
- max_k_idx = atoi(zz[1]);
- }
-
- /* Maximum v_idx */
- else if (zz[0][0] == 'V')
- {
- max_v_idx = atoi(zz[1]);
- }
-
- /* Maximum f_idx */
- else if (zz[0][0] == 'F')
- {
- max_f_idx = atoi(zz[1]);
- }
-
- /* Maximum a_idx */
- else if (zz[0][0] == 'A')
- {
- max_a_idx = atoi(zz[1]);
- }
-
- /* Maximum al_idx */
- else if (zz[0][0] == 'a')
- {
- max_al_idx = atoi(zz[1]);
- }
-
- /* Maximum e_idx */
- else if (zz[0][0] == 'E')
- {
- max_e_idx = atoi(zz[1]);
- }
-
- /* Maximum ra_idx */
- else if (zz[0][0] == 'Z')
- {
- max_ra_idx = atoi(zz[1]);
- }
-
- /* Maximum o_idx */
- else if (zz[0][0] == 'O')
- {
- max_o_idx = atoi(zz[1]);
- }
-
- /* Maximum player types */
- else if (zz[0][0] == 'P')
- {
- if (zz[1][0] == 'R')
- {
- max_rp_idx = atoi(zz[2]);
- }
- else if (zz[1][0] == 'S')
- {
- max_rmp_idx = atoi(zz[2]);
- }
- else if (zz[1][0] == 'C')
- {
- max_c_idx = atoi(zz[2]);
- }
- else if (zz[1][0] == 'M')
- {
- max_mc_idx = atoi(zz[2]);
- }
- else if (zz[1][0] == 'H')
- {
- max_bg_idx = atoi(zz[2]);
- }
- }
-
- /* Maximum m_idx */
- else if (zz[0][0] == 'M')
- {
- max_m_idx = atoi(zz[1]);
- }
-
- /* Maximum tr_idx */
- else if (zz[0][0] == 'U')
- {
- max_t_idx = atoi(zz[1]);
- }
-
- /* Maximum wf_idx */
- else if (zz[0][0] == 'W')
- {
- max_wf_idx = atoi(zz[1]);
- }
-
- /* Maximum ba_idx */
- else if (zz[0][0] == 'B')
- {
- max_ba_idx = atoi(zz[1]);
- }
-
- /* Maximum st_idx */
- else if (zz[0][0] == 'S')
- {
- max_st_idx = atoi(zz[1]);
- }
-
- /* Maximum set_idx */
- else if (zz[0][0] == 's')
- {
- max_set_idx = atoi(zz[1]);
- }
-
- /* Maximum ow_idx */
- else if (zz[0][0] == 'N')
- {
- max_ow_idx = atoi(zz[1]);
- }
-
- /* Maximum wilderness x size */
- else if (zz[0][0] == 'X')
- {
- max_wild_x = atoi(zz[1]);
- }
-
- /* Maximum wilderness y size */
- else if (zz[0][0] == 'Y')
- {
- max_wild_y = atoi(zz[1]);
- }
-
- /* Maximum d_idx */
- else if (zz[0][0] == 'D')
- {
- max_d_idx = atoi(zz[1]);
- }
-
- return (0);
- }
- }
-
- /* Failure */
- return (1);
-}
-
-
-
-
-/*
- * Helper function for "process_dungeon_file()"
- */
-static cptr process_dungeon_file_expr(char **sp, char *fp)
-{
- cptr v;
-
- char *b;
- char *s;
-
- char b1 = '[';
- char b2 = ']';
-
- char f = ' ';
-
- /* Initial */
- s = (*sp);
-
- /* Skip spaces */
- while (isspace(*s)) s++;
-
- /* Save start */
- b = s;
-
- /* Default */
- v = "?o?o?";
-
- /* Analyze */
- if (*s == b1)
- {
- const char *p;
- const char *t;
-
- /* Skip b1 */
- s++;
-
- /* First */
- t = process_dungeon_file_expr(&s, &f);
-
- /* Oops */
- if (!*t)
- {
- /* Nothing */
- }
-
- /* Function: IOR */
- else if (streq(t, "IOR"))
- {
- v = "0";
- while (*s && (f != b2))
- {
- t = process_dungeon_file_expr(&s, &f);
- if (*t && !streq(t, "0")) v = "1";
- }
- }
-
- /* Function: AND */
- else if (streq(t, "AND"))
- {
- v = "1";
- while (*s && (f != b2))
- {
- t = process_dungeon_file_expr(&s, &f);
- if (*t && streq(t, "0")) v = "0";
- }
- }
-
- /* Function: NOT */
- else if (streq(t, "NOT"))
- {
- v = "1";
- while (*s && (f != b2))
- {
- t = process_dungeon_file_expr(&s, &f);
- if (*t && streq(t, "1")) v = "0";
- }
- }
-
- /* Function: EQU */
- else if (streq(t, "EQU"))
- {
- v = "1";
- if (*s && (f != b2))
- {
- t = process_dungeon_file_expr(&s, &f);
- }
- while (*s && (f != b2))
- {
- p = t;
- t = process_dungeon_file_expr(&s, &f);
- if (*t && !streq(p, t)) v = "0";
- }
- }
-
- /* Function: LEQ */
- else if (streq(t, "LEQ"))
- {
- v = "1";
- if (*s && (f != b2))
- {
- t = process_dungeon_file_expr(&s, &f);
- }
- while (*s && (f != b2))
- {
- p = t;
- t = process_dungeon_file_expr(&s, &f);
- if (*t && (strcmp(p, t) > 0)) v = "0";
- }
- }
-
- /* Function: GEQ */
- else if (streq(t, "GEQ"))
- {
- v = "1";
- if (*s && (f != b2))
- {
- t = process_dungeon_file_expr(&s, &f);
- }
- while (*s && (f != b2))
- {
- p = t;
- t = process_dungeon_file_expr(&s, &f);
- if (*t && (strcmp(p, t) < 0)) v = "0";
- }
- }
-
- /* Oops */
- else
- {
- while (*s && (f != b2))
- {
- t = process_dungeon_file_expr(&s, &f);
- }
- }
-
- /* Verify ending */
- if (f != b2) v = "?x?x?";
-
- /* Extract final and Terminate */
- if ((f = *s) != '\0') * s++ = '\0';
- }
-
- /* Other */
- else
- {
- bool_ text_mode = FALSE;
-
- /* Accept all printables except spaces and brackets */
- while (isprint(*s))
- {
- if (*s == '"') text_mode = !text_mode;
- if (!text_mode)
- {
- if (strchr(" []", *s))
- break;
- }
- else
- {
- if (strchr("[]", *s))
- break;
- }
-
- ++s;
- }
-
- /* Extract final and Terminate */
- if ((f = *s) != '\0') * s++ = '\0';
-
- /* Variable */
- if (*b == '$')
- {
- /* System */
- if (streq(b + 1, "SYS"))
- {
- v = ANGBAND_SYS;
- }
-
- /* Graphics */
- else if (streq(b + 1, "GRAF"))
- {
- v = ANGBAND_GRAF;
- }
-
- /* Race */
- else if (streq(b + 1, "RACE"))
- {
- v = rp_ptr->title + rp_name;
- }
-
- /* Race Mod */
- else if (streq(b + 1, "RACEMOD"))
- {
- v = rmp_ptr->title + rmp_name;
- }
-
- /* Class */
- else if (streq(b + 1, "CLASS"))
- {
- v = cp_ptr->title + c_name;
- }
-
- /* Player */
- else if (streq(b + 1, "PLAYER"))
- {
- v = player_base;
- }
-
- /* Town */
- else if (streq(b + 1, "TOWN"))
- {
- strnfmt(pref_tmp_value, 8, "%d", p_ptr->town_num);
- v = pref_tmp_value;
- }
-
- /* Town destroyed */
- else if (prefix(b + 1, "TOWN_DESTROY"))
- {
- strnfmt(pref_tmp_value, 8, "%d", town_info[atoi(b + 13)].destroyed);
- v = pref_tmp_value;
- }
-
- /* Current quest number */
- else if (streq(b + 1, "QUEST_NUMBER"))
- {
- strnfmt(pref_tmp_value, 8, "%d", p_ptr->inside_quest);
- v = pref_tmp_value;
- }
-
- /* Number of last quest */
- else if (streq(b + 1, "LEAVING_QUEST"))
- {
- strnfmt(pref_tmp_value, 8, "%d", leaving_quest);
- v = pref_tmp_value;
- }
-
- /* DAYTIME status */
- else if (prefix(b + 1, "DAYTIME"))
- {
- if ((bst(HOUR, turn) >= 6) && (bst(HOUR, turn) < 18))
- v = "1";
- else
- v = "0";
- }
-
- /* Quest status */
- else if (prefix(b + 1, "QUEST"))
- {
- /* "QUEST" uses a special parameter to determine the number of the quest */
- if (*(b + 6) != '"')
- strnfmt(pref_tmp_value, 8, "%d", quest[atoi(b + 6)].status);
- else
- {
- char c[80];
- int i;
-
- /* Copy it to temp array, so that we can modify it safely */
- strcpy(c, b + 7);
-
- /* Hunt & shoot the ending " */
- 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++)
- {
- if (streq(c, quest[i].name))
- {
- strnfmt(pref_tmp_value, 8, "%d", quest[i].status);
- break;
- }
- }
- }
- v = pref_tmp_value;
- }
-
- /* Variant name */
- else if (streq(b + 1, "VARIANT"))
- {
- v = "ToME";
- }
-
- /* Wilderness */
- else if (streq(b + 1, "WILDERNESS"))
- {
- v = "NORMAL";
- }
- }
-
- /* Constant */
- else
- {
- v = b;
- }
- }
-
- /* Save */
- (*fp) = f;
-
- /* Save */
- (*sp) = s;
-
- /* Result */
- return (v);
-}
-
-
-errr process_dungeon_file(cptr name, int *yval, int *xval, int ymax, int xmax, bool_ init, bool_ full)
-{
- FILE *fp = 0;
-
- char buf[1024];
-
- int num = -1, i;
-
- errr err = 0;
-
- bool_ bypass = FALSE;
-
- /* Save the start since it ought to be modified */
- int xmin = *xval;
-
- if (init)
- {
- meta_sleep = TRUE;
- for (i = 0; i < 255; i++)
- {
- letter[i].defined = FALSE;
- if (i == ' ') letter[i].ok = TRUE;
- else letter[i].ok = FALSE;
- letter[i].bx = 0;
- letter[i].by = 0;
- }
- }
-
- /* Build the filename */
- path_build(buf, 1024, ANGBAND_DIR_EDIT, name);
-
- /* Open the file */
- fp = my_fopen(buf, "r");
-
- /* No such file */
- if (!fp)
- {
- msg_format("Cannot find file %s at %s", name, buf);
- return ( -1);
- }
-
- /* Process the file */
- while (0 == my_fgets(fp, buf, 1024))
- {
- /* Count lines */
- num++;
-
-
- /* Skip "empty" lines */
- if (!buf[0]) continue;
-
- /* Skip "blank" lines */
- if (isspace(buf[0])) continue;
-
- /* Skip comments */
- if (buf[0] == '#') continue;
-
-
- /* Process "?:<expr>" */
- if ((buf[0] == '?') && (buf[1] == ':'))
- {
- char f;
- cptr v;
- char *s;
-
- /* Start */
- s = buf + 2;
-
- /* Parse the expr */
- v = process_dungeon_file_expr(&s, &f);
-
- /* Set flag */
- bypass = (streq(v, "0") ? TRUE : FALSE);
-
- /* Continue */
- continue;
- }
-
- /* Apply conditionals */
- if (bypass) continue;
-
-
- /* Process "%:<file>" */
- if (buf[0] == '%')
- {
- /* Process that file if allowed */
- (void)process_dungeon_file(buf + 2, yval, xval, ymax, xmax, FALSE, full);
-
- /* Continue */
- continue;
- }
-
-
- /* Process the line */
- err = process_dungeon_file_aux(buf, yval, xval, xmin, ymax, xmax, full);
-
- /* Oops */
- if (err) break;
- }
-
-
- /* Error */
- if (err)
- {
- /* Useful error message */
- msg_format("Error %d in line %d of file '%s'.", err, num, name);
- msg_format("Parsing '%s'", buf);
- }
-
- /* Close the file */
- my_fclose(fp);
-
- /* Result */
- return (err);
-}
diff --git a/src/init1.cc b/src/init1.cc
new file mode 100644
index 00000000..e367f603
--- /dev/null
+++ b/src/init1.cc
@@ -0,0 +1,6941 @@
+#include "init1.hpp"
+
+#include "ability_type.hpp"
+#include "artifact_type.hpp"
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "dungeon_info_type.hpp"
+#include "dungeon_flag.hpp"
+#include "ego_flag.hpp"
+#include "ego_item_type.hpp"
+#include "feature_flag.hpp"
+#include "feature_type.hpp"
+#include "files.hpp"
+#include "game.hpp"
+#include "gods.hpp"
+#include "init2.hpp"
+#include "monster2.hpp"
+#include "monster_ego.hpp"
+#include "monster_race.hpp"
+#include "monster_race_flag.hpp"
+#include "monster_spell.hpp"
+#include "monster_type.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_flag.hpp"
+#include "object_flag_meta.hpp"
+#include "object_kind.hpp"
+#include "player_class.hpp"
+#include "player_race.hpp"
+#include "player_race_flag.hpp"
+#include "player_race_mod.hpp"
+#include "player_type.hpp"
+#include "set_type.hpp"
+#include "skill_flag.hpp"
+#include "skill_type.hpp"
+#include "skills.hpp"
+#include "spells5.hpp"
+#include "store_flag.hpp"
+#include "store_info_type.hpp"
+#include "tables.hpp"
+#include "town_type.hpp"
+#include "util.hpp"
+#include "util.h"
+#include "variable.h"
+#include "variable.hpp"
+#include "wilderness_type_info.hpp"
+#include "z-rand.hpp"
+
+#include <boost/algorithm/string/predicate.hpp>
+#include <boost/algorithm/string/classification.hpp>
+#include <boost/algorithm/string/split.hpp>
+
+using boost::algorithm::iequals;
+using boost::algorithm::ends_with;
+
+
+/**
+ * Expand vector such that it has room for an item at index i.
+ * If the vector is already large enough, nothing happens.
+ */
+template <class T> typename std::vector<T>::reference expand_to_fit_index(std::vector<T> &v, std::size_t i)
+{
+ if (v.size() < i + 1)
+ {
+ v.resize(i + 1);
+ }
+ return v[i];
+}
+
+
+/*
+ * This file is used to initialize various variables and arrays for the
+ * Angband game. Note the use of "fd_read()" and "fd_write()" to bypass
+ * the common limitation of "read()" and "write()" to only 32767 bytes
+ * at a time.
+ *
+ * Several of the arrays for Angband are built from "template" files in
+ * the "lib/file" directory, from which quick-load binary "image" files
+ * are constructed whenever they are not present in the "lib/data"
+ * directory, or if those files become obsolete, if we are allowed.
+ *
+ * Warning -- the "ascii" file parsers use a minor hack to collect the
+ * name and text information in a single pass. Thus, the game will not
+ * be able to load any template file with more than 20K of names or 60K
+ * of text, even though technically, up to 64K should be legal.
+ */
+
+
+/*** Helper arrays for parsing ascii template files ***/
+
+/*
+ * Monster Blow Methods
+ */
+static cptr r_info_blow_method[] =
+{
+ "*",
+ "HIT",
+ "TOUCH",
+ "PUNCH",
+ "KICK",
+ "CLAW",
+ "BITE",
+ "STING",
+ "XXX1",
+ "BUTT",
+ "CRUSH",
+ "ENGULF",
+ "CHARGE",
+ "CRAWL",
+ "DROOL",
+ "SPIT",
+ "EXPLODE",
+ "GAZE",
+ "WAIL",
+ "SPORE",
+ "XXX4",
+ "BEG",
+ "INSULT",
+ "MOAN",
+ "SHOW",
+ NULL
+};
+
+
+/*
+ * Monster Blow Effects
+ */
+static cptr r_info_blow_effect[] =
+{
+ "*",
+ "HURT",
+ "POISON",
+ "UN_BONUS",
+ "UN_POWER",
+ "EAT_GOLD",
+ "EAT_ITEM",
+ "EAT_FOOD",
+ "EAT_LITE",
+ "ACID",
+ "ELEC",
+ "FIRE",
+ "COLD",
+ "BLIND",
+ "CONFUSE",
+ "TERRIFY",
+ "PARALYZE",
+ "LOSE_STR",
+ "LOSE_INT",
+ "LOSE_WIS",
+ "LOSE_DEX",
+ "LOSE_CON",
+ "LOSE_CHR",
+ "LOSE_ALL",
+ "SHATTER",
+ "EXP_10",
+ "EXP_20",
+ "EXP_40",
+ "EXP_80",
+ "DISEASE",
+ "TIME",
+ "INSANITY",
+ "HALLU",
+ "PARASITE",
+ "ABOMINATION",
+ NULL
+};
+
+
+/*
+ * Helpers for looking up flags in the above arrays
+ * and extracting "bitmasks" from them.
+ */
+
+namespace { // anonymous
+
+namespace detail {
+
+/**
+ * A "tie" (see e.g. std::tuple) between a "flags" value pointer and its
+ * corresponding array of text strings. Implementation detail.
+ */
+template <size_t N> struct flag_tie_impl {
+private:
+ u32b *m_mask;
+ cptr (&m_flags)[N];
+public:
+ flag_tie_impl(u32b *mask, cptr (&flags)[N]): m_mask(mask), m_flags(flags) {
+ // Empty
+ }
+
+ bool match(cptr flag) {
+ for (unsigned int i = 0; i < N; i++)
+ {
+ if (streq(flag, m_flags[i]))
+ {
+ *m_mask |= (1L << i);
+ return true;
+ }
+ }
+ return false;
+ }
+};
+
+} // namespace detail
+
+/**
+ * Tie a flags value pointer and its corresponding array
+ * of text strings.
+ */
+template<size_t N> detail::flag_tie_impl<N> flag_tie(u32b *mask, cptr (&flags)[N]) {
+ static_assert(N <= 32, "Array too large to represent result");
+ return detail::flag_tie_impl<N>(mask, flags);
+}
+
+/**
+ * Look up flag in array of flags.
+ */
+template<size_t N> bool lookup_flags(cptr)
+{
+ // Base case: No match
+ return false;
+}
+
+/**
+ * Look up flag in array of flags.
+ */
+template<size_t N, typename... Pairs> bool lookup_flags(cptr flag, detail::flag_tie_impl<N> tie, Pairs&&...rest) {
+ // Inductive case: Check against current "tie"
+ if (tie.match(flag)) {
+ // Match
+ return true;
+ } else {
+ // No match; check against rest of the array of flags
+ return lookup_flags<N>(flag, rest...);
+ }
+}
+
+} // namespace anonymous
+
+
+
+/*
+ * Dungeon effect types (used in E:damage:frequency:type entry in d_info.txt)
+ */
+static struct
+{
+cptr name;
+int feat;
+}
+d_info_dtypes[] =
+{
+ {"ELEC", GF_ELEC},
+ {"POISON", GF_POIS},
+ {"ACID", GF_ACID},
+ {"COLD", GF_COLD},
+ {"FIRE", GF_FIRE},
+ {"MISSILE", GF_MISSILE},
+ {"ARROW", GF_ARROW},
+ {"PLASMA", GF_PLASMA},
+ {"WATER", GF_WATER},
+ {"LITE", GF_LITE},
+ {"DARK", GF_DARK},
+ {"LITE_WEAK", GF_LITE_WEAK},
+ {"LITE_DARK", GF_DARK_WEAK},
+ {"SHARDS", GF_SHARDS},
+ {"SOUND", GF_SOUND},
+ {"CONFUSION", GF_CONFUSION},
+ {"FORCE", GF_FORCE},
+ {"INERTIA", GF_INERTIA},
+ {"MANA", GF_MANA},
+ {"METEOR", GF_METEOR},
+ {"ICE", GF_ICE},
+ {"CHAOS", GF_CHAOS},
+ {"NETHER", GF_NETHER},
+ {"DISENCHANT", GF_DISENCHANT},
+ {"NEXUS", GF_NEXUS},
+ {"TIME", GF_TIME},
+ {"GRAVITY", GF_GRAVITY},
+ {"ROCKET", GF_ROCKET},
+ {"NUKE", GF_NUKE},
+ {"HOLY_FIRE", GF_HOLY_FIRE},
+ {"HELL_FIRE", GF_HELL_FIRE},
+ {"DISINTEGRATE", GF_DISINTEGRATE},
+ {"DESTRUCTION", GF_DESTRUCTION},
+ {"RAISE", GF_RAISE},
+ {NULL, 0}
+};
+
+static const char *activation_names[] =
+{
+ "NO_ACTIVATION", /* 0*/
+ "SUNLIGHT", /* 1*/
+ "BO_MISS_1", /* 2*/
+ "BA_POIS_1", /* 3*/
+ "BO_ELEC_1", /* 4*/
+ "BO_ACID_1", /* 5*/
+ "BO_COLD_1", /* 6*/
+ "BO_FIRE_1", /* 7*/
+ "BA_COLD_1", /* 8*/
+ "BA_FIRE_1", /* 9*/
+ "DRAIN_1", /* 10*/
+ "BA_COLD_2", /* 11*/
+ "BA_ELEC_2", /* 12*/
+ "DRAIN_2", /* 13*/
+ "VAMPIRE_1", /* 14*/
+ "BO_MISS_2", /* 15*/
+ "BA_FIRE_2", /* 16*/
+ "BA_COLD_3", /* 17*/
+ "BA_ELEC_3", /* 18*/
+ "WHIRLWIND", /* 19*/
+ "VAMPIRE_2", /* 20*/
+ "CALL_CHAOS", /* 21*/
+ "ROCKET", /* 22*/
+ "DISP_EVIL", /* 23*/
+ "BA_MISS_3", /* 24*/
+ "DISP_GOOD", /* 25*/
+ "GILGALAD", /* 26*/
+ "CELEBRIMBOR", /* 27*/
+ "SKULLCLEAVER", /* 28*/
+ "HARADRIM", /* 29*/
+ "FUNDIN", /* 30*/
+ "EOL", /* 31*/
+ "UMBAR", /* 32*/
+ "NUMENOR", /* 33*/
+ "KNOWLEDGE", /* 34*/
+ "UNDEATH", /* 35*/
+ "THRAIN", /* 36*/
+ "BARAHIR", /* 37*/
+ "TULKAS", /* 38*/
+ "NARYA", /* 39*/
+ "NENYA", /* 40*/
+ "VILYA", /* 41*/
+ "POWER", /* 42*/
+ "STONE_LORE", /* 43*/
+ "RAZORBACK", /* 44*/
+ "BLADETURNER", /* 45*/
+ "MEDIATOR", /* 46*/
+ "BELEGENNON", /* 47*/
+ "GORLIM", /* 48*/
+ "COLLUIN", /* 49*/
+ "BELANGIL", /* 50*/
+ "CONFUSE", /* 51*/
+ "SLEEP", /* 52*/
+ "QUAKE", /* 53*/
+ "TERROR", /* 54*/
+ "TELE_AWAY", /* 55*/
+ "BANISH_EVIL", /* 56*/
+ "GENOCIDE", /* 57*/
+ "MASS_GENO", /* 58*/
+ "ANGUIREL", /* 59*/
+ "ERU", /* 60*/
+ "DAWN", /* 61*/
+ "FIRESTAR", /* 62*/
+ "TURMIL", /* 63*/
+ "CUBRAGOL", /* 64*/
+ "CHARM_ANIMAL", /* 65*/
+ "CHARM_UNDEAD", /* 66*/
+ "CHARM_OTHER", /* 67*/
+ "CHARM_ANIMALS", /* 68*/
+ "CHARM_OTHERS", /* 69*/
+ "SUMMON_ANIMAL", /* 70*/
+ "SUMMON_PHANTOM", /* 71*/
+ "SUMMON_ELEMENTAL", /* 72*/
+ "SUMMON_DEMON", /* 73*/
+ "SUMMON_UNDEAD", /* 74*/
+ "ELESSAR", /* 75*/
+ "GANDALF", /* 76*/
+ "MARDA", /* 77*/
+ "PALANTIR", /* 78*/
+ "XXX79",
+ "XXX80",
+ "CURE_LW", /* 81*/
+ "CURE_MW", /* 82*/
+ "CURE_POISON", /* 83*/
+ "REST_LIFE", /* 84*/
+ "REST_ALL", /* 85*/
+ "CURE_700", /* 86*/
+ "CURE_1000", /* 87*/
+ "XXX88",
+ "EREBOR", /* 89*/
+ "DRUEDAIN", /* 90*/
+ "ESP", /* 91*/
+ "BERSERK", /* 92*/
+ "PROT_EVIL", /* 93*/
+ "RESIST_ALL", /* 94*/
+ "SPEED", /* 95*/
+ "XTRA_SPEED", /* 96*/
+ "WRAITH", /* 97*/
+ "INVULN", /* 98*/
+ "ROHAN", /* 99*/
+ "HELM", /* 100*/
+ "BOROMIR", /* 101*/
+ "HURIN", /* 102*/
+ "AXE_GOTHMOG", /* 103*/
+ "MELKOR", /* 104*/
+ "GROND", /* 105*/
+ "NATUREBANE", /* 106*/
+ "NIGHT", /* 107*/
+ "ORCHAST", /* 108*/
+ "XXX109",
+ "XXX110",
+ "LIGHT", /* 111*/
+ "MAP_LIGHT", /* 112*/
+ "DETECT_ALL", /* 113*/
+ "DETECT_XTRA", /* 114*/
+ "ID_FULL", /* 115*/
+ "ID_PLAIN", /* 116*/
+ "RUNE_EXPLO", /* 117*/
+ "RUNE_PROT", /* 118*/
+ "SATIATE", /* 119*/
+ "DEST_DOOR", /* 120*/
+ "STONE_MUD", /* 121*/
+ "RECHARGE", /* 122*/
+ "ALCHEMY", /* 123*/
+ "DIM_DOOR", /* 124*/
+ "TELEPORT", /* 125*/
+ "RECALL", /* 126*/
+ "DEATH", /* 127*/
+ "RUINATION", /* 128*/
+ "DESTRUC", /* 129*/
+ "UNINT", /* 130*/
+ "UNSTR", /* 131*/
+ "UNCON", /* 132*/
+ "UNCHR", /* 133*/
+ "UNDEX", /* 134*/
+ "UNWIS", /* 135*/
+ "STATLOSS", /* 136*/
+ "HISTATLOSS", /* 137*/
+ "EXPLOSS", /* 138*/
+ "HIEXPLOSS", /* 139*/
+ "SUMMON_MONST", /* 140*/
+ "PARALYZE", /* 141*/
+ "HALLU", /* 142*/
+ "POISON", /* 143*/
+ "HUNGER", /* 144*/
+ "STUN", /* 145*/
+ "CUTS", /* 146*/
+ "PARANO", /* 147*/
+ "CONFUSION", /* 148*/
+ "BLIND", /* 149*/
+ "PET_SUMMON", /* 150*/
+ "CURE_PARA", /* 151*/
+ "CURE_HALLU", /* 152*/
+ "CURE_POIS", /* 153*/
+ "CURE_HUNGER", /* 154*/
+ "CURE_STUN", /* 155*/
+ "CURE_CUTS", /* 156*/
+ "CURE_FEAR", /* 157*/
+ "CURE_CONF", /* 158*/
+ "CURE_BLIND", /* 159*/
+ "CURING", /* 160*/
+ "DARKNESS", /* 161*/
+ "LEV_TELE", /* 162*/
+ "ACQUIREMENT", /* 163*/
+ "WEIRD", /* 164*/
+ "AGGRAVATE", /* 165*/
+ "MUT", /* 166*/
+ "CURE_INSANITY", /* 167*/
+ "CURE_MUT", /* 168*/
+ "LIGHT_ABSORBTION", /* 169*/
+ "BA_FIRE_H", /* 170*/
+ "BA_COLD_H", /* 171*/
+ "BA_ELEC_H", /* 172*/
+ "BA_ACID_H", /* 173*/
+ "SPIN", /* 174*/
+ "NOLDOR", /* 175*/
+ "SPECTRAL", /* 176*/
+ "JUMP", /* 177*/
+ "DEST_TELE", /* 178*/
+ "BA_POIS_4", /* 179*/
+ "BA_COLD_4", /* 180*/
+ "BA_FIRE_4", /* 181*/
+ "BA_ACID_4", /* 182*/
+ "BA_ELEC_4", /* 183*/
+ "BR_ELEC", /* 184*/
+ "BR_COLD", /* 185*/
+ "BR_FIRE", /* 186*/
+ "BR_ACID", /* 187*/
+ "BR_POIS", /* 188*/
+ "BR_MANY", /* 189*/
+ "BR_CONF", /* 190*/
+ "BR_SOUND", /* 191*/
+ "BR_CHAOS", /* 192*/
+ "BR_SHARD", /* 193*/
+ "BR_BALANCE", /* 194*/
+ "BR_LIGHT", /* 195*/
+ "BR_POWER", /* 196*/
+ "GROW_MOLD", /* 197*/
+ "XXX198",
+ "XXX199",
+ "MUSIC", /* 200*/
+ "ETERNAL_FLAME", /* 201 */
+ "MAGGOT", /* 202 */
+ "LEBOHAUM", /* 203 */
+ "DURANDIL", /* 204 */
+ "RADAGAST", /* 205, Theme */
+ "VALAROMA", /* 206, Theme */
+ ""
+};
+
+/*
+ * Convert a "color letter" into an "actual" color
+ * The colors are: dwsorgbuDWvyRGBU, as shown below
+ */
+int color_char_to_attr(char c)
+{
+ switch (c)
+ {
+ case 'd':
+ return (TERM_DARK);
+ case 'w':
+ return (TERM_WHITE);
+ case 's':
+ return (TERM_SLATE);
+ case 'o':
+ return (TERM_ORANGE);
+ case 'r':
+ return (TERM_RED);
+ case 'g':
+ return (TERM_GREEN);
+ case 'b':
+ return (TERM_BLUE);
+ case 'u':
+ return (TERM_UMBER);
+
+ case 'D':
+ return (TERM_L_DARK);
+ case 'W':
+ return (TERM_L_WHITE);
+ case 'v':
+ return (TERM_VIOLET);
+ case 'y':
+ return (TERM_YELLOW);
+ case 'R':
+ return (TERM_L_RED);
+ case 'G':
+ return (TERM_L_GREEN);
+ case 'B':
+ return (TERM_L_BLUE);
+ case 'U':
+ return (TERM_L_UMBER);
+ }
+
+ return ( -1);
+}
+
+/*
+ * Attr value-to-char convertion table
+ */
+byte conv_color[16] =
+{
+ 'd',
+ 'w',
+ 's',
+ 'o',
+ 'r',
+ 'g',
+ 'b',
+ 'u',
+ 'D',
+ 'W',
+ 'v',
+ 'y',
+ 'R',
+ 'G',
+ 'B',
+ 'U',
+};
+
+
+/* Values in re_info can be fixed, added, substracted or percented */
+static byte monster_ego_modify(char c)
+{
+ switch (c)
+ {
+ case '+':
+ return MEGO_ADD;
+ case '-':
+ return MEGO_SUB;
+ case '=':
+ return MEGO_FIX;
+ case '%':
+ return MEGO_PRC;
+ default:
+ {
+ msg_format("Unknown mego value modifier %c.", c);
+ return MEGO_ADD;
+ }
+ }
+}
+
+/**
+ * Version of strdup() which just aborts if an allocation
+ * error occurs.
+ */
+static char *my_strdup(const char *s)
+{
+ char *p = strdup(s);
+ if (!p)
+ {
+ abort();
+ }
+ return p;
+}
+
+
+/**
+ * Append one string to the end of another, reallocating if
+ * necessary.
+ */
+static void strappend(char **s, const char *t)
+{
+ // Do we need to initialize the destination string?
+ if (*s == nullptr)
+ {
+ // Costs an extra allocation which could be avoided
+ // but this leads to simpler code.
+ *s = my_strdup("");
+ }
+ // We should really be preserving the original pointer and
+ // do something else in case of failure to realloc(), but
+ // instead we just do the lazy thing and call abort() if
+ // reallocation fails. In practice it won't.
+ *s = static_cast<char *>(realloc(*s, strlen(*s) + strlen(t) + 1));
+ if (*s == nullptr)
+ {
+ abort(); // Cannot handle failure to reallocate
+ }
+
+ /* Append 't' to the destination string */
+ strcat(*s, t);
+}
+
+/*** Initialize from ascii template files ***/
+
+/*
+ * Grab one race flag from a textual string
+ */
+static bool_ unknown_shut_up = FALSE;
+static errr grab_one_class_flag(u32b *choice, cptr what)
+{
+ auto const &class_info = game->edit_data.class_info;
+
+ /* Scan classes flags */
+ for (std::size_t i = 0; i < class_info.size(); i++)
+ {
+ if (class_info[i].title == what)
+ {
+ (choice[i / 32]) |= (1L << i);
+ return (0);
+ }
+ }
+
+ /* Oops */
+ if (!unknown_shut_up) msg_format("Unknown class flag '%s'.", what);
+
+ /* Failure */
+ return (1);
+}
+
+static errr grab_one_race_allow_flag(u32b *choice, cptr what)
+{
+ auto const &race_info = game->edit_data.race_info;
+
+ /* Scan classes flags */
+ for (std::size_t i = 0; i < race_info.size(); i++)
+ {
+ if (race_info[i].title == what)
+ {
+ (choice[i / 32]) |= (1L << i);
+ return (0);
+ }
+ }
+
+ /* Oops */
+ if (!unknown_shut_up) msg_format("(1)Unknown race flag '%s'.", what);
+
+ /* Failure */
+ return (1);
+}
+
+/*
+ * Grab one flag from a textual string
+ */
+static errr grab_one_skill_flag(skill_flag_set *flags, cptr what)
+{
+#define SKF(tier, index, name) \
+ if (streq(what, #name)) \
+ { \
+ *flags |= BOOST_PP_CAT(SKF_,name); \
+ return 0; \
+ };
+#include "skill_flag_list.hpp"
+#undef SKF
+
+ /* Oops */
+ msg_format("(2)Unknown skill flag '%s'.", what);
+
+ /* Error */
+ return (1);
+}
+/*
+ * Grab one flag from a textual string
+ */
+static errr grab_one_player_race_flag(player_race_flag_set *flags, cptr what)
+{
+#define PR(tier, index, name) \
+ if (streq(what, #name)) \
+ { \
+ *flags |= BOOST_PP_CAT(PR_,name); \
+ return 0; \
+ };
+#include "player_race_flag_list.hpp"
+#undef PR
+
+ /* Oops */
+ msg_format("(2)Unknown race flag '%s'.", what);
+
+ /* Error */
+ return (1);
+}
+
+/* Get an activation number (good for artifacts, recipes, egos, and object kinds) */
+static int get_activation(char *activation)
+{
+ int i;
+ for ( i = 0 ; activation_names[i][0] ; i++)
+ {
+ if (!strncmp(activation_names[i], activation, 19))
+ {
+ return i;
+ }
+ }
+
+ msg_format("Unknown activation '%s'.", activation);
+ return -1;
+}
+
+/*
+ * Convert string to object_flag_set value
+ */
+static object_flag_set object_flag_set_from_string(cptr what)
+{
+ for (auto const flag_meta: object_flags_meta())
+ {
+ if (streq(what, flag_meta->e_name))
+ {
+ return flag_meta->flag_set;
+ };
+ }
+
+ return object_flag_set();
+}
+
+/*
+ * Grab one flag in an object_kind from a textual string
+ */
+static errr grab_object_flag(object_flag_set *flags, cptr what)
+{
+ if (object_flag_set f = object_flag_set_from_string(what))
+ {
+ *flags |= f;
+ return 0;
+ }
+
+ /* Oops */
+ msg_format("Unknown object flag '%s'.", what);
+
+ /* Error */
+ return (1);
+}
+
+/*
+ * Read skill values
+ */
+static int read_skill_modifiers(skill_modifiers *skill_modifiers, cptr buf)
+{
+ long val, mod;
+ char v, m;
+ char name[200];
+
+ if (5 != sscanf(buf, "%c%ld:%c%ld:%s", &v, &val, &m, &mod, name))
+ {
+ return 1;
+ }
+
+ long i;
+ if ((i = find_skill(name)) == -1)
+ {
+ return 1;
+ }
+
+ auto s = &expand_to_fit_index(skill_modifiers->modifiers, i);
+
+ s->basem = monster_ego_modify(v);
+ s->base = val;
+ s->modm = monster_ego_modify(m);
+ s->mod = mod;
+
+ return 0;
+}
+
+
+/*
+ * Read prototype objects
+ */
+static int read_proto_object(std::vector<object_proto> *protos, cptr buf)
+{
+ int s0, s1, s2, s3, s4;
+
+ if (5 != sscanf(buf, "%d:%d:%d:%dd%d", &s0, &s1, &s4, &s2, &s3))
+ {
+ s4 = 0;
+
+ if (4 != sscanf(buf, "%d:%d:%dd%d", &s0, &s1, &s2, &s3))
+ {
+ return 1;
+ }
+ }
+
+ object_proto proto;
+ proto.pval = s4;
+ proto.tval = s0;
+ proto.sval = s1;
+ proto.dd = s2;
+ proto.ds = s3;
+
+ protos->emplace_back(proto);
+
+ return 0;
+}
+
+
+/*
+ * Read an ability assignment
+ */
+static int read_ability(std::vector<player_race_ability_type> *abilities, char *buf)
+{
+ int level = 0;
+ char *name = nullptr;
+
+ // Find the ':' separator
+ if (!(name = strchr(buf, ':')))
+ {
+ return 1;
+ }
+
+ // Split the buffer there and advance to point at the ability name
+ name++;
+
+ // Extract the level
+ if (1 != sscanf(buf, "%d:", &level))
+ {
+ return 1;
+ }
+
+ // Try to find the ability by name
+ int idx = find_ability(name);
+ if (idx < 0)
+ {
+ return 1;
+ }
+
+ // Insert
+ player_race_ability_type ability;
+ ability.ability = idx;
+ ability.level = level;
+ abilities->emplace_back(ability);
+
+ return 0;
+}
+
+
+/*
+ * Initialize the "player" arrays, by parsing an ascii "template" file
+ */
+errr init_player_info_txt(FILE *fp)
+{
+ auto &class_info = game->edit_data.class_info;
+ auto &race_info = game->edit_data.race_info;
+ auto &race_mod_info = game->edit_data.race_mod_info;
+ auto &gen_skill = game->edit_data.gen_skill;
+
+ int lev = 1;
+ int tit_idx = 0;
+ char buf[1024];
+
+ /* Current entry */
+ player_race *rp_ptr = NULL;
+ player_race_mod *rmp_ptr = NULL;
+ player_class *c_ptr = NULL;
+ player_spec *s_ptr = NULL;
+
+
+ /* Just before the first record */
+ error_idx = -1;
+
+ /* Just before the first line */
+ error_line = -1;
+
+ /* Parse */
+ while (0 == my_fgets(fp, buf, 1024))
+ {
+ /* Advance the line number */
+ error_line++;
+
+ /* Skip comments and blank lines */
+ if (!buf[0] || (buf[0] == '#')) continue;
+
+ /* Verify correct "colon" format */
+ if (buf[1] != ':') return (1);
+
+ /* Reinit error_idx */
+ if (buf[0] == 'I')
+ {
+ error_idx = -1;
+ continue;
+ }
+
+ /* Process 'G:k' for "General skills" */
+ if ((buf[0] == 'G') && (buf[2] == 'k'))
+ {
+ if (read_skill_modifiers(&gen_skill, buf + 4))
+ {
+ return 1;
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'N' for "New/Number/Name" */
+ if ((buf[0] == 'R') && (buf[2] == 'N'))
+ {
+ /* Find the colon before the name */
+ char *s = strchr(buf + 4, ':');
+
+ /* Verify that colon */
+ if (!s) return (1);
+
+ /* Nuke the colon, advance to the name */
+ *s++ = '\0';
+
+ /* Paranoia -- require a name */
+ if (!*s) return (1);
+
+ /* Get the index */
+ int i = atoi(buf + 4);
+
+ /* Verify information */
+ if (i < error_idx) return (4);
+
+ /* Save the index */
+ error_idx = i;
+
+ /* Point at the "info" */
+ rp_ptr = &expand_to_fit_index(race_info, i);
+ assert(rp_ptr->title.empty());
+
+ /* Copy title */
+ rp_ptr->title = s;
+
+ /* Initialize */
+ lev = 1;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'D' for "Description" */
+ if ((buf[0] == 'R') && (buf[2] == 'D'))
+ {
+ // Need newline?
+ if (!rp_ptr->desc.empty())
+ {
+ rp_ptr->desc += '\n';
+ }
+
+ // Append
+ rp_ptr->desc += (buf + 4);
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'E' for "body parts" */
+ if ((buf[0] == 'R') && (buf[2] == 'E'))
+ {
+ int s[BODY_MAX], z;
+
+ /* Scan for the values */
+ if (BODY_MAX != sscanf(buf + 4, "%d:%d:%d:%d:%d:%d",
+ &s[0], &s[1], &s[2], &s[3], &s[4], &s[5])) return (1);
+
+ for (z = 0; z < BODY_MAX; z++)
+ rp_ptr->body_parts[z] = s[z];
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'R' for "flag level" */
+ if ((buf[0] == 'R') && (buf[2] == 'R'))
+ {
+ int s[2];
+
+ /* Scan for the values */
+ if (2 != sscanf(buf + 4, "%d:%d",
+ &s[0], &s[1])) return (1);
+
+ lev = s[0];
+ rp_ptr->lflags[lev].pval = s[1];
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'S' for "Stats" */
+ if ((buf[0] == 'R') && (buf[2] == 'S'))
+ {
+ int s[7], z;
+
+ /* Scan for the values */
+ if (7 != sscanf(buf + 4, "%d:%d:%d:%d:%d:%d:%d",
+ &s[0], &s[1], &s[2], &s[3], &s[4], &s[5], &s[6])) return (1);
+
+ rp_ptr->luck = s[6];
+ for (z = 0; z < 6; z++)
+ {
+ rp_ptr->ps.adj[z] = s[z];
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'Z' for "powers" */
+ if ((buf[0] == 'R') && (buf[2] == 'Z'))
+ {
+ /* Acquire the text */
+ char const *s = buf + 4;
+
+ /* Find it in the list */
+ int i;
+ for (i = 0; i < POWER_MAX; i++)
+ {
+ if (iequals(s, powers_type[i].name)) break;
+ }
+
+ if (i == POWER_MAX) return (6);
+
+ rp_ptr->ps.powers.push_back(i);
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'k' for "skills" */
+ if ((buf[0] == 'R') && (buf[2] == 'k'))
+ {
+ if (read_skill_modifiers(&rp_ptr->skill_modifiers, buf + 4))
+ {
+ return 1;
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'b' for "abilities" */
+ if ((buf[0] == 'R') && (buf[2] == 'b'))
+ {
+ if (read_ability(&rp_ptr->abilities, buf + 4))
+ {
+ return 1;
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'P' for "xtra" */
+ if ((buf[0] == 'R') && (buf[2] == 'P'))
+ {
+ int s[3];
+
+ /* Scan for the values */
+ if (3 != sscanf(buf + 4, "%d:%d:%d",
+ &s[0], &s[1], &s[2])) return (1);
+
+ rp_ptr->ps.mhp = s[0];
+ rp_ptr->ps.exp = s[1];
+ rp_ptr->infra = s[2];
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'G' for "Player flags" (multiple lines) */
+ if ((buf[0] == 'R') && (buf[2] == 'G'))
+ {
+ if (0 != grab_one_player_race_flag(&rp_ptr->flags, buf + 4))
+ {
+ return (5);
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'F' for "level Flags" (multiple lines) */
+ if ((buf[0] == 'R') && (buf[2] == 'F'))
+ {
+ if (grab_object_flag(&rp_ptr->lflags[lev].oflags, buf + 4))
+ {
+ return (5);
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'O' for "Object birth" */
+ if ((buf[0] == 'R') && (buf[2] == 'O'))
+ {
+ if (read_proto_object(&rp_ptr->object_protos, buf + 4))
+ {
+ return 1;
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'C' for "Class choice flags" (multiple lines) */
+ if ((buf[0] == 'R') && (buf[2] == 'C'))
+ {
+ if (0 != grab_one_class_flag(rp_ptr->choice, buf + 4))
+ {
+ return (5);
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'N' for "New/Number/Name" */
+ if ((buf[0] == 'S') && (buf[2] == 'N'))
+ {
+ /* Find the colon before the name */
+ char *s = strchr(buf + 4, ':');
+
+ /* Verify that colon */
+ if (!s) return (1);
+
+ /* Nuke the colon, advance to the name */
+ *s++ = '\0';
+
+ /* Paranoia -- require a name */
+ if (!*s) return (1);
+
+ /* Get the index */
+ int i = atoi(buf + 4);
+
+ /* Verify information */
+ if (i < error_idx) return (4);
+
+ /* Save the index */
+ error_idx = i;
+
+ /* Point at the "info" */
+ rmp_ptr = &expand_to_fit_index(race_mod_info, i);
+ assert(rmp_ptr->title.empty());
+
+ /* Copy title */
+ rmp_ptr->title = s;
+
+ /* Initialize */
+ lev = 1;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'D' for "Description" */
+ if ((buf[0] == 'S') && (buf[2] == 'D'))
+ {
+ /* Acquire the text */
+ char const *s = buf + 6;
+
+ /* Place */
+ if (buf[4] == 'A')
+ {
+ rmp_ptr->place = TRUE;
+ }
+ else
+ {
+ rmp_ptr->place = FALSE;
+ }
+
+ /* Description */
+ if (!rmp_ptr->description.empty())
+ {
+ rmp_ptr->description += '\n';
+ }
+ rmp_ptr->description += s;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'E' for "body parts" */
+ if ((buf[0] == 'S') && (buf[2] == 'E'))
+ {
+ int s[BODY_MAX], z;
+
+ /* Scan for the values */
+ if (BODY_MAX != sscanf(buf + 4, "%d:%d:%d:%d:%d:%d",
+ &s[0], &s[1], &s[2], &s[3], &s[4], &s[5])) return (1);
+
+ for (z = 0; z < BODY_MAX; z++)
+ rmp_ptr->body_parts[z] = s[z];
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'R' for "flag level" */
+ if ((buf[0] == 'S') && (buf[2] == 'R'))
+ {
+ int s[2];
+
+ /* Scan for the values */
+ if (2 != sscanf(buf + 4, "%d:%d",
+ &s[0], &s[1])) return (1);
+
+ lev = s[0];
+ rmp_ptr->lflags[lev].pval = s[1];
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'S' for "Stats" */
+ if ((buf[0] == 'S') && (buf[2] == 'S'))
+ {
+ int s[8], z;
+
+ /* Scan for the values */
+ if (8 != sscanf(buf + 4, "%d:%d:%d:%d:%d:%d:%d:%d",
+ &s[0], &s[1], &s[2], &s[3], &s[4], &s[5], &s[6], &s[7])) return (1);
+
+ rmp_ptr->mana = s[7];
+ rmp_ptr->luck = s[6];
+ for (z = 0; z < 6; z++)
+ {
+ rmp_ptr->ps.adj[z] = s[z];
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'Z' for "powers" */
+ if ((buf[0] == 'S') && (buf[2] == 'Z'))
+ {
+ /* Acquire the text */
+ char const *s = buf + 4;
+
+ /* Find it in the list */
+ int i;
+ for (i = 0; i < POWER_MAX; i++)
+ {
+ if (iequals(s, powers_type[i].name)) break;
+ }
+
+ if (i == POWER_MAX) return (6);
+
+ rmp_ptr->ps.powers.push_back(i);
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'k' for "skills" */
+ if ((buf[0] == 'S') && (buf[2] == 'k'))
+ {
+ if (read_skill_modifiers(&rmp_ptr->skill_modifiers, buf + 4))
+ {
+ return 1;
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'b' for "abilities" */
+ if ((buf[0] == 'S') && (buf[2] == 'b'))
+ {
+ if (read_ability(&rmp_ptr->abilities, buf + 4))
+ {
+ return (1);
+ }
+
+ continue;
+ }
+
+ /* Process 'P' for "xtra" */
+ if ((buf[0] == 'S') && (buf[2] == 'P'))
+ {
+ int s[3];
+
+ /* Scan for the values */
+ if (3 != sscanf(buf + 4, "%d:%d:%d",
+ &s[0], &s[1], &s[2])) return (1);
+
+ rmp_ptr->ps.mhp = s[0];
+ rmp_ptr->ps.exp = s[1];
+ rmp_ptr->infra = s[2];
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'G' for "Player flags" (multiple lines) */
+ if ((buf[0] == 'S') && (buf[2] == 'G'))
+ {
+ if (0 != grab_one_player_race_flag(&rmp_ptr->flags, buf + 4))
+ {
+ return (5);
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'F' for "level Flags" (multiple lines) */
+ if ((buf[0] == 'S') && (buf[2] == 'F'))
+ {
+ if (0 != grab_object_flag(&rmp_ptr->lflags[lev].oflags, buf + 4))
+ {
+ return (5);
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'O' for "Object birth" */
+ if ((buf[0] == 'S') && (buf[2] == 'O'))
+ {
+ if (read_proto_object(&rmp_ptr->object_protos, buf + 4))
+ {
+ return 1;
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'A' for "Allowed races" (multiple lines) */
+ if ((buf[0] == 'S') && (buf[2] == 'A'))
+ {
+ if (0 != grab_one_race_allow_flag(rmp_ptr->choice, buf + 4))
+ {
+ return (5);
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'C' for "Class choice flags" (multiple lines) */
+ if ((buf[0] == 'S') && (buf[2] == 'C'))
+ {
+ u32b choice[2] = {0, 0};
+ if (0 != grab_one_class_flag(choice, buf + 6))
+ {
+ return (5);
+ }
+
+ /* Combine into the class flags */
+ for (int z = 0; z < 2; z++)
+ {
+ if (buf[4] == 'A')
+ {
+ rmp_ptr->pclass[z] |= choice[z];
+ }
+ else
+ {
+ rmp_ptr->mclass[z] |= choice[z];
+ }
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'N' for "New/Number/Name" */
+ if ((buf[0] == 'C') && (buf[2] == 'N'))
+ {
+ /* Advance beyond prefix */
+ char *s = strchr(buf + 4, ':');
+
+ /* Verify that colon */
+ if (!s) return (1);
+
+ /* Extract the suffix */
+ std::string suffix(s + 1);
+ if (suffix.empty()) return (1);
+
+ /* Split suffix into fields */
+ std::vector<std::string> fields;
+ boost::algorithm::split(fields, suffix, boost::is_any_of(":"));
+
+ /* Make sure we have two fields */
+ if (fields.size() < 2) return (1);
+
+ /* Get the entry index */
+ int i = atoi(buf + 4);
+ if (i < error_idx) return (4);
+
+ /* Save the index */
+ error_idx = i;
+
+ /* Point at the "info" */
+ c_ptr = &expand_to_fit_index(class_info, i);
+ assert(c_ptr->title.empty());
+
+ /* Initialize */
+ c_ptr->display_order_idx = std::stoi(fields[0]);
+ c_ptr->title = fields[1];
+
+ /* Initialize */
+ lev = 1;
+ tit_idx = 0;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'D' for "Description" */
+ if ((buf[0] == 'C') && (buf[2] == 'D'))
+ {
+ /* Acquire the text */
+ char const *s = buf + 6;
+
+ switch (buf[4])
+ {
+ case '0': /* Class description */
+ // Need newline?
+ if (!c_ptr->desc.empty())
+ {
+ c_ptr->desc += '\n';
+ }
+ // Append
+ c_ptr->desc += s;
+ break;
+
+ case '1': /* Class title */
+ /* Copy */
+ assert(!c_ptr->titles[tit_idx]);
+ c_ptr->titles[tit_idx] = my_strdup(s);
+
+ /* Go to next title in array */
+ tit_idx++;
+
+ break;
+
+ default: /* Unknown */
+ return (6);
+ break;
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'O' for "Object birth" */
+ if ((buf[0] == 'C') && (buf[2] == 'O'))
+ {
+ if (read_proto_object(&c_ptr->object_protos, buf + 4))
+ {
+ return 1;
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'E' for "body parts" */
+ if ((buf[0] == 'C') && (buf[2] == 'E'))
+ {
+ int s[BODY_MAX], z;
+
+ /* Scan for the values */
+ if (BODY_MAX != sscanf(buf + 4, "%d:%d:%d:%d:%d:%d",
+ &s[0], &s[1], &s[2], &s[3], &s[4], &s[5])) return (1);
+
+ for (z = 0; z < BODY_MAX; z++)
+ c_ptr->body_parts[z] = s[z];
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'R' for "flag level" */
+ if ((buf[0] == 'C') && (buf[2] == 'R'))
+ {
+ int s[2];
+
+ /* Scan for the values */
+ if (2 != sscanf(buf + 4, "%d:%d",
+ &s[0], &s[1])) return (1);
+
+ lev = s[0];
+ c_ptr->lflags[lev].pval = s[1];
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'C' for "Stats" */
+ if ((buf[0] == 'C') && (buf[2] == 'S'))
+ {
+ int s[8], z;
+
+ /* Scan for the values */
+ if (8 != sscanf(buf + 4, "%d:%d:%d:%d:%d:%d:%d:%d",
+ &s[0], &s[1], &s[2], &s[3], &s[4], &s[5], &s[6], &s[7])) return (1);
+
+ c_ptr->mana = s[6];
+ c_ptr->extra_blows = s[7];
+ for (z = 0; z < 6; z++)
+ {
+ c_ptr->ps.adj[z] = s[z];
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'k' for "skills" */
+ if ((buf[0] == 'C') && (buf[2] == 'k'))
+ {
+ if (read_skill_modifiers(&c_ptr->skill_modifiers, buf + 4))
+ {
+ return 1;
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'b' for "abilities" */
+ if ((buf[0] == 'C') && (buf[2] == 'b'))
+ {
+ if (read_ability(&c_ptr->abilities, buf + 4))
+ {
+ return 1;
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'g' for "gods" */
+ if ((buf[0] == 'C') && (buf[2] == 'g'))
+ {
+ int i;
+
+ if (streq(buf + 4, "All Gods"))
+ c_ptr->gods = 0xFFFFFFFF;
+ else
+ {
+ if ((i = find_god(buf + 4)) == -1) return (1);
+ c_ptr->gods |= BIT(i);
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'Z' for "powers" */
+ if ((buf[0] == 'C') && (buf[2] == 'Z'))
+ {
+ /* Acquire the text */
+ char const *s = buf + 4;
+
+ /* Find it in the list */
+ int i;
+ for (i = 0; i < POWER_MAX; i++)
+ {
+ if (iequals(s, powers_type[i].name)) break;
+ }
+
+ if (i == POWER_MAX) return (6);
+
+ c_ptr->ps.powers.push_back(i);
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'P' for "xtra" */
+ if ((buf[0] == 'C') && (buf[2] == 'P'))
+ {
+ int s[2];
+
+ /* Scan for the values */
+ if (2 != sscanf(buf + 4, "%d:%d",
+ &s[0], &s[1])) return (1);
+
+ c_ptr->ps.mhp = s[0];
+ c_ptr->ps.exp = s[1];
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'B' for "blows" */
+ if ((buf[0] == 'C') && (buf[2] == 'B'))
+ {
+ int s[3];
+
+ /* Scan for the values */
+ if (3 != sscanf(buf + 4, "%d:%d:%d",
+ &s[0], &s[1], &s[2])) return (1);
+
+ c_ptr->blow_num = s[0];
+ c_ptr->blow_wgt = s[1];
+ c_ptr->blow_mul = s[2];
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'G' for "Player flags" (multiple lines) */
+ if ((buf[0] == 'C') && (buf[2] == 'G'))
+ {
+ if (0 != grab_one_player_race_flag(&c_ptr->flags, buf + 4))
+ {
+ return (5);
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'F' for "level Flags" (multiple lines) */
+ if ((buf[0] == 'C') && (buf[2] == 'F'))
+ {
+ /* Parse every entry */
+ for (char *s = buf + 4; *s; )
+ {
+ char *t;
+
+ /* Find the end of this entry */
+ for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
+
+ /* Nuke and skip any dividers */
+ if (*t)
+ {
+ *t++ = '\0';
+ while (*t == ' ' || *t == '|') t++;
+ }
+
+ /* Parse this entry */
+ if (0 != grab_object_flag(&c_ptr->lflags[lev].oflags, s))
+ {
+ return (5);
+ }
+
+ /* Start the next entry */
+ s = t;
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Specialities */
+ if ((buf[0] == 'C') && (buf[2] == 'a'))
+ {
+ /* Process 'N' for "New/Number/Name" */
+ if (buf[4] == 'N')
+ {
+ /* Find the colon before the name */
+ char const *s = buf + 6;
+
+ /* Paranoia -- require a name */
+ if (!*s) return (1);
+
+ /* Create the spec entry */
+ c_ptr->spec.emplace_back(player_spec());
+
+ /* Fill in initial values */
+ s_ptr = &c_ptr->spec.back();
+ s_ptr->title = my_strdup(s);
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'D' for "Description" */
+ if (buf[4] == 'D')
+ {
+ /* Acquire the text */
+ char const *s = buf + 6;
+
+ if (!s_ptr->desc)
+ {
+ s_ptr->desc = my_strdup(s);
+ }
+ else
+ {
+ strappend(&s_ptr->desc, format("\n%s", s));
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'O' for "Object birth" */
+ if (buf[4] == 'O')
+ {
+ if (read_proto_object(&s_ptr->object_protos, buf + 6))
+ {
+ return 1;
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'g' for "gods" */
+ if (buf[4] == 'g')
+ {
+ int i;
+
+ if (streq(buf + 6, "All Gods"))
+ s_ptr->gods = 0xFFFFFFFF;
+ else
+ {
+ if ((i = find_god(buf + 6)) == -1) return (1);
+ s_ptr->gods |= BIT(i);
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'k' for "skills" */
+ if (buf[4] == 'k')
+ {
+ if (read_skill_modifiers(&s_ptr->skill_modifiers, buf + 6))
+ {
+ return 1;
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'b' for "abilities" */
+ if (buf[4] == 'b')
+ {
+ if (read_ability(&s_ptr->abilities, buf + 6))
+ {
+ return 1;
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'G' for "Player flags" (multiple lines) */
+ if (buf[4] == 'G')
+ {
+ /* Parse every entry */
+ for (char *s = buf + 6; *s; )
+ {
+ char *t;
+
+ /* Find the end of this entry */
+ for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
+
+ /* Nuke and skip any dividers */
+ if (*t)
+ {
+ *t++ = '\0';
+ while (*t == ' ' || *t == '|') t++;
+ }
+
+ /* Parse this entry */
+ if (0 != grab_one_player_race_flag(&s_ptr->flags, s))
+ {
+ return (5);
+ }
+
+ /* Start the next entry */
+ s = t;
+ }
+
+ /* Next... */
+ continue;
+ }
+ }
+
+ /* Oops */
+ return (6);
+ }
+
+ /* Success */
+ return (0);
+}
+
+
+/*
+ * Initialize the "v_info" array, by parsing an ascii "template" file
+ */
+errr init_v_info_txt(FILE *fp)
+{
+ char buf[1024];
+
+ auto &v_info = game->edit_data.v_info;
+
+ /* Current entry */
+ vault_type *v_ptr = nullptr;
+
+ /* Just before the first record */
+ error_idx = -1;
+
+ /* Just before the first line */
+ error_line = -1;
+
+ /* Parse */
+ while (0 == my_fgets(fp, buf, 1024))
+ {
+ /* Advance the line number */
+ error_line++;
+
+ /* Skip comments and blank lines */
+ if (!buf[0] || (buf[0] == '#')) continue;
+ if ((buf[0] == 'Q') || (buf[0] == 'T')) continue;
+
+ /* Verify correct "colon" format */
+ if (buf[1] != ':') return (1);
+
+ /* Process 'N' for "New/Number/Name" */
+ if (buf[0] == 'N')
+ {
+ /* Find the colon before the name */
+ char *s = strchr(buf + 2, ':');
+
+ /* Verify that colon */
+ if (!s) return (1);
+
+ /* Nuke the colon, advance to the name */
+ *s++ = '\0';
+
+ /* Paranoia -- require a name */
+ if (!*s) return (1);
+
+ /* Get the index */
+ int i = atoi(buf + 2);
+
+ /* Verify information */
+ if (i <= error_idx) return (4);
+
+ /* Save the index */
+ error_idx = i;
+
+ /* Point at the "info" */
+ v_ptr = &expand_to_fit_index(v_info, i);
+
+ /* Next... */
+ continue;
+ }
+
+ /* There better be a current v_ptr */
+ if (!v_ptr) return (3);
+
+ /* Process 'D' for "Description" */
+ if (buf[0] == 'D')
+ {
+ /* Acquire the text */
+ cptr s = buf + 2;
+
+ /* Append data */
+ v_ptr->data += s;
+
+ /* Next... */
+ continue;
+ }
+
+
+ /* Process 'X' for "Extra info" (one line only) */
+ if (buf[0] == 'X')
+ {
+ int typ, rat, hgt, wid;
+
+ /* Scan for the values */
+ if (4 != sscanf(buf + 2, "%d:%d:%d:%d",
+ &typ, &rat, &hgt, &wid)) return (1);
+
+ /* Save the values */
+ v_ptr->typ = typ;
+ v_ptr->rat = rat;
+ v_ptr->hgt = hgt;
+ v_ptr->wid = wid;
+
+ /* Next... */
+ continue;
+ }
+
+ /* There better be a current v_ptr */
+ if (!v_ptr) return (3);
+
+ /* Process monster, item and level info for special levels */
+ if (buf[0] == 'Y')
+ {
+
+ int mon1, mon2, mon3, mon4, mon5, mon6, mon7, mon8, mon9;
+ int mon10, item1, item2, item3, lvl, dun_type;
+
+ /* Scan for the values */
+ if (15 != sscanf(buf + 2, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
+ &mon1, &mon2, &mon3, &mon4, &mon5, &mon6, &mon7, &mon8, &mon9, &mon10, &item1, &item2, &item3, &lvl, &dun_type)) return (1);
+
+ /* Save the values */
+ v_ptr->mon[0] = mon1;
+ v_ptr->mon[1] = mon2;
+ v_ptr->mon[2] = mon3;
+ v_ptr->mon[3] = mon4;
+ v_ptr->mon[4] = mon5;
+ v_ptr->mon[5] = mon6;
+ v_ptr->mon[6] = mon7;
+ v_ptr->mon[7] = mon8;
+ v_ptr->mon[8] = mon9;
+ v_ptr->mon[9] = mon10;
+ v_ptr->item[0] = item1;
+ v_ptr->item[1] = item2;
+ v_ptr->item[2] = item3;
+ v_ptr->lvl = lvl;
+ v_ptr->dun_type = dun_type;
+
+ /* Next... */
+ continue;
+ }
+
+
+ /* Oops */
+ return (6);
+ }
+
+
+ /* Success */
+ return (0);
+}
+
+
+/*
+ * Grab one flag in an feature_type from a textual string
+ */
+static int grab_one_feature_flag(cptr what, feature_flag_set *flags)
+{
+#define FF(tier, index, name) \
+ if (streq(what, #name)) \
+ { \
+ *flags |= BOOST_PP_CAT(FF_,name); \
+ return 0; \
+ };
+#include "feature_flag_list.hpp"
+#undef FF
+
+ /* Oops */
+ msg_format("Unknown feature flag '%s'.", what);
+
+ /* Error */
+ return (1);
+}
+
+
+/*
+ * Initialize the "f_info" array, by parsing an ascii "template" file
+ */
+errr init_f_info_txt(FILE *fp)
+{
+ auto &f_info = game->edit_data.f_info;
+
+ char buf[1024];
+
+ /* Current entry */
+ feature_type *f_ptr = NULL;
+
+ /* Just before the first record */
+ error_idx = -1;
+
+ /* Just before the first line */
+ error_line = -1;
+
+ /* Parse */
+ while (0 == my_fgets(fp, buf, 1024))
+ {
+ /* Advance the line number */
+ error_line++;
+
+ /* Skip comments and blank lines */
+ if (!buf[0] || (buf[0] == '#')) continue;
+
+ /* Verify correct "colon" format */
+ if (buf[1] != ':') return (1);
+
+ /* Process 'N' for "New/Number/Name" */
+ if (buf[0] == 'N')
+ {
+ /* Find the colon before the name */
+ char *s = strchr(buf + 2, ':');
+
+ /* Verify that colon */
+ if (!s) return (1);
+
+ /* Nuke the colon, advance to the name */
+ *s++ = '\0';
+
+ /* Paranoia -- require a name */
+ if (!*s) return (1);
+
+ /* Get the index */
+ int i = atoi(buf + 2);
+
+ /* Verify information */
+ if (i <= error_idx) return (4);
+
+ /* Save the index */
+ error_idx = i;
+
+ /* Point at the "info" */
+ f_ptr = &expand_to_fit_index(f_info, i);
+
+ /* Copy name */
+ assert(!f_ptr->name);
+ f_ptr->name = my_strdup(s);
+
+ /* Initialize */
+ f_ptr->mimic = i;
+ f_ptr->text = DEFAULT_FEAT_TEXT;
+ f_ptr->tunnel = DEFAULT_FEAT_TUNNEL;
+ f_ptr->block = DEFAULT_FEAT_BLOCK;
+
+ /* Next... */
+ continue;
+ }
+
+ /* There better be a current f_ptr */
+ if (!f_ptr) return (3);
+
+
+ /* Process 'D' for "Descriptions" */
+ if (buf[0] == 'D')
+ {
+ /* Acquire the text */
+ const char *s = buf + 4;
+
+ switch (buf[2])
+ {
+ case '0':
+ assert(f_ptr->text == DEFAULT_FEAT_TEXT);
+ f_ptr->text = my_strdup(s);
+ break;
+ case '1':
+ assert(f_ptr->tunnel == DEFAULT_FEAT_TUNNEL);
+ f_ptr->tunnel = my_strdup(s);
+ break;
+ case '2':
+ assert(f_ptr->block == DEFAULT_FEAT_BLOCK);
+ f_ptr->block = my_strdup(s);
+ break;
+ default:
+ return (6);
+ }
+
+ /* Next... */
+ continue;
+ }
+
+
+ /* Process 'M' for "Mimic" (one line only) */
+ if (buf[0] == 'M')
+ {
+ int mimic;
+
+ /* Scan for the values */
+ if (1 != sscanf(buf + 2, "%d",
+ &mimic)) return (1);
+
+ /* Save the values */
+ f_ptr->mimic = mimic;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'S' for "Shimmer" (one line only) */
+ if (buf[0] == 'S')
+ {
+ char s0, s1, s2, s3, s4, s5, s6;
+
+ /* Scan for the values */
+ if (7 != sscanf(buf + 2, "%c:%c:%c:%c:%c:%c:%c",
+ &s0, &s1, &s2, &s3, &s4, &s5, &s6)) return (1);
+
+ /* Save the values */
+ f_ptr->shimmer[0] = color_char_to_attr(s0);
+ f_ptr->shimmer[1] = color_char_to_attr(s1);
+ f_ptr->shimmer[2] = color_char_to_attr(s2);
+ f_ptr->shimmer[3] = color_char_to_attr(s3);
+ f_ptr->shimmer[4] = color_char_to_attr(s4);
+ f_ptr->shimmer[5] = color_char_to_attr(s5);
+ f_ptr->shimmer[6] = color_char_to_attr(s6);
+
+ /* Next... */
+ continue;
+ }
+
+
+ /* Process 'G' for "Graphics" (one line only) */
+ if (buf[0] == 'G')
+ {
+ int tmp;
+
+ /* Paranoia */
+ if (!buf[2]) return (1);
+ if (!buf[3]) return (1);
+ if (!buf[4]) return (1);
+
+ /* Extract the color */
+ tmp = color_char_to_attr(buf[4]);
+
+ /* Paranoia */
+ if (tmp < 0) return (1);
+
+ /* Save the values */
+ f_ptr->d_attr = tmp;
+ f_ptr->d_char = buf[2];
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'E' for "Effects" (up to four lines) -SC- */
+ if (buf[0] == 'E')
+ {
+ int side, dice, freq, type;
+ cptr tmp;
+ int i;
+
+ /* Find the next empty blow slot (if any) */
+ for (i = 0; i < 4; i++) if ((!f_ptr->d_side[i]) &&
+ (!f_ptr->d_dice[i])) break;
+
+ /* Oops, no more slots */
+ if (i == 4) return (1);
+
+ /* Scan for the values */
+ if (4 != sscanf(buf + 2, "%dd%d:%d:%d",
+ &dice, &side, &freq, &type))
+ {
+ int j;
+
+ if (3 != sscanf(buf + 2, "%dd%d:%d",
+ &dice, &side, &freq)) return (1);
+
+ tmp = buf + 2;
+ for (j = 0; j < 2; j++)
+ {
+ tmp = strchr(tmp, ':');
+ if (tmp == NULL) return (1);
+ tmp++;
+ }
+
+ j = 0;
+
+ while (d_info_dtypes[j].name != NULL)
+ if (strcmp(d_info_dtypes[j].name, tmp) == 0)
+ {
+ f_ptr->d_type[i] = d_info_dtypes[j].feat;
+ break;
+ }
+ else j++;
+
+ if (d_info_dtypes[j].name == NULL) return (1);
+ }
+ else
+ f_ptr->d_type[i] = type;
+
+ freq *= 10;
+ /* Save the values */
+ f_ptr->d_side[i] = side;
+ f_ptr->d_dice[i] = dice;
+ f_ptr->d_frequency[i] = freq;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Hack -- Process 'F' for flags */
+ if (buf[0] == 'F')
+ {
+ if (0 != grab_one_feature_flag(buf + 2, &f_ptr->flags))
+ {
+ return (5);
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Oops */
+ return (6);
+ }
+
+ /* Success */
+ return (0);
+}
+
+
+/*
+ * Initialize the "k_info" array, by parsing an ascii "template" file
+ */
+errr init_k_info_txt(FILE *fp)
+{
+ auto &k_info = game->edit_data.k_info;
+
+ int i;
+ char buf[1024];
+ char *s, *t;
+
+ /* Current entry */
+ object_kind *k_ptr = NULL;
+
+
+ /* Just before the first record */
+ error_idx = -1;
+
+ /* Just before the first line */
+ error_line = -1;
+
+
+ /* Parse */
+ while (0 == my_fgets(fp, buf, 1024))
+ {
+ /* Advance the line number */
+ error_line++;
+
+ /* Skip comments and blank lines */
+ if (!buf[0] || (buf[0] == '#')) continue;
+
+ /* Verify correct "colon" format */
+ if (buf[1] != ':') return (1);
+
+
+ /* Process 'N' for "New/Number/Name" */
+ if (buf[0] == 'N')
+ {
+ /* Find the colon before the name */
+ s = strchr(buf + 2, ':');
+
+ /* Verify that colon */
+ if (!s) return (1);
+
+ /* Nuke the colon, advance to the name */
+ *s++ = '\0';
+
+ /* Paranoia -- require a name */
+ if (!*s) return (1);
+
+ /* Get the index */
+ i = atoi(buf + 2);
+
+ /* Verify information */
+ if (i <= error_idx) return (4);
+
+ /* Save the index */
+ error_idx = i;
+
+ /* Point at the "info" */
+ k_ptr = &expand_to_fit_index(k_info, i);
+
+ /* Advance and Save the name index */
+ assert(!k_ptr->name);
+ k_ptr->name = my_strdup(s);
+
+ /* Ensure empty description */
+ k_ptr->text = my_strdup("");
+
+ /* Needed hack */
+ k_ptr->power = -1;
+
+ /* Next... */
+ continue;
+ }
+
+ /* There better be a current k_ptr */
+ if (!k_ptr) return (3);
+
+ /* Process 'D' for "Description" */
+ if (buf[0] == 'D')
+ {
+ /* Acquire the text */
+ s = buf + 2;
+
+ if (!k_ptr->text)
+ {
+ k_ptr->text = my_strdup(s);
+ }
+ else
+ {
+ strappend(&k_ptr->text, format("\n%s", s));
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'G' for "Graphics" (one line only) */
+ if (buf[0] == 'G')
+ {
+ char sym;
+ int tmp;
+
+ /* Paranoia */
+ if (!buf[2]) return (1);
+ if (!buf[3]) return (1);
+ if (!buf[4]) return (1);
+
+ /* Extract the char */
+ sym = buf[2];
+
+ /* Extract the attr */
+ tmp = color_char_to_attr(buf[4]);
+
+ /* Paranoia */
+ if (tmp < 0) return (1);
+
+ /* Save the values */
+ k_ptr->d_attr = tmp;
+ k_ptr->d_char = sym;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'I' for "Info" (one line only) */
+ if (buf[0] == 'I')
+ {
+ int tval, sval, pval, pval2 = 0;
+
+ /* Scan for the values */
+ if (4 != sscanf(buf + 2, "%d:%d:%d:%d",
+ &tval, &sval, &pval, &pval2))
+ {
+ char spl[70];
+
+ if (4 != sscanf(buf + 2, "%d:%d:%d:SPELL=%s",
+ &tval, &sval, &pval, spl))
+ {
+ if (3 != sscanf(buf + 2, "%d:%d:%d",
+ &tval, &sval, &pval))
+ return (1);
+ }
+ else
+ {
+ char *spl = strchr(buf + 2, '=') + 1;
+
+ pval2 = find_spell(spl);
+ }
+ }
+
+ /* Save the values */
+ k_ptr->tval = tval;
+ k_ptr->sval = sval;
+ k_ptr->pval = pval;
+ k_ptr->pval2 = pval2;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'W' for "More Info" (one line only) */
+ if (buf[0] == 'W')
+ {
+ int level, unused, wgt;
+ long cost;
+
+ /* Scan for the values */
+ if (4 != sscanf(buf + 2, "%d:%d:%d:%ld",
+ &level, &unused, &wgt, &cost)) return (1);
+
+ /* Save the values */
+ k_ptr->level = level;
+ k_ptr->weight = wgt;
+ k_ptr->cost = cost;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'T' for "arTifact Info" (one line only) */
+ if (buf[0] == 'T')
+ {
+ int btval, bsval;
+
+ /* Scan for the values */
+ if (2 != sscanf(buf + 2, "%d:%d",
+ &btval, &bsval)) return (1);
+
+ /* Save the values */
+ k_ptr->btval = btval;
+ k_ptr->bsval = bsval;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'Z' for "Granted power" */
+ if (buf[0] == 'Z')
+ {
+ int i;
+
+ /* Acquire the text */
+ s = buf + 2;
+
+ /* Find it in the list */
+ for (i = 0; i < POWER_MAX; i++)
+ {
+ if (iequals(s, powers_type[i].name)) break;
+ }
+
+ if (i == POWER_MAX) return (6);
+
+ k_ptr->power = i;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'a' for Activation */
+ if ( buf[0] == 'a')
+ {
+ k_ptr->activate = get_activation(buf + 2);
+ if (k_ptr->activate == -1)
+ {
+ return 1;
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'A' for "Allocation" (one line only) */
+ if (buf[0] == 'A')
+ {
+ int i;
+
+ /* XXX XXX XXX Simply read each number following a colon */
+ for (i = 0, s = buf + 1; s && (s[0] == ':') && s[1]; ++i)
+ {
+ if (i >= ALLOCATION_MAX) {
+ msg_print("Too many allocation entries.");
+ return 1;
+ }
+
+ /* Default chance */
+ k_ptr->chance[i] = 1;
+
+ /* Store the level */
+ k_ptr->locale[i] = atoi(s + 1);
+
+ /* Find the slash */
+ t = strchr(s + 1, '/');
+
+ /* Find the next colon */
+ s = strchr(s + 1, ':');
+
+ /* If the slash is "nearby", use it */
+ if (t && (!s || t < s))
+ {
+ int chance = atoi(t + 1);
+ if (chance > 0) {
+ k_ptr->chance[i] = chance;
+ }
+ }
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Hack -- Process 'P' for "power" and such */
+ if (buf[0] == 'P')
+ {
+ int ac, hd1, hd2, th, td, ta;
+
+ /* Scan for the values */
+ if (6 != sscanf(buf + 2, "%d:%dd%d:%d:%d:%d",
+ &ac, &hd1, &hd2, &th, &td, &ta)) return (1);
+
+ k_ptr->ac = ac;
+ k_ptr->dd = hd1;
+ k_ptr->ds = hd2;
+ k_ptr->to_h = th;
+ k_ptr->to_d = td;
+ k_ptr->to_a = ta;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Hack -- Process 'F' for flags */
+ if (buf[0] == 'F')
+ {
+ if (0 != grab_object_flag(&k_ptr->flags, buf + 2))
+ {
+ return (5);
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Hack -- Process 'f' for obvious flags */
+ if (buf[0] == 'f')
+ {
+ if (0 != grab_object_flag(&k_ptr->oflags, buf + 2))
+ {
+ return (5);
+ }
+
+ /* Next... */
+ continue;
+ }
+
+
+ /* Oops */
+ return (6);
+ }
+
+ /* Success */
+ return (0);
+}
+
+
+
+/*
+ * Initialize the "a_info" array, by parsing an ascii "template" file
+ */
+errr init_a_info_txt(FILE *fp)
+{
+ auto &a_info = game->edit_data.a_info;
+
+ int i;
+ char buf[1024];
+ char *s;
+
+ /* Current entry */
+ artifact_type *a_ptr = NULL;
+
+
+ /* Just before the first record */
+ error_idx = -1;
+
+ /* Just before the first line */
+ error_line = -1;
+
+
+ /* Parse */
+ while (0 == my_fgets(fp, buf, 1024))
+ {
+ /* Advance the line number */
+ error_line++;
+
+ /* Skip comments and blank lines */
+ if (!buf[0] || (buf[0] == '#')) continue;
+
+ /* Verify correct "colon" format */
+ if (buf[1] != ':') return (1);
+
+ /* Process 'N' for "New/Number/Name" */
+ if (buf[0] == 'N')
+ {
+ /* Find the colon before the name */
+ s = strchr(buf + 2, ':');
+
+ /* Verify that colon */
+ if (!s) return (1);
+
+ /* Nuke the colon, advance to the name */
+ *s++ = '\0';
+
+ /* Paranoia -- require a name */
+ if (!*s) return (1);
+
+ /* Get the index */
+ i = atoi(buf + 2);
+
+ /* Verify information */
+ if (i < error_idx) return (4);
+
+ /* Save the index */
+ error_idx = i;
+
+ /* Point at the "info" */
+ a_ptr = &expand_to_fit_index(a_info, i);
+
+ /* Copy name */
+ assert(!a_ptr->name);
+ a_ptr->name = my_strdup(s);
+
+ /* Ensure empty description */
+ a_ptr->text = my_strdup("");
+
+ /* Ignore everything */
+ a_ptr->flags |= TR_IGNORE_ACID |
+ TR_IGNORE_ELEC |
+ TR_IGNORE_FIRE |
+ TR_IGNORE_COLD;
+
+ /* Needed hack */
+ a_ptr->power = -1;
+
+ /*Require activating artifacts to have a activation type */
+ if (a_ptr && (a_ptr->flags & TR_ACTIVATE) && !a_ptr->activate)
+ {
+ msg_print("Activate flag without activate type");
+ return 1;
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* There better be a current a_ptr */
+ if (!a_ptr) return (3);
+
+ /* Process 'D' for "Description" */
+ if (buf[0] == 'D')
+ {
+ /* Acquire the text */
+ s = buf + 2;
+
+ /* Add separator if necessary */
+ if (*a_ptr->text != '\0' && !ends_with(a_ptr->text, " ")) {
+ strappend(&a_ptr->text, " ");
+ }
+
+ /* Append to description */
+ strappend(&a_ptr->text, s);
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'I' for "Info" (one line only) */
+ if (buf[0] == 'I')
+ {
+ int tval, sval, pval;
+
+ /* Scan for the values */
+ if (3 != sscanf(buf + 2, "%d:%d:%d",
+ &tval, &sval, &pval))
+ {
+ return (1);
+ }
+
+ /* Save the values */
+ a_ptr->tval = tval;
+ a_ptr->sval = sval;
+ a_ptr->pval = pval;
+
+ /* Verify */
+ if (!lookup_kind(tval, sval)) return (6);
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'W' for "More Info" (one line only) */
+ if (buf[0] == 'W')
+ {
+ int level, rarity, wgt;
+ long cost;
+
+ /* Scan for the values */
+ if (4 != sscanf(buf + 2, "%d:%d:%d:%ld",
+ &level, &rarity, &wgt, &cost)) return (1);
+
+ /* Save the values */
+ a_ptr->level = level;
+ a_ptr->rarity = rarity;
+ a_ptr->weight = wgt;
+ a_ptr->cost = cost;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Hack -- Process 'P' for "power" and such */
+ if (buf[0] == 'P')
+ {
+ int ac, hd1, hd2, th, td, ta;
+
+ /* Scan for the values */
+ if (6 != sscanf(buf + 2, "%d:%dd%d:%d:%d:%d",
+ &ac, &hd1, &hd2, &th, &td, &ta)) return (1);
+
+ a_ptr->ac = ac;
+ a_ptr->dd = hd1;
+ a_ptr->ds = hd2;
+ a_ptr->to_h = th;
+ a_ptr->to_d = td;
+ a_ptr->to_a = ta;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'Z' for "Granted power" */
+ if (buf[0] == 'Z')
+ {
+ int i;
+
+ /* Acquire the text */
+ s = buf + 2;
+
+ /* Find it in the list */
+ for (i = 0; i < POWER_MAX; i++)
+ {
+ if (iequals(s, powers_type[i].name)) break;
+ }
+
+ if (i == POWER_MAX) return (6);
+
+ a_ptr->power = i;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Hack -- Process 'F' for flags */
+ if (buf[0] == 'F')
+ {
+ if (grab_object_flag(&a_ptr->flags, buf+2))
+ {
+ return (5);
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Hack -- Process 'f' for obvious flags */
+ if (buf[0] == 'f')
+ {
+ if (grab_object_flag(&a_ptr->oflags, buf+2))
+ {
+ return (5);
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Read activation type. */
+ if (buf[0] == 'a')
+ {
+ a_ptr->activate = get_activation(buf + 2);
+ if (a_ptr->activate == -1)
+ {
+ return 1;
+ }
+
+ /* Next... */
+ continue;
+ }
+
+
+ /* Oops */
+ return (6);
+ }
+
+ /* Success */
+ return (0);
+}
+
+/*
+* Initialize the "set_info" array, by parsing an ascii "template" file
+*/
+errr init_set_info_txt(FILE *fp)
+{
+ auto &set_info = game->edit_data.set_info;
+
+ int cur_art = 0, cur_num = 0;
+ char buf[1024];
+
+ /* Current entry */
+ set_type *set_ptr = NULL;
+
+
+ /* Just before the first record */
+ error_idx = -1;
+
+ /* Just before the first line */
+ error_line = -1;
+
+
+ /* Parse */
+ while (0 == my_fgets(fp, buf, 1024))
+ {
+ /* Advance the line number */
+ error_line++;
+
+ /* Skip comments and blank lines */
+ if (!buf[0] || (buf[0] == '#')) continue;
+
+ /* Verify correct "colon" format */
+ if (buf[1] != ':') return (1);
+
+ /* Process 'N' for "New/Number/Name" */
+ if (buf[0] == 'N')
+ {
+ /* Find the colon before the name */
+ char *s = strchr(buf + 2, ':');
+
+ /* Verify that colon */
+ if (!s) return (1);
+
+ /* Nuke the colon, advance to the name */
+ *s++ = '\0';
+
+ /* Paranoia -- require a name */
+ if (!*s) return (1);
+
+ /* Get the index */
+ int i = atoi(buf + 2);
+
+ /* Verify information */
+ if (i < error_idx) return (4);
+
+ /* Save the index */
+ error_idx = i;
+
+ /* Point at the "info" */
+ set_ptr = &expand_to_fit_index(set_info, i);
+ assert(set_ptr->name.empty());
+
+ /* Copy name */
+ set_ptr->name = s;
+
+ /* Next... */
+ continue;
+ }
+
+ /* There better be a current set_ptr */
+ if (!set_ptr) return (3);
+
+ /* Process 'D' for "Description" */
+ if (buf[0] == 'D')
+ {
+ /* Need newline? */
+ if (!set_ptr->desc.empty())
+ {
+ set_ptr->desc += '\n';
+ }
+
+ /* Append */
+ set_ptr->desc += (buf + 2);
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'P' for "Power" (up to 6) */
+ if (buf[0] == 'P')
+ {
+ int a_idx, num, pval;
+ int z;
+
+ /* Scan for the values */
+ if (3 != sscanf(buf + 2, "%d:%d:%d",
+ &a_idx, &num, &pval))
+ {
+ return (1);
+ }
+
+ for (z = 0; z < set_ptr->num; z++)
+ if (set_ptr->arts[z].a_idx == a_idx) break;
+ if (z == set_ptr->num)
+ {
+ set_ptr->num++;
+ set_ptr->arts[z].a_idx = a_idx;
+ }
+
+ /* Save the values */
+ set_ptr->arts[z].pval[num - 1] = pval;
+ cur_art = z;
+ cur_num = num - 1;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'F' for flags */
+ if (buf[0] == 'F')
+ {
+ if (grab_object_flag(&set_ptr->arts[cur_art].flags[cur_num], buf + 2))
+ {
+ return (5);
+ }
+
+ /* Next... */
+ continue;
+ }
+
+
+ /* Oops */
+ return (6);
+ }
+
+ /* Success */
+ return (0);
+}
+
+
+/*
+ * Initialize the "s_info" array, by parsing an ascii "template" file
+ */
+errr init_s_info_txt(FILE *fp)
+{
+ auto &s_descriptors = game->edit_data.s_descriptors;
+ auto &s_info = game->s_info;
+
+ int order = 1;
+ char buf[1024];
+
+ /* Current entry */
+ skill_descriptor *s_ptr = NULL;
+
+
+ /* Just before the first record */
+ error_idx = -1;
+
+ /* Just before the first line */
+ error_line = -1;
+
+
+ /* Parse */
+ while (0 == my_fgets(fp, buf, 1024))
+ {
+ /* Advance the line number */
+ error_line++;
+
+ /* Skip comments and blank lines */
+ if (!buf[0] || (buf[0] == '#')) continue;
+
+ /* Verify correct "colon" format */
+ if (buf[1] != ':') return (1);
+
+ /* Process 'T' for "skill Tree" */
+ if (buf[0] == 'T')
+ {
+ char *sec;
+ s16b s1, s2;
+
+ /* Scan for the values */
+ if (NULL == (sec = strchr(buf + 2, ':')))
+ {
+ return (1);
+ }
+ *sec = '\0';
+ sec++;
+ if (!*sec) return (1);
+
+ s1 = find_skill(buf + 2);
+ s2 = find_skill(sec);
+ if (s2 == -1) return (1);
+
+ s_descriptors[s2].father = s1;
+ s_descriptors[s2].order = order++;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'E' for "Exclusive" */
+ if (buf[0] == 'E')
+ {
+ char *sec;
+ s16b s1, s2;
+
+ /* Scan for the values */
+ if (NULL == (sec = strchr(buf + 2, ':')))
+ {
+ return (1);
+ }
+ *sec = '\0';
+ sec++;
+ if (!*sec) return (1);
+
+ s1 = find_skill(buf + 2);
+ s2 = find_skill(sec);
+ if ((s1 == -1) || (s2 == -1)) return (1);
+
+ // The "exclusive" relation is symmetric, so
+ // add summetrically so we don't have to specify
+ // twice in data files.
+ s_descriptors[s1].excludes.push_back(s2);
+ s_descriptors[s2].excludes.push_back(s1);
+
+ /* Next... */
+ continue;
+ }
+
+
+ /* Process 'A' for "Amical/friendly" */
+ if (buf[0] == 'f')
+ {
+ char *sec, *cval;
+ s16b s1, s2;
+
+ /* Scan for the values */
+ if (NULL == (sec = strchr(buf + 2, ':')))
+ {
+ return (1);
+ }
+ *sec = '\0';
+ sec++;
+ if (!*sec) return (1);
+ if (NULL == (cval = strchr(sec, '%')))
+ {
+ return (1);
+ }
+ *cval = '\0';
+ cval++;
+ if (!*cval) return (1);
+
+ s1 = find_skill(buf + 2);
+ s2 = find_skill(sec);
+ if ((s1 == -1) || (s2 == -1)) return (1);
+
+ s_descriptors[s1].increases.emplace_back(
+ std::make_tuple(s2, atoi(cval)));
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'N' for "New/Number/Name" */
+ if (buf[0] == 'N')
+ {
+ /* Find the colon before the name */
+ char *s = strchr(buf + 2, ':');
+
+ /* Verify that colon */
+ if (!s) return (1);
+
+ /* Nuke the colon, advance to the name */
+ *s++ = '\0';
+
+ /* Paranoia -- require a name */
+ if (!*s) return (1);
+
+ /* Get the index */
+ int i = atoi(buf + 2);
+
+ /* Save the index */
+ error_idx = i;
+
+ /* Point at the "info" */
+ s_ptr = &expand_to_fit_index(s_descriptors, i);
+ assert(s_ptr->name.empty());
+
+ /* Make sure s_info also expands appropriately */
+ expand_to_fit_index(s_info, i);
+
+ /* Copy name */
+ s_ptr->name = my_strdup(s);
+
+ /* Next... */
+ continue;
+ }
+
+ /* There better be a current s_ptr */
+ if (!s_ptr) return (3);
+
+ /* Process 'D' for "Description" */
+ if (buf[0] == 'D')
+ {
+ /* Need newline? */
+ if (!s_ptr->desc.empty())
+ {
+ s_ptr->desc += '\n';
+ }
+
+ /* Append */
+ s_ptr->desc += (buf + 2);
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'A' for "Activation Description" (one line only) */
+ if (buf[0] == 'A')
+ {
+ char *txt;
+
+ /* Acquire the text */
+ char *s = buf + 2;
+
+ if (NULL == (txt = strchr(s, ':'))) return (1);
+ *txt = '\0';
+ txt++;
+
+ /* Copy action description */
+ assert(s_ptr->action_desc.empty());
+ s_ptr->action_desc = txt;
+
+ /* Copy mkey index */
+ s_ptr->action_mkey = atoi(s);
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'G' for "random Gain" (one line only) */
+ if (buf[0] == 'G')
+ {
+ int chance;
+
+ /* Scan for the values */
+ if (1 != sscanf(buf + 2, "%d", &chance))
+ {
+ return (1);
+ }
+
+ /* Save the values */
+ s_ptr->random_gain_chance = chance;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'F' for flags */
+ if (buf[0] == 'F')
+ {
+ if (0 != grab_one_skill_flag(&s_ptr->flags, buf + 2))
+ {
+ return (5);
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Oops */
+ return (6);
+ }
+
+ /* Success */
+ return (0);
+}
+
+/*
+ * Initialize the "ab_info" array, by parsing an ascii "template" file
+ */
+errr init_ab_info_txt(FILE *fp)
+{
+ auto &ab_info = game->edit_data.ab_info;
+
+ char buf[1024];
+
+ /* Current entry */
+ ability_type *ab_ptr = NULL;
+
+
+ /* Just before the first record */
+ error_idx = -1;
+
+ /* Just before the first line */
+ error_line = -1;
+
+
+ /* Parse */
+ while (0 == my_fgets(fp, buf, 1024))
+ {
+ /* Advance the line number */
+ error_line++;
+
+ /* Skip comments and blank lines */
+ if (!buf[0] || (buf[0] == '#')) continue;
+
+ /* Verify correct "colon" format */
+ if (buf[1] != ':') return (1);
+
+ /* Process 'N' for "New/Number/Name" */
+ if (buf[0] == 'N')
+ {
+ /* Find the colon before the name */
+ char *s = strchr(buf + 2, ':');
+
+ /* Verify that colon */
+ if (!s) return (1);
+
+ /* Nuke the colon, advance to the name */
+ *s++ = '\0';
+
+ /* Paranoia -- require a name */
+ if (!*s) return (1);
+
+ /* Get the index */
+ int i = atoi(buf + 2);
+
+ /* Save the index */
+ error_idx = i;
+
+ /* Point at the "info" */
+ ab_ptr = &expand_to_fit_index(ab_info, i);
+ assert(ab_ptr->name.empty());
+
+ /* Copy name */
+ ab_ptr->name = s;
+
+ /* Next... */
+ continue;
+ }
+
+ /* There better be a current ab_ptr */
+ if (!ab_ptr) return (3);
+
+ /* Process 'D' for "Description" */
+ if (buf[0] == 'D')
+ {
+ /* Need newline? */
+ if (!ab_ptr->desc.empty())
+ {
+ ab_ptr->desc += '\n';
+ }
+
+ /* Append */
+ ab_ptr->desc += (buf + 2);
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'A' for "Activation Description" */
+ if (buf[0] == 'A')
+ {
+ char *txt;
+
+ /* Acquire the text */
+ char *s = buf + 2;
+
+ if (NULL == (txt = strchr(s, ':'))) return (1);
+ *txt = '\0';
+ txt++;
+
+ /* Copy name */
+ assert(ab_ptr->action_desc.empty());
+ ab_ptr->action_desc = txt;
+
+ /* Set mkey */
+ ab_ptr->action_mkey = atoi(s);
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'I' for "Info" (one line only) */
+ if (buf[0] == 'I')
+ {
+ int cost;
+
+ /* Scan for the values */
+ if (1 != sscanf(buf + 2, "%d", &cost))
+ {
+ return (1);
+ }
+
+ /* Save the values */
+ ab_ptr->cost = cost;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'k' for "Skill" */
+ if (buf[0] == 'k')
+ {
+ char *sec;
+
+ /* Scan for the values */
+ if (NULL == (sec = strchr(buf + 2, ':')))
+ {
+ return (1);
+ }
+ *sec = '\0';
+ sec++;
+ if (!*sec) return (1);
+
+ s16b level = atoi(buf + 2);
+ s16b skill = find_skill(sec);
+ if (skill == -1) return (1);
+
+ ability_type::skill_requirement req;
+ req.skill_idx = skill;
+ req.level = level;
+
+ ab_ptr->need_skills.emplace_back(req);
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'a' for "needed ability" */
+ if (buf[0] == 'a')
+ {
+ s16b ab = find_ability(buf + 2);
+ if (ab == -1)
+ {
+ return (1);
+ }
+
+ ab_ptr->need_abilities.push_back(ab);
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'S' for "Stat" */
+ if (buf[0] == 'S')
+ {
+ char *sec;
+ s16b stat;
+
+ /* Scan for the values */
+ if (NULL == (sec = strchr(buf + 2, ':')))
+ {
+ return (1);
+ }
+ *sec = '\0';
+ sec++;
+ if (!*sec) return (1);
+
+ for (stat = 0; stat < 6; stat++)
+ {
+ if (!strcmp(stat_names[stat], sec))
+ break;
+ }
+
+ if (stat == 6) return (1);
+
+ ab_ptr->stat[stat] = atoi(buf + 2);
+
+ /* Next... */
+ continue;
+ }
+
+ /* Oops */
+ return (6);
+ }
+
+ /* Success */
+ return (0);
+}
+
+
+/*
+ * Look up ego flag
+ */
+static ego_flag_set lookup_ego_flag(const char *what)
+{
+#define ETR(tier, index, name) \
+ if (streq(what, #name)) \
+ { \
+ return BOOST_PP_CAT(ETR_,name); \
+ };
+#include "ego_flag_list.hpp"
+#undef ETR
+ return ego_flag_set();
+}
+
+
+/*
+ * Grab one flag in a ego-item_type from a textual string.
+ *
+ * We explicitly allow nullptr for the "ego" parameter.
+ */
+static bool_ grab_one_ego_item_flag(object_flag_set *flags, ego_flag_set *ego, cptr what)
+{
+ /* Lookup as an object_flag */
+ if (auto f = object_flag_set_from_string(what))
+ {
+ *flags |= f;
+ return 0;
+ }
+
+ /* Lookup as ego flag */
+ if (ego)
+ {
+ if (auto f = lookup_ego_flag(what))
+ {
+ *ego |= f;
+ return (0);
+ }
+ }
+
+ /* Oops */
+ msg_format("Unknown ego-item flag '%s'.", what);
+
+ /* Error */
+ return (1);
+}
+
+
+
+/*
+ * Initialize the "e_info" array, by parsing an ascii "template" file
+ */
+errr init_e_info_txt(FILE *fp)
+{
+ auto &e_info = game->edit_data.e_info;
+
+ int i, cur_r = -1, cur_t = 0;
+ char buf[1024];
+ char *s, *t;
+
+ /* Current entry */
+ ego_item_type *e_ptr = NULL;
+
+
+ /* Just before the first record */
+ error_idx = -1;
+
+ /* Just before the first line */
+ error_line = -1;
+
+
+ /* Parse */
+ while (0 == my_fgets(fp, buf, 1024))
+ {
+ /* Advance the line number */
+ error_line++;
+
+ /* Skip comments and blank lines */
+ if (!buf[0] || (buf[0] == '#')) continue;
+
+ /* Verify correct "colon" format */
+ if (buf[1] != ':') return (1);
+
+ /* Process 'N' for "New/Number/Name" */
+ if (buf[0] == 'N')
+ {
+ /* Find the colon before the name */
+ s = strchr(buf + 2, ':');
+
+ /* Verify that colon */
+ if (!s) return (1);
+
+ /* Nuke the colon, advance to the name */
+ *s++ = '\0';
+
+ /* Paranoia -- require a name */
+ if (!*s) return (1);
+
+ /* Get the index */
+ i = atoi(buf + 2);
+
+ /* Verify information */
+ if (i < error_idx) return (4);
+
+ /* Save the index */
+ error_idx = i;
+
+ /* Reset cur_* variables */
+ cur_r = -1;
+ cur_t = 0;
+
+ /* Point at the "info" */
+ e_ptr = &expand_to_fit_index(e_info, i);
+
+ /* Copy name */
+ assert(!e_ptr->name);
+ e_ptr->name = my_strdup(s);
+
+ /* Next... */
+ continue;
+ }
+
+ /* There better be a current e_ptr */
+ if (!e_ptr) return (3);
+
+
+ /* Process 'T' for "Tval/Sval" (up to 5 lines) */
+ if (buf[0] == 'T')
+ {
+ int tv, minsv, maxsv;
+
+ if (cur_t == 10) return 1;
+
+ /* Scan for the values */
+ if (3 != sscanf(buf + 2, "%d:%d:%d",
+ &tv, &minsv, &maxsv)) return (1);
+
+ /* Save the values */
+ e_ptr->tval[cur_t] = tv;
+ e_ptr->min_sval[cur_t] = minsv;
+ e_ptr->max_sval[cur_t] = maxsv;
+
+ cur_t++;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'R' for "flags rarity" (up to 5 lines) */
+ if (buf[0] == 'R')
+ {
+ int rar;
+
+ cur_r++;
+
+ if (cur_r >= FLAG_RARITY_MAX) {
+ return 1;
+ }
+
+ /* Scan for the values */
+ if (1 != sscanf(buf + 2, "%d",
+ &rar)) return (1);
+
+ /* Save the values */
+ e_ptr->rar[cur_r] = rar;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'X' for "Xtra" (one line only) */
+ if (buf[0] == 'X')
+ {
+ int slot, rating;
+ char pos;
+
+ /* Scan for the values */
+ if (3 != sscanf(buf + 2, "%c:%d:%d",
+ &pos, &slot, &rating)) return (1);
+
+ /* Save the values */
+ /* e_ptr->slot = slot; */
+ e_ptr->rating = rating;
+ e_ptr->before = (pos == 'B') ? TRUE : FALSE;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'W' for "More Info" (one line only) */
+ if (buf[0] == 'W')
+ {
+ int level, rarity, rarity2;
+ long cost;
+
+ /* Scan for the values */
+ if (4 != sscanf(buf + 2, "%d:%d:%d:%ld",
+ &level, &rarity, &rarity2, &cost)) return (1);
+
+ /* Save the values */
+ e_ptr->level = level;
+ e_ptr->rarity = rarity;
+ e_ptr->mrarity = rarity2;
+ e_ptr->cost = cost;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Hack -- Process 'C' for "creation" */
+ if (buf[0] == 'C')
+ {
+ int th, td, ta, pv;
+
+ /* Scan for the values */
+ if (4 != sscanf(buf + 2, "%d:%d:%d:%d",
+ &th, &td, &ta, &pv)) return (1);
+
+ e_ptr->max_to_h = th;
+ e_ptr->max_to_d = td;
+ e_ptr->max_to_a = ta;
+ e_ptr->max_pval = pv;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'Z' for "Granted power" */
+ if (buf[0] == 'Z')
+ {
+ int i;
+
+ /* Acquire the text */
+ s = buf + 2;
+
+ /* Find it in the list */
+ for (i = 0; i < POWER_MAX; i++)
+ {
+ if (iequals(s, powers_type[i].name)) break;
+ }
+
+ if (i == POWER_MAX) return (6);
+
+ e_ptr->power = i;
+
+ /* Next... */
+ continue;
+ }
+
+ if (buf[0] == 'a')
+ {
+ e_ptr->activate = get_activation(buf + 2);
+ if (e_ptr->activate == -1)
+ {
+ return 1;
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Hack -- Process 'r:N' for needed flags */
+ if ((buf[0] == 'r') && (buf[2] == 'N'))
+ {
+ /* Parse every entry textually */
+ for (s = buf + 4; *s; )
+ {
+ /* Find the end of this entry */
+ for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
+
+ /* Nuke and skip any dividers */
+ if (*t)
+ {
+ *t++ = '\0';
+ while ((*t == ' ') || (*t == '|')) t++;
+ }
+
+ /* Parse this entry */
+ if (grab_object_flag(&e_ptr->need_flags, s))
+ {
+ return (5);
+ }
+
+ /* Start the next entry */
+ s = t;
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Hack -- Process 'r:F' for forbidden flags */
+ if ((buf[0] == 'r') && (buf[2] == 'F'))
+ {
+ if (grab_object_flag(&e_ptr->forbid_flags, buf + 4))
+ {
+ return (5);
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Hack -- Process 'F' for flags */
+ if (buf[0] == 'F')
+ {
+ if (cur_r == -1) return (6);
+
+ /* Parse every entry textually */
+ for (s = buf + 2; *s; )
+ {
+ /* Find the end of this entry */
+ for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
+
+ /* Nuke and skip any dividers */
+ if (*t)
+ {
+ *t++ = '\0';
+ while ((*t == ' ') || (*t == '|')) t++;
+ }
+
+ /* Parse this entry */
+ assert(cur_r < FLAG_RARITY_MAX);
+ if (0 != grab_one_ego_item_flag(
+ &e_ptr->flags[cur_r],
+ &e_ptr->fego[cur_r],
+ s))
+ {
+ return (5);
+ }
+
+ /* Start the next entry */
+ s = t;
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Hack -- Process 'f' for obvious flags */
+ if (buf[0] == 'f')
+ {
+ if (cur_r == -1) return (6);
+
+ /* Parse every entry textually */
+ for (s = buf + 2; *s; )
+ {
+ /* Find the end of this entry */
+ for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
+
+ /* Nuke and skip any dividers */
+ if (*t)
+ {
+ *t++ = '\0';
+ while ((*t == ' ') || (*t == '|')) t++;
+ }
+
+ /* Parse this entry */
+ assert(cur_r < FLAG_RARITY_MAX);
+ if (0 != grab_one_ego_item_flag(
+ &e_ptr->oflags[cur_r],
+ nullptr,
+ s))
+ {
+ return (5);
+ }
+
+ /* Start the next entry */
+ s = t;
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Oops */
+ return (6);
+ }
+
+ /* Success */
+ return (0);
+}
+
+
+
+/*
+ * Initialize the "ra_info" array, by parsing an ascii "template" file
+ */
+errr init_ra_info_txt(FILE *fp)
+{
+ auto &ra_gen = game->edit_data.ra_gen;
+ auto &ra_info = game->edit_data.ra_info;
+
+ char buf[1024];
+
+ /* Current entry */
+ randart_part_type *ra_ptr = NULL;
+
+
+ /* Just before the first record */
+ error_idx = -1;
+
+ /* Just before the first line */
+ error_line = -1;
+
+
+ /* Parse */
+ while (0 == my_fgets(fp, buf, 1024))
+ {
+ /* Advance the line number */
+ error_line++;
+
+ /* Skip comments and blank lines */
+ if (!buf[0] || (buf[0] == '#')) continue;
+
+ /* Verify correct "colon" format */
+ if (buf[1] != ':') return (1);
+
+ /* Process 'G' for "General" (up to 30 lines) */
+ if (buf[0] == 'G')
+ {
+ int chance, dd, ds, plus;
+
+ /* Scan for the values */
+ if (4 != sscanf(buf + 2, "%d:%dd%d:%d",
+ &chance, &dd, &ds, &plus)) return (1);
+
+ /* Save the values */
+ randart_gen_type gen;
+ gen.chance = chance;
+ gen.dd = dd;
+ gen.ds = ds;
+ gen.plus = plus;
+
+ /* Add to data */
+ ra_gen.emplace_back(gen);
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'N' for "New/Number" */
+ if (buf[0] == 'N')
+ {
+ /* Get the index */
+ int i = atoi(buf + 2);
+
+ /* Verify information */
+ if (i < error_idx) return (4);
+
+ /* Save the index */
+ error_idx = i;
+
+ /* Point at the "info" */
+ ra_ptr = &expand_to_fit_index(ra_info, i);
+
+ /* Next... */
+ continue;
+ }
+
+ /* There better be a current ra_ptr */
+ if (!ra_ptr) return (3);
+
+ /* Process 'T' for "Tval/Sval" (up to 5 lines) */
+ if (buf[0] == 'T')
+ {
+ /* Scan for the values */
+ int tv, minsv, maxsv;
+ if (3 != sscanf(buf + 2, "%d:%d:%d",
+ &tv, &minsv, &maxsv)) return (1);
+
+ /* Set up filter */
+ randart_part_type::kind_filter_t filter;
+ filter.tval = tv;
+ filter.min_sval = minsv;
+ filter.max_sval = maxsv;
+
+ /* Add filter */
+ ra_ptr->kind_filter.emplace_back(filter);
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'X' for "Xtra" (one line only) */
+ if (buf[0] == 'X')
+ {
+ int power, max;
+
+ /* Scan for the values */
+ if (2 != sscanf(buf + 2, "%d:%d",
+ &power, &max)) return (1);
+
+ /* Save the values */
+ ra_ptr->value = power;
+ ra_ptr->max = max;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'W' for "More Info" (one line only) */
+ if (buf[0] == 'W')
+ {
+ int level, rarity, rarity2;
+
+ /* Scan for the values */
+ if (3 != sscanf(buf + 2, "%d:%d:%d",
+ &level, &rarity, &rarity2)) return (1);
+
+ /* Save the values */
+ ra_ptr->level = level;
+ ra_ptr->rarity = rarity;
+ ra_ptr->mrarity = rarity2;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Hack -- Process 'C' for "creation" */
+ if (buf[0] == 'C')
+ {
+ int th, td, ta, pv;
+
+ /* Scan for the values */
+ if (4 != sscanf(buf + 2, "%d:%d:%d:%d",
+ &th, &td, &ta, &pv)) return (1);
+
+ ra_ptr->max_to_h = th;
+ ra_ptr->max_to_d = td;
+ ra_ptr->max_to_a = ta;
+ ra_ptr->max_pval = pv;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'Z' for "Granted power" */
+ if (buf[0] == 'Z')
+ {
+ /* Acquire the text */
+ char const *s = buf + 2;
+
+ /* Find it in the list */
+ std::size_t i;
+ for (i = 0; i < POWER_MAX; i++)
+ {
+ if (iequals(s, powers_type[i].name)) break;
+ }
+
+ /* Not present? Fail */
+ if (i == POWER_MAX)
+ {
+ return (6);
+ }
+
+ ra_ptr->power = i;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'F' for flags */
+ if (buf[0] == 'F')
+ {
+ if (0 != grab_one_ego_item_flag(
+ &ra_ptr->flags,
+ &ra_ptr->fego,
+ buf + 2))
+ {
+ return (5);
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'A' for antagonic flags */
+ if (buf[0] == 'A')
+ {
+ if (0 != grab_one_ego_item_flag(
+ &ra_ptr->aflags,
+ nullptr,
+ buf + 2))
+ {
+ return (5);
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Oops */
+ return (6);
+ }
+
+ /* Success */
+ return (0);
+}
+
+
+static errr grab_monster_race_flag(monster_race_flag_set *flags, cptr what)
+{
+#define RF(tier, index, name) \
+ if (streq(what, #name)) \
+ { \
+ *flags |= BOOST_PP_CAT(RF_,name); \
+ return 0; \
+ };
+#include "monster_race_flag_list.hpp"
+#undef RF
+
+ /* Oops */
+ msg_format("Unknown monster flag '%s'.", what);
+
+ /* Failure */
+ return (1);
+}
+
+
+/*
+ * Grab one (spell) flag in a monster_race from a textual string
+ */
+static errr grab_one_monster_spell_flag(monster_spell_flag_set *flags, cptr what)
+{
+ for (auto const &monster_spell: monster_spells())
+ {
+ if (streq(what, monster_spell->name))
+ {
+ *flags |= monster_spell->flag_set;
+ return 0;
+ }
+ }
+
+ /* Oops */
+ msg_format("Unknown monster flag '%s'.", what);
+
+ /* Failure */
+ return (1);
+}
+
+
+/*
+ * Initialize the "r_info" array, by parsing an ascii "template" file
+ */
+errr init_r_info_txt(FILE *fp)
+{
+ auto &r_info = game->edit_data.r_info;
+
+ char buf[1024];
+
+ /* Current entry */
+ monster_race *r_ptr = NULL;
+
+
+ /* Just before the first record */
+ error_idx = -1;
+
+ /* Just before the first line */
+ error_line = -1;
+
+
+ /* Parse */
+ while (0 == my_fgets(fp, buf, 1024))
+ {
+ /* Advance the line number */
+ error_line++;
+
+ /* Skip comments and blank lines */
+ if (!buf[0] || (buf[0] == '#')) continue;
+
+ /* Verify correct "colon" format */
+ if (buf[1] != ':') return (1);
+
+ /* Process 'N' for "New/Number/Name" */
+ if (buf[0] == 'N')
+ {
+ /* Find the colon before the name */
+ char *s = strchr(buf + 2, ':');
+
+ /* Verify that colon */
+ if (!s) return (1);
+
+ /* Nuke the colon, advance to the name */
+ *s++ = '\0';
+
+ /* Paranoia -- require a name */
+ if (!*s) return (1);
+
+ /* Get the index */
+ int i = atoi(buf + 2);
+
+ /* Verify information */
+ if (i < error_idx) return (4);
+
+ /* Save the index */
+ error_idx = i;
+
+ /* Point at the "info" */
+ r_ptr = &expand_to_fit_index(r_info, i);
+
+ /* Allocate name string. */
+ assert(!r_ptr->name); // Sanity check that we aren't overwriting anything
+ r_ptr->name = my_strdup(s);
+
+ /* Ensure empty description */
+ r_ptr->text = my_strdup("");
+
+ /* Set default drop theme */
+ r_ptr->drops = obj_theme::defaults();
+
+ r_ptr->freq_inate = 0;
+ r_ptr->freq_spell = 0;
+
+ /* Next... */
+ continue;
+ }
+
+ /* There better be a current r_ptr */
+ if (!r_ptr) return (3);
+
+
+ /* Process 'D' for "Description" */
+ if (buf[0] == 'D')
+ {
+ /* Append to description */
+ strappend(&r_ptr->text, buf + 2);
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'G' for "Graphics" (one line only) */
+ if (buf[0] == 'G')
+ {
+ char sym;
+ int tmp;
+
+ /* Paranoia */
+ if (!buf[2]) return (1);
+ if (!buf[3]) return (1);
+ if (!buf[4]) return (1);
+
+ /* Extract the char */
+ sym = buf[2];
+
+ /* Extract the attr */
+ tmp = color_char_to_attr(buf[4]);
+
+ /* Paranoia */
+ if (tmp < 0) return (1);
+
+ /* Save the values */
+ r_ptr->d_char = sym;
+ r_ptr->d_attr = tmp;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'I' for "Info" (one line only) */
+ if (buf[0] == 'I')
+ {
+ int spd, hp1, hp2, aaf, ac, slp;
+
+ /* Scan for the other values */
+ if (6 != sscanf(buf + 2, "%d:%dd%d:%d:%d:%d",
+ &spd, &hp1, &hp2, &aaf, &ac, &slp)) return (1);
+
+ /* Save the values */
+ r_ptr->speed = spd;
+ r_ptr->hdice = hp1;
+ r_ptr->hside = hp2;
+ r_ptr->aaf = aaf;
+ r_ptr->ac = ac;
+ r_ptr->sleep = slp;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'E' for "Body Parts" (one line only) */
+ if (buf[0] == 'E')
+ {
+ int weap, tors, fing, head, arms, legs;
+
+ /* Scan for the other values */
+ if (BODY_MAX != sscanf(buf + 2, "%d:%d:%d:%d:%d:%d",
+ &weap, &tors, &arms, &fing, &head, &legs)) return (1);
+
+ /* Save the values */
+ r_ptr->body_parts[BODY_WEAPON] = weap;
+ r_ptr->body_parts[BODY_TORSO] = tors;
+ r_ptr->body_parts[BODY_ARMS] = arms;
+ r_ptr->body_parts[BODY_FINGER] = fing;
+ r_ptr->body_parts[BODY_HEAD] = head;
+ r_ptr->body_parts[BODY_LEGS] = legs;
+
+ /* Mega debugging hack */
+ if (weap > arms) quit(format("monster %d, %d weapon(s), %d arm(s) !", error_idx, weap, arms));
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'O' for "Object type" (one line only) */
+ if (buf[0] == 'O')
+ {
+ int treasure, combat, magic, tools;
+
+ /* Scan for the values */
+ if (4 != sscanf(buf + 2, "%d:%d:%d:%d",
+ &treasure, &combat, &magic, &tools)) return (1);
+
+ /* Save the values */
+ r_ptr->drops.treasure = treasure;
+ r_ptr->drops.combat = combat;
+ r_ptr->drops.magic = magic;
+ r_ptr->drops.tools = tools;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'A' for standard artifact drop (one line only) */
+ if (buf[0] == 'A')
+ {
+ int artifact_idx;
+ int artifact_chance;
+
+ /* Scan for values */
+ if (2 != sscanf(buf + 2, "%d:%d",
+ &artifact_idx,
+ &artifact_chance)) return (1);
+
+ /* Save the values */
+ r_ptr->artifact_idx = artifact_idx;
+ r_ptr->artifact_chance = artifact_chance;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'W' for "More Info" (one line only) */
+ if (buf[0] == 'W')
+ {
+ int lev, rar, wt;
+ long exp;
+
+ /* Scan for the values */
+ if (4 != sscanf(buf + 2, "%d:%d:%d:%ld",
+ &lev, &rar, &wt, &exp)) return (1);
+
+ /* Save the values */
+ r_ptr->level = lev;
+ r_ptr->rarity = rar;
+ /* MEGA HACK */
+ if (!wt) wt = 100;
+ r_ptr->weight = wt;
+ r_ptr->mexp = exp;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'B' for "Blows" (up to four lines) */
+ if (buf[0] == 'B')
+ {
+ int i, n1, n2;
+ char *s;
+ char *t;
+
+ /* Find the next empty blow slot (if any) */
+ for (i = 0; i < 4; i++) if (!r_ptr->blow[i].method) break;
+
+ /* Oops, no more slots */
+ if (i == 4) return (1);
+
+ /* Analyze the first field */
+ for (s = t = buf + 2; *t && (*t != ':'); t++) /* loop */;
+
+ /* Terminate the field (if necessary) */
+ if (*t == ':') *t++ = '\0';
+
+ /* Analyze the method */
+ for (n1 = 0; r_info_blow_method[n1]; n1++)
+ {
+ if (streq(s, r_info_blow_method[n1])) break;
+ }
+
+ /* Invalid method */
+ if (!r_info_blow_method[n1]) return (1);
+
+ /* Analyze the second field */
+ for (s = t; *t && (*t != ':'); t++) /* loop */;
+
+ /* Terminate the field (if necessary) */
+ if (*t == ':') *t++ = '\0';
+
+ /* Analyze effect */
+ for (n2 = 0; r_info_blow_effect[n2]; n2++)
+ {
+ if (streq(s, r_info_blow_effect[n2])) break;
+ }
+
+ /* Invalid effect */
+ if (!r_info_blow_effect[n2]) return (1);
+
+ /* Analyze the third field */
+ for (s = t; *t && (*t != 'd'); t++) /* loop */;
+
+ /* Terminate the field (if necessary) */
+ if (*t == 'd') *t++ = '\0';
+
+ /* Save the method */
+ r_ptr->blow[i].method = n1;
+
+ /* Save the effect */
+ r_ptr->blow[i].effect = n2;
+
+ /* Extract the damage dice and sides */
+ r_ptr->blow[i].d_dice = atoi(s);
+ r_ptr->blow[i].d_side = atoi(t);
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'F' for "Basic Flags" (multiple lines) */
+ if (buf[0] == 'F')
+ {
+ if (0 != grab_monster_race_flag(&r_ptr->flags, buf + 2))
+ {
+ return (5);
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'S' for "Spell Flags" (multiple lines) */
+ if (buf[0] == 'S')
+ {
+ char const *s = buf + 2;
+ int i;
+
+ /* XXX XXX XXX Hack -- Read spell frequency */
+ if (1 == sscanf(s, "1_IN_%d", &i))
+ {
+ /* Extract a "frequency" */
+ r_ptr->freq_spell = r_ptr->freq_inate = 100 / i;
+ }
+
+ /* Parse this entry */
+ else
+ {
+ if (0 != grab_one_monster_spell_flag(&r_ptr->spells, s))
+ {
+ return (5);
+ }
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Oops */
+ return (6);
+ }
+
+ /* Success */
+ return (0);
+}
+
+
+/*
+ * Initialize the "re_info" array, by parsing an ascii "template" file
+ */
+errr init_re_info_txt(FILE *fp)
+{
+ auto &re_info = game->edit_data.re_info;
+
+ char buf[1024];
+ byte blow_num = 0;
+ int r_char_number = 0;
+ int nr_char_number = 0;
+
+ /* Current entry */
+ monster_ego *re_ptr = NULL;
+
+
+ /* Just before the first record */
+ error_idx = -1;
+
+ /* Just before the first line */
+ error_line = -1;
+
+ /* Parse */
+ while (0 == my_fgets(fp, buf, 1024))
+ {
+ /* Advance the line number */
+ error_line++;
+
+ /* Skip comments and blank lines */
+ if (!buf[0] || (buf[0] == '#')) continue;
+
+ /* Verify correct "colon" format */
+ if (buf[1] != ':') return (1);
+
+ /* Process 'N' for "New/Number/Name" */
+ if (buf[0] == 'N')
+ {
+ /* Find the colon before the name */
+ char *s = strchr(buf + 2, ':');
+
+ /* Verify that colon */
+ if (!s) return (1);
+
+ /* Nuke the colon, advance to the name */
+ *s++ = '\0';
+
+ /* Paranoia -- require a name */
+ if (!*s) return (1);
+
+ /* Get the index */
+ int i = atoi(buf + 2);
+
+ /* Verify information */
+ if (i < error_idx) return (4);
+
+ /* Save the index */
+ error_idx = i;
+
+ /* Point at the "info" */
+ re_ptr = &expand_to_fit_index(re_info, i);
+
+ /* Copy name */
+ assert(!re_ptr->name);
+ re_ptr->name = my_strdup(s);
+
+ /* Some inits */
+ blow_num = 0;
+ r_char_number = 0;
+ nr_char_number = 0;
+
+ for (std::size_t j = 0; j < 4; j++)
+ {
+ re_ptr->blow[j].method = 0;
+ re_ptr->blow[j].effect = 0;
+ re_ptr->blow[j].d_dice = 0;
+ re_ptr->blow[j].d_side = 0;
+ re_ptr->blowm[j][0] = MEGO_ADD;
+ re_ptr->blowm[j][1] = MEGO_ADD;
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* There better be a current re_ptr */
+ if (!re_ptr) return (3);
+
+ /* Process 'G' for "Graphics" (one line only) */
+ if (buf[0] == 'G')
+ {
+ char sym;
+ int tmp;
+
+ /* Paranoia */
+ if (!buf[2]) return (1);
+ if (!buf[3]) return (1);
+ if (!buf[4]) return (1);
+
+ /* Extract the char */
+ if (buf[2] != '*') sym = buf[2];
+ else sym = MEGO_CHAR_ANY;
+
+ /* Extract the attr */
+ if (buf[4] != '*') tmp = color_char_to_attr(buf[4]);
+ else tmp = MEGO_CHAR_ANY;
+
+ /* Paranoia */
+ if (tmp < 0) return (1);
+
+ /* Save the values */
+ re_ptr->d_char = sym;
+ re_ptr->d_attr = tmp;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'I' for "Info" (one line only) */
+ if (buf[0] == 'I')
+ {
+ int spd, hp1, hp2, aaf, ac, slp;
+ char mspd, mhp1, mhp2, maaf, mac, mslp;
+
+ /* Scan for the other values */
+ if (12 != sscanf(buf + 2, "%c%d:%c%dd%c%d:%c%d:%c%d:%c%d",
+ &mspd, &spd, &mhp1, &hp1, &mhp2, &hp2, &maaf, &aaf, &mac, &ac, &mslp, &slp)) return (1);
+
+ /* Save the values */
+ re_ptr->speed = (spd << 2) + monster_ego_modify(mspd);
+ re_ptr->hdice = (hp1 << 2) + monster_ego_modify(mhp1);
+ re_ptr->hside = (hp2 << 2) + monster_ego_modify(mhp2);
+ re_ptr->aaf = (aaf << 2) + monster_ego_modify(maaf);
+ re_ptr->ac = (ac << 2) + monster_ego_modify(mac);
+ re_ptr->sleep = (slp << 2) + monster_ego_modify(mslp);
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'W' for "More Info" (one line only) */
+ if (buf[0] == 'W')
+ {
+ int lev, rar, wt;
+ char mlev, mwt, mexp, pos;
+ long exp;
+
+ /* Scan for the values */
+ if (8 != sscanf(buf + 2, "%c%d:%d:%c%d:%c%ld:%c",
+ &mlev, &lev, &rar, &mwt, &wt, &mexp, &exp, &pos)) return (1);
+
+ /* Save the values */
+ re_ptr->level = (lev << 2) + monster_ego_modify(mlev);
+ re_ptr->rarity = rar;
+ re_ptr->weight = (wt << 2) + monster_ego_modify(mwt);
+ re_ptr->mexp = (exp << 2) + monster_ego_modify(mexp);
+ re_ptr->before = (pos == 'B') ? TRUE : FALSE;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'B' for "Blows" (up to four lines) */
+ if (buf[0] == 'B')
+ {
+ int n1, n2, dice, side;
+ char mdice, mside;
+ char *s;
+ char *t;
+
+ /* Oops, no more slots */
+ if (blow_num == 4) return (1);
+
+ /* Analyze the first field */
+ for (s = t = buf + 2; *t && (*t != ':'); t++) /* loop */;
+
+ /* Terminate the field (if necessary) */
+ if (*t == ':') *t++ = '\0';
+
+ /* Analyze the method */
+ for (n1 = 0; r_info_blow_method[n1]; n1++)
+ {
+ if (streq(s, r_info_blow_method[n1])) break;
+ }
+
+ /* Invalid method */
+ if (!r_info_blow_method[n1]) return (1);
+
+ /* Analyze the second field */
+ for (s = t; *t && (*t != ':'); t++) /* loop */;
+
+ /* Terminate the field (if necessary) */
+ if (*t == ':') *t++ = '\0';
+
+ /* Analyze effect */
+ for (n2 = 0; r_info_blow_effect[n2]; n2++)
+ {
+ if (streq(s, r_info_blow_effect[n2])) break;
+ }
+
+ /* Invalid effect */
+ if (!r_info_blow_effect[n2]) return (1);
+
+ /* Save the method */
+ re_ptr->blow[blow_num].method = n1;
+
+ /* Save the effect */
+ re_ptr->blow[blow_num].effect = n2;
+
+ /* Extract the damage dice and sides */
+ if (4 != sscanf(t, "%c%dd%c%d",
+ &mdice, &dice, &mside, &side)) return (1);
+
+ re_ptr->blow[blow_num].d_dice = dice;
+ re_ptr->blow[blow_num].d_side = side;
+ re_ptr->blowm[blow_num][0] = monster_ego_modify(mdice);
+ re_ptr->blowm[blow_num][1] = monster_ego_modify(mside);
+ blow_num++;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'F' for "Flags monster must have" (multiple lines) */
+ if (buf[0] == 'F')
+ {
+ char r_char;
+
+ /* Parse every entry */
+ char const *s = buf + 2;
+
+ /* XXX XXX XXX Hack -- Read monster symbols */
+ if (1 == sscanf(s, "R_CHAR_%c", &r_char))
+ {
+ /* Limited to 5 races */
+ if (r_char_number >= 5) continue;
+
+ /* Extract a "frequency" */
+ re_ptr->r_char[r_char_number++] = r_char;
+ }
+
+ /* Parse this entry */
+ else {
+ if (0 != grab_monster_race_flag(&re_ptr->flags, s))
+ {
+ return (5);
+ }
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'H' for "Flags monster must not have" (multiple lines) */
+ if (buf[0] == 'H')
+ {
+ char r_char;
+
+ /* Parse every entry */
+ char const *s = buf + 2;
+
+ /* XXX XXX XXX Hack -- Read monster symbols */
+ if (1 == sscanf(s, "R_CHAR_%c", &r_char))
+ {
+ /* Limited to 5 races */
+ if (nr_char_number >= 5) continue;
+
+ /* Extract a "frequency" */
+ re_ptr->nr_char[nr_char_number++] = r_char;
+ }
+
+ /* Parse this entry */
+ else {
+ if (0 != grab_monster_race_flag(&re_ptr->hflags, s))
+ {
+ return (5);
+ }
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'M' for "Basic Monster Flags" (multiple lines) */
+ if (buf[0] == 'M')
+ {
+ if (0 != grab_monster_race_flag(&re_ptr->mflags, buf + 2))
+ {
+ return (5);
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'O' for "Basic Monster -Flags" (multiple lines) */
+ if (buf[0] == 'O')
+ {
+ char const *s = buf + 2;
+
+ /* XXX XXX XXX Hack -- Read no flags */
+ if (!strcmp(s, "MF_ALL"))
+ {
+ re_ptr->nflags = ~monster_race_flag_set();
+ }
+
+ /* Parse this entry */
+ else {
+ if (0 != grab_monster_race_flag(&re_ptr->nflags, s))
+ {
+ return (5);
+ }
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'S' for "Spell Flags" (multiple lines) */
+ if (buf[0] == 'S')
+ {
+ char const *s = buf + 2;
+ int i;
+
+ /* XXX XXX XXX Hack -- Read spell frequency */
+ if (1 == sscanf(s, "1_IN_%d", &i))
+ {
+ /* Extract a "frequency" */
+ re_ptr->freq_spell = re_ptr->freq_inate = 100 / i;
+ }
+
+ /* Parse this entry */
+ else {
+ if (0 != grab_one_monster_spell_flag(&re_ptr->mspells, s))
+ {
+ return (5);
+ }
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'T' for "Spell -Flags" (multiple lines) */
+ if (buf[0] == 'T')
+ {
+ /* Parse every entry */
+ for (char *s = buf + 2; *s; )
+ {
+ char *t;
+
+ /* Find the end of this entry */
+ for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
+
+ /* Nuke and skip any dividers */
+ if (*t)
+ {
+ *t++ = '\0';
+ while ((*t == ' ') || (*t == '|')) t++;
+ }
+
+ /* XXX XXX XXX Hack -- Read no flags */
+ if (!strcmp(s, "MF_ALL"))
+ {
+ /* No flags */
+ re_ptr->nspells = ~monster_spell_flag_set();
+
+ /* Start at next entry */
+ s = t;
+
+ /* Continue */
+ continue;
+ }
+
+ /* Parse this entry */
+ if (0 != grab_one_monster_spell_flag(&re_ptr->nspells, s)) return (5);
+
+ /* Start the next entry */
+ s = t;
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Oops */
+ return (6);
+ }
+
+ /* Success */
+ return (0);
+}
+
+
+/*
+ * Grab one flag for a dungeon type from a textual string
+ */
+errr grab_one_dungeon_flag(dungeon_flag_set *flags, const char *str)
+{
+#define DF(tier, index, name) \
+ if (streq(str, #name)) { *flags |= DF_##name; return 0; }
+#include "dungeon_flag_list.hpp"
+#undef DF
+
+ /* Oops */
+ msg_format("Unknown dungeon type flag '%s'.", str);
+
+ /* Failure */
+ return (1);
+}
+
+
+/*
+ * Initialize the "d_info" array, by parsing an ascii "template" file
+ */
+errr init_d_info_txt(FILE *fp)
+{
+ auto &d_info = game->edit_data.d_info;
+
+ char buf[1024];
+
+ s16b rule_num = 0;
+
+ byte r_char_number = 0;
+
+ /* Current entry */
+ dungeon_info_type *d_ptr = NULL;
+
+
+ /* Just before the first record */
+ error_idx = -1;
+
+ /* Just before the first line */
+ error_line = -1;
+
+ /* Parse */
+ while (0 == my_fgets(fp, buf, 1024))
+ {
+ /* Advance the line number */
+ error_line++;
+
+ /* Skip comments and blank lines */
+ if (!buf[0] || (buf[0] == '#')) continue;
+
+ /* Verify correct "colon" format */
+ if (buf[1] != ':') return (1);
+
+ /* Process 'N' for "New/Number/Name" */
+ if (buf[0] == 'N')
+ {
+ /* Find the colon before the name */
+ char *s = strchr(buf + 2, ':');
+
+ /* Verify that colon */
+ if (!s) return (1);
+
+ /* Nuke the colon, advance to the name */
+ *s++ = '\0';
+
+ /* Paranoia -- require a name */
+ if (!*s) return (1);
+
+ /* Get the index */
+ int i = atoi(buf + 2);
+
+ /* Verify information */
+ if (i < error_idx) return (4);
+
+ /* Save the index */
+ error_idx = i;
+
+ /* Point at the "info" */
+ d_ptr = &expand_to_fit_index(d_info, i);
+ assert(d_ptr->name.empty());
+
+ /* Copy name */
+ d_ptr->name = s;
+
+ /* HACK -- Those ones HAVE to have a set default value */
+ d_ptr->size_x = -1;
+ d_ptr->size_y = -1;
+ d_ptr->ix = -1;
+ d_ptr->iy = -1;
+ d_ptr->ox = -1;
+ d_ptr->oy = -1;
+ d_ptr->fill_method = 1;
+ rule_num = -1;
+ r_char_number = 0;
+ for (std::size_t j = 0; j < 5; j++)
+ {
+ d_ptr->rules[j].mode = DUNGEON_MODE_NONE;
+ d_ptr->rules[j].percent = 0;
+
+ for (std::size_t k = 0; k < 5; k++)
+ {
+ d_ptr->rules[j].r_char[k] = 0;
+ }
+ }
+
+ /* Set default drop theme */
+ d_ptr->objs = obj_theme::defaults();
+
+ /* The default generator */
+ d_ptr->generator = "dungeon";
+
+ /* Next... */
+ continue;
+ }
+
+ /* There better be a current d_ptr */
+ if (!d_ptr) return (3);
+
+ /* Process 'D' for "Description */
+ if (buf[0] == 'D')
+ {
+ /* Acquire short name */
+ d_ptr->short_name += buf[2];
+ d_ptr->short_name += buf[3];
+ d_ptr->short_name += buf[4];
+
+ /* Append to description */
+ d_ptr->text += (buf + 6);
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'W' for "More Info" (one line only) */
+ if (buf[0] == 'W')
+ {
+ int min_lev, max_lev;
+ int min_plev;
+ int min_alloc, max_chance;
+
+ /* Scan for the values */
+ if (5 != sscanf(buf + 2, "%d:%d:%d:%d:%d",
+ &min_lev, &max_lev, &min_plev, &min_alloc, &max_chance)) return (1);
+
+ /* Save the values */
+ d_ptr->mindepth = min_lev;
+ d_ptr->maxdepth = max_lev;
+ d_ptr->min_plev = min_plev;
+ d_ptr->min_m_alloc_level = min_alloc;
+ d_ptr->max_m_alloc_chance = max_chance;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'L' for "fLoor type" (one line only) */
+ if (buf[0] == 'L')
+ {
+ int f1, f2, f3;
+ int p1, p2, p3;
+ int i;
+
+ /* Scan for the values */
+ if (6 != sscanf(buf + 2, "%d:%d:%d:%d:%d:%d",
+ &f1, &p1, &f2, &p2, &f3, &p3))
+ {
+ /* Scan for the values - part ii*/
+ if (3 != sscanf(buf + 2, "%d:%d:%d", &p1, &p2,
+ &p3)) return (1);
+
+ /* Save the values */
+ d_ptr->floor_percent1[1] = p1;
+ d_ptr->floor_percent2[1] = p2;
+ d_ptr->floor_percent3[1] = p3;
+
+ continue;
+ }
+
+ /* Save the values */
+ d_ptr->floor1 = f1;
+ d_ptr->floor2 = f2;
+ d_ptr->floor3 = f3;
+
+ for (i = 0; i < 2; i++)
+ {
+ d_ptr->floor_percent1[i] = p1;
+ d_ptr->floor_percent2[i] = p2;
+ d_ptr->floor_percent3[i] = p3;
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'O' for "Object type" (one line only) */
+ if (buf[0] == 'O')
+ {
+ int treasure, combat, magic, tools;
+
+ /* Scan for the values */
+ if (4 != sscanf(buf + 2, "%d:%d:%d:%d",
+ &treasure, &combat, &magic, &tools)) return (1);
+
+ /* Save the values */
+ d_ptr->objs.treasure = treasure;
+ d_ptr->objs.combat = combat;
+ d_ptr->objs.magic = magic;
+ d_ptr->objs.tools = tools;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'G' for "Generator" (one line only) */
+ if (buf[0] == 'G')
+ {
+ d_ptr->generator = (buf + 2);
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'A' for "wAll type" (one line only) */
+ if (buf[0] == 'A')
+ {
+ int w1, w2, w3, outer, inner;
+ int p1, p2, p3;
+ int i;
+
+ /* Scan for the values */
+ if (8 != sscanf(buf + 2, "%d:%d:%d:%d:%d:%d:%d:%d",
+ &w1, &p1, &w2, &p2, &w3, &p3, &outer, &inner))
+ {
+ /* Scan for the values - part ii*/
+ if (3 != sscanf(buf + 2, "%d:%d:%d", &p1, &p2,
+ &p3)) return (1);
+
+ /* Save the values */
+ d_ptr->fill_percent1[1] = p1;
+ d_ptr->fill_percent2[1] = p2;
+ d_ptr->fill_percent3[1] = p3;
+ continue;
+ }
+
+ /* Save the values */
+ d_ptr->fill_type1 = w1;
+ d_ptr->fill_type2 = w2;
+ d_ptr->fill_type3 = w3;
+
+ for (i = 0; i < 2; i++)
+ {
+ d_ptr->fill_percent1[i] = p1;
+ d_ptr->fill_percent2[i] = p2;
+ d_ptr->fill_percent3[i] = p3;
+ }
+
+ d_ptr->outer_wall = outer;
+ d_ptr->inner_wall = inner;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'E' for "Effects" (up to four lines) -SC- */
+ if (buf[0] == 'E')
+ {
+ int side, dice, freq, type;
+ cptr tmp;
+
+ /* Find the next empty blow slot (if any) */
+ std::size_t i;
+ for (i = 0; i < 4; i++)
+ {
+ if ((!d_ptr->d_side[i]) &&
+ (!d_ptr->d_dice[i]))
+ {
+ break;
+ }
+ }
+
+ /* Oops, no more slots */
+ if (i == 4) return (1);
+
+ /* Scan for the values */
+ if (4 != sscanf(buf + 2, "%dd%d:%d:%d",
+ &dice, &side, &freq, &type))
+ {
+ int j;
+
+ if (3 != sscanf(buf + 2, "%dd%d:%d",
+ &dice, &side, &freq)) return (1);
+
+ tmp = buf + 2;
+ for (j = 0; j < 2; j++)
+ {
+ tmp = strchr(tmp, ':');
+ if (tmp == NULL) return (1);
+ tmp++;
+ }
+
+ j = 0;
+
+ while (d_info_dtypes[j].name != NULL)
+ if (strcmp(d_info_dtypes[j].name, tmp) == 0)
+ {
+ d_ptr->d_type[i] = d_info_dtypes[j].feat;
+ break;
+ }
+ else j++;
+
+ if (d_info_dtypes[j].name == NULL) return (1);
+ }
+ else
+ d_ptr->d_type[i] = type;
+
+ freq *= 10;
+ /* Save the values */
+ d_ptr->d_side[i] = side;
+ d_ptr->d_dice[i] = dice;
+ d_ptr->d_frequency[i] = freq;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'F' for "Dungeon Flags" (multiple lines) */
+ if (buf[0] == 'F')
+ {
+ int artif = 0, monst = 0, obj = 0;
+ int ix = -1, iy = -1, ox = -1, oy = -1;
+ int fill_method;
+
+ char const *s = buf + 2;
+
+ /* Read dungeon in/out coords */
+ if (4 == sscanf(s, "WILD_%d_%d__%d_%d", &ix, &iy, &ox, &oy))
+ {
+ d_ptr->ix = ix;
+ d_ptr->iy = iy;
+ d_ptr->ox = ox;
+ d_ptr->oy = oy;
+ }
+
+ /* Read dungeon size */
+ else if (2 == sscanf(s, "SIZE_%d_%d", &ix, &iy))
+ {
+ d_ptr->size_x = ix;
+ d_ptr->size_y = iy;
+ }
+
+ /* Read dungeon fill method */
+ else if (1 == sscanf(s, "FILL_METHOD_%d", &fill_method))
+ {
+ d_ptr->fill_method = fill_method;
+ }
+
+ /* Read Final Object */
+ else if (1 == sscanf(s, "FINAL_OBJECT_%d", &obj))
+ {
+ /* Extract a "Final Artifact" */
+ d_ptr->final_object = obj;
+ }
+
+ /* Read Final Artifact */
+ else if (1 == sscanf(s, "FINAL_ARTIFACT_%d", &artif ))
+ {
+ /* Extract a "Final Artifact" */
+ d_ptr->final_artifact = artif ;
+ }
+
+ /* Read Artifact Guardian */
+ else if (1 == sscanf(s, "FINAL_GUARDIAN_%d", &monst))
+ {
+ /* Extract a "Artifact Guardian" */
+ d_ptr->final_guardian = monst;
+ }
+
+ /* Parse this entry */
+ else {
+ if (0 != grab_one_dungeon_flag(&d_ptr->flags, s))
+ {
+ return (5);
+ }
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'R' for "monster generation Rule" (up to 5 lines) */
+ if (buf[0] == 'R')
+ {
+ int percent, mode;
+ int z, y, lims[5];
+
+ /* Scan for the values */
+ if (2 != sscanf(buf + 2, "%d:%d",
+ &percent, &mode)) return (1);
+
+ /* Save the values */
+ r_char_number = 0;
+ rule_num++;
+
+ d_ptr->rules[rule_num].percent = percent;
+ d_ptr->rules[rule_num].mode = mode;
+
+ /* Lets remap the flat percents */
+ lims[0] = d_ptr->rules[0].percent;
+ for (y = 1; y <= rule_num; y++)
+ {
+ lims[y] = lims[y - 1] + d_ptr->rules[y].percent;
+ }
+ for (z = 0; z < 100; z++)
+ {
+ for (y = rule_num; y >= 0; y--)
+ {
+ if (z < lims[y]) d_ptr->rule_percents[z] = y;
+ }
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'M' for "Basic Flags" (multiple lines) */
+ if (buf[0] == 'M')
+ {
+ byte r_char;
+ char const *s = buf + 2;
+
+ /* Read monster symbols */
+ if (1 == sscanf(s, "R_CHAR_%c", &r_char))
+ {
+ /* Limited to 5 races */
+ if (r_char_number >= 5) continue;
+
+ /* Extract a "frequency" */
+ d_ptr->rules[rule_num].r_char[r_char_number++] = r_char;
+ }
+
+ /* Parse this entry */
+ else {
+ if (0 != grab_monster_race_flag(&d_ptr->rules[rule_num].mflags, s))
+ {
+ return (5);
+ }
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'S' for "Spell Flags" (multiple lines) */
+ if (buf[0] == 'S')
+ {
+ char const *s = buf + 2;
+
+ /* Parse this entry */
+ if (0 != grab_one_monster_spell_flag(&d_ptr->rules[rule_num].mspells, s))
+ {
+ return (5);
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Oops */
+ return (6);
+ }
+
+ /* Success */
+ return (0);
+}
+
+/*
+ * Grab one race flag from a textual string
+ */
+static errr grab_one_race_flag(owner_type *ow_ptr, int state, cptr what)
+{
+ /* Scan race flags */
+ unknown_shut_up = TRUE;
+ if (!grab_one_race_allow_flag(ow_ptr->races[state], what))
+ {
+ unknown_shut_up = FALSE;
+ return (0);
+ }
+
+ /* Scan classes flags */
+ if (!grab_one_class_flag(ow_ptr->classes[state], what))
+ {
+ unknown_shut_up = FALSE;
+ return (0);
+ }
+
+ /* Oops */
+ unknown_shut_up = FALSE;
+ msg_format("Unknown race/class flag '%s'.", what);
+
+ /* Failure */
+ return (1);
+}
+
+/*
+ * Grab one store flag from a textual string
+ */
+static errr grab_one_store_flag(store_flag_set *flags, cptr what)
+{
+#define STF(tier, index, name) \
+ if (streq(what, #name)) { \
+ *flags |= BOOST_PP_CAT(STF_,name); \
+ return 0; \
+ }
+#include "store_flag_list.hpp"
+#undef STF
+
+ /* Oops */
+ msg_format("Unknown store flag '%s'.", what);
+
+ /* Failure */
+ return (1);
+}
+
+/*
+ * Initialize the "st_info" array, by parsing an ascii "template" file
+ */
+errr init_st_info_txt(FILE *fp)
+{
+ auto &st_info = game->edit_data.st_info;
+
+ char buf[1024];
+
+ /* Current entry */
+ store_info_type *st_ptr = NULL;
+
+
+ /* Just before the first record */
+ error_idx = -1;
+
+ /* Just before the first line */
+ error_line = -1;
+
+ /* Parse */
+ while (0 == my_fgets(fp, buf, 1024))
+ {
+ /* Advance the line number */
+ error_line++;
+
+ /* Skip comments and blank lines */
+ if (!buf[0] || (buf[0] == '#')) continue;
+
+ /* Verify correct "colon" format */
+ if (buf[1] != ':') return (1);
+
+ /* Process 'N' for "New/Number/Name" */
+ if (buf[0] == 'N')
+ {
+ /* Find the colon before the name */
+ char *s = strchr(buf + 2, ':');
+
+ /* Verify that colon */
+ if (!s) return (1);
+
+ /* Nuke the colon, advance to the name */
+ *s++ = '\0';
+
+ /* Paranoia -- require a name */
+ if (!*s) return (1);
+
+ /* Get the index */
+ int i = atoi(buf + 2);
+
+ /* Verify information */
+ if (i < error_idx) return (4);
+
+ /* Save the index */
+ error_idx = i;
+
+ /* Point at the "info" */
+ st_ptr = &expand_to_fit_index(st_info, i);
+ assert(st_ptr->name.empty());
+
+ /* Copy name */
+ st_ptr->name = s;
+
+ /* Next... */
+ continue;
+ }
+
+ /* There better be a current st_ptr */
+ if (!st_ptr) return (3);
+
+ /* Process 'I' for "Items" (multiple lines) */
+ if (buf[0] == 'I')
+ {
+ /* Find the colon before the name */
+ char *s = strchr(buf + 2, ':');
+
+ /* Verify that colon */
+ if (!s) return (1);
+
+ /* Nuke the colon, advance to the name */
+ *s++ = '\0';
+
+ /* Paranoia -- require a name */
+ if (!*s) return (1);
+
+ /* Add to items array */
+ store_item item;
+ item.chance = atoi(buf + 2);
+ item.kind = test_item_name(s);
+ st_ptr->items.emplace_back(item);
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'T' for "Tval/sval" */
+ if (buf[0] == 'T')
+ {
+ int tv1, sv1, rar1;
+
+ /* Scan for the values */
+ if (3 != sscanf(buf + 2, "%d:%d:%d",
+ &rar1, &tv1, &sv1)) return (1);
+
+ /* Add to the items array */
+ store_item item;
+ item.chance = rar1;
+ item.kind = (sv1 < 256)
+ ? lookup_kind(tv1, sv1)
+ : tv1 + 10000; /* An SVAL of 256 means all possible items. */
+ st_ptr->items.emplace_back(item);
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'G' for "Graphics" one line only) */
+ if (buf[0] == 'G')
+ {
+ char c, a;
+ int attr;
+
+ /* Scan for the values */
+ if (2 != sscanf(buf + 2, "%c:%c",
+ &c, &a)) return (1);
+
+ /* Extract the color */
+ attr = color_char_to_attr(a);
+
+ /* Paranoia */
+ if (attr < 0) return (1);
+
+ /* Save the values */
+ st_ptr->d_char = c;
+ st_ptr->d_attr = attr;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'A' for "Actions" (one line only) */
+ if (buf[0] == 'A')
+ {
+ int a1, a2, a3, a4, a5, a6;
+
+ /* Scan for the values */
+ if (6 != sscanf(buf + 2, "%d:%d:%d:%d:%d:%d",
+ &a1, &a2, &a3, &a4, &a5, &a6)) return (1);
+
+ /* Save the values */
+ st_ptr->actions.push_back(a1);
+ st_ptr->actions.push_back(a2);
+ st_ptr->actions.push_back(a3);
+ st_ptr->actions.push_back(a4);
+ st_ptr->actions.push_back(a5);
+ st_ptr->actions.push_back(a6);
+
+ /* Remove zero entries since they have no effect */
+ st_ptr->actions.erase(
+ std::remove(st_ptr->actions.begin(), st_ptr->actions.end(), 0),
+ st_ptr->actions.end()
+ );
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'F' for "store Flags" (multiple lines) */
+ if (buf[0] == 'F')
+ {
+ if (0 != grab_one_store_flag(&st_ptr->flags, buf + 2))
+ {
+ return (5);
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'O' for "Owners" (one line only) */
+ if (buf[0] == 'O')
+ {
+ int a1, a2, a3, a4;
+
+ /* Scan for the values */
+ if (4 != sscanf(buf + 2, "%d:%d:%d:%d",
+ &a1, &a2, &a3, &a4))
+ {
+ return 1;
+ }
+
+ /* Get a reference to the owners */
+ auto owners = &st_ptr->owners;
+
+ /* Save the values */
+ owners->push_back(a1);
+ owners->push_back(a2);
+ owners->push_back(a3);
+ owners->push_back(a4);
+
+ /* Sort and remove duplicates */
+ std::sort(owners->begin(), owners->end());
+ owners->erase(std::unique(owners->begin(), owners->end()), owners->end());
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'W' for "Extra info" (one line only) */
+ if (buf[0] == 'W')
+ {
+ int max_obj;
+
+ /* Scan for the values */
+ if (1 != sscanf(buf + 2, "%d",
+ &max_obj)) return (1);
+
+ /* Save the values */
+ if (max_obj > STORE_INVEN_MAX) max_obj = STORE_INVEN_MAX;
+ st_ptr->max_obj = max_obj;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Oops */
+ return (6);
+ }
+
+ /* Success */
+ return (0);
+}
+
+/*
+ * Initialize the "ba_info" array, by parsing an ascii "template" file
+ */
+errr init_ba_info_txt(FILE *fp)
+{
+ auto &ba_info = game->edit_data.ba_info;
+
+ char buf[1024];
+
+ /* Current entry */
+ store_action_type *ba_ptr = NULL;
+
+
+ /* Just before the first record */
+ error_idx = -1;
+
+ /* Just before the first line */
+ error_line = -1;
+
+ /* Parse */
+ while (0 == my_fgets(fp, buf, 1024))
+ {
+ /* Advance the line number */
+ error_line++;
+
+ /* Skip comments and blank lines */
+ if (!buf[0] || (buf[0] == '#')) continue;
+
+ /* Verify correct "colon" format */
+ if (buf[1] != ':') return (1);
+
+ /* Process 'N' for "New/Number/Name" */
+ if (buf[0] == 'N')
+ {
+ /* Find the colon before the name */
+ char *s = strchr(buf + 2, ':');
+
+ /* Verify that colon */
+ if (!s) return (1);
+
+ /* Nuke the colon, advance to the name */
+ *s++ = '\0';
+
+ /* Paranoia -- require a name */
+ if (!*s) return (1);
+
+ /* Get the index */
+ int i = atoi(buf + 2);
+
+ /* Verify information */
+ if (i < error_idx) return (4);
+
+ /* Save the index */
+ error_idx = i;
+
+ /* Point at the "info" */
+ ba_ptr = &expand_to_fit_index(ba_info, i);
+
+ /* Copy name */
+ ba_ptr->name = s;
+
+ /* Next... */
+ continue;
+ }
+
+ /* There better be a current ba_ptr */
+ if (!ba_ptr) return (3);
+
+ /* Process 'C' for "Costs" (one line only) */
+ if (buf[0] == 'C')
+ {
+ int ch, cn, cl;
+
+ /* Scan for the values */
+ if (3 != sscanf(buf + 2, "%d:%d:%d",
+ &ch, &cn, &cl)) return (1);
+
+ /* Save the values */
+ ba_ptr->costs[STORE_HATED] = ch;
+ ba_ptr->costs[STORE_NORMAL] = cn;
+ ba_ptr->costs[STORE_LIKED] = cl;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'I' for "Infos" (one line only) */
+ if (buf[0] == 'I')
+ {
+ int act, act_res;
+ char letter, letter_aux = 0;
+
+ /* Scan for the values */
+ if (4 != sscanf(buf + 2, "%d:%d:%c:%c", &act, &act_res, &letter, &letter_aux))
+ if (3 != sscanf(buf + 2, "%d:%d:%c", &act, &act_res, &letter))
+ return (1);
+
+ /* Save the values */
+ ba_ptr->action = act;
+ ba_ptr->action_restr = act_res;
+ ba_ptr->letter = letter;
+ ba_ptr->letter_aux = letter_aux;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Oops */
+ return (6);
+ }
+
+ /* Success */
+ return (0);
+}
+
+/*
+ * Initialize the "ow_info" array, by parsing an ascii "template" file
+ */
+errr init_ow_info_txt(FILE *fp)
+{
+ auto &ow_info = game->edit_data.ow_info;
+
+ char buf[1024];
+
+ /* Current entry */
+ owner_type *ow_ptr = NULL;
+
+ /* Just before the first record */
+ error_idx = -1;
+
+ /* Just before the first line */
+ error_line = -1;
+
+ /* Parse */
+ while (0 == my_fgets(fp, buf, 1024))
+ {
+ /* Advance the line number */
+ error_line++;
+
+ /* Skip comments and blank lines */
+ if (!buf[0] || (buf[0] == '#')) continue;
+
+ /* Verify correct "colon" format */
+ if (buf[1] != ':') return (1);
+
+ /* Process 'N' for "New/Number/Name" */
+ if (buf[0] == 'N')
+ {
+ /* Find the colon before the name */
+ char *s = strchr(buf + 2, ':');
+
+ /* Verify that colon */
+ if (!s) return (1);
+
+ /* Nuke the colon, advance to the name */
+ *s++ = '\0';
+
+ /* Paranoia -- require a name */
+ if (!*s) return (1);
+
+ /* Get the index */
+ int i = atoi(buf + 2);
+
+ /* Verify information */
+ if (i < error_idx) return (4);
+
+ /* Save the index */
+ error_idx = i;
+
+ /* Point at the "info" */
+ ow_ptr = &expand_to_fit_index(ow_info, i);
+
+ /* Copy name */
+ ow_ptr->name = s;
+
+ /* Next... */
+ continue;
+ }
+
+ /* There better be a current ow_ptr */
+ if (!ow_ptr) return (3);
+
+
+ /* Process 'C' for "Costs" (one line only) */
+ if (buf[0] == 'C')
+ {
+ int ch, cn, cl;
+
+ /* Scan for the values */
+ if (3 != sscanf(buf + 2, "%d:%d:%d",
+ &ch, &cn, &cl)) return (1);
+
+ /* Save the values */
+ ow_ptr->costs[STORE_HATED] = ch;
+ ow_ptr->costs[STORE_NORMAL] = cn;
+ ow_ptr->costs[STORE_LIKED] = cl;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'I' for "Info" (multiple lines line only) */
+ if (buf[0] == 'I')
+ {
+ int cost, inf;
+
+ /* Scan for the values */
+ if (2 != sscanf(buf + 2, "%d:%d",
+ &cost, &inf)) return (1);
+
+ /* Save the values */
+ ow_ptr->max_cost = cost;
+ ow_ptr->inflation = inf;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'L' for "Liked races/classes" (multiple lines) */
+ if (buf[0] == 'L')
+ {
+ if (0 != grab_one_race_flag(ow_ptr, STORE_LIKED, buf + 2))
+ {
+ return (5);
+ }
+
+ /* Next... */
+ continue;
+ }
+ /* Process 'H' for "Hated races/classes" (multiple lines) */
+ if (buf[0] == 'H')
+ {
+ if (0 != grab_one_race_flag(ow_ptr, STORE_HATED, buf + 2))
+ {
+ return (5);
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Oops */
+ return (6);
+ }
+
+ /* Success */
+ return (0);
+}
+
+/*
+ * Initialize the "wf_info" array, by parsing an ascii "template" file
+ */
+errr init_wf_info_txt(FILE *fp)
+{
+ auto &wf_info = game->edit_data.wf_info;
+
+ char buf[1024];
+
+ /* Current entry */
+ wilderness_type_info *wf_ptr = NULL;
+
+ /* Just before the first record */
+ error_idx = -1;
+
+ /* Just before the first line */
+ error_line = -1;
+
+ /* Parse */
+ while (0 == my_fgets(fp, buf, 1024))
+ {
+ /* Advance the line number */
+ error_line++;
+
+ /* Skip comments and blank lines */
+ if (!buf[0] || (buf[0] == '#')) continue;
+
+ /* Verify correct "colon" format */
+ if (buf[1] != ':') return (1);
+
+ /* Process 'N' for "New/Number/Name" */
+ if (buf[0] == 'N')
+ {
+ /* Find the colon before the name */
+ char *s = strchr(buf + 2, ':');
+
+ /* Verify that colon */
+ if (!s) return (1);
+
+ /* Nuke the colon, advance to the name */
+ *s++ = '\0';
+
+ /* Paranoia -- require a name */
+ if (!*s) return (1);
+
+ /* Get the index */
+ int i = atoi(buf + 2);
+
+ /* Verify information */
+ if (i < error_idx) return (4);
+
+ /* Save the index */
+ error_idx = i;
+
+ /* Point at the "info" */
+ wf_ptr = &expand_to_fit_index(wf_info, i);
+
+ /* Copy the name */
+ assert(!wf_ptr->name);
+ wf_ptr->name = my_strdup(s);
+
+ /* Next... */
+ continue;
+ }
+
+ /* There better be a current wf_ptr */
+ if (!wf_ptr) return (3);
+
+ /* Process 'D' for "Description (one line only) */
+ if (buf[0] == 'D')
+ {
+ /* Acquire the text */
+ char *s = buf + 2;
+
+ /* Copy description */
+ assert(!wf_ptr->text);
+ wf_ptr->text = my_strdup(s);
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'W' for "More Info" (one line only) */
+ if (buf[0] == 'W')
+ {
+ int entrance, level;
+ int road, feat, ter_idx;
+ char car;
+
+ /* Scan for the values */
+ if (6 != sscanf(buf + 2, "%d:%d:%d:%d:%d:%c",
+ &level, &entrance, &road, &feat, &ter_idx, &car)) return (1);
+
+ /* Save the values */
+ wf_ptr->level = level;
+ wf_ptr->entrance = entrance;
+ wf_ptr->road = road;
+ wf_ptr->feat = feat;
+ wf_ptr->terrain_idx = ter_idx;
+
+ /* To acces it easily from the map structure */
+ wildc2i[(int)car] = error_idx;
+
+ /* Next... */
+ continue;
+ }
+
+ /* Process 'X' for "More Info" (one line only) */
+ if (buf[0] == 'X')
+ {
+ int terrain[MAX_WILD_TERRAIN], i;
+
+ /* Scan for the values */
+ if (MAX_WILD_TERRAIN != sscanf(buf + 2, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
+ &terrain[0], &terrain[1], &terrain[2],
+ &terrain[3], &terrain[4], &terrain[5],
+ &terrain[6], &terrain[7], &terrain[8],
+ &terrain[9], &terrain[10], &terrain[11],
+ &terrain[12], &terrain[13], &terrain[14],
+ &terrain[15], &terrain[16], &terrain[17])) return (1);
+
+ /* Save the values */
+ for (i = 0; i < MAX_WILD_TERRAIN; i++)
+ {
+ wf_ptr->terrain[i] = terrain[i];
+ }
+
+ /* Next... */
+ continue;
+ }
+
+ /* Oops */
+ return (6);
+ }
+
+ /* Success */
+ return (0);
+}
+
+
+/* Random dungeon grid effects */
+#define RANDOM_NONE 0x00
+#define RANDOM_FEATURE 0x01
+#define RANDOM_MONSTER 0x02
+#define RANDOM_OBJECT 0x04
+#define RANDOM_EGO 0x08
+#define RANDOM_ARTIFACT 0x10
+
+
+typedef struct dungeon_grid dungeon_grid;
+
+struct dungeon_grid
+{
+ int feature; /* Terrain feature */
+ int monster; /* Monster */
+ int object; /* Object */
+ int ego; /* Ego-Item */
+ int artifact; /* Artifact */
+ int cave_info; /* Flags for CAVE_MARK, CAVE_GLOW, CAVE_ICKY, CAVE_ROOM */
+ int special; /* Reserved for special terrain info */
+ int random; /* Number of the random effect */
+ int bx, by; /* For between gates */
+ int mimic; /* Mimiced features */
+ s32b mflag; /* monster's mflag */
+ bool_ ok;
+ bool_ defined;
+};
+static bool_ meta_sleep = TRUE;
+
+static dungeon_grid letter[255];
+
+/*
+ * Parse a sub-file of the "extra info"
+ */
+static errr process_dungeon_file_aux(char *buf, int *yval, int *xval, int xvalstart, int ymax, int xmax, bool_ full)
+{
+ auto &wilderness = game->wilderness;
+ auto &wf_info = game->edit_data.wf_info;
+ auto &a_info = game->edit_data.a_info;
+
+ int i;
+
+ char *zz[33];
+
+
+ /* 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 "%:<fname>" */
+ if (buf[0] == '%')
+ {
+ /* Attempt to Process the given file */
+ return (process_dungeon_file(buf + 2, yval, xval, ymax, xmax, FALSE, full));
+ }
+
+ /* Process "N:<sleep>" */
+ if (buf[0] == 'N')
+ {
+ int num;
+
+ if ((num = tokenize(buf + 2, 1, zz, ':', '/')) > 0)
+ {
+ meta_sleep = atoi(zz[0]);
+ }
+
+ return (0);
+ }
+
+ /* Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<special>:<mimic>:<mflag>" -- info for dungeon grid */
+ if (buf[0] == 'F')
+ {
+ int num;
+
+ if ((num = tokenize(buf + 2, 10, zz, ':', '/')) > 1)
+ {
+ int index = zz[0][0];
+
+ /* Reset the feature */
+ letter[index].feature = 0;
+ letter[index].monster = 0;
+ letter[index].object = 0;
+ letter[index].ego = 0;
+ letter[index].artifact = 0;
+ letter[index].cave_info = 0;
+ letter[index].special = 0;
+ letter[index].random = 0;
+ letter[index].mimic = 0;
+ letter[index].mflag = 0;
+ letter[index].ok = TRUE;
+ letter[index].defined = TRUE;
+
+ if (num > 1)
+ {
+ if (zz[1][0] == '*')
+ {
+ letter[index].random |= RANDOM_FEATURE;
+ if (zz[1][1])
+ {
+ zz[1]++;
+ letter[index].feature = atoi(zz[1]);
+ }
+ }
+ else
+ {
+ letter[index].feature = atoi(zz[1]);
+ }
+ }
+
+ if (num > 2)
+ letter[index].cave_info = atoi(zz[2]);
+
+ /* Monster */
+ if (num > 3)
+ {
+ if (zz[3][0] == '*')
+ {
+ letter[index].random |= RANDOM_MONSTER;
+ if (zz[3][1])
+ {
+ zz[3]++;
+ letter[index].monster = atoi(zz[3]);
+ }
+ }
+ else
+ {
+ letter[index].monster = atoi(zz[3]);
+ }
+ }
+
+ /* Object */
+ if (num > 4)
+ {
+ if (zz[4][0] == '*')
+ {
+ letter[index].random |= RANDOM_OBJECT;
+
+ if (zz[4][1])
+ {
+ zz[4]++;
+ letter[index].object = atoi(zz[4]);
+ }
+ }
+ else
+ {
+ letter[index].object = atoi(zz[4]);
+ }
+ }
+
+ /* Ego-Item */
+ if (num > 5)
+ {
+ if (zz[5][0] == '*')
+ {
+ letter[index].random |= RANDOM_EGO;
+
+ if (zz[5][1])
+ {
+ zz[5]++;
+ letter[index].ego = atoi(zz[5]);
+ }
+ }
+ else
+ {
+ letter[index].ego = atoi(zz[5]);
+ }
+ }
+
+ /* Artifact */
+ if (num > 6)
+ {
+ if (zz[6][0] == '*')
+ {
+ letter[index].random |= RANDOM_ARTIFACT;
+
+ if (zz[6][1])
+ {
+ zz[6]++;
+ letter[index].artifact = atoi(zz[6]);
+ }
+ }
+ else
+ {
+ letter[index].artifact = atoi(zz[6]);
+ }
+ }
+
+ if (num > 7)
+ {
+ char *field = zz[7];
+ /* Quests can be defined by name only */
+ if (field[0] == '"')
+ {
+ /* Hunt & shoot the ending " */
+ int i = strlen(field) - 1;
+ if (field[i] == '"') field[i] = '\0';
+ letter[index].special = 0;
+ for (i = 0; i < MAX_Q_IDX; i++)
+ {
+ if (!strcmp(&field[1], quest[i].name))
+ {
+ letter[index].special = i;
+ break;
+ }
+ }
+ }
+ else
+ letter[index].special = atoi(field);
+ }
+
+ if (num > 8)
+ {
+ letter[index].mimic = atoi(zz[8]);
+ }
+
+ if (num > 9)
+ {
+ letter[index].mflag = atoi(zz[9]);
+ }
+
+ return (0);
+ }
+ }
+
+ /* Process "f:flags" -- level flags */
+ else if (buf[0] == 'f')
+ {
+ char *s, *t;
+
+ /* Parse every entry textually */
+ for (s = buf + 2; *s; )
+ {
+ /* Find the end of this entry */
+ for (t = s; *t && (*t != ' ') && (*t != '|'); ++t) /* loop */;
+
+ /* Nuke and skip any dividers */
+ if (*t)
+ {
+ *t++ = '\0';
+ while (*t == ' ' || *t == '|') t++;
+ }
+
+ /* Parse this entry */
+ if (0 != grab_one_dungeon_flag(&dungeon_flags, s)) return 1;
+
+ /* Start the next entry */
+ s = t;
+ }
+
+ return 0;
+ }
+
+ /* Process "D:<dungeon>" -- info for the cave grids */
+ else if (buf[0] == 'D')
+ {
+ int x, m_idx = 0;
+
+ object_type object_type_body;
+
+ /* Acquire the text */
+ char *s = buf + 2;
+
+ /* Length of the text */
+ int len = strlen(s);
+
+ int y = *yval;
+ *xval = xvalstart;
+ for (x = *xval, i = 0; ((x < xmax) && (i < len)); x++, s++, i++)
+ {
+ /* Access the grid */
+ cave_type *c_ptr = &cave[y][x];
+
+ int idx = s[0];
+
+ int object_index = letter[idx].object;
+ int monster_index = letter[idx].monster;
+ int random = letter[idx].random;
+ int artifact_index = letter[idx].artifact;
+
+ if (!letter[idx].ok) msg_format("Warning '%c' not defined but used.", idx);
+
+ if (init_flags & INIT_GET_SIZE) continue;
+
+ /* use the plasma generator wilderness */
+ if (((!dun_level) || (!letter[idx].defined)) && (idx == ' ')) continue;
+
+ /* Clear some info */
+ c_ptr->info = 0;
+
+ /* Lay down a floor */
+ c_ptr->mimic = letter[idx].mimic;
+ cave_set_feat(y, x, letter[idx].feature);
+
+ /* Cave info */
+ c_ptr->info |= letter[idx].cave_info;
+
+ /* Create a monster */
+ if (random & RANDOM_MONSTER)
+ {
+ int level = monster_level;
+
+ monster_level = quest[p_ptr->inside_quest].level + monster_index;
+
+ m_idx = place_monster(y, x, meta_sleep, FALSE);
+
+ monster_level = level;
+ }
+ else if (monster_index)
+ {
+ /* Place it */
+ m_allow_special[monster_index] = TRUE;
+ m_idx = place_monster_aux(y, x, monster_index, meta_sleep, FALSE, MSTATUS_ENEMY);
+ m_allow_special[monster_index] = FALSE;
+ }
+
+ /* Set the mflag of the monster */
+ if (m_idx) m_list[m_idx].mflag |= letter[idx].mflag;
+
+ /* Object (and possible trap) */
+ if (random & RANDOM_OBJECT)
+ {
+ /* Create an out of deep object */
+ if (object_index)
+ {
+ int level = object_level;
+
+ object_level = quest[p_ptr->inside_quest].level + object_index;
+ if (rand_int(100) < 75)
+ place_object(y, x, FALSE, FALSE, OBJ_FOUND_SPECIAL);
+ else if (rand_int(100) < 80)
+ place_object(y, x, TRUE, FALSE, OBJ_FOUND_SPECIAL);
+ else
+ place_object(y, x, TRUE, TRUE, OBJ_FOUND_SPECIAL);
+
+ object_level = level;
+ }
+ else if (rand_int(100) < 75)
+ {
+ place_object(y, x, FALSE, FALSE, OBJ_FOUND_SPECIAL);
+ }
+ else if (rand_int(100) < 80)
+ {
+ place_object(y, x, TRUE, FALSE, OBJ_FOUND_SPECIAL);
+ }
+ else
+ {
+ place_object(y, x, TRUE, TRUE, OBJ_FOUND_SPECIAL);
+ }
+ }
+ else if (object_index)
+ {
+ /* Get local object */
+ object_type *o_ptr = &object_type_body;
+
+ k_allow_special[object_index] = TRUE;
+
+ /* Create the item */
+ object_prep(o_ptr, object_index);
+
+ /* Apply magic (no messages, no artifacts) */
+ apply_magic(o_ptr, dun_level, FALSE, TRUE, FALSE);
+
+ o_ptr->found = OBJ_FOUND_SPECIAL;
+
+ k_allow_special[object_index] = FALSE;
+
+ drop_near(o_ptr, -1, y, x);
+ }
+
+ /* Artifact */
+ if (artifact_index)
+ {
+ int I_kind = 0;
+
+ auto a_ptr = &a_info[artifact_index];
+
+ /* Get local object */
+ object_type forge;
+ object_type *q_ptr = &forge;
+
+ a_allow_special[artifact_index] = TRUE;
+
+ /* Wipe the object */
+ object_wipe(q_ptr);
+
+ /* Acquire the "kind" index */
+ I_kind = lookup_kind(a_ptr->tval, a_ptr->sval);
+
+ /* Create the artifact */
+ object_prep(q_ptr, I_kind);
+
+ /* Save the name */
+ q_ptr->name1 = artifact_index;
+
+ /* Extract the fields */
+ q_ptr->pval = a_ptr->pval;
+ q_ptr->ac = a_ptr->ac;
+ q_ptr->dd = a_ptr->dd;
+ q_ptr->ds = a_ptr->ds;
+ q_ptr->to_a = a_ptr->to_a;
+ q_ptr->to_h = a_ptr->to_h;
+ q_ptr->to_d = a_ptr->to_d;
+ q_ptr->weight = a_ptr->weight;
+ q_ptr->found = OBJ_FOUND_SPECIAL;
+
+ random_artifact_resistance(q_ptr);
+
+ a_info[artifact_index].cur_num = 1;
+
+ a_allow_special[artifact_index] = FALSE;
+
+ /* It's amazing that this "creating objects anywhere"
+ junk ever worked.
+ Let's just HACK around one observed bug: Shadow Cloak
+ of Luthien [Globe of Light] */
+ {
+ auto const flags = object_flags(q_ptr);
+ if (flags & TR_SPELL_CONTAIN)
+ {
+ q_ptr->pval2 = -1;
+ }
+ }
+
+ /* Drop the artifact */
+ drop_near(q_ptr, -1, y, x);
+
+ }
+
+ /* Terrain special */
+ if (letter[idx].special == -1)
+ {
+ if (!letter[idx].bx)
+ {
+ letter[idx].bx = x;
+ letter[idx].by = y;
+ }
+ else
+ {
+ c_ptr->special = (letter[idx].by << 8) + letter[idx].bx;
+ cave[letter[idx].by][letter[idx].bx].special = (y << 8) + x;
+ }
+ }
+ else
+ {
+ c_ptr->special = letter[idx].special;
+ }
+ }
+ if (full && (*xval < x)) *xval = x;
+ (*yval)++;
+
+ return (0);
+ }
+
+ /* Process "W:<command>: ..." -- info for the wilderness */
+ else if (buf[0] == 'W')
+ {
+ /* Process "W:D:<layout> */
+ /* Layout of the wilderness */
+ if (buf[2] == 'D')
+ {
+ /* Acquire the text */
+ char *s = buf + 4;
+
+ int y = *yval;
+
+ for (std::size_t x = 0; x < wilderness.width(); x++)
+ {
+ char i;
+ if (1 != sscanf(s + x, "%c", &i))
+ {
+ return (1);
+ }
+
+ auto const wi = wildc2i[(int)i];
+
+ wilderness(x, y).feat = wi;
+
+ /*
+ * If this is a town/dungeon entrance, note
+ * its coordinates. (Have to check for
+ * duplicate Morias...)
+ */
+ if (wf_info[wi].entrance && wf_info[wi].wild_x == 0)
+ {
+ wf_info[wi].wild_x = x;
+ wf_info[wi].wild_y = y;
+ }
+ }
+
+ (*yval)++;
+
+ return (0);
+ }
+ /* Process "M:<plus>:<line>" -- move line lines */
+ else if (buf[2] == 'M')
+ {
+ if (tokenize(buf + 4, 2, zz, ':', '/') == 2)
+ {
+ if (atoi(zz[0]))
+ {
+ (*yval) += atoi(zz[1]);
+ }
+ else
+ {
+ (*yval) -= atoi(zz[1]);
+ }
+ }
+ else
+ {
+ return (1);
+ }
+ return (0);
+ }
+ /* Process "W:P:<x>:<y> - starting position in the wilderness */
+ else if (buf[2] == 'P')
+ {
+ if ((p_ptr->wilderness_x == 0) &&
+ (p_ptr->wilderness_y == 0))
+ {
+ if (tokenize(buf + 4, 2, zz, ':', '/') == 2)
+ {
+ p_ptr->wilderness_x = atoi(zz[0]);
+ p_ptr->wilderness_y = atoi(zz[1]);
+ }
+ else
+ {
+ return (1);
+ }
+ }
+
+ return (0);
+ }
+ /* Process "W:E:<dungeon>:<y>:<x> - entrance to the dungeon <dungeon> */
+ else if (buf[2] == 'E')
+ {
+ if (tokenize(buf + 4, 3, zz, ':', '/') == 3)
+ {
+ int y = atoi(zz[1]);
+ int x = atoi(zz[2]);
+ wilderness(x, y).entrance = 1000 + atoi(zz[0]);
+ }
+ else
+ {
+ return (1);
+ }
+
+ return (0);
+ }
+ }
+
+ /* Process "P:<y>:<x>" -- player position */
+ else if (buf[0] == 'P')
+ {
+ if (init_flags & INIT_CREATE_DUNGEON)
+ {
+ if (tokenize(buf + 2, 2, zz, ':', '/') == 2)
+ {
+ /* Place player in a quest level */
+ if (p_ptr->inside_quest || (init_flags & INIT_POSITION))
+ {
+ p_ptr->py = atoi(zz[0]);
+ p_ptr->px = atoi(zz[1]);
+ }
+ /* Place player in the town */
+ else if ((p_ptr->oldpx == 0) && (p_ptr->oldpy == 0))
+ {
+ p_ptr->oldpy = atoi(zz[0]);
+ p_ptr->oldpx = atoi(zz[1]);
+ }
+ }
+ }
+
+ return (0);
+ }
+
+ /* Process "M:<type>:<maximum>" -- set maximum values */
+ else if (buf[0] == 'M')
+ {
+ if (tokenize(buf + 2, 3, zz, ':', '/') >= 2)
+ {
+ /* Maximum towns */
+ if (zz[0][0] == 'T')
+ {
+ max_towns = atoi(zz[1]);
+ }
+
+ /* Maximum real towns */
+ if (zz[0][0] == 't')
+ {
+ max_real_towns = atoi(zz[1]);
+ }
+
+ /* Maximum o_idx */
+ else if (zz[0][0] == 'O')
+ {
+ max_o_idx = atoi(zz[1]);
+ }
+
+ /* Maximum m_idx */
+ else if (zz[0][0] == 'M')
+ {
+ max_m_idx = atoi(zz[1]);
+ }
+
+ /* Maximum wilderness x size */
+ else if (zz[0][0] == 'X')
+ {
+ wilderness.width(atoi(zz[1]));
+ }
+
+ /* Maximum wilderness y size */
+ else if (zz[0][0] == 'Y')
+ {
+ wilderness.height(atoi(zz[1]));
+ }
+
+ return (0);
+ }
+ }
+
+ /* Failure */
+ return (1);
+}
+
+
+
+
+/*
+ * Helper function for "process_dungeon_file()"
+ */
+static cptr process_dungeon_file_expr(char **sp, char *fp)
+{
+ static char pref_tmp_value[8];
+ cptr v;
+
+ char *b;
+ char *s;
+
+ char b1 = '[';
+ char b2 = ']';
+
+ char f = ' ';
+
+ /* Initial */
+ s = (*sp);
+
+ /* Skip spaces */
+ while (isspace(*s)) s++;
+
+ /* Save start */
+ b = s;
+
+ /* Default */
+ v = "?o?o?";
+
+ /* Analyze */
+ if (*s == b1)
+ {
+ const char *p;
+ const char *t;
+
+ /* Skip b1 */
+ s++;
+
+ /* First */
+ t = process_dungeon_file_expr(&s, &f);
+
+ /* Oops */
+ if (!*t)
+ {
+ /* Nothing */
+ }
+
+ /* Function: IOR */
+ else if (streq(t, "IOR"))
+ {
+ v = "0";
+ while (*s && (f != b2))
+ {
+ t = process_dungeon_file_expr(&s, &f);
+ if (*t && !streq(t, "0")) v = "1";
+ }
+ }
+
+ /* Function: AND */
+ else if (streq(t, "AND"))
+ {
+ v = "1";
+ while (*s && (f != b2))
+ {
+ t = process_dungeon_file_expr(&s, &f);
+ if (*t && streq(t, "0")) v = "0";
+ }
+ }
+
+ /* Function: NOT */
+ else if (streq(t, "NOT"))
+ {
+ v = "1";
+ while (*s && (f != b2))
+ {
+ t = process_dungeon_file_expr(&s, &f);
+ if (*t && streq(t, "1")) v = "0";
+ }
+ }
+
+ /* Function: EQU */
+ else if (streq(t, "EQU"))
+ {
+ v = "1";
+ if (*s && (f != b2))
+ {
+ t = process_dungeon_file_expr(&s, &f);
+ }
+ while (*s && (f != b2))
+ {
+ p = t;
+ t = process_dungeon_file_expr(&s, &f);
+ if (*t && !streq(p, t)) v = "0";
+ }
+ }
+
+ /* Function: LEQ */
+ else if (streq(t, "LEQ"))
+ {
+ v = "1";
+ if (*s && (f != b2))
+ {
+ t = process_dungeon_file_expr(&s, &f);
+ }
+ while (*s && (f != b2))
+ {
+ p = t;
+ t = process_dungeon_file_expr(&s, &f);
+ if (*t && (strcmp(p, t) > 0)) v = "0";
+ }
+ }
+
+ /* Function: GEQ */
+ else if (streq(t, "GEQ"))
+ {
+ v = "1";
+ if (*s && (f != b2))
+ {
+ t = process_dungeon_file_expr(&s, &f);
+ }
+ while (*s && (f != b2))
+ {
+ p = t;
+ t = process_dungeon_file_expr(&s, &f);
+ if (*t && (strcmp(p, t) < 0)) v = "0";
+ }
+ }
+
+ /* Oops */
+ else
+ {
+ while (*s && (f != b2))
+ {
+ t = process_dungeon_file_expr(&s, &f);
+ }
+ }
+
+ /* Verify ending */
+ if (f != b2) v = "?x?x?";
+
+ /* Extract final and Terminate */
+ if ((f = *s) != '\0') * s++ = '\0';
+ }
+
+ /* Other */
+ else
+ {
+ bool_ text_mode = FALSE;
+
+ /* Accept all printables except spaces and brackets */
+ while (isprint(*s))
+ {
+ if (*s == '"') text_mode = !text_mode;
+ if (!text_mode)
+ {
+ if (strchr(" []", *s))
+ break;
+ }
+ else
+ {
+ if (strchr("[]", *s))
+ break;
+ }
+
+ ++s;
+ }
+
+ /* Extract final and Terminate */
+ if ((f = *s) != '\0') * s++ = '\0';
+
+ /* Variable */
+ if (*b == '$')
+ {
+ /* System */
+ if (streq(b + 1, "SYS"))
+ {
+ v = ANGBAND_SYS;
+ }
+
+ /* Race */
+ else if (streq(b + 1, "RACE"))
+ {
+ v = rp_ptr->title.c_str(); // The string SHOULD be stable enough for this
+ }
+
+ /* Race Mod */
+ else if (streq(b + 1, "RACEMOD"))
+ {
+ v = rmp_ptr->title.c_str(); // The string SHOULD be stable enough for this
+ }
+
+ /* Class */
+ else if (streq(b + 1, "CLASS"))
+ {
+ v = cp_ptr->title.c_str(); // The string SHOULD be stable enough for this
+ }
+
+ /* Player */
+ else if (streq(b + 1, "PLAYER"))
+ {
+ v = game->player_base.c_str(); // The string SHOULD be stable enough for this
+ }
+
+ /* Town */
+ else if (streq(b + 1, "TOWN"))
+ {
+ strnfmt(pref_tmp_value, 8, "%d", p_ptr->town_num);
+ v = pref_tmp_value;
+ }
+
+ /* Town destroyed */
+ else if (prefix(b + 1, "TOWN_DESTROY"))
+ {
+ strnfmt(pref_tmp_value, 8, "%d", town_info[atoi(b + 13)].destroyed);
+ v = pref_tmp_value;
+ }
+
+ /* Current quest number */
+ else if (streq(b + 1, "QUEST_NUMBER"))
+ {
+ strnfmt(pref_tmp_value, 8, "%d", p_ptr->inside_quest);
+ v = pref_tmp_value;
+ }
+
+ /* Number of last quest */
+ else if (streq(b + 1, "LEAVING_QUEST"))
+ {
+ strnfmt(pref_tmp_value, 8, "%d", leaving_quest);
+ v = pref_tmp_value;
+ }
+
+ /* DAYTIME status */
+ else if (prefix(b + 1, "DAYTIME"))
+ {
+ if ((bst(HOUR, turn) >= 6) && (bst(HOUR, turn) < 18))
+ v = "1";
+ else
+ v = "0";
+ }
+
+ /* Quest status */
+ else if (prefix(b + 1, "QUEST"))
+ {
+ /* "QUEST" uses a special parameter to determine the number of the quest */
+ if (*(b + 6) != '"')
+ strnfmt(pref_tmp_value, 8, "%d", quest[atoi(b + 6)].status);
+ else
+ {
+ char c[80];
+ int i;
+
+ /* Copy it to temp array, so that we can modify it safely */
+ strcpy(c, b + 7);
+
+ /* Hunt & shoot the ending " */
+ 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++)
+ {
+ if (streq(c, quest[i].name))
+ {
+ strnfmt(pref_tmp_value, 8, "%d", quest[i].status);
+ break;
+ }
+ }
+ }
+ v = pref_tmp_value;
+ }
+
+ /* Variant name */
+ else if (streq(b + 1, "VARIANT"))
+ {
+ v = "ToME";
+ }
+
+ /* Wilderness */
+ else if (streq(b + 1, "WILDERNESS"))
+ {
+ v = "NORMAL";
+ }
+ }
+
+ /* Constant */
+ else
+ {
+ v = b;
+ }
+ }
+
+ /* Save */
+ (*fp) = f;
+
+ /* Save */
+ (*sp) = s;
+
+ /* Result */
+ return (v);
+}
+
+
+errr process_dungeon_file(cptr name, int *yval, int *xval, int ymax, int xmax, bool_ init, bool_ full)
+{
+ FILE *fp = 0;
+
+ char buf[1024];
+
+ int num = -1, i;
+
+ errr err = 0;
+
+ bool_ bypass = FALSE;
+
+ /* Save the start since it ought to be modified */
+ int xmin = *xval;
+
+ if (init)
+ {
+ meta_sleep = TRUE;
+ for (i = 0; i < 255; i++)
+ {
+ letter[i].defined = FALSE;
+ if (i == ' ') letter[i].ok = TRUE;
+ else letter[i].ok = FALSE;
+ letter[i].bx = 0;
+ letter[i].by = 0;
+ }
+ }
+
+ /* Build the filename */
+ path_build(buf, 1024, ANGBAND_DIR_EDIT, name);
+
+ /* Open the file */
+ fp = my_fopen(buf, "r");
+
+ /* No such file */
+ if (!fp)
+ {
+ msg_format("Cannot find file %s at %s", name, buf);
+ return ( -1);
+ }
+
+ /* Process the file */
+ while (0 == my_fgets(fp, buf, 1024))
+ {
+ /* Count lines */
+ num++;
+
+
+ /* Skip "empty" lines */
+ if (!buf[0]) continue;
+
+ /* Skip "blank" lines */
+ if (isspace(buf[0])) continue;
+
+ /* Skip comments */
+ if (buf[0] == '#') continue;
+
+
+ /* Process "?:<expr>" */
+ if ((buf[0] == '?') && (buf[1] == ':'))
+ {
+ char f;
+ cptr v;
+ char *s;
+
+ /* Start */
+ s = buf + 2;
+
+ /* Parse the expr */
+ v = process_dungeon_file_expr(&s, &f);
+
+ /* Set flag */
+ bypass = (streq(v, "0") ? TRUE : FALSE);
+
+ /* Continue */
+ continue;
+ }
+
+ /* Apply conditionals */
+ if (bypass) continue;
+
+
+ /* Process "%:<file>" */
+ if (buf[0] == '%')
+ {
+ /* Process that file if allowed */
+ process_dungeon_file(buf + 2, yval, xval, ymax, xmax, FALSE, full);
+
+ /* Continue */
+ continue;
+ }
+
+
+ /* Process the line */
+ err = process_dungeon_file_aux(buf, yval, xval, xmin, ymax, xmax, full);
+
+ /* Oops */
+ if (err) break;
+ }
+
+
+ /* Error */
+ if (err)
+ {
+ /* Useful error message */
+ msg_format("Error %d in line %d of file '%s'.", err, num, name);
+ msg_format("Parsing '%s'", buf);
+ }
+
+ /* Close the file */
+ my_fclose(fp);
+
+ /* Result */
+ return (err);
+}
diff --git a/src/init1.hpp b/src/init1.hpp
new file mode 100644
index 00000000..1c417285
--- /dev/null
+++ b/src/init1.hpp
@@ -0,0 +1,27 @@
+#pragma once
+
+#include "h-basic.h"
+#include "dungeon_flag_set.hpp"
+
+int color_char_to_attr(char c);
+extern byte conv_color[16];
+errr init_player_info_txt(FILE *fp);
+errr init_ab_info_txt(FILE *fp);
+errr init_s_info_txt(FILE *fp);
+errr init_set_info_txt(FILE *fp);
+errr init_v_info_txt(FILE *fp);
+errr init_f_info_txt(FILE *fp);
+errr init_k_info_txt(FILE *fp);
+errr init_a_info_txt(FILE *fp);
+errr init_ra_info_txt(FILE *fp);
+errr init_e_info_txt(FILE *fp);
+errr init_r_info_txt(FILE *fp);
+errr init_re_info_txt(FILE *fp);
+errr init_d_info_txt(FILE *fp);
+errr init_t_info_txt(FILE *fp);
+errr init_ba_info_txt(FILE *fp);
+errr init_st_info_txt(FILE *fp);
+errr init_ow_info_txt(FILE *fp);
+errr init_wf_info_txt(FILE *fp);
+errr grab_one_dungeon_flag(dungeon_flag_set *flags, const char *str);
+errr process_dungeon_file(cptr name, int *yval, int *xval, int ymax, int xmax, bool_ init, bool_ full);
diff --git a/src/init2.c b/src/init2.c
deleted file mode 100644
index 5239426c..00000000
--- a/src/init2.c
+++ /dev/null
@@ -1,2918 +0,0 @@
-/* File: init2.c */
-
-/* Purpose: Initialisation (part 2) -BEN- */
-
-#include "angband.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
- * the common limitation of "read()" and "write()" to only 32767 bytes
- * at a time.
- *
- * Several of the arrays for Angband are built from "template" files in
- * the "lib/file" directory, from which quick-load binary "image" files
- * are constructed whenever they are not present in the "lib/data"
- * directory, or if those files become obsolete, if we are allowed.
- *
- * Warning -- the "ascii" file parsers use a minor hack to collect the
- * name and text information in a single pass. Thus, the game will not
- * be able to load any template file with more than 20K of names or 60K
- * of text, even though technically, up to 64K should be legal.
- *
- * The "init1.c" file is used only to parse the ascii template files.
- */
-
-
-
-/*
- * Find the default paths to all of our important sub-directories.
- *
- * The purpose of each sub-directory is described in "variable.c".
- *
- * All of the sub-directories should, by default, be located inside
- * the main "lib" directory, whose location is very system dependant.
- *
- * This function takes a writable buffer, initially containing the
- * "path" to the "lib" directory, for example, "/pkg/lib/angband/",
- * or a system dependant string, for example, ":lib:". The buffer
- * must be large enough to contain at least 32 more characters.
- *
- * Various command line options may allow some of the important
- * directories to be changed to user-specified directories, most
- * importantly, the "info" and "user" and "save" directories,
- * but this is done after this function, see "main.c".
- *
- * In general, the initial path should end in the appropriate "PATH_SEP"
- * string. All of the "sub-directory" paths (created below or supplied
- * by the user) will NOT end in the "PATH_SEP" string, see the special
- * "path_build()" function in "util.c" for more information.
- *
- * Mega-Hack -- support fat raw files under NEXTSTEP, using special
- * "suffixed" directories for the "ANGBAND_DIR_DATA" directory, but
- * requiring the directories to be created by hand by the user.
- *
- * Hack -- first we free all the strings, since this is known
- * to succeed even if the strings have not been allocated yet,
- * as long as the variables start out as "NULL". This allows
- * this function to be called multiple times, for example, to
- * try several base "path" values until a good one is found.
- */
-void init_file_paths(char *path)
-{
- char *tail;
- int pathlen;
-
- /*** Free everything ***/
-
- /* Free the main 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);
- string_free(ANGBAND_DIR_EDIT);
- string_free(ANGBAND_DIR_FILE);
- string_free(ANGBAND_DIR_HELP);
- string_free(ANGBAND_DIR_INFO);
- string_free(ANGBAND_DIR_MODULES);
- string_free(ANGBAND_DIR_NOTE);
- string_free(ANGBAND_DIR_SAVE);
- string_free(ANGBAND_DIR_SCPT);
- string_free(ANGBAND_DIR_PREF);
- string_free(ANGBAND_DIR_PATCH);
- string_free(ANGBAND_DIR_USER);
- string_free(ANGBAND_DIR_XTRA);
- string_free(ANGBAND_DIR_CMOV);
-
-
- /*** Prepare the "path" ***/
-
- pathlen = strlen(path);
-
- /* Hack -- save the main directory without trailing PATH_SEP if present */
- if (strlen(PATH_SEP) > 0 && pathlen > 0)
- {
- int seplen = strlen(PATH_SEP);
-
- if (strcmp(path + pathlen - seplen, PATH_SEP) == 0)
- {
- path[pathlen - seplen] = '\0';
- ANGBAND_DIR = string_make(path);
- path[pathlen - seplen] = *PATH_SEP;
- }
- else
- {
- ANGBAND_DIR = string_make(path);
- }
- }
- else
- {
- ANGBAND_DIR = string_make(path);
- }
-
- /* Prepare to append to the Base Path */
- tail = path + pathlen;
-
-
-
- /*** 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);
-
- /* Build a path name */
- strcpy(tail, "dngn");
- ANGBAND_DIR_DNGN = string_make(path);
-
- /* Build a path name */
- strcpy(tail, "data");
- ANGBAND_DIR_DATA = string_make(path);
-
- /* Build a path name */
- strcpy(tail, "edit");
- ANGBAND_DIR_EDIT = string_make(path);
-
- /* Build a path name */
- strcpy(tail, "file");
- ANGBAND_DIR_FILE = string_make(path);
-
- /* Build a path name */
- strcpy(tail, "help");
- ANGBAND_DIR_HELP = string_make(path);
-
- /* Build a path name */
- strcpy(tail, "info");
- ANGBAND_DIR_INFO = string_make(path);
-
- /* Build a path name */
- strcpy(tail, "mods");
- ANGBAND_DIR_MODULES = string_make(path);
-
- /* Build a path name */
- strcpy(tail, "patch");
- ANGBAND_DIR_PATCH = string_make(path);
-
- /* Build a path name */
- strcpy(tail, "scpt");
- ANGBAND_DIR_SCPT = string_make(path);
-
- /* Build a path name */
- strcpy(tail, "pref");
- ANGBAND_DIR_PREF = string_make(path);
-
- /* synchronize with module_reset_dir */
- {
- char user_path[1024];
-
- /* Get an absolute path from the file name */
- path_parse(user_path, 1024, PRIVATE_USER_PATH);
- strcat(user_path, USER_PATH_VERSION);
- ANGBAND_DIR_USER = string_make(user_path);
- ANGBAND_DIR_NOTE = string_make(user_path);
- ANGBAND_DIR_CMOV = string_make(user_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];
- strcpy(user_path_data, user_path);
- strcat(user_path_data, "/data");
- ANGBAND_DIR_DATA = string_make(user_path_data);
- }
-#endif
-
- /* Savefiles are in user directory */
- strcat(user_path, "/save");
- ANGBAND_DIR_SAVE = string_make(user_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 */
-
-}
-
-
-/**
- * Realloc the given character array.
- */
-static void z_realloc(char **p, size_t n) {
- /* realloc doesn't really support size 0, but we want to shrink the allocated area regardless. */
- if (n == 0) {
- n = 1;
- }
- /* do the reallocation */
- *p = realloc(*p, n);
- if (*p == NULL) {
- quit("Error during realloc.");
- }
-}
-
-/*
- * Hack -- help give useful error messages
- */
-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
- */
-static cptr err_str[9] =
-{
- NULL,
- "parse error",
- "obsolete file",
- "missing record header",
- "non-sequential records",
- "invalid flag specification",
- "undefined directive",
- "out of memory",
- "invalid skill chart"
-};
-
-
-/*
- * Hack -- take notes on line 23
- */
-static void note(cptr str)
-{
- Term_erase(0, 23, 255);
- Term_putstr(20, 23, -1, TERM_WHITE, str);
- Term_fresh();
-}
-
-
-
-/*
- * Initialise the "f_info" array
- *
- * Note that we let each entry have a unique "name" and "text" string,
- * even if the string happens to be empty (everyone has a unique '\0').
- */
-static errr init_f_info(void)
-{
- errr err = 0;
-
- FILE *fp;
-
- /* General buffer */
- char buf[1024];
-
-
- /*** Make the header ***/
-
- /* Allocate the "header" */
- MAKE(f_head, header);
-
- /* Save the "record" information */
- f_head->info_num = max_f_idx;
-
-
- /*** 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);
-
-
- /*** Load the ascii template file ***/
-
- /* Build the filename */
- path_build(buf, 1024, ANGBAND_DIR_EDIT, "f_info.txt");
-
- /* Open the file */
- fp = my_fopen(buf, "r");
-
- /* Parse it */
- if (!fp) quit("Cannot open 'f_info.txt' file.");
-
- /* Parse the file */
- err = init_f_info_txt(fp, buf);
-
- /* Close it */
- my_fclose(fp);
-
- /* Errors */
- if (err)
- {
- cptr oops;
-
- /* Error string */
- oops = (((err > 0) && (err < 8)) ? err_str[err] : "unknown");
-
- /* Oops */
- msg_format("Error %d at line %d of 'f_info.txt'.", err, error_line);
- msg_format("Record %d contains a '%s' error.", error_idx, oops);
- msg_format("Parsing '%s'.", buf);
- msg_print(NULL);
-
- /* Quit */
- quit("Error in 'f_info.txt' file.");
- }
-
- /* Reduce sizes of the arrays */
- z_realloc(&f_name, f_head->name_size);
- z_realloc(&f_text, f_head->text_size);
-
- /* Success */
- return (0);
-}
-
-
-
-/*
- * Initialise the "k_info" array
- *
- * Note that we let each entry have a unique "name" and "text" string,
- * even if the string happens to be empty (everyone has a unique '\0').
- */
-static errr init_k_info(void)
-{
- errr err = 0;
-
- FILE *fp;
-
- /* General buffer */
- char buf[1024];
-
-
- /*** Make the header ***/
-
- /* Allocate the "header" */
- MAKE(k_head, header);
-
- /* Save the "record" information */
- k_head->info_num = max_k_idx;
-
-
- /*** 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);
-
-
- /*** Load the ascii template file ***/
-
- /* Build the filename */
- path_build(buf, 1024, ANGBAND_DIR_EDIT, "k_info.txt");
-
- /* Open the file */
- fp = my_fopen(buf, "r");
-
- /* Parse it */
- if (!fp) quit("Cannot open 'k_info.txt' file.");
-
- /* Parse the file */
- err = init_k_info_txt(fp, buf);
-
- /* Close it */
- my_fclose(fp);
-
- /* Errors */
- if (err)
- {
- cptr oops;
-
- /* Error string */
- oops = (((err > 0) && (err < 8)) ? err_str[err] : "unknown");
-
- /* Oops */
- msg_format("Error %d at line %d of 'k_info.txt'.", err, error_line);
- msg_format("Record %d contains a '%s' error.", error_idx, oops);
- msg_format("Parsing '%s'.", buf);
- msg_print(NULL);
-
- /* Quit */
- quit("Error in 'k_info.txt' file.");
- }
-
- /* Reduce sizes of the arrays */
- z_realloc(&k_name, k_head->name_size);
- z_realloc(&k_text, k_head->text_size);
-
- /* Success */
- return (0);
-}
-
-
-
-/*
- * Initialise the "set_info" array
- *
- * Note that we let each entry have a unique "name" and "text" string,
- * even if the string happens to be empty (everyone has a unique '\0').
- */
-static errr init_set_info(void)
-{
- errr err = 0;
-
- FILE *fp;
-
- /* General buffer */
- char buf[1024];
-
-
- /*** Make the "header" ***/
-
- /* Allocate the "header" */
- MAKE(set_head, header);
-
- /* Save the "record" information */
- set_head->info_num = max_set_idx;
-
-
- /*** 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);
-
-
- /*** Load the ascii template file ***/
-
- /* Build the filename */
- path_build(buf, 1024, ANGBAND_DIR_EDIT, "set_info.txt");
-
- /* Open the file */
- fp = my_fopen(buf, "r");
-
- /* Parse it */
- if (!fp) quit("Cannot open 'set_info.txt' file.");
-
- /* Parse the file */
- err = init_set_info_txt(fp, buf);
-
- /* Close it */
- my_fclose(fp);
-
- /* Errors */
- if (err)
- {
- cptr oops;
-
- /* Error string */
- oops = (((err > 0) && (err < 8)) ? err_str[err] : "unknown");
-
- /* Oops */
- msg_format("Error %d at line %d of 'set_info.txt'.", err, error_line);
- msg_format("Record %d contains a '%s' error.", error_idx, oops);
- msg_format("Parsing '%s'.", buf);
- msg_print(NULL);
-
- /* Quit */
- quit("Error in 'set_info.txt' file.");
- }
-
- /* Reduce sizes of the arrays */
- z_realloc(&set_name, set_head->name_size);
- z_realloc(&set_text, set_head->text_size);
-
- /* Success */
- return (0);
-}
-
-
-/*
- * Initialise the "a_info" array
- *
- * Note that we let each entry have a unique "name" and "text" string,
- * even if the string happens to be empty (everyone has a unique '\0').
- */
-static errr init_a_info(void)
-{
- errr err = 0;
-
- FILE *fp;
-
- /* General buffer */
- char buf[1024];
-
-
- /*** Make the "header" ***/
-
- /* Allocate the "header" */
- MAKE(a_head, header);
-
- /* Save the "record" information */
- a_head->info_num = max_a_idx;
-
-
- /*** 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);
-
-
- /*** Load the ascii template file ***/
-
- /* Build the filename */
- path_build(buf, 1024, ANGBAND_DIR_EDIT, "a_info.txt");
-
- /* Open the file */
- fp = my_fopen(buf, "r");
-
- /* Parse it */
- if (!fp) quit("Cannot open 'a_info.txt' file.");
-
- /* Parse the file */
- err = init_a_info_txt(fp, buf);
-
- /* Close it */
- my_fclose(fp);
-
- /* Errors */
- if (err)
- {
- cptr oops;
-
- /* Error string */
- oops = (((err > 0) && (err < 8)) ? err_str[err] : "unknown");
-
- /* Oops */
- msg_format("Error %d at line %d of 'a_info.txt'.", err, error_line);
- msg_format("Record %d contains a '%s' error.", error_idx, oops);
- msg_format("Parsing '%s'.", buf);
- msg_print(NULL);
-
- /* Quit */
- quit("Error in 'a_info.txt' file.");
- }
-
- /* Reduce sizes of the arrays */
- z_realloc(&a_name, a_head->name_size);
- z_realloc(&a_text, a_head->text_size);
-
- /* Success */
- return (0);
-}
-
-
-/*
- * Initialise the "s_info" array
- *
- * Note that we let each entry have a unique "name" and "text" string,
- * even if the string happens to be empty (everyone has a unique '\0').
- */
-static errr init_s_info(void)
-{
- errr err = 0;
-
- FILE *fp;
-
- /* General buffer */
- char buf[1024];
-
-
- /*** Make the "header" ***/
-
- /* Allocate the "header" */
- MAKE(s_head, header);
-
- /* Save the "record" information */
- s_head->info_num = max_s_idx;
-
-
- /*** 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);
-
- /*** Load the ascii template file ***/
-
- /* Build the filename */
- path_build(buf, 1024, ANGBAND_DIR_EDIT, "s_info.txt");
-
- /* Open the file */
- fp = my_fopen(buf, "r");
-
- /* Parse it */
- if (!fp) quit("Cannot open 's_info.txt' file.");
-
- /* Parse the file */
- err = init_s_info_txt(fp, buf);
-
- /* Close it */
- my_fclose(fp);
-
- /* Errors */
- if (err)
- {
- cptr oops;
-
- /* Error string */
- oops = (((err > 0) && (err < 8)) ? err_str[err] : "unknown");
-
- /* Oops */
- msg_format("Error %d at line %d of 's_info.txt'.", err, error_line);
- msg_format("Record %d contains a '%s' error.", error_idx, oops);
- msg_format("Parsing '%s'.", buf);
- msg_print(NULL);
-
- /* Quit */
- quit("Error in 's_info.txt' file.");
- }
-
- /* Reduce sizes of the arrays */
- z_realloc(&s_name, s_head->name_size);
- z_realloc(&s_text, s_head->text_size);
-
- /* Success */
- return (0);
-}
-
-/*
- * Initialise the "ab_info" array
- *
- * Note that we let each entry have a unique "name" and "text" string,
- * even if the string happens to be empty (everyone has a unique '\0').
- */
-static errr init_ab_info(void)
-{
- errr err = 0;
-
- FILE *fp;
-
- /* General buffer */
- char buf[1024];
-
-
-
- /*** Make the "header" ***/
-
- /* Allocate the "header" */
- MAKE(ab_head, header);
-
- /* Save the "record" information */
- ab_head->info_num = max_ab_idx;
-
-
- /*** 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);
-
- /*** Load the ascii template file ***/
-
- /* Build the filename */
- path_build(buf, 1024, ANGBAND_DIR_EDIT, "ab_info.txt");
-
- /* Open the file */
- fp = my_fopen(buf, "r");
-
- /* Parse it */
- if (!fp) quit("Cannot open 'ab_info.txt' file.");
-
- /* Parse the file */
- err = init_ab_info_txt(fp, buf);
-
- /* Close it */
- my_fclose(fp);
-
- /* Errors */
- if (err)
- {
- cptr oops;
-
- /* Error string */
- oops = (((err > 0) && (err < 8)) ? err_str[err] : "unknown");
-
- /* Oops */
- msg_format("Error %d at line %d of 'ab_info.txt'.", err, error_line);
- msg_format("Record %d contains a '%s' error.", error_idx, oops);
- msg_format("Parsing '%s'.", buf);
- msg_print(NULL);
-
- /* Quit */
- quit("Error in 'ab_info.txt' file.");
- }
-
- /* Reduce sizes of the arrays */
- z_realloc(&ab_name, ab_head->name_size);
- z_realloc(&ab_text, ab_head->text_size);
-
- /* Success */
- return (0);
-}
-
-
-
-/*
- * Initialise the "e_info" array
- *
- * Note that we let each entry have a unique "name" and "text" string,
- * even if the string happens to be empty (everyone has a unique '\0').
- */
-static errr init_e_info(void)
-{
- errr err = 0;
-
- FILE *fp;
-
- /* General buffer */
- char buf[1024];
-
-
- /*** Make the "header" ***/
-
- /* Allocate the "header" */
- MAKE(e_head, header);
-
- /* Save the "record" information */
- e_head->info_num = max_e_idx;
-
-
- /*** 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);
-
-
- /*** Load the ascii template file ***/
-
- /* Build the filename */
- path_build(buf, 1024, ANGBAND_DIR_EDIT, "e_info.txt");
-
- /* Open the file */
- fp = my_fopen(buf, "r");
-
- /* Parse it */
- if (!fp) quit("Cannot open 'e_info.txt' file.");
-
- /* Parse the file */
- err = init_e_info_txt(fp, buf);
-
- /* Close it */
- my_fclose(fp);
-
- /* Errors */
- if (err)
- {
- cptr oops;
-
- /* Error string */
- oops = (((err > 0) && (err < 8)) ? err_str[err] : "unknown");
-
- /* Oops */
- msg_format("Error %d at line %d of 'e_info.txt'.", err, error_line);
- msg_format("Record %d contains a '%s' error.", error_idx, oops);
- msg_format("Parsing '%s'.", buf);
- msg_print(NULL);
-
- /* Quit */
- quit("Error in 'e_info.txt' file.");
- }
-
- /* Reduce sizes of the arrays */
- z_realloc(&e_name, e_head->name_size);
- z_realloc(&e_text, e_head->text_size);
-
- /* Success */
- return (0);
-}
-
-
-
-/*
- * Initialise the "ra_info" array
- *
- * Note that we let each entry have a unique "name" and "text" string,
- * even if the string happens to be empty (everyone has a unique '\0').
- */
-static errr init_ra_info(void)
-{
- errr err = 0;
-
- FILE *fp;
-
- /* General buffer */
- char buf[1024];
-
- /*** Make the "header" ***/
-
- /* Allocate the "header" */
- MAKE(ra_head, header);
-
- /* Save the "record" information */
- ra_head->info_num = max_ra_idx;
-
-
- /*** 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);
-
- /*** Load the ascii template file ***/
-
- /* Build the filename */
- path_build(buf, 1024, ANGBAND_DIR_EDIT, "ra_info.txt");
-
- /* Open the file */
- fp = my_fopen(buf, "r");
-
- /* Parse it */
- if (!fp) quit("Cannot open 'ra_info.txt' file.");
-
- /* Parse the file */
- err = init_ra_info_txt(fp, buf);
-
- /* Close it */
- my_fclose(fp);
-
- /* Errors */
- if (err)
- {
- cptr oops;
-
- /* Error string */
- oops = (((err > 0) && (err < 8)) ? err_str[err] : "unknown");
-
- /* Oops */
- msg_format("Error %d at line %d of 'ra_info.txt'.", err, error_line);
- msg_format("Record %d contains a '%s' error.", error_idx, oops);
- msg_format("Parsing '%s'.", buf);
- msg_print(NULL);
-
- /* Quit */
- quit("Error in 'ra_info.txt' file.");
- }
-
- /* Success */
- return (0);
-}
-
-
-
-/*
- * Initialise the "r_info" array
- *
- * Note that we let each entry have a unique "name" and "text" string,
- * even if the string happens to be empty (everyone has a unique '\0').
- */
-static errr init_r_info(void)
-{
- errr err = 0;
-
- FILE *fp;
-
- /* General buffer */
- char buf[1024];
-
-
- /*** Make the header ***/
-
- /* Allocate the "header" */
- MAKE(r_head, header);
-
- /* Save the "record" information */
- r_head->info_num = max_r_idx;
-
-
- /*** 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);
-
-
- /*** Load the ascii template file ***/
-
- /* Build the filename */
- path_build(buf, 1024, ANGBAND_DIR_EDIT, "r_info.txt");
-
- /* Open the file */
- fp = my_fopen(buf, "r");
-
- /* Parse it */
- if (!fp) quit("Cannot open 'r_info.txt' file.");
-
- /* Parse the file */
- err = init_r_info_txt(fp, buf);
-
- /* Close it */
- my_fclose(fp);
-
- /* Errors */
- if (err)
- {
- cptr oops;
-
- /* Error string */
- oops = (((err > 0) && (err < 8)) ? err_str[err] : "unknown");
-
- /* Oops */
- msg_format("Error %d at line %d of 'r_info.txt'.", err, error_line);
- msg_format("Record %d contains a '%s' error.", error_idx, oops);
- msg_format("Parsing '%s'.", buf);
- msg_print(NULL);
-
- /* Quit */
- quit("Error in 'r_info.txt' file.");
- }
-
- /* Reduce sizes of the arrays */
- z_realloc(&r_name, r_head->name_size);
- z_realloc(&r_text, r_head->text_size);
-
- /* Success */
- return (0);
-}
-
-
-/*
- * Initialise the "re_info" array
- *
- * Note that we let each entry have a unique "name" string,
- * even if the string happens to be empty (everyone has a unique '\0').
- */
-static errr init_re_info(void)
-{
- errr err = 0;
-
- FILE *fp;
-
- /* General buffer */
- char buf[1024];
-
-
- /*** Make the header ***/
-
- /* Allocate the "header" */
- MAKE(re_head, header);
-
- /* Save the "record" information */
- re_head->info_num = max_re_idx;
-
-
- /*** 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);
-
-
- /*** Load the ascii template file ***/
-
- /* Build the filename */
- path_build(buf, 1024, ANGBAND_DIR_EDIT, "re_info.txt");
-
- /* Open the file */
- fp = my_fopen(buf, "r");
-
- /* Parse it */
- if (!fp) quit("Cannot open 're_info.txt' file.");
-
- /* Parse the file */
- err = init_re_info_txt(fp, buf);
-
- /* Close it */
- my_fclose(fp);
-
- /* Errors */
- if (err)
- {
- cptr oops;
-
- /* Error string */
- oops = (((err > 0) && (err < 8)) ? err_str[err] : "unknown");
-
- /* Oops */
- msg_format("Error %d at line %d of 're_info.txt'.", err, error_line);
- msg_format("Record %d contains a '%s' error.", error_idx, oops);
- msg_format("Parsing '%s'.", buf);
- msg_print(NULL);
-
- /* Quit */
- quit("Error in 're_info.txt' file.");
- }
-
- /* Reduce sizes of the arrays */
- z_realloc(&re_name, re_head->name_size);
-
- /* Success */
- return (0);
-}
-
-
-/*
- * Initialise the "d_info" array
- *
- * Note that we let each entry have a unique "name" and "short name" string,
- * even if the string happens to be empty (everyone has a unique '\0').
- */
-static errr init_d_info(void)
-{
- errr err = 0;
-
- FILE *fp;
-
- /* General buffer */
- char buf[1024];
-
-
- /*** Make the header ***/
-
- /* Allocate the "header" */
- MAKE(d_head, header);
-
- /* Save the "record" information */
- d_head->info_num = max_d_idx;
-
-
- /*** 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);
-
-
- /*** Load the ascii template file ***/
-
- /* Build the filename */
- path_build(buf, 1024, ANGBAND_DIR_EDIT, "d_info.txt");
-
- /* Open the file */
- fp = my_fopen(buf, "r");
-
- /* Parse it */
- if (!fp) quit("Cannot open 'd_info.txt' file.");
-
- /* Parse the file */
- err = init_d_info_txt(fp, buf);
-
- /* Close it */
- my_fclose(fp);
-
- /* Errors */
- if (err)
- {
- cptr oops;
-
- /* Error string */
- oops = (((err > 0) && (err < 8)) ? err_str[err] : "unknown");
-
- /* Oops */
- msg_format("Error %d at line %d df 'd_info.txt'.", err, error_line);
- msg_format("Record %d contains a '%s' error.", error_idx, oops);
- msg_format("Parsing '%s'.", buf);
- msg_print(NULL);
-
- /* Quit */
- quit("Error in 'd_info.txt' file.");
- }
-
- /* Reduce sizes of the arrays */
- z_realloc(&d_name, d_head->name_size);
- z_realloc(&d_text, d_head->text_size);
-
- /* Success */
- return (0);
-}
-
-
-/*
- * Initialise the "player" arrays
- *
- * Note that we let each entry have a unique "name" and "short name" string,
- * even if the string happens to be empty (everyone has a unique '\0').
- */
-static errr init_player_info(void)
-{
- int i;
-
- errr err = 0;
-
- FILE *fp;
-
- /* General buffer */
- char buf[1024];
-
-
- /*** Make the header ***/
-
- /* Allocate the "header" */
- MAKE(rp_head, header);
-
- /* Save the "record" information */
- rp_head->info_num = max_rp_idx;
-
-
- /*** Make the header ***/
-
- /* Allocate the "header" */
- MAKE(rmp_head, header);
-
- /* Save the "record" information */
- rmp_head->info_num = max_rmp_idx;
-
-
- /*** Make the header ***/
-
- /* Allocate the "header" */
- MAKE(c_head, header);
-
- /* Save the "record" information */
- c_head->info_num = max_c_idx;
-
-
- /*** 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);
-
- /* 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);
-
- /* 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);
-
- /* Allocate the "bg" array */
- C_MAKE(bg, max_bg_idx, hist_type);
-
- /* Allocate the "meta_class" array */
- C_MAKE(meta_class_info, max_mc_idx, meta_class_type);
- for (i = 0; i < max_mc_idx; i++)
- {
- C_MAKE(meta_class_info[i].classes, max_c_idx, s16b);
- }
-
- /*** Load the ascii template file ***/
-
- /* Build the filename */
- path_build(buf, 1024, ANGBAND_DIR_EDIT, "p_info.txt");
-
- /* Open the file */
- fp = my_fopen(buf, "r");
-
- /* Parse it */
- if (!fp) quit("Cannot open 'p_info.txt' file.");
-
- /* Parse the file */
- err = init_player_info_txt(fp, buf);
-
- /* Close it */
- my_fclose(fp);
-
- /* Errors */
- if (err)
- {
- cptr oops;
-
- /* Error string */
- oops = (((err > 0) && (err < 8)) ? err_str[err] : "unknown");
-
- /* Oops */
- msg_format("Error %d at line %d df 'p_info.txt'.", err, error_line);
- msg_format("Record %d contains a '%s' error.", error_idx, oops);
- msg_format("Parsing '%s'.", buf);
- msg_print(NULL);
-
- /* Quit */
- quit("Error in 'p_info.txt' file.");
- }
-
- /* Reallocate arrays. */
- z_realloc(&rp_name, rp_head->name_size);
- z_realloc(&rp_text, rp_head->text_size);
- z_realloc(&rmp_name, rmp_head->name_size);
- z_realloc(&rmp_text, rmp_head->text_size);
- z_realloc(&c_name, c_head->name_size);
- z_realloc(&c_text, c_head->text_size);
-
- /* Success */
- return (0);
-}
-
-/*
- * Initialise the "st_info" array
- *
- * Note that we let each entry have a unique "name" and "short name" string,
- * even if the string happens to be empty (everyone has a unique '\0').
- */
-static errr init_st_info(void)
-{
- errr err = 0;
-
- FILE *fp;
-
- /* General buffer */
- char buf[1024];
-
-
- /*** Make the header ***/
-
- /* Allocate the "header" */
- MAKE(st_head, header);
-
- /* Save the "record" information */
- st_head->info_num = max_st_idx;
-
-
- /*** 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);
-
-
- /*** Load the ascii template file ***/
-
- /* Build the filename */
- path_build(buf, 1024, ANGBAND_DIR_EDIT, "st_info.txt");
-
- /* Open the file */
- fp = my_fopen(buf, "r");
-
- /* Parse it */
- if (!fp) quit("Cannot open 'st_info.txt' file.");
-
- /* Parse the file */
- err = init_st_info_txt(fp, buf);
-
- /* Close it */
- my_fclose(fp);
-
- /* Errors */
- if (err)
- {
- cptr oops;
-
- /* Error string */
- oops = (((err > 0) && (err < 8)) ? err_str[err] : "unknown");
-
- /* Oops */
- msg_format("Error %d at line %d df 'st_info.txt'.", err, error_line);
- msg_format("Record %d contains a '%s' error.", error_idx, oops);
- msg_format("Parsing '%s'.", buf);
- msg_print(NULL);
-
- /* Quit */
- quit("Error in 'st_info.txt' file.");
- }
-
- /* Reduce sizes of the arrays */
- z_realloc(&st_name, st_head->name_size);
-
- /* Success */
- return (0);
-}
-
-/*
- * Initialise the "ow_info" array
- *
- * Note that we let each entry have a unique "name" and "short name" string,
- * even if the string happens to be empty (everyone has a unique '\0').
- */
-static errr init_ow_info(void)
-{
- errr err = 0;
-
- FILE *fp;
-
- /* General buffer */
- char buf[1024];
-
-
- /*** Make the header ***/
-
- /* Allocate the "header" */
- MAKE(ow_head, header);
-
- /* Save the "record" information */
- ow_head->info_num = max_ow_idx;
-
-
- /*** 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);
-
-
- /*** Load the ascii template file ***/
-
- /* Build the filename */
- path_build(buf, 1024, ANGBAND_DIR_EDIT, "ow_info.txt");
-
- /* Open the file */
- fp = my_fopen(buf, "r");
-
- /* Parse it */
- if (!fp) quit("Cannot open 'ow_info.txt' file.");
-
- /* Parse the file */
- err = init_ow_info_txt(fp, buf);
-
- /* Close it */
- my_fclose(fp);
-
- /* Errors */
- if (err)
- {
- cptr oops;
-
- /* Error string */
- oops = (((err > 0) && (err < 8)) ? err_str[err] : "unknown");
-
- /* Oops */
- msg_format("Error %d at line %d df 'ow_info.txt'.", err, error_line);
- msg_format("Record %d contains a '%s' error.", error_idx, oops);
- msg_format("Parsing '%s'.", buf);
- msg_print(NULL);
-
- /* Quit */
- quit("Error in 'ow_info.txt' file.");
- }
-
- /* Reduce sizes of the arrays */
- z_realloc(&ow_name, ow_head->name_size);
-
- /* Success */
- return (0);
-}
-
-/*
- * Initialise the "ba_info" array
- *
- * Note that we let each entry have a unique "name" and "short name" string,
- * even if the string happens to be empty (everyone has a unique '\0').
- */
-static errr init_ba_info(void)
-{
- errr err = 0;
-
- FILE *fp;
-
- /* General buffer */
- char buf[1024];
-
-
- /*** Make the header ***/
-
- /* Allocate the "header" */
- MAKE(ba_head, header);
-
- /* Save the "record" information */
- ba_head->info_num = max_ba_idx;
-
-
- /*** 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);
-
-
- /*** Load the ascii template file ***/
-
- /* Build the filename */
- path_build(buf, 1024, ANGBAND_DIR_EDIT, "ba_info.txt");
-
- /* Open the file */
- fp = my_fopen(buf, "r");
-
- /* Parse it */
- if (!fp) quit("Cannot open 'ba_info.txt' file.");
-
- /* Parse the file */
- err = init_ba_info_txt(fp, buf);
-
- /* Close it */
- my_fclose(fp);
-
- /* Errors */
- if (err)
- {
- cptr oops;
-
- /* Error string */
- oops = (((err > 0) && (err < 8)) ? err_str[err] : "unknown");
-
- /* Oops */
- msg_format("Error %d at line %d df 'ba_info.txt'.", err, error_line);
- msg_format("Record %d contains a '%s' error.", error_idx, oops);
- msg_format("Parsing '%s'.", buf);
- msg_print(NULL);
-
- /* Quit */
- quit("Error in 'ba_info.txt' file.");
- }
-
- /* Reduce sizes of the arrays */
- z_realloc(&ba_name, ba_head->name_size);
-
- /* Success */
- return (0);
-}
-
-/*
- * Initialise the "wf_info" array
- *
- * Note that we let each entry have a unique "name" and "short name" string,
- * even if the string happens to be empty (everyone has a unique '\0').
- */
-static errr init_wf_info(void)
-{
- errr err = 0;
-
- FILE *fp;
-
- /* General buffer */
- char buf[1024];
-
-
- /*** Make the header ***/
-
- /* Allocate the "header" */
- MAKE(wf_head, header);
-
- /* Save the "record" information */
- wf_head->info_num = max_wf_idx;
-
-
- /*** 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);
-
-
- /*** Load the ascii template file ***/
-
- /* Build the filename */
- path_build(buf, 1024, ANGBAND_DIR_EDIT, "wf_info.txt");
-
- /* Open the file */
- fp = my_fopen(buf, "r");
-
- /* Parse it */
- if (!fp) quit("Cannot open 'wf_info.txt' file.");
-
- /* Parse the file */
- err = init_wf_info_txt(fp, buf);
-
- /* Close it */
- my_fclose(fp);
-
- /* Errors */
- if (err)
- {
- cptr oops;
-
- /* Error string */
- oops = (((err > 0) && (err < 8)) ? err_str[err] : "unknown");
-
- /* Oops */
- msg_format("Error %d at line %d df 'wf_info.txt'.", err, error_line);
- msg_format("Record %d contains a '%s' error.", error_idx, oops);
- msg_format("Parsing '%s'.", buf);
- msg_print(NULL);
-
- /* Quit */
- quit("Error in 'wf_info.txt' file.");
- }
-
- /* Reduce sizes of the arrays */
- z_realloc(&wf_name, wf_head->name_size);
- z_realloc(&wf_text, wf_head->text_size);
-
- /* Success */
- return (0);
-}
-
-
-/*
- * Initialise the "t_info" array
- *
- * Note that we let each entry have a unique "name" and "text" string,
- * even if the string happens to be empty (everyone has a unique '\0').
- */
-static errr init_t_info(void)
-{
- errr err = 0;
-
- FILE *fp;
-
- /* General buffer */
- char buf[1024];
-
-
- /*** Make the header ***/
-
- /* Allocate the "header" */
- MAKE(t_head, header);
-
- /* Save the "record" information */
- t_head->info_num = max_t_idx;
-
-
- /*** 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);
-
-
- /*** Load the ascii template file ***/
-
- /* Build the filename */
- path_build(buf, 1024, ANGBAND_DIR_EDIT, "tr_info.txt");
-
- /* Open the file */
- fp = my_fopen(buf, "r");
-
- /* Parse it */
- if (!fp) quit("Cannot open 'tr_info.txt' file.");
-
- /* Parse the file */
- err = init_t_info_txt(fp, buf);
-
- /* Close it */
- my_fclose(fp);
-
- /* Errors */
- if (err)
- {
- cptr oops;
-
- /* Error string */
- oops = (((err > 0) && (err < 8)) ? err_str[err] : "unknown");
-
- /* Oops */
- msg_format("Error %d at line %d of 'tr_info.txt'.", err, error_line);
- msg_format("Record %d contains a '%s' error.", error_idx, oops);
- msg_format("Parsing '%s'.", buf);
- msg_print(NULL);
-
- /* Quit */
- quit("Error in 'tr_info.txt' file.");
- }
-
- /* Reduce sizes of the arrays */
- z_realloc(&t_name, t_head->name_size);
- z_realloc(&t_text, t_head->text_size);
-
- /* Success */
- return (0);
-}
-
-
-/*
- * Initialise the "al_info" array
- *
- * Not a flat array, but an array none the less
- */
-errr init_al_info(void)
-{
- errr err;
-
- FILE *fp;
-
- /* General buffer */
- char buf[1024];
-
- /*** Make the header ***/
-
- /* Allocate the "header" */
- MAKE(al_head, header);
-
- /* Save the "record" information */
- al_head->info_num = max_al_idx;
-
-
-
-
- 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);
-
- /* Allocate the fake arrays */
- /* ok, so we fudge a bit, but
- fake text size will ALWAYS be larger
- 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);
-
- {
- char *hack;
- C_MAKE(hack, fake_text_size, char);
- a_select_flags = (artifact_select_flag *) hack;
- }
-
- /*** Load the ascii template file ***/
-
-
- /* Build the filename */
- path_build(buf, 1024, ANGBAND_DIR_EDIT, "al_info.txt");
-
- /* Open the file */
- fp = my_fopen(buf, "r");
-
- /* Parse it */
- if (!fp) quit("Cannot open 'al_info.txt' file.");
-
- /* Parse the file */
- err = init_al_info_txt(fp, buf);
-
- /* Close it */
- my_fclose(fp);
-
- /* Errors */
- if (err)
- {
- cptr oops;
-
- /* Error string */
- oops = (((err > 0) && (err < 8)) ? err_str[err] : "unknown");
-
- /* Oops */
- msg_format("Error %d at line %d of 'al_info.txt'.", err, error_line);
- msg_format("Record %d contains a '%s' error.", error_idx, oops);
- msg_format("Parsing '%s'.", buf);
- msg_print(NULL);
-
- /* Quit */
- quit("Error in 'al_info.txt' file.");
- }
-
- /* Reduce sizes of the arrays */
- z_realloc(&al_name, al_head->name_size);
-
- /* Success */
- return (0);
-}
-
-
-/*
- * Initialise the "v_info" array
- *
- * Note that we let each entry have a unique "name" and "text" string,
- * even if the string happens to be empty (everyone has a unique '\0').
- */
-errr init_v_info(void)
-{
- errr err;
-
- FILE *fp;
-
- /* General buffer */
- char buf[1024];
-
-
- /*** Make the header ***/
-
- /* Allocate the "header" */
- MAKE(v_head, header);
-
- /* Save the "record" information */
- v_head->info_num = max_v_idx;
-
-
- /*** 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);
-
-
- /*** Load the ascii template file ***/
-
- /* Build the filename */
- path_build(buf, 1024, ANGBAND_DIR_EDIT, "v_info.txt");
-
- /* Open the file */
- fp = my_fopen(buf, "r");
-
- /* Parse it */
- if (!fp) quit("Cannot open 'v_info.txt' file.");
-
- /* Parse the file */
- err = init_v_info_txt(fp, buf, TRUE);
-
- /* Close it */
- my_fclose(fp);
-
- /* Errors */
- if (err)
- {
- cptr oops;
-
- /* Error string */
- oops = (((err > 0) && (err < 8)) ? err_str[err] : "unknown");
-
- /* Oops */
- msg_format("Error %d at line %d of 'v_info.txt'.", err, error_line);
- msg_format("Record %d contains a '%s' error.", error_idx, oops);
- msg_format("Parsing '%s'.", buf);
- msg_print(NULL);
-
- /* Quit */
- quit("Error in 'v_info.txt' file.");
- }
-
- /* Reduce sizes of the arrays */
- z_realloc(&v_name, v_head->name_size);
- z_realloc(&v_text, v_head->text_size);
-
- /* Success */
- return (0);
-}
-
-/*
- * Initialize the very basic arrays
- */
-static void init_basic()
-{
- int i;
-
- /* Macro variables */
- C_MAKE(macro__pat, MACRO_MAX, cptr);
- C_MAKE(macro__act, MACRO_MAX, cptr);
- C_MAKE(macro__cmd, MACRO_MAX, bool_);
-
- /* Macro action buffer */
- C_MAKE(macro__buf, 1024, char);
-
- /* Extended trigger macros */
- C_MAKE(cli_info, CLI_MAX, cli_comm);
-
- /* Wipe the directory list */
- for (i = 0; i < 255; i++)
- {
- scansubdir_result[i] = NULL;
- }
-}
-
-/*
- * 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
- */
-static errr init_misc(void)
-{
- int xstart = 0;
- int ystart = 0;
- int i;
- s32b allow_quest;
- s32b allow_rquest;
-
- /*** Prepare the various "bizarre" arrays ***/
-
- /* 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;
-
- /* 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 */
- 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;
- reinit_gods(max_gods);
-
- C_COPY(deity_info, deity_info_init, MAX_GODS_INIT, deity_type);
-
- /* Prepare schools */
- max_spells = 0;
- max_schools = 0;
- schools = NULL;
- school_spells = NULL;
-
- process_hooks(HOOK_INIT_GAME, "(s)", "begin");
-
- /* Initialise the values */
- process_dungeon_file("misc.txt", &ystart, &xstart, 0, 0, TRUE, FALSE);
-
- /* Init the spell effects */
- for (i = 0; i < MAX_EFFECTS; i++)
- effects[i].time = 0;
-
- return 0;
-}
-
-
-/*
- * Initialise town array
- */
-static errr init_towns(void)
-{
- int i = 0, j = 0;
-
- /*** Prepare the Towns ***/
-
- /* Allocate the towns */
- C_MAKE(town_info, max_towns, town_type);
-
- for (i = 1; i < max_towns; i++)
- {
- if (i <= max_real_towns) town_info[i].flags |= (TOWN_REAL);
-
- /* Allocate the stores */
- C_MAKE(town_info[i].store, max_st_idx, store_type);
-
- /* Fill in each store */
- for (j = 0; j < max_st_idx; j++)
- {
- /* Access the store */
- store_type *st_ptr = &town_info[i].store[j];
-
- /* Know who we are */
- st_ptr->st_idx = j;
-
- /* Assume full stock */
- st_ptr->stock_size = 0;
- }
- }
- return 0;
-}
-
-void create_stores_stock(int t)
-{
- int j;
- town_type *t_ptr = &town_info[t];
-
- if (t_ptr->stocked) return;
-
- for (j = 0; j < max_st_idx; j++)
- {
- store_type *st_ptr = &t_ptr->store[j];
-
- /* Assume full stock */
- st_ptr->stock_size = st_info[j].max_obj;
-
- /* Allocate the stock */
- C_MAKE(st_ptr->stock, st_ptr->stock_size, object_type);
- }
- t_ptr->stocked = TRUE;
-}
-
-/*
- * Pointer to wilderness_map
- */
-typedef wilderness_map *wilderness_map_ptr;
-
-/*
- * Initialise wilderness map array
- */
-static errr init_wilderness(void)
-{
- int i;
-
- /* Allocate the wilderness (two-dimension array) */
- C_MAKE(wild_map, max_wild_y, wilderness_map_ptr);
- C_MAKE(wild_map[0], max_wild_x * max_wild_y, wilderness_map);
-
- /* Init the other pointers */
- for (i = 1; i < max_wild_y; i++)
- wild_map[i] = wild_map[0] + i * max_wild_x;
-
- /* No encounter right now */
- generate_encounter = FALSE;
-
- 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;
-
- 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;
-
- 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 */
- C_MAKE(school_spells, new_size, spell_type);
- max_spells = new_size;
-}
-
-void init_schools(s16b new_size)
-{
- /* allocate the extra memory */
- C_MAKE(schools, new_size, school_type);
- 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
- */
-static errr init_other(void)
-{
- int i, n;
-
- /*** Prepare the "dungeon" information ***/
-
- /* Allocate and Wipe the special gene flags */
- C_MAKE(m_allow_special, max_r_idx, bool_);
- C_MAKE(k_allow_special, max_k_idx, bool_);
- C_MAKE(a_allow_special, max_a_idx, bool_);
-
-
- /*** Prepare "vinfo" array ***/
-
- /* Used by "update_view()" */
- (void)vinfo_init();
-
-
- /* Allocate and Wipe the object list */
- C_MAKE(o_list, max_o_idx, object_type);
-
- /* Allocate and Wipe the monster list */
- C_MAKE(m_list, max_m_idx, monster_type);
-
- /* Allocate and Wipe the to keep monster list */
- C_MAKE(km_list, max_m_idx, monster_type);
-
- /* Allocate and Wipe the max dungeon level */
- C_MAKE(max_dlv, max_d_idx, s16b);
-
- /* Allocate and Wipe the special levels */
- for (i = 0; i < MAX_DUNGEON_DEPTH; i++)
- {
- C_MAKE(special_lvl[i], max_d_idx, bool_);
- }
-
- /* Allocate and wipe each line of the cave */
- for (i = 0; i < MAX_HGT; i++)
- {
- /* Allocate one row of the cave */
- C_MAKE(cave[i], MAX_WID, cave_type);
- }
-
- /*** Pre-allocate the basic "auto-inscriptions" ***/
-
- /* The "basic" feelings */
- (void)quark_add("cursed");
- (void)quark_add("broken");
- (void)quark_add("average");
- (void)quark_add("good");
-
- /* The "extra" feelings */
- (void)quark_add("excellent");
- (void)quark_add("worthless");
- (void)quark_add("special");
- (void)quark_add("terrible");
-
- /* Some extra strings */
- (void)quark_add("uncursed");
- (void)quark_add("on sale");
-
-
- /*** Prepare the options ***/
-
- /* Scan 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)
- {
- /* Accept */
- option_mask[os] |= (1L << ob);
-
- /* Set */
- if (option_info[i].o_norm)
- {
- /* Set */
- option_flag[os] |= (1L << ob);
- }
-
- /* Clear */
- else
- {
- /* Clear */
- option_flag[os] &= ~(1L << ob);
- }
- }
- }
-
- /* Analyze the windows */
- for (n = 0; n < 8; n++)
- {
- /* Analyze the options */
- for (i = 0; i < 32; i++)
- {
- /* Accept */
- if (window_flag_desc[i])
- {
- /* Accept */
- window_mask[n] |= (1L << i);
- }
- }
- }
-
-
- /*
- * Install the various level generators
- */
- add_level_generator("dungeon", level_generate_dungeon, TRUE, TRUE, TRUE, TRUE);
- add_level_generator("maze", level_generate_maze, TRUE, TRUE, TRUE, TRUE);
- add_level_generator("life", level_generate_life, TRUE, TRUE, TRUE, TRUE);
-
- /*** Pre-allocate space for the "format()" buffer ***/
-
- /* Hack -- Just call the "format()" function */
- (void)format("%s (%s).", "Dark God <darkgod@t-o-m-e.net>", MAINTAINER);
-
- /* Success */
- return (0);
-}
-
-
-
-/*
- * Initialise some other arrays
- */
-static errr init_alloc(void)
-{
- int i, j;
-
- object_kind *k_ptr;
-
- monster_race *r_ptr;
-
- alloc_entry *table;
-
- s16b num[MAX_DEPTH_MONSTER];
-
- s16b aux[MAX_DEPTH_MONSTER];
-
- /*** Analyze object allocation info ***/
-
- /* Clear the "aux" array */
- C_WIPE(&aux, MAX_DEPTH_MONSTER, s16b);
-
- /* Clear the "num" array */
- C_WIPE(&num, MAX_DEPTH_MONSTER, s16b);
-
- /* Size of "alloc_kind_table" */
- alloc_kind_size = 0;
-
- /* Scan the objects */
- for (i = 1; i < max_k_idx; i++)
- {
- k_ptr = &k_info[i];
-
- /* Scan allocation pairs */
- for (j = 0; j < 4; j++)
- {
- /* Count the "legal" entries */
- if (k_ptr->chance[j])
- {
- /* Count the entries */
- alloc_kind_size++;
-
- /* Group by level */
- num[k_ptr->locale[j]]++;
- }
- }
- }
-
- /* Collect the level indexes */
- for (i = 1; i < MAX_DEPTH_MONSTER; i++)
- {
- /* Group by level */
- num[i] += num[i - 1];
- }
-
- /* Paranoia */
- if (!num[0]) quit("No town objects!");
-
-
- /*** Initialise object allocation info ***/
-
- /* Allocate the alloc_kind_table */
- C_MAKE(alloc_kind_table, alloc_kind_size, alloc_entry);
-
- /* Access the table entry */
- table = alloc_kind_table;
-
- /* Scan the objects */
- for (i = 1; i < max_k_idx; i++)
- {
- k_ptr = &k_info[i];
-
- /* Scan allocation pairs */
- for (j = 0; j < 4; j++)
- {
- /* Count the "legal" entries */
- if (k_ptr->chance[j])
- {
- int p, x, y, z;
-
- /* Extract the base level */
- x = k_ptr->locale[j];
-
- /* Extract the base probability */
- p = (100 / k_ptr->chance[j]);
-
- /* Skip entries preceding our locale */
- y = (x > 0) ? num[x - 1] : 0;
-
- /* Skip previous entries at this locale */
- z = y + aux[x];
-
- /* Load the entry */
- table[z].index = i;
- table[z].level = x;
- table[z].prob1 = p;
- table[z].prob2 = p;
- table[z].prob3 = p;
-
- /* Another entry complete for this locale */
- aux[x]++;
- }
- }
- }
-
-
- /*** Analyze monster allocation info ***/
-
- /* Clear the "aux" array */
- C_WIPE(&aux, MAX_DEPTH_MONSTER, s16b);
-
- /* Clear the "num" array */
- C_WIPE(&num, MAX_DEPTH_MONSTER, s16b);
-
- /* Size of "alloc_race_table" */
- alloc_race_size = 0;
-
- /* Scan the monsters */
- for (i = 1; i < max_r_idx; i++)
- {
- /* Get the i'th race */
- r_ptr = &r_info[i];
-
- /* Legal monsters */
- if (r_ptr->rarity)
- {
- /* Count the entries */
- alloc_race_size++;
-
- /* Group by level */
- num[r_ptr->level]++;
- }
- }
-
- /* Collect the level indexes */
- for (i = 1; i < MAX_DEPTH_MONSTER; i++)
- {
- /* Group by level */
- num[i] += num[i - 1];
- }
-
- /* Paranoia */
- if (!num[0]) quit("No town monsters!");
-
-
- /*** Initialise monster allocation info ***/
-
- /* Allocate the alloc_race_table */
- C_MAKE(alloc_race_table, alloc_race_size, alloc_entry);
-
- /* Access the table entry */
- table = alloc_race_table;
-
- /* Scan the monsters */
- for (i = 1; i < max_r_idx; i++)
- {
- /* Get the i'th race */
- r_ptr = &r_info[i];
-
- /* Count valid pairs */
- if (r_ptr->rarity)
- {
- int p, x, y, z;
-
- /* Extract the base level */
- x = r_ptr->level;
-
- /* Extract the base probability */
- p = (100 / r_ptr->rarity);
-
- /* Skip entries preceding our locale */
- y = (x > 0) ? num[x - 1] : 0;
-
- /* Skip previous entries at this locale */
- z = y + aux[x];
-
- /* Load the entry */
- table[z].index = i;
- table[z].level = x;
- table[z].prob1 = p;
- table[z].prob2 = p;
- table[z].prob3 = p;
-
- /* Another entry complete for this locale */
- aux[x]++;
- }
- }
-
-
- /* Success */
- return (0);
-}
-
-/* Init the sets in a_info */
-void init_sets_aux()
-{
- int i, j;
-
- for (i = 0; i < max_a_idx; i++)
- a_info[i].set = -1;
- for (i = 0; i < max_set_idx; i++)
- {
- for (j = 0; j < set_info[i].num; j++)
- {
- a_info[set_info[i].arts[j].a_idx].set = i;
- }
- }
-}
-
-/*
- * Mark guardians and their artifacts with SPECIAL_GENE flag
- */
-static void init_guardians(void)
-{
- int i;
-
- /* Scan dungeons */
- for (i = 0; i < max_d_idx; i++)
- {
- dungeon_info_type *d_ptr = &d_info[i];
-
- /* Mark the guadian monster */
- if (d_ptr->final_guardian)
- {
- monster_race *r_ptr = &r_info[d_ptr->final_guardian];
-
- r_ptr->flags9 |= RF9_SPECIAL_GENE;
-
- /* Mark the final artifact */
- if (d_ptr->final_artifact)
- {
- artifact_type *a_ptr = &a_info[d_ptr->final_artifact];
-
- a_ptr->flags4 |= TR4_SPECIAL_GENE;
- }
-
- /* Mark the final object */
- if (d_ptr->final_object)
- {
- object_kind *k_ptr = &k_info[d_ptr->final_object];
-
- k_ptr->flags4 |= TR4_SPECIAL_GENE;
- }
-
- /* Give randart if there are no final artifacts */
- if (!(d_ptr->final_artifact) && !(d_ptr->final_object))
- {
- r_ptr->flags7 |= RF7_DROP_RANDART;
- }
- }
- }
-}
-
-/*
- * Hack -- Explain a broken "lib" folder and quit (see below).
- *
- * XXX XXX XXX This function is "messy" because various things
- * may or may not be initialised, but the "plog()" and "quit()"
- * functions are "supposed" to work under any conditions.
- */
-static void init_angband_aux(cptr why)
-{
- /* Why */
- plog(why);
-
- /* Explain */
- plog("The 'lib' directory is probably missing or broken.");
-
- /* More details */
- plog("Perhaps the archive was not extracted correctly.");
-
- /* Explain */
- plog("See the 'README' file for more information.");
-
- /* Quit with error */
- quit("Fatal Error.");
-}
-
-/*
- * Hack -- main Angband initialisation entry point
- *
- * Verify some files, display the "news.txt" file, create
- * the high score file, initialise all internal arrays, and
- * load the basic "user pref files".
- *
- * Note that we blindly assume that "news2.txt" exists. XXX
- *
- * Be very careful to keep track of the order in which things
- * are initialised, in particular, the only thing *known* to
- * be available when this function is called is the "z-term.c"
- * package, and that may not be fully initialised until the
- * end of this function, when the default "user pref files"
- * are loaded and "Term_xtra(TERM_XTRA_REACT,0)" is called.
- *
- * Note that this function attempts to verify the "news" file,
- * and the game aborts (cleanly) on failure, since without the
- * "news" file, it is likely that the "lib" folder has not been
- * correctly located. Otherwise, the news file is displayed for
- * the user.
- *
- * Note that this function attempts to verify (or create) the
- * "high score" file, and the game aborts (cleanly) on failure,
- * since one of the most common "extraction" failures involves
- * failing to extract all sub-directories (even empty ones), such
- * as by failing to use the "-d" option of "pkunzip", or failing
- * to use the "save empty directories" option with "Compact Pro".
- * This error will often be caught by the "high score" creation
- * code below, since the "lib/apex" directory, being empty in the
- * standard distributions, is most likely to be "lost", making it
- * impossible to create the high score file.
- *
- * Note that various things are initialised by this function,
- * including everything that was once done by "init_some_arrays".
- *
- * This initialisation involves the parsing of special files
- * in the "lib/data" and sometimes the "lib/edit" directories.
- *
- * Note that the "template" files are initialised first, since they
- * often contain errors. This means that macros and message recall
- * and things like that are not available until after they are done.
- *
- * We load the default "user pref files" here in case any "color"
- * changes are needed before character creation.
- *
- * Note that the "graf-xxx.prf" file must be loaded separately,
- * if needed, in the first (?) pass through "TERM_XTRA_REACT".
- */
-void init_angband(void)
-{
- int fd = -1;
-
- int mode = FILE_MODE;
-
- FILE *fp;
-
- char *news_file;
-
- char buf[1024];
-
- /* Init some VERY basic stuff, like macro arrays */
- init_basic();
-
- /* Select & init a module if needed */
- select_module();
-
- /*** Choose which news.txt file to use ***/
-
- /* Choose the news file */
- switch (time(NULL) % 2)
- {
- default:
- {
- news_file = "news.txt";
- break;
- }
-
- case 0:
- {
- news_file = "news2.txt";
- break;
- }
- }
-
- /*** Verify the "news" file ***/
-
- /* Build the filename */
- path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, news_file);
-
- /* Attempt to open the file */
- fd = fd_open(buf, O_RDONLY);
-
- /* Failure */
- if (fd < 0)
- {
- char why[1024];
-
- /* Message */
- sprintf(why, "Cannot access the '%s' file!", buf);
-
- /* Crash and burn */
- init_angband_aux(why);
- }
-
- /* Close it */
- (void)fd_close(fd);
-
-
- /*** Display the "news" file ***/
-
- /* Clear screen */
- Term_clear();
-
- /* Build the filename */
- path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, news_file);
-
- /* Open the News file */
- fp = my_fopen(buf, "r");
-
- /* Dump */
- if (fp)
- {
- int i = 0;
-
- /* Dump the file to the screen */
- while (0 == my_fgets(fp, buf, 1024))
- {
- /* Display and advance - we use display_message to parse colour codes XXX */
- display_message(0, i++, strlen(buf), TERM_WHITE, buf);
- }
-
- /* Close */
- my_fclose(fp);
- }
-
- /* Flush it */
- Term_fresh();
-
-
- /*** Verify (or create) the "high score" file ***/
-
- /* Build the filename */
- path_build(buf, 1024, ANGBAND_DIR_APEX, "scores.raw");
-
- /* Attempt to open the high score file */
- fd = fd_open(buf, O_RDONLY);
-
- /* Failure */
- if (fd < 0)
- {
- /* File type is "DATA" */
- FILE_TYPE(FILE_TYPE_DATA);
-
- /* Create a new high score file */
- fd = fd_make(buf, mode);
-
- /* Failure */
- if (fd < 0)
- {
- char why[1024];
-
- /* Message */
- sprintf(why, "Cannot create the '%s' file!", buf);
-
- /* Crash and burn */
- init_angband_aux(why);
- }
- }
-
- /* Close it */
- (void)fd_close(fd);
-
-
- /*** Initialise some arrays ***/
-
- /* Initialise misc. values */
- note("[Initialising values... (misc)]");
- if (init_misc()) quit("Cannot initialise misc. values");
-
- wipe_hooks();
-
- /* Initialise some other arrays */
- note("[Initialising lua scripting... (lua)]");
- init_lua();
- init_lua_init();
-
- /* Initialise skills info */
- note("[Initialising arrays... (skills)]");
- if (init_s_info()) quit("Cannot initialise skills");
-
- /* Initialise abilities info */
- note("[Initialising arrays... (abilities)]");
- if (init_ab_info()) quit("Cannot initialise abilities");
-
- /* Initialise alchemy info */
- note("[Initialising arrays... (alchemy)]");
- if (init_al_info()) quit("Cannot initialise alchemy");
-
- /* Initialise player info */
- note("[Initialising arrays... (players)]");
- if (init_player_info()) quit("Cannot initialise players");
-
- /* Initialise feature info */
- note("[Initialising arrays... (features)]");
- if (init_f_info()) quit("Cannot initialise features");
-
- /* Initialise object info */
- note("[Initialising arrays... (objects)]");
- if (init_k_info()) quit("Cannot initialise objects");
-
- /* Initialise artifact info */
- note("[Initialising arrays... (artifacts)]");
- if (init_a_info()) quit("Cannot initialise artifacts");
-
- /* Initialise set info */
- note("[Initialising item sets... (sets)]");
- if (init_set_info()) quit("Cannot initialise item sets");
- init_sets_aux();
-
- /* Initialise ego-item info */
- note("[Initialising arrays... (ego-items)]");
- if (init_e_info()) quit("Cannot initialise ego-items");
-
- /* Initialise randart parts info */
- note("[Initialising arrays... (randarts)]");
- if (init_ra_info()) quit("Cannot initialise randarts");
-
- /* Initialise monster info */
- note("[Initialising arrays... (monsters)]");
- if (init_r_info()) quit("Cannot initialise monsters");
-
- /* Initialise ego monster info */
- note("[Initialising arrays... (ego monsters)]");
- if (init_re_info()) quit("Cannot initialise ego monsters");
-
- /* Initialise dungeon type info */
- note("[Initialising arrays... (dungeon types)]");
- if (init_d_info()) quit("Cannot initialise dungeon types");
- init_guardians();
-
- /* Initialise actions type info */
- note("[Initialising arrays... (action types)]");
- if (init_ba_info()) quit("Cannot initialise action types");
-
- /* Initialise owners type info */
- note("[Initialising arrays... (owners types)]");
- if (init_ow_info()) quit("Cannot initialise owners types");
-
- /* Initialise stores type info */
- note("[Initialising arrays... (stores types)]");
- if (init_st_info()) quit("Cannot initialise stores types");
-
- /* Initialise wilderness features array */
- note("[Initialising arrays... (wilderness features)]");
- if (init_wf_info()) quit("Cannot initialise wilderness features");
-
- /* Initialise wilderness map array */
- note("[Initialising arrays... (wilderness map)]");
- if (init_wilderness()) quit("Cannot initialise wilderness map");
-
- /* Initialise town array */
- note("[Initialising arrays... (towns)]");
- if (init_towns()) quit("Cannot initialise towns");
-
- /* Initialise trap info */
- note("[Initialising arrays... (traps)]");
- if (init_t_info()) quit("Cannot initialise traps");
-
- /* Initialise some other arrays */
- note("[Initialising arrays... (other)]");
- if (init_other()) quit("Cannot initialise other stuff");
-
- /* Initialise some other arrays */
- note("[Initialising arrays... (alloc)]");
- if (init_alloc()) quit("Cannot initialise alloc stuff");
-
- /* Init random artifact names */
- build_prob(artifact_names_list);
-
- /*** Load default user pref files ***/
-
- /* Initialise feature info */
- note("[Initialising user pref files...]");
-
- /* Access the "basic" pref file */
- strcpy(buf, "pref.prf");
-
- /* Process that file */
- process_pref_file(buf);
-
- /* Access the "basic" system pref file */
- sprintf(buf, "pref-%s.prf", ANGBAND_SYS);
-
- /* Process that file */
- process_pref_file(buf);
-
- /* Access the "user" pref file */
- sprintf(buf, "user.prf");
-
- /* Process that file */
- process_pref_file(buf);
-
- /* Access the "user" system pref file */
- sprintf(buf, "user-%s.prf", ANGBAND_SYS);
-
- /* Process that file */
- 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);
-
- /* Done */
- note("[Initialisation complete]");
-
- process_hooks(HOOK_INIT_GAME, "(s)", "end");
-}
diff --git a/src/init2.cc b/src/init2.cc
new file mode 100644
index 00000000..894e4767
--- /dev/null
+++ b/src/init2.cc
@@ -0,0 +1,1278 @@
+#include "init2.hpp"
+#include "init2.h"
+
+#include "ability_type.hpp"
+#include "alloc_entry.hpp"
+#include "artifact_type.hpp"
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "cli_comm.hpp"
+#include "dungeon_info_type.hpp"
+#include "ego_item_type.hpp"
+#include "files.hpp"
+#include "feature_type.hpp"
+#include "game.hpp"
+#include "generate.hpp"
+#include "gen_evol.hpp"
+#include "gen_maze.hpp"
+#include "hooks.hpp"
+#include "init1.hpp"
+#include "lua_bind.hpp"
+#include "messages.hpp"
+#include "modules.hpp"
+#include "monster_ego.hpp"
+#include "monster_race.hpp"
+#include "monster_race_flag.hpp"
+#include "monster_type.hpp"
+#include "object_flag.hpp"
+#include "object_kind.hpp"
+#include "object_type.hpp"
+#include "owner_type.hpp"
+#include "player_class.hpp"
+#include "player_race.hpp"
+#include "player_race_mod.hpp"
+#include "q_library.hpp"
+#include "randart.hpp"
+#include "randart_part_type.hpp"
+#include "set_type.hpp"
+#include "skill_type.hpp"
+#include "spells3.hpp"
+#include "spells4.hpp"
+#include "spells5.hpp"
+#include "spells6.hpp"
+#include "squeltch.hpp"
+#include "store_action_type.hpp"
+#include "store_info_type.hpp"
+#include "store_type.hpp"
+#include "tables.hpp"
+#include "tome/make_array.hpp"
+#include "town_type.hpp"
+#include "util.hpp"
+#include "util.h"
+#include "variable.h"
+#include "variable.hpp"
+#include "vault_type.hpp"
+#include "wilderness_map.hpp"
+#include "wilderness_type_info.hpp"
+
+#include <cassert>
+#include <type_traits>
+
+/*
+ * 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
+ * the common limitation of "read()" and "write()" to only 32767 bytes
+ * at a time.
+ *
+ * Several of the arrays for Angband are built from "template" files in
+ * the "lib/file" directory, from which quick-load binary "image" files
+ * are constructed whenever they are not present in the "lib/data"
+ * directory, or if those files become obsolete, if we are allowed.
+ *
+ * Warning -- the "ascii" file parsers use a minor hack to collect the
+ * name and text information in a single pass. Thus, the game will not
+ * be able to load any template file with more than 20K of names or 60K
+ * of text, even though technically, up to 64K should be legal.
+ *
+ * The "init1.c" file is used only to parse the ascii template files.
+ */
+
+
+
+/*
+ * Find the default paths to all of our important sub-directories.
+ *
+ * The purpose of each sub-directory is described in "variable.c".
+ *
+ * All of the sub-directories should, by default, be located inside
+ * the main "lib" directory, whose location is very system dependant.
+ *
+ * This function takes a writable buffer, initially containing the
+ * "path" to the "lib" directory, for example, "/pkg/lib/angband/",
+ * or a system dependant string, for example, ":lib:". The buffer
+ * must be large enough to contain at least 32 more characters.
+ *
+ * Various command line options may allow some of the important
+ * directories to be changed to user-specified directories, most
+ * importantly, the "info" and "user" and "save" directories,
+ * but this is done after this function, see "main.c".
+ *
+ * In general, the initial path should end in the appropriate "PATH_SEP"
+ * string. All of the "sub-directory" paths (created below or supplied
+ * by the user) will NOT end in the "PATH_SEP" string, see the special
+ * "path_build()" function in "util.c" for more information.
+ *
+ * Mega-Hack -- support fat raw files under NEXTSTEP, using special
+ * "suffixed" directories for the "ANGBAND_DIR_DATA" directory, but
+ * requiring the directories to be created by hand by the user.
+ *
+ * Hack -- first we free all the strings, since this is known
+ * to succeed even if the strings have not been allocated yet,
+ * as long as the variables start out as "NULL". This allows
+ * this function to be called multiple times, for example, to
+ * try several base "path" values until a good one is found.
+ */
+void init_file_paths(char *path)
+{
+ char *tail;
+ int pathlen;
+
+ assert(path != nullptr);
+
+ /*** Free everything ***/
+
+ /* Free the main path */
+ free(ANGBAND_DIR);
+
+ /* Free the sub-paths */
+ free(ANGBAND_DIR_CORE);
+ free(ANGBAND_DIR_DNGN);
+ free(ANGBAND_DIR_DATA);
+ free(ANGBAND_DIR_EDIT);
+ free(ANGBAND_DIR_FILE);
+ free(ANGBAND_DIR_HELP);
+ free(ANGBAND_DIR_INFO);
+ free(ANGBAND_DIR_MODULES);
+ free(ANGBAND_DIR_NOTE);
+ free(ANGBAND_DIR_SAVE);
+ free(ANGBAND_DIR_PREF);
+ free(ANGBAND_DIR_USER);
+ free(ANGBAND_DIR_XTRA);
+
+
+ /*** Prepare the "path" ***/
+
+ pathlen = strlen(path);
+
+ /* Hack -- save the main directory without trailing PATH_SEP if present */
+ if (strlen(PATH_SEP) > 0 && pathlen > 0)
+ {
+ int seplen = strlen(PATH_SEP);
+
+ if (strcmp(path + pathlen - seplen, PATH_SEP) == 0)
+ {
+ path[pathlen - seplen] = '\0';
+ ANGBAND_DIR = strdup(path);
+ path[pathlen - seplen] = *PATH_SEP;
+ }
+ else
+ {
+ ANGBAND_DIR = strdup(path);
+ }
+ }
+ else
+ {
+ ANGBAND_DIR = strdup(path);
+ }
+
+ /* Prepare to append to the Base Path */
+ tail = path + pathlen;
+
+
+
+ /*** Build the sub-directory names ***/
+
+ /* Build a path name */
+ strcpy(tail, "core");
+ ANGBAND_DIR_CORE = strdup(path);
+
+ /* Build a path name */
+ strcpy(tail, "dngn");
+ ANGBAND_DIR_DNGN = strdup(path);
+
+ /* Build a path name */
+ strcpy(tail, "data");
+ ANGBAND_DIR_DATA = strdup(path);
+
+ /* Build a path name */
+ strcpy(tail, "edit");
+ ANGBAND_DIR_EDIT = strdup(path);
+
+ /* Build a path name */
+ strcpy(tail, "file");
+ ANGBAND_DIR_FILE = strdup(path);
+
+ /* Build a path name */
+ strcpy(tail, "help");
+ ANGBAND_DIR_HELP = strdup(path);
+
+ /* Build a path name */
+ strcpy(tail, "info");
+ ANGBAND_DIR_INFO = strdup(path);
+
+ /* Build a path name */
+ strcpy(tail, "mods");
+ ANGBAND_DIR_MODULES = strdup(path);
+
+ /* Build a path name */
+ strcpy(tail, "pref");
+ ANGBAND_DIR_PREF = strdup(path);
+
+ /* synchronize with module_reset_dir */
+ {
+ char user_path[1024];
+
+ /* Get an absolute path from the file name */
+ path_parse(user_path, 1024, PRIVATE_USER_PATH);
+ strcat(user_path, USER_PATH_VERSION);
+ ANGBAND_DIR_USER = strdup(user_path);
+ ANGBAND_DIR_NOTE = strdup(user_path);
+
+ /* Savefiles are in user directory */
+ strcat(user_path, "/save");
+ ANGBAND_DIR_SAVE = strdup(user_path);
+ }
+
+ /* Build a path name */
+ strcpy(tail, "xtra");
+ ANGBAND_DIR_XTRA = strdup(path);
+}
+
+
+
+/*
+ * Hack -- help give useful error messages
+ */
+s16b error_idx;
+s16b error_line;
+
+
+/*
+ * Standard error message text
+ */
+static cptr err_str[9] =
+{
+ NULL,
+ "parse error",
+ "obsolete file",
+ "missing record header",
+ "non-sequential records",
+ "invalid flag specification",
+ "undefined directive",
+ "out of memory",
+ "invalid skill chart"
+};
+
+
+/*
+ * Hack -- take notes on line 23
+ */
+static void note(cptr str)
+{
+ Term_erase(0, 23, 255);
+ Term_putstr(20, 23, -1, TERM_WHITE, str);
+ Term_fresh();
+}
+
+
+/*
+ * Traits for data arrays
+ */
+namespace {
+
+ struct f_info_traits {
+
+ static constexpr char const *name = "f_info.txt";
+
+ static errr parse(FILE *fp)
+ {
+ return init_f_info_txt(fp);
+ }
+
+ };
+
+ struct k_info_traits {
+
+ static constexpr char const *name = "k_info.txt";
+
+ static errr parse(FILE *fp)
+ {
+ return init_k_info_txt(fp);
+ };
+
+ };
+
+ struct set_info_traits {
+
+ static constexpr char const *name = "set_info.txt";
+
+ static errr parse(FILE *fp)
+ {
+ return init_set_info_txt(fp);
+ }
+
+ };
+
+ struct a_info_traits {
+
+ static constexpr char const *name = "a_info.txt";
+
+ static errr parse(FILE *fp)
+ {
+ return init_a_info_txt(fp);
+ }
+
+ };
+
+ struct s_info_traits {
+
+ static constexpr char const *name = "s_info.txt";
+
+ static errr parse(FILE *fp)
+ {
+ return init_s_info_txt(fp);
+ }
+
+ };
+
+ struct ab_info_traits {
+
+ static constexpr char const *name = "ab_info.txt";
+
+ static errr parse(FILE *fp)
+ {
+ return init_ab_info_txt(fp);
+ }
+
+ };
+
+ struct e_info_traits {
+
+ static constexpr char const *name = "e_info.txt";
+
+ static errr parse(FILE *fp)
+ {
+ return init_e_info_txt(fp);
+ }
+
+ };
+
+ struct ra_info_traits {
+
+ static constexpr char const *name = "ra_info.txt";
+
+ static errr parse(FILE *fp)
+ {
+ return init_ra_info_txt(fp);
+ }
+
+ };
+
+ struct r_info_traits {
+
+ static constexpr char const *name = "r_info.txt";
+
+ static errr parse(FILE *fp)
+ {
+ return init_r_info_txt(fp);
+ }
+
+ };
+
+ struct re_info_traits {
+
+ static constexpr char const *name = "re_info.txt";
+
+ static errr parse(FILE *fp)
+ {
+ return init_re_info_txt(fp);
+ }
+
+ };
+
+ struct d_info_traits {
+
+ static constexpr char const *name = "d_info.txt";
+
+ static errr parse(FILE *fp)
+ {
+ return init_d_info_txt(fp);
+ }
+
+ };
+
+ struct st_info_traits {
+
+ static constexpr char const *name = "st_info.txt";
+
+ static errr parse(FILE *fp)
+ {
+ return init_st_info_txt(fp);
+ }
+
+ };
+
+ struct ow_info_traits {
+
+ static constexpr char const *name = "ow_info.txt";
+
+ static errr parse(FILE *fp)
+ {
+ return init_ow_info_txt(fp);
+ }
+
+ };
+
+ struct ba_info_traits {
+
+ static constexpr char const *name = "ba_info.txt";
+
+ static errr parse(FILE *fp)
+ {
+ return init_ba_info_txt(fp);
+ }
+
+ };
+
+ struct wf_info_traits {
+
+ static constexpr char const *name = "wf_info.txt";
+
+ static errr parse(FILE *fp)
+ {
+ return init_wf_info_txt(fp);
+ }
+
+ };
+
+ struct v_info_traits {
+
+ static constexpr char const *name = "v_info.txt";
+
+ static errr parse(FILE *fp)
+ {
+ return init_v_info_txt(fp);
+ }
+
+ };
+
+ struct p_info_traits {
+
+ static constexpr char const *name = "p_info.txt";
+
+ static errr parse(FILE *fp)
+ {
+ return init_player_info_txt(fp);
+ }
+
+ };
+
+}
+
+template<typename T> static errr init_x_info() {
+
+ /* Build the filename */
+ boost::filesystem::path path(ANGBAND_DIR_EDIT);
+ path /= T::name;
+
+ /* Open the file */
+ FILE *fp = my_fopen(path.c_str(), "r");
+
+ /* Parse it */
+ if (!fp)
+ {
+ quit_fmt("Cannot open '%s' file.", T::name);
+ }
+
+ /* Parse the file */
+ errr err = T::parse(fp);
+
+ /* Close it */
+ my_fclose(fp);
+
+ /* Errors */
+ if (err)
+ {
+ /* Error string */
+ cptr oops = (((err > 0) && (err < 8)) ? err_str[err] : "unknown");
+
+ /* Oops */
+ msg_format("Error %d at line %d of '%s'.", err, error_line, T::name);
+ msg_format("Record %d contains a '%s' error.", error_idx, oops);
+ msg_print(NULL);
+
+ /* Quit */
+ quit_fmt("Error in '%s' file.", T::name);
+ }
+
+ /* Success */
+ return (0);
+}
+
+errr init_v_info()
+{
+ return init_x_info<v_info_traits>();
+}
+
+/*
+ * Initialize the very basic arrays
+ */
+static void init_basic()
+{
+ /* Macro variables */
+ macro__pat = make_array<char *>(MACRO_MAX);
+ macro__act = make_array<char *>(MACRO_MAX);
+ macro__cmd = make_array<bool_>(MACRO_MAX);
+
+ /* Macro action buffer */
+ macro__buf = make_array<char>(1024);
+
+ /* Extended trigger macros */
+ cli_info = make_array<cli_comm>(CLI_MAX);
+
+ /* Options */
+ options = new struct options();
+}
+
+
+/*
+ * Initialise misc. values
+ */
+static errr init_misc()
+{
+ int xstart = 0;
+ int ystart = 0;
+ int i;
+
+ /*** Prepare the various "bizarre" arrays ***/
+
+ /* Initialise the values */
+ process_dungeon_file("misc.txt", &ystart, &xstart, 0, 0, TRUE, FALSE);
+
+ /* Init the spell effects */
+ for (i = 0; i < MAX_EFFECTS; i++)
+ effects[i].time = 0;
+
+ /* Initialize timers */
+ TIMER_INERTIA_CONTROL =
+ new_timer(meta_inertia_control_timer_callback,
+ 10);
+ TIMER_AGGRAVATE_EVIL =
+ new_timer(timer_aggravate_evil_callback,
+ 10);
+
+ return 0;
+}
+
+
+/*
+ * Initialise town array
+ */
+static errr init_towns()
+{
+ auto const &st_info = game->edit_data.st_info;
+
+ town_info = new town_type[max_towns];
+
+ for (std::size_t i = 1; i < max_towns; i++)
+ {
+ if (i <= max_real_towns)
+ {
+ town_info[i].flags |= TOWN_REAL;
+ }
+
+ /* Fill in each store */
+ for (std::size_t j = 0; j < st_info.size(); j++)
+ {
+ /* Create the store */
+ town_info[i].store.emplace_back(store_type());
+ store_type *st_ptr = &town_info[i].store[j];
+
+ /* Know who we are */
+ st_ptr->st_idx = j;
+
+ /* Assume full stock */
+ st_ptr->stock_size = 0;
+ }
+ }
+
+ return 0;
+}
+
+void create_stores_stock(int t)
+{
+ auto const &st_info = game->edit_data.st_info;
+
+ town_type *t_ptr = &town_info[t];
+
+ if (t_ptr->stocked) return;
+
+ for (std::size_t j = 0; j < st_info.size(); j++)
+ {
+ store_type *st_ptr = &t_ptr->store[j];
+
+ /* Assume full stock */
+ st_ptr->stock_size = st_info[j].max_obj;
+
+ /* Reserve space for stock */
+ st_ptr->stock.reserve(st_ptr->stock_size);
+ }
+
+ t_ptr->stocked = TRUE;
+}
+
+/*
+ * Initialise some other arrays
+ */
+static errr init_other()
+{
+ auto const &d_info = game->edit_data.d_info;
+ auto const &r_info = game->edit_data.r_info;
+ auto const &k_info = game->edit_data.k_info;
+ auto const &a_info = game->edit_data.a_info;
+ auto &level_markers = game->level_markers;
+
+ /*** Prepare the "dungeon" information ***/
+
+ /* Allocate and Wipe the special gene flags */
+ m_allow_special = make_array<bool_>(r_info.size());
+ k_allow_special = make_array<bool_>(k_info.size());
+ a_allow_special = make_array<bool_>(a_info.size());
+
+
+ /*** Prepare "vinfo" array ***/
+
+ /* Used by "update_view()" */
+ vinfo_init();
+
+
+ /* Allocate and Wipe the object list */
+ o_list = new object_type[max_o_idx];
+
+ /* Allocate and Wipe the monster list */
+ m_list = new monster_type[max_m_idx];
+
+ /* Allocate and Wipe the to keep monster list */
+ km_list = new monster_type[max_m_idx];
+
+ /* Allocate and Wipe the max dungeon level */
+ max_dlv = make_array<s16b>(d_info.size());
+
+ /* Allocate level markers */
+ level_markers.resize(boost::extents[MAX_DUNGEON_DEPTH][d_info.size()]);
+
+ /* Allocate and wipe each line of the cave */
+ cave = new cave_type *[MAX_HGT];
+ for (std::size_t i = 0; i < MAX_HGT; i++)
+ {
+ /* Allocate one row of the cave */
+ cave[i] = new cave_type[MAX_WID];
+ }
+
+ /* Analyze the windows */
+ for (std::size_t n = 0; n < 8; n++)
+ {
+ /* Analyze the options */
+ for (std::size_t i = 0; i < 32; i++)
+ {
+ /* Accept */
+ if (window_flag_desc[i])
+ {
+ /* Accept */
+ window_mask[n] |= (1L << i);
+ }
+ }
+ }
+
+
+ /*
+ * Install the various level generators
+ */
+ add_level_generator("dungeon", level_generate_dungeon);
+ add_level_generator("maze", level_generate_maze);
+ add_level_generator("life", level_generate_life);
+
+ /*** Pre-allocate space for the "format()" buffer ***/
+
+ /* Hack -- Just call the "format()" function */
+ format("%s (%s).", "Dark God <darkgod@t-o-m-e.net>", MAINTAINER);
+
+ /* Success */
+ return (0);
+}
+
+
+
+/*
+ * Initialise some other arrays
+ */
+static errr init_alloc()
+{
+ auto const &r_info = game->edit_data.r_info;
+ auto const &k_info = game->edit_data.k_info;
+ auto &alloc = game->alloc;
+
+ s16b num[MAX_DEPTH_MONSTER];
+
+ s16b aux[MAX_DEPTH_MONSTER];
+
+ /*** Analyze object allocation info ***/
+
+ /* Clear the "aux" array */
+ memset(aux, 0, MAX_DEPTH_MONSTER * sizeof(s16b));
+
+ /* Clear the "num" array */
+ memset(num, 0, MAX_DEPTH_MONSTER * sizeof(s16b));
+
+ /* Scan the objects */
+ std::size_t kind_size = 0;
+ for (auto const &k_ref: k_info)
+ {
+ auto k_ptr = &k_ref;
+
+ /* Scan allocation pairs */
+ for (std::size_t j = 0; j < ALLOCATION_MAX; j++)
+ {
+ /* Count the "legal" entries */
+ if (k_ptr->chance[j])
+ {
+ /* Count the entries */
+ kind_size++;
+
+ /* Group by level */
+ num[k_ptr->locale[j]]++;
+ }
+ }
+ }
+
+ /* Collect the level indexes */
+ for (std::size_t i = 1; i < MAX_DEPTH_MONSTER; i++)
+ {
+ /* Group by level */
+ num[i] += num[i - 1];
+ }
+
+ /* Paranoia */
+ if (!num[0]) quit("No town objects!");
+
+
+ /*** Initialise object allocation info ***/
+
+ /* Allocate the alloc_kind_table */
+ alloc.kind_table.clear();
+ alloc.kind_table.resize(kind_size);
+
+ /* Scan the objects */
+ for (std::size_t i = 1; i < k_info.size(); i++)
+ {
+ auto k_ptr = &k_info[i];
+
+ /* Scan allocation pairs */
+ for (std::size_t j = 0; j < ALLOCATION_MAX; j++)
+ {
+ /* Count the "legal" entries */
+ if (k_ptr->chance[j])
+ {
+ int p, x, y, z;
+
+ /* Extract the base level */
+ x = k_ptr->locale[j];
+
+ /* Extract the base probability */
+ p = (100 / k_ptr->chance[j]);
+
+ /* Skip entries preceding our locale */
+ y = (x > 0) ? num[x - 1] : 0;
+
+ /* Skip previous entries at this locale */
+ z = y + aux[x];
+
+ /* Load the entry */
+ auto &entry = alloc.kind_table[z];
+ entry.index = i;
+ entry.level = x;
+ entry.prob1 = p;
+ entry.prob2 = p;
+ entry.prob3 = p;
+
+ /* Another entry complete for this locale */
+ aux[x]++;
+ }
+ }
+ }
+
+
+ /*** Analyze monster allocation info ***/
+
+ /* Clear the "aux" array */
+ memset(aux, 0, MAX_DEPTH_MONSTER * sizeof(s16b));
+
+ /* Clear the "num" array */
+ memset(num, 0, MAX_DEPTH_MONSTER * sizeof(s16b));
+
+ /* Scan the monsters */
+ std::size_t race_size = 0;
+ for (auto &r_ref: r_info)
+ {
+ /* Get the i'th race */
+ auto r_ptr = &r_ref;
+
+ /* Legal monsters */
+ if (r_ptr->rarity)
+ {
+ /* Count the entries */
+ race_size++;
+
+ /* Group by level */
+ num[r_ptr->level]++;
+ }
+ }
+
+ /* Collect the level indexes */
+ for (std::size_t i = 1; i < MAX_DEPTH_MONSTER; i++)
+ {
+ /* Group by level */
+ num[i] += num[i - 1];
+ }
+
+ /* Paranoia */
+ if (!num[0]) quit("No town monsters!");
+
+
+ /*** Initialise monster allocation info ***/
+
+ /* Allocate the alloc_race_table */
+ alloc.race_table.clear();
+ alloc.race_table.resize(race_size);
+
+ /* Scan the monsters */
+ for (std::size_t i = 1; i < r_info.size(); i++)
+ {
+ /* Get the i'th race */
+ auto r_ptr = &r_info[i];
+
+ /* Count valid pairs */
+ if (r_ptr->rarity)
+ {
+ int p, x, y, z;
+
+ /* Extract the base level */
+ x = r_ptr->level;
+
+ /* Extract the base probability */
+ p = (100 / r_ptr->rarity);
+
+ /* Skip entries preceding our locale */
+ y = (x > 0) ? num[x - 1] : 0;
+
+ /* Skip previous entries at this locale */
+ z = y + aux[x];
+
+ /* Load the entry */
+ auto &entry = alloc.race_table[z];
+ entry.index = i;
+ entry.level = x;
+ entry.prob1 = p;
+ entry.prob2 = p;
+ entry.prob3 = p;
+
+ /* Another entry complete for this locale */
+ aux[x]++;
+ }
+ }
+
+
+ /* Success */
+ return (0);
+}
+
+/* Init the sets in a_info */
+static void init_sets_aux()
+{
+ auto const &set_info = game->edit_data.set_info;
+ auto &a_info = game->edit_data.a_info;
+
+ for (auto &a_ref: a_info)
+ {
+ a_ref.set = -1;
+ }
+
+ for (std::size_t i = 0; i < set_info.size(); i++)
+ {
+ auto const &set_ref = set_info[i];
+
+ for (std::size_t j = 0; j < set_ref.num; j++)
+ {
+ a_info[set_ref.arts[j].a_idx].set = i;
+ }
+ }
+}
+
+/*
+ * Mark guardians and their artifacts with SPECIAL_GENE flag
+ */
+static void init_guardians()
+{
+ auto const &d_info = game->edit_data.d_info;
+ auto &r_info = game->edit_data.r_info;
+ auto &k_info = game->edit_data.k_info;
+ auto &a_info = game->edit_data.a_info;
+
+ /* Scan dungeons */
+ for (std::size_t i = 0; i < d_info.size(); i++)
+ {
+ auto d_ptr = &d_info[i];
+
+ /* Mark the guadian monster */
+ if (d_ptr->final_guardian)
+ {
+ auto r_ptr = &r_info[d_ptr->final_guardian];
+
+ r_ptr->flags |= RF_SPECIAL_GENE;
+
+ /* Mark the final artifact */
+ if (d_ptr->final_artifact)
+ {
+ auto a_ptr = &a_info[d_ptr->final_artifact];
+ a_ptr->flags |= TR_SPECIAL_GENE;
+ }
+
+ /* Mark the final object */
+ if (d_ptr->final_object)
+ {
+ auto k_ptr = &k_info[d_ptr->final_object];
+ k_ptr->flags |= TR_SPECIAL_GENE;
+ }
+
+ /* Give randart if there are no final artifacts */
+ if (!(d_ptr->final_artifact) && !(d_ptr->final_object))
+ {
+ r_ptr->flags |= RF_DROP_RANDART;
+ }
+ }
+ }
+}
+
+/*
+ * Hack -- Explain a broken "lib" folder and quit (see below).
+ *
+ * XXX XXX XXX This function is "messy" because various things
+ * may or may not be initialised, but the "plog()" and "quit()"
+ * functions are "supposed" to work under any conditions.
+ */
+static void init_angband_aux(cptr why)
+{
+ /* Why */
+ plog(why);
+
+ /* Explain */
+ plog("The 'lib' directory is probably missing or broken.");
+
+ /* More details */
+ plog("Perhaps the archive was not extracted correctly.");
+
+ /* Explain */
+ plog("See the 'README' file for more information.");
+
+ /* Quit with error */
+ quit("Fatal Error.");
+}
+
+/*
+ * Hack -- main Angband initialisation entry point
+ *
+ * Verify some files, display the "news.txt" file, create
+ * the high score file, initialise all internal arrays, and
+ * load the basic "user pref files".
+ *
+ * Note that we blindly assume that "news2.txt" exists. XXX
+ *
+ * Be very careful to keep track of the order in which things
+ * are initialised, in particular, the only thing *known* to
+ * be available when this function is called is the "z-term.c"
+ * package, and that may not be fully initialised until the
+ * end of this function, when the default "user pref files"
+ * are loaded and "Term_xtra(TERM_XTRA_REACT,0)" is called.
+ *
+ * Note that this function attempts to verify the "news" file,
+ * and the game aborts (cleanly) on failure, since without the
+ * "news" file, it is likely that the "lib" folder has not been
+ * correctly located. Otherwise, the news file is displayed for
+ * the user.
+ *
+ * Note that this function attempts to verify (or create) the
+ * "high score" file, and the game aborts (cleanly) on failure,
+ * since one of the most common "extraction" failures involves
+ * failing to extract all sub-directories (even empty ones), such
+ * as by failing to use the "-d" option of "pkunzip", or failing
+ * to use the "save empty directories" option with "Compact Pro".
+ * This error will often be caught by the "high score" creation
+ * code below, since the "lib/apex" directory, being empty in the
+ * standard distributions, is most likely to be "lost", making it
+ * impossible to create the high score file.
+ *
+ * Note that various things are initialised by this function,
+ * including everything that was once done by "init_some_arrays".
+ *
+ * This initialisation involves the parsing of special files
+ * in the "lib/data" and sometimes the "lib/edit" directories.
+ *
+ * Note that the "template" files are initialised first, since they
+ * often contain errors. This means that macros and message recall
+ * and things like that are not available until after they are done.
+ *
+ * We load the default "user pref files" here in case any "color"
+ * changes are needed before character creation.
+ *
+ * Note that the "graf-xxx.prf" file must be loaded separately,
+ * if needed, in the first (?) pass through "TERM_XTRA_REACT".
+ */
+void init_angband()
+{
+ int fd = -1;
+
+ int mode = FILE_MODE;
+
+ FILE *fp;
+
+ const char *news_file;
+
+ char buf[1024];
+
+ /* Init some VERY basic stuff, like macro arrays */
+ init_basic();
+
+ /* Select & init a module if needed */
+ select_module();
+
+ /*** Choose which news.txt file to use ***/
+
+ /* Choose the news file */
+ switch (time(NULL) % 2)
+ {
+ default:
+ {
+ news_file = "news.txt";
+ break;
+ }
+
+ case 0:
+ {
+ news_file = "news2.txt";
+ break;
+ }
+ }
+
+ /*** Verify the "news" file ***/
+
+ /* Build the filename */
+ path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, news_file);
+
+ /* Attempt to open the file */
+ fd = fd_open(buf, O_RDONLY);
+
+ /* Failure */
+ if (fd < 0)
+ {
+ char why[1024];
+
+ /* Message */
+ sprintf(why, "Cannot access the '%s' file!", buf);
+
+ /* Crash and burn */
+ init_angband_aux(why);
+ }
+
+ /* Close it */
+ fd_close(fd);
+
+
+ /*** Display the "news" file ***/
+
+ /* Clear screen */
+ Term_clear();
+
+ /* Build the filename */
+ path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, news_file);
+
+ /* Open the News file */
+ fp = my_fopen(buf, "r");
+
+ /* Dump */
+ if (fp)
+ {
+ int i = 0;
+
+ /* Dump the file to the screen */
+ while (0 == my_fgets(fp, buf, 1024))
+ {
+ /* Display and advance - we use display_message to parse colour codes XXX */
+ display_message(0, i++, strlen(buf), TERM_WHITE, buf);
+ }
+
+ /* Close */
+ my_fclose(fp);
+ }
+
+ /* Flush it */
+ Term_fresh();
+
+
+ /*** Verify (or create) the "high score" file ***/
+
+ /* Build the filename */
+ path_build(buf, 1024, ANGBAND_DIR_USER, "scores.raw");
+
+ /* Attempt to open the high score file */
+ fd = fd_open(buf, O_RDONLY);
+
+ /* Failure */
+ if (fd < 0)
+ {
+ /* Create a new high score file */
+ fd = fd_make(buf, mode);
+
+ /* Failure */
+ if (fd < 0)
+ {
+ char why[1024];
+
+ /* Message */
+ sprintf(why, "Cannot create the '%s' file!", buf);
+
+ /* Crash and burn */
+ init_angband_aux(why);
+ }
+ }
+
+ /* Close it */
+ fd_close(fd);
+
+ /*** Initialise some arrays ***/
+
+ /* Initialise misc. values */
+ note("[Initialising values... (misc)]");
+ if (init_misc()) quit("Cannot initialise misc. values");
+
+ /* Initialise some other arrays */
+ {
+ note("[Initialising scripting... (script)]");
+
+ /* Initialize schooled spells */
+ schools_init();
+ school_spells_init();
+ init_school_books();
+
+ /* Post-spell creation initialization */
+ initialize_bookable_spells();
+
+ /* Finish up the corruptions */
+ init_corruptions();
+ }
+
+ /* Initialise skills info */
+ note("[Initialising arrays... (skills)]");
+ if (init_x_info<s_info_traits>()) quit("Cannot initialise skills");
+
+ /* Initialise abilities info */
+ note("[Initialising arrays... (abilities)]");
+ if (init_x_info<ab_info_traits>()) quit("Cannot initialise abilities");
+
+ /* Initialise player info */
+ note("[Initialising arrays... (players)]");
+ if (init_x_info<p_info_traits>()) quit("Cannot initialise players");
+
+ /* Initialise feature info */
+ note("[Initialising arrays... (features)]");
+ if (init_x_info<f_info_traits>()) quit("Cannot initialise features");
+
+ /* Initialise object info */
+ note("[Initialising arrays... (objects)]");
+ if (init_x_info<k_info_traits>()) quit("Cannot initialise objects");
+
+ /* Initialise artifact info */
+ note("[Initialising arrays... (artifacts)]");
+ if (init_x_info<a_info_traits>()) quit("Cannot initialise artifacts");
+
+ /* Initialise set info */
+ note("[Initialising item sets... (sets)]");
+ if (init_x_info<set_info_traits>()) quit("Cannot initialise item sets");
+ init_sets_aux();
+
+ /* Initialise ego-item info */
+ note("[Initialising arrays... (ego-items)]");
+ if (init_x_info<e_info_traits>()) quit("Cannot initialise ego-items");
+
+ /* Initialise randart parts info */
+ note("[Initialising arrays... (randarts)]");
+ if (init_x_info<ra_info_traits>()) quit("Cannot initialise randarts");
+
+ /* Initialise monster info */
+ note("[Initialising arrays... (monsters)]");
+ if (init_x_info<r_info_traits>()) quit("Cannot initialise monsters");
+
+ /* Initialise ego monster info */
+ note("[Initialising arrays... (ego monsters)]");
+ if (init_x_info<re_info_traits>()) quit("Cannot initialise ego monsters");
+
+ /* Initialise dungeon type info */
+ note("[Initialising arrays... (dungeon types)]");
+ if (init_x_info<d_info_traits>()) quit("Cannot initialise dungeon types");
+ init_guardians();
+
+ /* Initialise actions type info */
+ note("[Initialising arrays... (action types)]");
+ if (init_x_info<ba_info_traits>()) quit("Cannot initialise action types");
+
+ /* Initialise owners type info */
+ note("[Initialising arrays... (owners types)]");
+ if (init_x_info<ow_info_traits>()) quit("Cannot initialise owners types");
+
+ /* Initialise stores type info */
+ note("[Initialising arrays... (stores types)]");
+ if (init_x_info<st_info_traits>()) quit("Cannot initialise stores types");
+
+ /* Initialise wilderness features array */
+ note("[Initialising arrays... (wilderness features)]");
+ if (init_x_info<wf_info_traits>()) quit("Cannot initialise wilderness features");
+
+ /* Initialise town array */
+ note("[Initialising arrays... (towns)]");
+ if (init_towns()) quit("Cannot initialise towns");
+
+ /* Initialise some other arrays */
+ note("[Initialising arrays... (other)]");
+ if (init_other()) quit("Cannot initialise other stuff");
+
+ /* Initialise some other arrays */
+ note("[Initialising arrays... (alloc)]");
+ if (init_alloc()) quit("Cannot initialise alloc stuff");
+
+ /* Init random artifact names */
+ build_prob(artifact_names_list);
+
+ /* Initialize the automatizer */
+ automatizer_init();
+
+ /*** Load default user pref files ***/
+
+ /* Initialise feature info */
+ note("[Initialising user pref files...]");
+
+ /* Access the "basic" pref file */
+ strcpy(buf, "pref.prf");
+
+ /* Process that file */
+ process_pref_file(buf);
+
+ /* Access the "basic" system pref file */
+ sprintf(buf, "pref-%s.prf", ANGBAND_SYS);
+
+ /* Process that file */
+ process_pref_file(buf);
+
+ /* Access the "user" pref file */
+ sprintf(buf, "user.prf");
+
+ /* Process that file */
+ process_pref_file(buf);
+
+ /* Access the "user" system pref file */
+ sprintf(buf, "user-%s.prf", ANGBAND_SYS);
+
+ /* Process that file */
+ process_pref_file(buf);
+
+ /* Done */
+ note("[Initialisation complete]");
+}
diff --git a/src/init2.h b/src/init2.h
new file mode 100644
index 00000000..bdc525bf
--- /dev/null
+++ b/src/init2.h
@@ -0,0 +1,13 @@
+#pragma once
+
+// C linkage required for these functions since main-* code uses them.
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void init_file_paths(char *path);
+void init_angband();
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/src/init2.hpp b/src/init2.hpp
new file mode 100644
index 00000000..de575e77
--- /dev/null
+++ b/src/init2.hpp
@@ -0,0 +1,9 @@
+#pragma once
+
+#include "h-basic.h"
+
+void init_corruptions();
+void create_stores_stock(int t);
+errr init_v_info();
+extern s16b error_idx;
+extern s16b error_line;
diff --git a/src/inscription_info_type.hpp b/src/inscription_info_type.hpp
new file mode 100644
index 00000000..4e1e4c32
--- /dev/null
+++ b/src/inscription_info_type.hpp
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * Inscriptions
+ */
+struct inscription_info_type
+{
+ char text[40]; /* The inscription itself */
+ byte when; /* When it is executed */
+ byte mana; /* Grid mana needed */
+};
diff --git a/src/inventory.hpp b/src/inventory.hpp
new file mode 100644
index 00000000..775f7a7e
--- /dev/null
+++ b/src/inventory.hpp
@@ -0,0 +1,35 @@
+#pragma once
+
+/*
+ * Maximum number of "normal" pack slots, and the index of the "overflow"
+ * slot, which can hold an item, but only temporarily, since it causes the
+ * pack to "overflow", dropping the "last" item onto the ground. Since this
+ * value is used as an actual slot, it must be less than "INVEN_WIELD" (below).
+ * Note that "INVEN_PACK" is probably hard-coded by its use in savefiles, and
+ * by the fact that the screen can only show 23 items plus a one-line prompt.
+ */
+#define INVEN_PACK 23
+
+/*
+ * Indexes used for various "equipment" slots (hard-coded by savefiles, etc).
+ */
+#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 */
+
+/*
+ * Total number of inventory slots (hard-coded).
+ */
+#define INVEN_TOTAL 52
+#define INVEN_EQ (INVEN_TOTAL - INVEN_WIELD)
diff --git a/src/iso/.cvsignore b/src/iso/.cvsignore
deleted file mode 100644
index f8d9fd47..00000000
--- a/src/iso/.cvsignore
+++ /dev/null
@@ -1 +0,0 @@
-.sconsign
diff --git a/src/joke.cc b/src/joke.cc
new file mode 100644
index 00000000..07149b3f
--- /dev/null
+++ b/src/joke.cc
@@ -0,0 +1,40 @@
+#include "joke.hpp"
+
+#include "monster2.hpp"
+#include "options.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+#include "z-rand.hpp"
+
+static void gen_joke_place_monster(int 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 (options->joke_monsters)
+ {
+ if ((dungeon_type == 20) &&
+ (dun_level == 72))
+ {
+ int r_idx = test_monster_name("Neil, the Sorceror");
+ m_allow_special[r_idx] = TRUE;
+ gen_joke_place_monster(r_idx);
+ m_allow_special[r_idx] = FALSE;
+ }
+ }
+
+ return FALSE;
+}
diff --git a/src/joke.hpp b/src/joke.hpp
new file mode 100644
index 00000000..2721636e
--- /dev/null
+++ b/src/joke.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+bool gen_joke_monsters(void *data, void *in, void *out);
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 <stddef.h>
-#include <stdio.h>
-
-#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/level_marker.cc b/src/level_marker.cc
new file mode 100644
index 00000000..ee1d8ebe
--- /dev/null
+++ b/src/level_marker.cc
@@ -0,0 +1,12 @@
+#include "level_marker.hpp"
+
+EnumStringMap<level_marker> const &level_marker_values()
+{
+ auto static instance = new EnumStringMap<level_marker> {
+ { level_marker::NORMAL, "normal" },
+ { level_marker::SPECIAL, "special" },
+ { level_marker::REGENERATE, "regenerate" }
+ };
+
+ return *instance;
+}
diff --git a/src/level_marker.hpp b/src/level_marker.hpp
new file mode 100644
index 00000000..07925b70
--- /dev/null
+++ b/src/level_marker.hpp
@@ -0,0 +1,25 @@
+#pragma once
+
+#include <tome/enum_string_map.hpp>
+
+/**
+ * Markers for 'special' levels.
+ */
+enum class level_marker {
+ NORMAL,
+ SPECIAL,
+ REGENERATE
+};
+
+/**
+ * Is the level "normal"?
+ */
+inline bool is_normal_level(level_marker m)
+{
+ return m == level_marker::NORMAL;
+}
+
+/**
+ * Bidrectional map between enum and strings.
+ */
+EnumStringMap<level_marker> const &level_marker_values();
diff --git a/src/levels.c b/src/levels.cc
index 71148fc5..2a1bb3ab 100644
--- a/src/levels.c
+++ b/src/levels.cc
@@ -1,7 +1,3 @@
-/* File: levels.c */
-
-/* Purpose: Levels functions */
-
/*
* Copyright (c) 1989 James E. Wilson, Robert A. Koeneke
*
@@ -10,14 +6,22 @@
* included in all such copies.
*/
-#include "angband.h"
+#include "levels.hpp"
+
+#include "dungeon_info_type.hpp"
+#include "game.hpp"
+#include "init1.hpp"
+#include "util.hpp"
+#include "util.h"
+#include "variable.h"
+#include "variable.hpp"
/*
* Return the parameter of the given command in the given file
*/
static int start_line = 0;
-bool_ get_command(const char *file, char comm, char *param)
+static bool_ get_command(const char *file, char comm, char *param)
{
char buf[1024];
int i = -1;
@@ -75,6 +79,8 @@ bool_ get_command(const char *file, char comm, char *param)
*/
int get_branch()
{
+ auto const &d_info = game->edit_data.d_info;
+
char file[20], buf[5];
sprintf(file, "dun%d.%d", dungeon_type, dun_level - d_info[dungeon_type].mindepth);
@@ -92,6 +98,8 @@ int get_branch()
*/
int get_fbranch()
{
+ auto const &d_info = game->edit_data.d_info;
+
char file[20], buf[5];
sprintf(file, "dun%d.%d", dungeon_type, dun_level - d_info[dungeon_type].mindepth);
@@ -109,6 +117,8 @@ int get_fbranch()
*/
int get_flevel()
{
+ auto const &d_info = game->edit_data.d_info;
+
char file[20], buf[5];
sprintf(file, "dun%d.%d", dungeon_type, dun_level - d_info[dungeon_type].mindepth);
@@ -126,6 +136,8 @@ int get_flevel()
*/
bool_ get_dungeon_save(char *buf)
{
+ auto const &d_info = game->edit_data.d_info;
+
char file[20];
sprintf(file, "dun%d.%d", dungeon_type, dun_level - d_info[dungeon_type].mindepth);
@@ -141,8 +153,9 @@ bool_ get_dungeon_save(char *buf)
*/
bool_ get_dungeon_generator(char *buf)
{
- char file[20];
+ auto const &d_info = game->edit_data.d_info;
+ char file[20];
sprintf(file, "dun%d.%d", dungeon_type, dun_level - d_info[dungeon_type].mindepth);
/* Get and return the level */
@@ -156,8 +169,9 @@ bool_ get_dungeon_generator(char *buf)
*/
bool_ get_dungeon_special(char *buf)
{
- char file[20];
+ auto const &d_info = game->edit_data.d_info;
+ char file[20];
sprintf(file, "dun%d.%d", dungeon_type, dun_level - d_info[dungeon_type].mindepth);
/* Get and return the level */
@@ -171,8 +185,9 @@ bool_ get_dungeon_special(char *buf)
*/
bool_ get_dungeon_name(char *buf)
{
- char file[20];
+ auto const &d_info = game->edit_data.d_info;
+ char file[20];
sprintf(file, "dun%d.%d", dungeon_type, dun_level - d_info[dungeon_type].mindepth);
/* Get and return the level */
@@ -186,6 +201,8 @@ bool_ get_dungeon_name(char *buf)
*/
void get_level_flags()
{
+ auto const &d_info = game->edit_data.d_info;
+
char file[20];
char buf[1024], *s, *t;
@@ -210,7 +227,7 @@ void get_level_flags()
}
/* Parse this entry */
- if (0 != grab_one_dungeon_flag(&dungeon_flags1, &dungeon_flags2, s)) return;
+ if (0 != grab_one_dungeon_flag(&dungeon_flags, s)) return;
/* Start the next entry */
s = t;
@@ -223,8 +240,9 @@ void get_level_flags()
*/
bool_ get_level_desc(char *buf)
{
- char file[20];
+ auto const &d_info = game->edit_data.d_info;
+ char file[20];
sprintf(file, "dun%d.%d", dungeon_type, dun_level - d_info[dungeon_type].mindepth);
/* Get and return the level */
diff --git a/src/levels.hpp b/src/levels.hpp
new file mode 100644
index 00000000..a48f1d95
--- /dev/null
+++ b/src/levels.hpp
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "h-basic.h"
+
+bool_ get_dungeon_generator(char *buf);
+bool_ get_level_desc(char *buf);
+void get_level_flags();
+bool_ get_dungeon_name(char *buf);
+bool_ get_dungeon_special(char *buf);
+int get_branch();
+int get_fbranch();
+int get_flevel();
+bool_ get_dungeon_save(char *buf);
diff --git a/src/loadsave.c b/src/loadsave.c
deleted file mode 100644
index 8cdb9f72..00000000
--- a/src/loadsave.c
+++ /dev/null
@@ -1,3288 +0,0 @@
-/* File: loadsave.c */
-
-/* Purpose: interact with savefiles. This file was made by
- unifying load2.c and save.c from the old codebase. Doing it
- this way makes maintenance easier and lets us share code. */
-
-#include "angband.h"
-
-static void do_byte(byte *, int);
-static void do_u16b(u16b *, int);
-static void do_s16b(s16b *, int);
-static void do_u32b(u32b *, int);
-static void do_s32b(s32b *, int);
-static void do_string(char *, int, int);
-static void do_lore(int, int);
-static void do_monster(monster_type *, int);
-static void do_randomizer(int flag);
-static void do_spells(int, int);
-static void note(cptr);
-static void do_fate(int, int);
-static void do_item(object_type *, int);
-static void do_options(int);
-static bool_ do_store(store_type *, int);
-static void do_messages(int flag);
-static void do_xtra(int, int);
-static bool_ do_savefile_aux(int);
-static void junkinit(void);
-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 do_ver_s16b(s16b *, u32b, s16b, int);
-
-static void skip_ver_byte(u32b, int);
-
-errr rd_savefile(void);
-
-static FILE *fff; /* Local savefile ptr */
-
-/*
- * Basic byte-level reading from savefile. This provides a single point
- * of interface to the pseudoencryption that ToME (and Angband)
- * uses. I'm thinking about if it might be faster/better to modify all
- * the do_* functions to directly do this stuff -- it'd make the code
- * somewhat uglier to maintain, but concievably might be much faster. Or
- * is it better maybe to scrap the pseudoencryption entirely and adopt
- * some other means of obfuscation, should it still prove useful in any
- * way? -- Improv
- *
- * What's the point of encryption on savefiles anyway? If I wanted to
- * make a cheater savefile, I'd activate debug mode, and hack the game
- * not to save it. There's no point. -- takkaria
- */
-
-static byte sf_get(void)
-{
- byte c;
-
- /* Get a character, decode the value */
- c = getc(fff) & 0xFF;
-
- /* Return the value */
- return (c);
-}
-
-
-static void sf_put(byte v)
-{
- (void)putc((int)v, fff);
-}
-
-/*
- * Do object memory and similar stuff
- */
-static void do_xtra(int k_idx, int flag)
-{
- byte tmp8u = 0;
- object_kind *k_ptr = &k_info[k_idx];
-
- if (flag == LS_SAVE)
- {
- if (k_ptr->aware) tmp8u |= 0x01;
- if (k_ptr->tried) tmp8u |= 0x02;
- if (k_ptr->know) tmp8u |= 0x04;
- if (k_ptr->artifact) tmp8u |= 0x80;
-
- do_byte(&tmp8u, flag);
- }
- if (flag == LS_LOAD)
- {
- do_byte(&tmp8u, flag);
- k_ptr->aware = ((tmp8u & 0x01) ? TRUE : FALSE);
- k_ptr->tried = ((tmp8u & 0x02) ? TRUE : FALSE);
- k_ptr->know = ((tmp8u & 0x04) ? TRUE : FALSE);
- k_ptr->artifact = ((tmp8u & 0x80) ? TRUE : FALSE);
- }
-}
-
-/*
- * Load/Save quick start data
- */
-void do_quick_start(int flag)
-{
- int i;
-
- do_s16b(&previous_char.sex, flag);
- do_s16b(&previous_char.race, flag);
- do_s16b(&previous_char.rmod, flag);
- do_s16b(&previous_char.pclass, flag);
- do_s16b(&previous_char.spec, flag);
- do_byte(&previous_char.quests, flag);
- do_byte(&previous_char.god, flag);
- do_s32b(&previous_char.grace, flag);
- do_s16b(&previous_char.age, flag);
- do_s16b(&previous_char.wt, flag);
- do_s16b(&previous_char.ht, flag);
- do_s16b(&previous_char.sc, flag);
- do_s32b(&previous_char.au, flag);
-
- for (i = 0; i < 6; i++) do_s16b(&(previous_char.stat[i]), flag);
- do_s16b(&previous_char.luck, flag);
-
- do_s16b(&previous_char.chaos_patron, flag);
- do_u32b(&previous_char.weapon, flag);
- do_byte((byte*)&previous_char.quick_ok, flag);
-
- for (i = 0; i < 4; i++) do_string(previous_char.history[i], 60, flag);
-}
-
-/*
- * The special saved subrace
- */
-static void do_subrace(int flag)
-{
- player_race_mod *sr_ptr = &race_mod_info[SUBRACE_SAVE];
- int i;
- char buf[81];
-
- if (flag == LS_SAVE)
- strncpy(buf, sr_ptr->title + rmp_name, 80);
- do_string(buf, 80, flag);
- if (flag == LS_LOAD)
- strncpy(sr_ptr->title + rmp_name, buf, 80);
-
- if (flag == LS_SAVE)
- strncpy(buf, sr_ptr->desc + rmp_text, 80);
- do_string(buf, 80, flag);
- if (flag == LS_LOAD)
- strncpy(sr_ptr->desc + rmp_text, buf, 80);
-
- do_byte((byte*)&sr_ptr->place, flag);
-
- for (i = 0; i < 6; i++)
- do_s16b(&sr_ptr->r_adj[i], flag);
-
- do_byte((byte*)&sr_ptr->luck, flag);
- do_s16b(&sr_ptr->mana, flag);
-
- do_s16b(&sr_ptr->r_dis, flag);
- do_s16b(&sr_ptr->r_dev, flag);
- do_s16b(&sr_ptr->r_sav, flag);
- do_s16b(&sr_ptr->r_stl, flag);
- do_s16b(&sr_ptr->r_srh, flag);
- do_s16b(&sr_ptr->r_fos, flag);
- do_s16b(&sr_ptr->r_thn, flag);
- do_s16b(&sr_ptr->r_thb, flag);
-
- do_byte((byte*)&sr_ptr->r_mhp, flag);
- do_s16b(&sr_ptr->r_exp, flag);
-
- do_byte((byte*)&sr_ptr->b_age, flag);
- do_byte((byte*)&sr_ptr->m_age, flag);
-
- do_byte((byte*)&sr_ptr->m_b_ht, flag);
- do_byte((byte*)&sr_ptr->m_m_ht, flag);
- do_byte((byte*)&sr_ptr->f_b_ht, flag);
- do_byte((byte*)&sr_ptr->f_m_ht, flag);
-
- do_byte((byte*)&sr_ptr->m_b_wt, flag);
- do_byte((byte*)&sr_ptr->m_m_wt, flag);
- do_byte((byte*)&sr_ptr->f_b_wt, flag);
- do_byte((byte*)&sr_ptr->f_m_wt, flag);
-
- do_byte((byte*)&sr_ptr->infra, flag);
-
- for (i = 0; i < 4; i++)
- do_s16b(&sr_ptr->powers[i], flag);
-
- for (i = 0; i < BODY_MAX; i++)
- do_byte((byte*)&sr_ptr->body_parts[i], flag);
-
- do_u32b(&sr_ptr->flags1, flag);
- do_u32b(&sr_ptr->flags2, flag);
-
- for (i = 0; i < PY_MAX_LEVEL + 1; i++)
- {
- do_u32b(&sr_ptr->oflags1[i], flag);
- do_u32b(&sr_ptr->oflags2[i], flag);
- do_u32b(&sr_ptr->oflags3[i], flag);
- do_u32b(&sr_ptr->oflags4[i], flag);
- do_u32b(&sr_ptr->oflags5[i], flag);
- do_u32b(&sr_ptr->oesp[i], flag);
- do_s16b(&sr_ptr->opval[i], flag);
- }
-
- do_byte(&sr_ptr->g_attr, flag);
- do_byte((byte*)&sr_ptr->g_char, flag);
-
- for (i = 0; i < MAX_SKILLS; i++)
- {
- do_byte((byte*)&sr_ptr->skill_basem[i], flag);
- do_u32b(&sr_ptr->skill_base[i], flag);
- do_byte((byte*)&sr_ptr->skill_modm[i], flag);
- do_s16b(&sr_ptr->skill_mod[i], flag);
- }
-}
-
-/*
- * Misc. other data
- */
-static char loaded_game_module[80];
-static bool_ do_extra(int flag)
-{
- int i, j;
- byte tmp8u;
- s16b tmp16s;
- u32b tmp32u;
- u16b tmp16b;
- u32b dummy32u = 0;
-
- do_string(player_name, 32, flag);
-
- do_string(died_from, 80, flag);
-
- for (i = 0; i < 4; i++)
- {
- do_string(history[i], 60, flag);
- }
-
- /* Handle the special levels info */
- if (flag == LS_SAVE)
- {
- tmp8u = max_d_idx;
- tmp16s = MAX_DUNGEON_DEPTH;
- }
- do_byte(&tmp8u, flag);
-
- if (flag == LS_LOAD)
- {
- if (tmp8u > max_d_idx)
- {
- note(format("Too many (%d) dungeon types!", tmp8u));
- }
- }
-
- do_s16b(&tmp16s, flag);
-
- if (flag == LS_LOAD)
- {
- if (tmp16s > MAX_DUNGEON_DEPTH)
- {
- note(format("Too many (%d) max level by dungeon type!", tmp16s));
- }
- }
-
- /* Load the special levels history */
- for (i = 0; i < tmp8u; i++)
- {
- for (j = 0; j < tmp16s; j++)
- {
- do_byte((byte*)&special_lvl[j][i], flag);
- }
- }
-
- do_byte((byte*)&generate_special_feeling, flag);
-
- /* Load the quick start data */
- do_quick_start(flag);
-
- /* Load/save the special subrace */
- do_subrace(flag);
-
- /* Race/Class/Gender/Spells */
- do_s32b(&p_ptr->lives, flag);
- do_byte(&p_ptr->prace, flag);
- do_byte(&p_ptr->pracem, flag);
- do_byte(&p_ptr->pclass, flag);
- do_byte(&p_ptr->pspec, flag);
- do_byte(&p_ptr->psex, flag);
- do_u16b(&tmp16b, flag);
- do_u16b(&tmp16b, flag);
- do_byte(&p_ptr->mimic_form, flag);
- do_s16b(&p_ptr->mimic_level, flag);
- if (flag == LS_SAVE) tmp8u = 0;
-
- do_byte(&p_ptr->hitdie, flag);
- do_u16b(&p_ptr->expfact, flag);
-
- do_s16b(&p_ptr->age, flag);
- do_s16b(&p_ptr->ht, flag);
- do_s16b(&p_ptr->wt, flag);
-
- /* Dump the stats (maximum and current) */
- for (i = 0; i < 6; ++i) do_s16b(&p_ptr->stat_max[i], flag);
- for (i = 0; i < 6; ++i) do_s16b(&p_ptr->stat_cur[i], flag);
- for (i = 0; i < 6; ++i) do_s16b(&p_ptr->stat_cnt[i], flag);
- for (i = 0; i < 6; ++i) do_s16b(&p_ptr->stat_los[i], flag);
-
- /* Dump the skills */
- do_s16b(&p_ptr->skill_points, flag);
- do_s16b(&p_ptr->skill_last_level, flag);
- do_s16b(&p_ptr->melee_style, flag);
- do_s16b(&p_ptr->use_piercing_shots, flag);
-
- tmp16s = MAX_SKILLS;
- do_s16b(&tmp16s, flag);
-
- if ((flag == LS_LOAD) && (tmp16s > MAX_SKILLS))
- {
- quit("Too many skills");
- }
-
- if (flag == LS_SAVE) old_max_s_idx = max_s_idx;
- do_u16b(&old_max_s_idx, flag);
- for (i = 0; i < tmp16s; ++i)
- {
- if (i < old_max_s_idx)
- {
- do_s32b(&s_info[i].value, flag);
- do_s32b(&s_info[i].mod, flag);
- do_byte((byte*)&s_info[i].dev, flag);
- do_byte((byte*)&s_info[i].hidden, flag);
- do_u32b(&s_info[i].uses, flag);
- }
- else
- {
- do_u32b(&tmp32u, flag);
- do_s16b(&tmp16s, flag);
- do_byte(&tmp8u, flag);
- do_byte(&tmp8u, flag);
- do_u32b(&tmp32u, flag);
- }
- }
-
- tmp16s = max_ab_idx;
- do_s16b(&tmp16s, flag);
-
- if ((flag == LS_LOAD) && (tmp16s > max_ab_idx))
- {
- quit("Too many abilities");
- }
-
- for (i = 0; i < tmp16s; ++i)
- {
- do_byte((byte*)&ab_info[i].acquired, flag);
- }
-
- do_s16b(&p_ptr->luck_base, flag);
- do_s16b(&p_ptr->luck_max, flag);
-
- /* Found 24 unused bytes here...
- Converted it to be the alchemist's
- known artifact flags.
- Note that the ego flags and the gained levels
- record are recorded here too, but we use the
- _ver_ format to protect save file compatablity.
- Note that the other alchemist knowledge (item types known)
- is stored in do_aux, and is a bit flag in a previously
- unused bit.
- */
- for (i = 0; i < 6 ; ++i)
- do_u32b(&alchemist_known_artifacts[i], flag);
-
- for (i = 0; i < 32 ; ++i)
- do_u32b(&alchemist_known_egos[i], flag);
-
- do_u32b(&alchemist_gained, flag);
-
- do_s32b(&p_ptr->au, flag);
-
- do_s32b(&p_ptr->max_exp, flag);
- do_s32b(&p_ptr->exp, flag);
- do_u16b(&p_ptr->exp_frac, flag);
- do_s16b(&p_ptr->lev, flag);
-
- do_s16b(&p_ptr->town_num, flag); /* -KMW- */
-
- /* Write arena and rewards information -KMW- */
- do_s16b(&p_ptr->arena_number, flag);
- do_s16b(&p_ptr->inside_arena, flag);
- do_s16b(&p_ptr->inside_quest, flag);
- do_byte((byte*)&p_ptr->exit_bldg, flag);
-
-
- /* Save/load spellbinder */
- do_byte(&p_ptr->spellbinder_num, flag);
- do_byte(&p_ptr->spellbinder_trigger, flag);
- for (i = 0; i < 4; i++)
- do_u32b(&p_ptr->spellbinder[i], flag);
-
-
- do_byte(&tmp8u, flag); /* tmp8u should be 0 at this point */
-
- if (flag == LS_SAVE) tmp8u = MAX_PLOTS;
- do_byte(&tmp8u, flag);
-
- if ((flag == LS_LOAD) && (tmp8u > MAX_PLOTS))
- {
- quit(format("Too many plots, %d %d", tmp8u, MAX_PLOTS));
- }
-
- for (i = 0; i < tmp8u; i++)
- {
- do_s16b(&plots[i], flag);
- }
-
- if (flag == LS_SAVE)
- {
- tmp8u = MAX_RANDOM_QUEST;
- }
- do_byte(&tmp8u, flag);
-
- if ((flag == LS_LOAD) &&
- (tmp8u > MAX_RANDOM_QUEST)) quit("Too many random quests");
- for (i = 0; i < tmp8u; i++)
- {
- do_byte(&random_quests[i].type, flag);
- do_s16b(&random_quests[i].r_idx, flag);
- do_byte((byte*)&random_quests[i].done, flag);
- }
-
- do_s16b(&p_ptr->oldpx, flag);
- do_s16b(&p_ptr->oldpy, flag);
-
- do_s16b(&p_ptr->mhp, flag);
- do_s16b(&p_ptr->chp, flag);
- do_u16b(&p_ptr->chp_frac, flag);
- do_s16b(&p_ptr->hp_mod, flag);
-
- do_s16b(&p_ptr->msane, flag);
- do_s16b(&p_ptr->csane, flag);
- do_u16b(&p_ptr->csane_frac, flag);
-
- do_s16b(&p_ptr->msp, flag);
- do_s16b(&p_ptr->csp, flag);
- do_u16b(&p_ptr->csp_frac, flag);
-
- /* XXX
- Here's where tank points were.
- Those who run the estate of you-know-who is really stupid.
- I'll never even consider reading her books now. -- neil */
- do_s16b(&tmp16s, flag);
- do_s16b(&tmp16s, flag);
- do_s16b(&tmp16s, flag);
- do_s16b(&tmp16s, flag);
-
- /* Gods */
- do_s32b(&p_ptr->grace, flag);
- do_byte((byte*)&p_ptr->praying, flag);
- do_s16b(&p_ptr->melkor_sacrifice, flag);
- do_byte(&p_ptr->pgod, flag);
-
- /* Max Player and Dungeon Levels */
- do_s16b(&p_ptr->max_plv, flag);
-
- if (flag == LS_SAVE)
- tmp8u = max_d_idx;
- do_byte(&tmp8u, flag);
- for (i = 0; i < tmp8u; i++)
- {
- if (flag == LS_SAVE)
- tmp16s = max_dlv[i];
- do_s16b(&tmp16s, flag);
- if ((flag == LS_LOAD) && (i <= max_d_idx))
- max_dlv[i] = tmp16s;
- }
- /* Repair max player level??? */
- if ((flag == LS_LOAD) && (p_ptr->max_plv < p_ptr->lev))
- p_ptr->max_plv = p_ptr->lev;
-
- do_byte((byte*)&(p_ptr->help.enabled), flag);
- do_u32b(&(p_ptr->help.help1), flag);
-
- /* More info */
- tmp16s = 0;
- do_s16b(&p_ptr->sc, flag);
- do_s16b(&p_ptr->blind, flag);
- do_s16b(&p_ptr->paralyzed, flag);
- do_s16b(&p_ptr->confused, flag);
- do_s16b(&p_ptr->food, flag);
- do_s32b(&p_ptr->energy, flag);
- do_s16b(&p_ptr->fast, flag);
- do_s16b(&p_ptr->speed_factor, flag);
- do_s16b(&p_ptr->slow, flag);
- do_s16b(&p_ptr->afraid, flag);
- do_s16b(&p_ptr->cut, flag);
- do_s16b(&p_ptr->stun, flag);
- do_s16b(&p_ptr->poisoned, flag);
- do_s16b(&p_ptr->image, flag);
- do_s16b(&p_ptr->protevil, flag);
- do_s16b(&p_ptr->protundead, flag);
- do_s16b(&p_ptr->invuln, flag);
- do_s16b(&p_ptr->hero, flag);
- do_s16b(&p_ptr->shero, flag);
- do_s16b(&p_ptr->shield, flag);
- do_s16b(&p_ptr->shield_power, flag);
- do_s16b(&p_ptr->shield_power_opt, flag);
- do_s16b(&p_ptr->shield_power_opt2, flag);
- do_s16b(&p_ptr->shield_opt, flag);
- do_s16b(&p_ptr->blessed, flag);
- do_s16b(&p_ptr->control, flag);
- do_byte(&p_ptr->control_dir, flag);
- do_s16b(&p_ptr->tim_thunder, flag);
- do_s16b(&p_ptr->tim_thunder_p1, flag);
- do_s16b(&p_ptr->tim_thunder_p2, flag);
- do_s16b(&p_ptr->tim_project, flag);
- do_s16b(&p_ptr->tim_project_dam, flag);
- do_s16b(&p_ptr->tim_project_gf, flag);
- do_s16b(&p_ptr->tim_project_rad, flag);
- do_s16b(&p_ptr->tim_project_flag, flag);
-
- do_s16b(&p_ptr->tim_magic_breath, flag);
- do_s16b(&p_ptr->tim_water_breath, flag);
-
- do_s16b(&p_ptr->tim_roots, flag);
- do_s16b(&p_ptr->tim_roots_ac, flag);
- do_s16b(&p_ptr->tim_roots_dam, flag);
-
- do_s16b(&p_ptr->tim_invis, flag);
- do_s16b(&p_ptr->word_recall, flag);
- do_s16b(&p_ptr->recall_dungeon, flag);
- do_s16b(&p_ptr->see_infra, flag);
- do_s16b(&p_ptr->tim_infra, flag);
- do_s16b(&p_ptr->oppose_fire, flag);
- do_s16b(&p_ptr->oppose_cold, flag);
- do_s16b(&p_ptr->oppose_acid, flag);
- do_s16b(&p_ptr->oppose_elec, flag);
- do_s16b(&p_ptr->oppose_pois, flag);
- do_s16b(&p_ptr->oppose_ld, flag);
- do_s16b(&p_ptr->oppose_cc, flag);
- do_s16b(&p_ptr->oppose_ss, flag);
- do_s16b(&p_ptr->oppose_nex, flag);
-
- do_s16b(&p_ptr->tim_esp, flag);
- do_s16b(&p_ptr->tim_wraith, flag);
- do_s16b(&p_ptr->tim_ffall, flag);
- do_ver_s16b(&p_ptr->tim_fly, SAVEFILE_VERSION, 0, flag);
- do_s16b(&p_ptr->tim_fire_aura, flag);
- do_ver_s16b(&p_ptr->tim_poison, SAVEFILE_VERSION, 0, flag);
- do_s16b(&p_ptr->resist_magic, flag);
- do_s16b(&p_ptr->tim_invisible, flag);
- do_s16b(&p_ptr->tim_inv_pow, flag);
- do_s16b(&p_ptr->tim_mimic, flag);
- do_s16b(&p_ptr->lightspeed, flag);
- do_s16b(&p_ptr->tim_lite, flag);
- do_ver_s16b(&p_ptr->tim_regen, SAVEFILE_VERSION, 0, flag);
- do_ver_s16b(&p_ptr->tim_regen_pow, SAVEFILE_VERSION, 0, flag);
- do_s16b(&p_ptr->holy, flag);
- do_s16b(&p_ptr->walk_water, flag);
- do_s16b(&p_ptr->tim_mental_barrier, flag);
- do_s16b(&p_ptr->immov_cntr, flag);
- do_s16b(&p_ptr->strike, flag);
- do_s16b(&p_ptr->meditation, flag);
- do_s16b(&p_ptr->tim_reflect, flag);
- do_s16b(&p_ptr->tim_res_time, flag);
- do_s16b(&p_ptr->tim_deadly, flag);
- do_s16b(&p_ptr->prob_travel, flag);
- do_s16b(&p_ptr->disrupt_shield, flag);
- do_s16b(&p_ptr->parasite, flag);
- do_s16b(&p_ptr->parasite_r_idx, flag);
- do_s32b(&p_ptr->loan, flag);
- do_s32b(&p_ptr->loan_time, flag);
- do_s16b(&p_ptr->absorb_soul, flag);
-
- do_s16b(&p_ptr->chaos_patron, flag);
-
- if (flag == LS_SAVE) tmp16s = max_corruptions;
- do_s16b(&tmp16s, flag);
-
- for (i = 0; i < tmp16s; i++)
- {
- if ((flag == LS_SAVE) && (i < max_corruptions))
- tmp8u = p_ptr->corruptions[i];
-
- do_byte(&tmp8u, flag);
-
- if ((flag == LS_LOAD) && (i < max_corruptions))
- p_ptr->corruptions[i] = tmp8u;
- }
-
- do_byte(&p_ptr->confusing, flag);
- do_byte((byte*)&p_ptr->black_breath, flag);
- do_byte((byte*)&fate_flag, flag);
- do_byte(&p_ptr->searching, flag);
- do_byte(&p_ptr->maximize, flag);
- do_byte(&p_ptr->preserve, flag);
- do_byte(&p_ptr->special, flag);
- do_byte((byte*)&ambush_flag, flag);
- do_byte(&p_ptr->allow_one_death, flag);
- do_s16b(&p_ptr->xtra_spells, flag);
-
- do_byte(&tmp8u, flag);
-
- do_s16b(&no_breeds, flag);
- do_s16b(&p_ptr->protgood, flag);
-
- /* Auxilliary variables */
- do_u32b(&p_ptr->mimic_extra, flag);
- do_u32b(&p_ptr->antimagic_extra, flag);
- do_u32b(&p_ptr->druid_extra, flag);
- do_u32b(&p_ptr->druid_extra2, flag);
- do_u32b(&p_ptr->druid_extra3, flag);
- do_u32b(&p_ptr->music_extra, flag);
- do_u32b(&p_ptr->music_extra2, flag);
- do_u32b(&p_ptr->necro_extra, flag);
- do_u32b(&p_ptr->necro_extra2, flag);
-
- do_u32b(&p_ptr->race_extra1, flag);
- do_u32b(&p_ptr->race_extra2, flag);
- do_u32b(&p_ptr->race_extra3, flag);
- do_u32b(&p_ptr->race_extra4, flag);
- do_u32b(&p_ptr->race_extra5, flag);
- do_u32b(&p_ptr->race_extra6, flag);
- do_u32b(&p_ptr->race_extra7, flag);
-
- do_u16b(&p_ptr->body_monster, flag);
- do_byte((byte*)&p_ptr->disembodied, flag);
-
- /* Are we in astral mode? */
- do_byte((byte*)&p_ptr->astral, flag);
-
- if (flag == LS_SAVE) tmp16s = POWER_MAX_INIT;
- do_s16b(&tmp16s, flag);
- if ((flag == LS_LOAD) && (tmp16s > POWER_MAX_INIT))
- note(format("Too many (%u) powers!", tmp16s));
- if (flag == LS_SAVE) tmp16s = POWER_MAX_INIT;
- for (i = 0; i < tmp16s; i++)
- do_byte((byte*)&p_ptr->powers_mod[i], flag);
-
- skip_ver_byte(100, flag);
-
- /* The tactic */
- do_byte((byte*)&p_ptr->tactic, flag);
-
- /* The movement */
- do_byte((byte*)&p_ptr->movement, flag);
-
- /* The comapnions killed */
- do_s16b(&p_ptr->companion_killed, flag);
-
- /* The fate */
- do_byte((byte*)&p_ptr->no_mortal, flag);
-
- /* The bounties */
- for (i = 0; i < MAX_BOUNTIES; i++)
- {
- do_s16b(&bounties[i][0], flag);
- do_s16b(&bounties[i][1], flag);
- }
- do_u32b(&total_bounties, flag);
- do_s16b(&spell_num, flag);
- for (i = 0; i < MAX_SPELLS; i++)
- do_spells(i, flag);
- do_s16b(&rune_num, flag);
- for (i = 0; i < MAX_RUNES; i++)
- {
- do_string(rune_spells[i].name, 30, flag);
- do_s16b(&rune_spells[i].type, flag);
- do_s16b(&rune_spells[i].rune2, flag);
- do_s16b(&rune_spells[i].mana, flag);
- }
-
- /* Load random seeds */
- do_u32b(&dummy32u, flag); /* Load-compatibility with old savefiles. */
- do_u32b(&seed_flavor, flag); /* For consistent object flavors. */
- do_u32b(&dummy32u, flag); /* Load-compatibility with old savefiles. */
-
- /* Special stuff */
- do_u16b(&tmp16b, flag); /* Dummy */
- do_u16b(&total_winner, flag);
- do_u16b(&has_won, flag);
- do_u16b(&noscore, flag);
-
- /* Write death */
- if (flag == LS_SAVE) tmp8u = death;
- do_byte(&tmp8u, flag);
- if (flag == LS_LOAD) death = tmp8u;
-
- /* Incompatible module? */
- if (flag == LS_LOAD)
- {
- s32b ok;
-
- call_lua("module_savefile_loadable", "(s,d)", "d", loaded_game_module, death, &ok);
-
- /* Argh bad game module! */
- if (!ok)
- {
- note(format("Bad game module. Savefile was saved with module '%s' but game is '%s'.", loaded_game_module, game_module));
- return (FALSE);
- }
- }
-
- /* Write feeling */
- if (flag == LS_SAVE) tmp8u = feeling;
- do_byte(&tmp8u, flag);
- if (flag == LS_LOAD) feeling = tmp8u;
-
- /* Turn of last "feeling" */
- do_s32b(&old_turn, flag);
-
- /* Current turn */
- do_s32b(&turn, flag);
-
- return TRUE;
-}
-
-/* Save the current persistent dungeon -SC- */
-void save_dungeon(void)
-{
- char tmp[16];
- char name[1024], buf[5];
-
- /* Save only persistent dungeons */
- if (!get_dungeon_save(buf) || (!dun_level)) return;
-
- /* Construct filename */
- sprintf(tmp, "%s.%s", player_base, buf);
- path_build(name, 1024, ANGBAND_DIR_SAVE, tmp);
-
- /* Open the file */
- fff = my_fopen(name, "wb");
-
- /* Save the dungeon */
- do_dungeon(LS_SAVE, TRUE);
-
- my_fclose(fff);
-}
-
-/*
- * Medium level player saver
- */
-static bool_ save_player_aux(char *name)
-{
- bool_ ok = FALSE;
- int fd = -1;
- int mode = 0644;
-
- /* No file yet */
- fff = NULL;
-
- /* File type is "SAVE" */
- FILE_TYPE(FILE_TYPE_SAVE);
-
- /* Create the savefile */
- fd = fd_make(name, mode);
-
- /* File is okay */
- if (fd >= 0)
- {
- /* Close the "fd" */
- (void)fd_close(fd);
-
- /* Open the savefile */
- fff = my_fopen(name, "wb");
-
- /* Successful open */
- if (fff)
- {
- /* Write the savefile */
- if (do_savefile_aux(LS_SAVE)) ok = TRUE;
-
- /* Attempt to close it */
- if (my_fclose(fff)) ok = FALSE;
- }
-
- /* "broken" savefile */
- if (!ok)
- {
- /* Remove "broken" files */
- (void)fd_kill(name);
- }
- }
-
- /* Failure */
- if (!ok) return (FALSE);
-
- /* Successful save */
- character_saved = TRUE;
-
- /* Success */
- return (TRUE);
-}
-
-/*
- * Attempt to save the player in a savefile
- */
-bool_ save_player(void)
-{
- int result = FALSE;
- char safe[1024];
-
- /* New savefile */
- strcpy(safe, savefile);
- strcat(safe, ".new");
-
- /* Remove it */
- fd_kill(safe);
-
- /* Attempt to save the player */
- if (save_player_aux(safe))
- {
- char temp[1024];
-
- /* Old savefile */
- strcpy(temp, savefile);
- strcat(temp, ".old");
-
- /* Remove it */
- fd_kill(temp);
-
- /* Preserve old savefile */
- fd_move(savefile, temp);
-
- /* Activate new savefile */
- fd_move(safe, savefile);
-
- /* Remove preserved savefile */
- fd_kill(temp);
-
- /* Hack -- Pretend the character was loaded */
- character_loaded = TRUE;
-
- /* Success */
- result = TRUE;
- }
-
- save_savefile_names();
-
- /* Return the result */
- return (result);
-}
-
-bool_ file_exist(char *buf)
-{
- int fd;
- bool_ result;
-
- /* Open savefile */
- fd = fd_open(buf, O_RDONLY);
-
- /* File exists */
- if (fd >= 0)
- {
- fd_close(fd);
- result = TRUE;
- }
- else
- result = FALSE;
-
- return result;
-}
-
-/*
- * Attempt to Load a "savefile"
- *
- * On multi-user systems, you may only "read" a savefile if you will be
- * allowed to "write" it later, this prevents painful situations in which
- * the player loads a savefile belonging to someone else, and then is not
- * allowed to save his game when he quits.
- *
- * We return "TRUE" if the savefile was usable, and we set the global
- * flag "character_loaded" if a real, living, character was loaded.
- *
- * Note that we always try to load the "current" savefile, even if
- * there is no such file, so we must check for "empty" savefile names.
- */
-bool_ load_player(void)
-{
- int fd = -1;
-
- errr err = 0;
-
- cptr what = "generic";
-
- /* Paranoia */
- turn = 0;
-
- /* Paranoia */
- death = FALSE;
-
-
- /* Allow empty savefile name */
- if (!savefile[0]) return (TRUE);
-
-
- /* XXX XXX XXX Fix this */
-
- /* Verify the existance of the savefile */
- if (!file_exist(savefile))
- {
- /* Give a message */
- msg_format("Savefile does not exist: %s", savefile);
- msg_print(NULL);
-
- /* Allow this */
- return (TRUE);
- }
-
- /* Okay */
- if (!err)
- {
- /* Open the savefile */
- fd = fd_open(savefile, O_RDONLY);
-
- /* No file */
- if (fd < 0) err = -1;
-
- /* Message (below) */
- if (err) what = "Cannot open savefile";
- }
-
- /* Process file */
- if (!err)
- {
- /* Open the file XXX XXX XXX XXX Should use Angband file interface */
- fff = my_fopen(savefile, "rb");
-/* fff = fdopen(fd, "r"); */
-
- /* Read the first four bytes */
- do_u32b(&vernum, LS_LOAD);
- do_byte(&sf_extra, LS_LOAD);
-
- /* XXX XXX XXX XXX Should use Angband file interface */
- my_fclose(fff);
- /* fclose(fff) */
-
- /* Close the file */
- fd_close(fd);
- }
-
- /* Process file */
- if (!err)
- {
-
- /* Extract version */
- sf_major = VERSION_MAJOR;
- sf_minor = VERSION_MINOR;
- sf_patch = VERSION_PATCH;
- sf_extra = VERSION_EXTRA;
-
- /* Clear screen */
- Term_clear();
-
- /* Attempt to load */
- err = rd_savefile();
-
- /* Message (below) */
- if (err) what = "Cannot parse savefile";
- }
-
- /* Paranoia */
- if (!err)
- {
- /* Invalid turn */
- if (!turn) err = -1;
-
- /* Message (below) */
- if (err) what = "Broken savefile";
- }
-
-
- /* Okay */
- if (!err)
- {
- /* Maybe the scripts want to resurrect char */
- if (process_hooks_ret(HOOK_LOAD_END, "d", "(d)", death))
- {
- character_loaded = process_hooks_return[0].num;
- death = process_hooks_return[1].num;
- return TRUE;
- }
-
- /* Player is dead */
- if (death)
- {
- /* Player is no longer "dead" */
- death = FALSE;
-
- /* Cheat death (unless the character retired) */
- if (arg_wizard && !total_winner)
- {
- /* A character was loaded */
- character_loaded = TRUE;
-
- /* Done */
- return (TRUE);
- }
-
- /* Count lives */
- sf_lives++;
-
- /* Forget turns */
- turn = old_turn = 0;
-
- /* Done */
- return (TRUE);
- }
-
- /* A character was loaded */
- character_loaded = TRUE;
-
- /* Still alive */
- if (p_ptr->chp >= 0)
- {
- /* Reset cause of death */
- (void)strcpy(died_from, "(alive and well)");
- }
-
- /* Success */
- return (TRUE);
- }
-
-
- /* Message */
- msg_format("Error (%s) reading %d.%d.%d savefile.",
- what, sf_major, sf_minor, sf_patch);
- msg_print(NULL);
-
- /* Oops */
- return (FALSE);
-}
-
-
-/*
- * Size-aware read/write routines for the savefile, do all their
- * work through sf_get and sf_put.
- */
-
-static void do_byte(byte *v, int flag)
-{
- if (flag == LS_LOAD)
- {
- *v = sf_get();
- return;
- }
- if (flag == LS_SAVE)
- {
- byte val = *v;
- sf_put(val);
- return;
- }
- /* We should never reach here, so bail out */
- printf("FATAL: do_byte passed %d\n", flag);
- exit(0);
-}
-
-static void do_u16b(u16b *v, int flag)
-{
- if (flag == LS_LOAD)
- {
- (*v) = sf_get();
- (*v) |= ((u16b)(sf_get()) << 8);
- return;
- }
- if (flag == LS_SAVE)
- {
- u16b val;
- val = *v;
- sf_put((byte)(val & 0xFF));
- sf_put((byte)((val >> 8) & 0xFF));
- return;
- }
- /* Never should reach here, bail out */
- printf("FATAL: do_u16b passed %d\n", flag);
- exit(0);
-}
-
-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);
-}
-
-static void do_u32b(u32b *ip, int flag)
-{
- if (flag == LS_LOAD)
- {
- (*ip) = sf_get();
- (*ip) |= ((u32b)(sf_get()) << 8);
- (*ip) |= ((u32b)(sf_get()) << 16);
- (*ip) |= ((u32b)(sf_get()) << 24);
- return;
- }
- if (flag == LS_SAVE)
- {
- u32b val = *ip;
- sf_put((byte)(val & 0xFF));
- sf_put((byte)((val >> 8) & 0xFF));
- sf_put((byte)((val >> 16) & 0xFF));
- sf_put((byte)((val >> 24) & 0xFF));
- return;
- }
- /* Bad news if you're here, because you're going down */
- printf("FATAL: do_u32b passed %d\n", flag);
- exit(0);
-}
-
-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);
-}
-
-static void do_string(char *str, int max, int flag)
-/* Max is ignored for writing */
-{
- if (flag == LS_LOAD)
- {
- int i;
-
- /* Read the string */
- for (i = 0; TRUE; i++)
- {
- byte tmp8u;
-
- /* Read a byte */
- do_byte(&tmp8u, LS_LOAD);
-
- /* Collect string while legal */
- if (i < max) str[i] = tmp8u;
-
- /* End of string */
- if (!tmp8u) break;
- }
- /* Terminate */
- str[max - 1] = '\0';
- return;
- }
- if (flag == LS_SAVE)
- {
- while (*str)
- {
- do_byte((byte*)str, flag);
- str++;
- }
- do_byte((byte*)str, flag); /* Output a terminator */
- return;
- }
- printf("FATAL: do_string passed flag %d\n", flag);
- exit(0);
-}
-
-static void skip_ver_byte(u32b version, int flag)
-/* Reads and discards a byte if the savefile is as old as/older than version */
-{
- if ((flag == LS_LOAD) && (vernum <= version))
- {
- byte forget;
- do_byte(&forget, flag);
- }
- return;
-}
-
-static void do_ver_s16b(s16b *v, u32b version, s16b defval, int flag)
-{
- if ((flag == LS_LOAD) && (vernum < version))
- {
- *v = defval;
- return;
- }
- do_s16b(v, flag);
-}
-
-/*
- * Show information on the screen, one line at a time.
- *
- * Avoid the top two lines, to avoid interference with "msg_print()".
- */
-static void note(cptr msg)
-{
- static int y = 2;
-
- /* Draw the message */
- prt(msg, y, 0);
-
- /* Advance one line (wrap if needed) */
- if (++y >= 24) y = 2;
-
- /* Flush it */
- Term_fresh();
-}
-
-
-/*
- * Determine if an item can be wielded/worn (e.g. helmet, sword, bow, arrow)
- */
-static bool_ wearable_p(object_type *o_ptr)
-{
- /* Valid "tval" codes */
- switch (o_ptr->tval)
- {
- case TV_WAND:
- case TV_STAFF:
- case TV_ROD:
- case TV_ROD_MAIN:
- case TV_SHOT:
- case TV_ARROW:
- case TV_BOLT:
- case TV_BOOMERANG:
- case TV_BOW:
- case TV_DIGGING:
- case TV_HAFTED:
- case TV_POLEARM:
- case TV_MSTAFF:
- case TV_SWORD:
- 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_SCROLL:
- case TV_LITE:
- case TV_POTION:
- case TV_POTION2:
- case TV_AMULET:
- case TV_RING:
- case TV_HYPNOS:
- case TV_INSTRUMENT:
- case TV_DAEMON_BOOK:
- case TV_TRAPKIT:
- case TV_TOOL:
- {
- return (TRUE);
- }
- }
-
- /* Nope */
- return (FALSE);
-}
-
-
-/*
- * rd/wr an object
- *
- * FIXME! This code probably has a lot of cruft from the old Z/V codebase.
- *
- */
-static void do_item(object_type *o_ptr, int flag)
-{
- byte old_dd;
- byte old_ds;
-
- u32b f1, f2, f3, f4, f5, esp;
-
- object_kind *k_ptr;
-
- /* Kind */
- do_s16b(&o_ptr->k_idx, flag);
-
- /* Location */
- do_byte(&o_ptr->iy, flag);
- do_byte(&o_ptr->ix, flag);
-
- /* Type/Subtype */
- do_byte(&o_ptr->tval, flag);
- do_byte(&o_ptr->sval, flag);
-
- /* Special pval */
- do_s32b(&o_ptr->pval, flag);
-
- /* Special pval */
- do_s16b(&o_ptr->pval2, flag);
-
- /* Special pval */
- do_s32b(&o_ptr->pval3, flag);
-
- do_byte(&o_ptr->discount, flag);
- do_byte(&o_ptr->number, flag);
- do_s32b(&o_ptr->weight, flag);
-
- do_byte(&o_ptr->name1, flag);
- do_s16b(&o_ptr->name2, flag);
- do_s16b(&o_ptr->name2b, flag);
- do_s16b(&o_ptr->timeout, flag);
-
- do_s16b(&o_ptr->to_h, flag);
- do_s16b(&o_ptr->to_d, flag);
- do_s16b(&o_ptr->to_a, flag);
-
- do_s16b(&o_ptr->ac, flag);
-
- /* We do special processing of this flag when reading */
- if (flag == LS_LOAD)
- {
- do_byte(&old_dd, LS_LOAD);
- do_byte(&old_ds, LS_LOAD);
- }
- if (flag == LS_SAVE)
- {
- do_byte(&o_ptr->dd, LS_SAVE);
- do_byte(&o_ptr->ds, LS_SAVE);
- }
-
- do_byte(&o_ptr->ident, flag);
-
- do_byte(&o_ptr->marked, flag);
-
- /* flags */
- do_u32b(&o_ptr->art_flags1, flag);
- do_u32b(&o_ptr->art_flags2, flag);
- do_u32b(&o_ptr->art_flags3, flag);
- do_u32b(&o_ptr->art_flags4, flag);
- do_u32b(&o_ptr->art_flags5, flag);
- do_u32b(&o_ptr->art_esp, flag);
-
- /* obvious flags */
- do_u32b(&o_ptr->art_oflags1, flag);
- do_u32b(&o_ptr->art_oflags2, flag);
- do_u32b(&o_ptr->art_oflags3, flag);
- do_u32b(&o_ptr->art_oflags4, flag);
- do_u32b(&o_ptr->art_oflags5, flag);
- do_u32b(&o_ptr->art_oesp, flag);
-
- /* Monster holding object */
- do_s16b(&o_ptr->held_m_idx, flag);
-
- /* Special powers */
- do_byte(&o_ptr->xtra1, flag);
- do_s16b(&o_ptr->xtra2, flag);
-
- do_byte(&o_ptr->elevel, flag);
- do_s32b(&o_ptr->exp, flag);
-
- /* Read the pseudo-id */
- do_byte(&o_ptr->sense, flag);
-
- /* Read the found info */
- do_byte(&o_ptr->found, flag);
- do_s16b(&o_ptr->found_aux1, flag);
- do_s16b(&o_ptr->found_aux2, flag);
- do_s16b(&o_ptr->found_aux3, flag);
- do_s16b(&o_ptr->found_aux4, flag);
-
- if (flag == LS_LOAD)
- {
- 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);
- }
- if (flag == LS_SAVE)
- {
- /* Save the inscription (if any) */
- if (o_ptr->note)
- {
- do_string((char *)quark_str(o_ptr->note), 0, LS_SAVE);
- }
- else
- {
- do_string("", 0, LS_SAVE);
- }
- if (o_ptr->art_name)
- {
- do_string((char *)quark_str(o_ptr->art_name), 0, LS_SAVE);
- }
- else
- {
- do_string("", 0, LS_SAVE);
- }
- }
-
- if (flag == LS_SAVE) return ; /* Stick any more shared code before this. The rest
- of this function is reserved for LS_LOAD's
- cleanup functions */
- /*********** END OF LS_SAVE ***************/
-
- /* Obtain the "kind" template */
- k_ptr = &k_info[o_ptr->k_idx];
-
- /* Obtain tval/sval from k_info */
- o_ptr->tval = k_ptr->tval;
- if (o_ptr->tval != TV_RANDART) o_ptr->sval = k_ptr->sval;
-
-
- /* Repair non "wearable" items */
- if (!wearable_p(o_ptr))
- {
- /* Acquire correct fields */
- o_ptr->to_h = k_ptr->to_h;
- o_ptr->to_d = k_ptr->to_d;
- o_ptr->to_a = k_ptr->to_a;
-
- /* Acquire correct fields */
- o_ptr->ac = k_ptr->ac;
- o_ptr->dd = k_ptr->dd;
- o_ptr->ds = k_ptr->ds;
-
- /* All done */
- return;
- }
-
-
- /* Extract the flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
-
- /* Paranoia */
- if (o_ptr->name1)
- {
- artifact_type *a_ptr;
-
- /* Obtain the artifact info */
- a_ptr = &a_info[o_ptr->name1];
-
- /* Verify that artifact */
- if (!a_ptr->name) o_ptr->name1 = 0;
- }
-
- /* Paranoia */
- if (o_ptr->name2)
- {
- ego_item_type *e_ptr;
-
- /* Obtain the ego-item info */
- e_ptr = &e_info[o_ptr->name2];
-
- /* Verify that ego-item */
- if (!e_ptr->name) o_ptr->name2 = 0;
- }
-
-
- /* Acquire standard fields */
- o_ptr->ac = k_ptr->ac;
- o_ptr->dd = k_ptr->dd;
- o_ptr->ds = k_ptr->ds;
-
- /* Artifacts */
- if (o_ptr->name1)
- {
- artifact_type *a_ptr;
-
- /* Obtain the artifact info */
- a_ptr = &a_info[o_ptr->name1];
-
- /* Acquire new artifact fields */
- o_ptr->ac = a_ptr->ac;
- o_ptr->dd = a_ptr->dd;
- o_ptr->ds = a_ptr->ds;
-
- /* Acquire new artifact weight */
- o_ptr->weight = a_ptr->weight;
- }
-
- /* Ego items */
- if (o_ptr->name2)
- {
- o_ptr->dd = old_dd;
- o_ptr->ds = old_ds;
- }
-
- if (o_ptr->art_name) /* A random artifact */
- {
- o_ptr->dd = old_dd;
- o_ptr->ds = old_ds;
- }
-}
-
-
-
-
-/*
- * Read a monster
- */
-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);
-
- do_u16b(&m_ptr->ego, flag);
-
- /* Read the other information */
- do_byte(&m_ptr->fy, flag);
- do_byte(&m_ptr->fx, flag);
-
- do_s32b(&m_ptr->hp, flag);
- do_s32b(&m_ptr->maxhp, flag);
-
- do_s16b(&m_ptr->csleep, flag);
- do_byte(&m_ptr->mspeed, flag);
- do_byte(&m_ptr->energy, flag);
- do_byte(&m_ptr->stunned, flag);
- do_byte(&m_ptr->confused, flag);
- do_byte(&m_ptr->monfear, flag);
- do_u32b(&m_ptr->smart, flag);
- do_s16b(&m_ptr->status, flag);
- do_s16b(&m_ptr->possessor, flag);
- do_byte(&m_ptr->speed, flag);
- do_byte(&m_ptr->level, flag);
- do_s16b(&m_ptr->ac, flag);
- do_u32b(&m_ptr->exp, flag);
- do_s16b(&m_ptr->target, flag);
-
- do_s16b(&m_ptr->bleeding, flag);
- do_s16b(&m_ptr->poisoned, flag);
-
- do_s32b(&m_ptr->mflag, flag);
-
- if (flag == LS_LOAD) m_ptr->mflag &= PERM_MFLAG_MASK;
-
- /* Attacks */
- for (i = 0; i < 4; i++)
- {
- do_byte(&m_ptr->blow[i].method, flag);
- do_byte(&m_ptr->blow[i].effect, flag);
- do_byte(&m_ptr->blow[i].d_dice, 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);
- 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);
- }
-}
-
-
-
-
-
-/*
- * Handle monster lore
- */
-static void do_lore(int r_idx, int flag)
-{
- monster_race *r_ptr = &r_info[r_idx];
-
- /* Count sights/deaths/kills */
- do_s16b(&r_ptr->r_sights, flag);
- do_s16b(&r_ptr->r_deaths, flag);
- do_s16b(&r_ptr->r_pkills, flag);
- do_s16b(&r_ptr->r_tkills, flag);
-
- /* Count wakes and ignores */
- do_byte(&r_ptr->r_wake, flag);
- do_byte(&r_ptr->r_ignore, flag);
-
- /* Extra stuff */
- do_byte(&r_ptr->r_xtra1, flag);
- do_byte(&r_ptr->r_xtra2, flag);
-
- /* Count drops */
- do_byte(&r_ptr->r_drop_gold, flag);
- do_byte(&r_ptr->r_drop_item, flag);
-
- /* Count spells */
- do_byte(&r_ptr->r_cast_inate, flag);
- do_byte(&r_ptr->r_cast_spell, flag);
-
- /* Count blows of each type */
- do_byte(&r_ptr->r_blows[0], flag);
- do_byte(&r_ptr->r_blows[1], flag);
- do_byte(&r_ptr->r_blows[2], flag);
- do_byte(&r_ptr->r_blows[3], flag);
-
- /* Memorize flags */
- do_u32b(&r_ptr->r_flags1, flag); /* Just to remind you */
- do_u32b(&r_ptr->r_flags2, flag); /* flag is unrelated to */
- do_u32b(&r_ptr->r_flags3, flag); /* the other argument */
- do_u32b(&r_ptr->r_flags4, flag);
- do_u32b(&r_ptr->r_flags5, flag);
- do_u32b(&r_ptr->r_flags6, flag);
- do_u32b(&r_ptr->r_flags7, flag);
- do_u32b(&r_ptr->r_flags8, flag);
- do_u32b(&r_ptr->r_flags9, flag);
-
- /* Read the "Racial" monster tmp16b per level */
- do_s16b(&r_ptr->max_num, flag);
-
- do_byte((byte*)&r_ptr->on_saved, flag);
-
- if (flag == LS_LOAD)
- {
- /* Lore flag repair? */
- 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;
- }
-}
-
-
-
-
-/*
- * Read a store
- */
-static bool_ do_store(store_type *str, int flag)
-/* FIXME! Why does this return anything when
- it always returns the same thing? */
-{
- int j;
-
- byte num;
-
- byte store_inven_max = STORE_INVEN_MAX;
-
- /* 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);
-
- /* Items */
- for (j = 0; j < num; j++)
- {
- if (flag == LS_LOAD)
- /* Can't this be cleaner? */
- {
- object_type forge;
- /* Wipe the object */
- object_wipe(&forge);
- /* Read the item */
- do_item(&forge, LS_LOAD);
- /* Acquire valid items */
- if ((str->stock_num < store_inven_max) && (str->stock_num < str->stock_size))
- {
- int k = str->stock_num++;
-
- /* Acquire the item */
- object_copy(&str->stock[k], &forge);
- }
- }
- if (flag == LS_SAVE) do_item(&str->stock[j], flag);
- }
-
- /* Success */
- return (TRUE);
-}
-
-/*
- * RNG state
- */
-static void do_randomizer(int flag)
-{
- int i;
-
- u16b tmp16u = 0;
-
- /* Tmp */
- do_u16b(&tmp16u, flag);
-
- /* Place */
- do_u16b(&Rand_place, flag);
-
- /* State */
- for (i = 0; i < RAND_DEG; i++)
- {
- do_u32b(&Rand_state[i], flag);
- }
-
- /* Accept */
- if (flag == LS_LOAD)
- {
- Rand_quick = FALSE;
- }
-}
-
-/*
- * Handle options
- *
- * Normal options are stored as a set of 256 bit flags,
- * plus a set of 256 bit masks to indicate which bit flags were defined
- * at the time the savefile was created. This will allow new options
- * to be added, and old options to be removed, at any time, without
- * hurting old savefiles.
- *
- * The window options are stored in the same way, but note that each
- * window gets 32 options, and their order is fixed by certain defines.
- */
-static void do_options(int flag)
-{
- int i, n;
-
- u32b oflag[8];
- u32b mask[8];
-
- /*** Special info */
-
- /* Read "delay_factor" */
- do_byte(&delay_factor, flag);
-
- /* Read "hitpoint_warn" */
- do_byte(&hitpoint_warn, flag);
-
- /*** Cheating options ***/
- if (flag == LS_LOAD) /* There *MUST* be some nice way to unify this! */
- {
- u16b c;
- do_u16b(&c, LS_LOAD);
- if (c & 0x0002) wizard = TRUE;
- cheat_peek = (c & 0x0100) ? TRUE : FALSE;
- cheat_hear = (c & 0x0200) ? TRUE : FALSE;
- cheat_room = (c & 0x0400) ? TRUE : FALSE;
- cheat_xtra = (c & 0x0800) ? TRUE : FALSE;
- cheat_know = (c & 0x1000) ? TRUE : FALSE;
- cheat_live = (c & 0x2000) ? TRUE : FALSE;
- }
- if (flag == LS_SAVE)
- {
- u16b c = 0;
- if (wizard) c |= 0x0002;
- if (cheat_peek) c |= 0x0100;
- if (cheat_hear) c |= 0x0200;
- if (cheat_room) c |= 0x0400;
- if (cheat_xtra) c |= 0x0800;
- if (cheat_know) c |= 0x1000;
- if (cheat_live) c |= 0x2000;
- do_u16b(&c, LS_SAVE);
- }
-
- do_byte((byte*)&autosave_l, flag);
- do_byte((byte*)&autosave_t, flag);
- do_s16b(&autosave_freq, flag);
-
- if (flag == LS_LOAD)
- {
- /* Read the option flags */
- for (n = 0; n < 8; n++) do_u32b(&oflag[n], flag);
-
- /* Read the option masks */
- for (n = 0; n < 8; n++) do_u32b(&mask[n], flag);
-
- /* Analyze the options */
- for (n = 0; n < 8; n++)
- {
- /* Analyze the options */
- for (i = 0; i < 32; i++)
- {
- /* Process valid flags */
- if (mask[n] & (1L << i))
- {
- /* Process valid flags */
- if (option_mask[n] & (1L << i))
- {
- /* Set */
- if (oflag[n] & (1L << i))
- {
- /* Set */
- option_flag[n] |= (1L << i);
- }
-
- /* Clear */
- else
- {
- /* Clear */
- option_flag[n] &= ~(1L << i);
- }
- }
- }
- }
- }
-
-
- /*** Window Options ***/
-
- /* Read the window flags */
- for (n = 0; n < 8; n++) do_u32b(&oflag[n], flag);
-
- /* Read the window masks */
- for (n = 0; n < 8; n++) do_u32b(&mask[n], flag);
-
- /* Analyze the options */
- for (n = 0; n < 8; n++)
- {
- /* Analyze the options */
- for (i = 0; i < 32; i++)
- {
- /* Process valid flags */
- if (mask[n] & (1L << i))
- {
- /* Process valid flags */
- if (window_mask[n] & (1L << i))
- {
- /* Set */
- if (oflag[n] & (1L << i))
- {
- /* Set */
- window_flag[n] |= (1L << i);
- }
-
- /* Clear */
- else
- {
- /* Clear */
- window_flag[n] &= ~(1L << i);
- }
- }
- }
- }
- }
- }
- if (flag == LS_SAVE)
- {
- /* Analyze 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;
-
- /* Process real entries */
- if (option_info[i].o_var)
- {
- /* Set */
- if (*option_info[i].o_var)
- {
- /* Set */
- option_flag[os] |= (1L << ob);
- }
-
- /* Clear */
- else
- {
- /* Clear */
- option_flag[os] &= ~(1L << ob);
- }
- }
- }
-
-
- /*** Normal options ***/
-
- /* Dump the flags */
- for (i = 0; i < 8; i++) do_u32b(&option_flag[i], flag);
-
- /* Dump the masks */
- for (i = 0; i < 8; i++) do_u32b(&option_mask[i], flag);
-
- /*** Window options ***/
-
- /* Dump the flags */
- for (i = 0; i < 8; i++) do_u32b(&window_flag[i], flag);
-
- /* Dump the masks */
- for (i = 0; i < 8; i++) do_u32b(&window_mask[i], flag);
- }
-}
-
-
-/* Load/Save the random spells info */
-static void do_spells(int i, int flag)
-{
- random_spell *s_ptr = &random_spells[i];
- do_string(s_ptr->name, 30, flag);
- do_string(s_ptr->desc, 30, flag);
- do_s16b(&s_ptr->mana, flag);
- do_s16b(&s_ptr->fail, flag);
- do_u32b(&s_ptr->proj_flags, flag);
- do_byte(&s_ptr->GF, flag);
- do_byte(&s_ptr->radius, flag);
- do_byte(&s_ptr->dam_sides, flag);
- do_byte(&s_ptr->dam_dice, flag);
- do_byte(&s_ptr->level, flag);
- do_byte((byte*)&s_ptr->untried, flag);
-}
-
-
-/*
- * Handle player inventory
- *
- * FIXME! This function probably could be unified better
- * Note that the inventory is "re-sorted" later by "dungeon()".
- */
-static bool_ do_inventory(int flag)
-{
- if (flag == LS_LOAD)
- {
- int slot = 0;
-
- object_type forge;
- object_type *q_ptr;
-
- /* No items */
- inven_cnt = 0;
- equip_cnt = 0;
-
- /* Read until done */
- while (1)
- {
- u16b n;
-
- /* Get the next item index */
- do_u16b(&n, LS_LOAD);
-
- /* Nope, we reached the end */
- if (n == 0xFFFF) break;
-
- /* Get local object */
- q_ptr = &forge;
-
- /* Wipe the object */
- object_wipe(q_ptr);
-
- /* Read the item */
- do_item(q_ptr, LS_LOAD);
-
- /* Hack -- verify item */
- if (!q_ptr->k_idx) return (FALSE);
-
- /* Wield equipment */
- if (n >= INVEN_WIELD)
- {
- /* Copy object */
- object_copy(&p_ptr->inventory[n], q_ptr);
-
- /* Take care of item sets */
- if (q_ptr->name1)
- {
- wield_set(q_ptr->name1, a_info[q_ptr->name1].set, TRUE);
- }
-
- /* One more item */
- equip_cnt++;
- }
-
- /* Warning -- backpack is full */
- else if (inven_cnt == INVEN_PACK)
- {
- /* Oops */
- note("Too many items in the inventory!");
-
- /* Fail */
- return (FALSE);
- }
-
- /* Carry inventory */
- else
- {
- /* Get a slot */
- n = slot++;
-
- /* Copy object */
- object_copy(&p_ptr->inventory[n], q_ptr);
-
- /* One more item */
- inven_cnt++;
- }
- }
- }
- if (flag == LS_SAVE)
- {
- u16b i;
- u16b sent = 0xFFFF;
- for (i = 0; i < INVEN_TOTAL; i++)
- {
- object_type *o_ptr = &p_ptr->inventory[i];
- if (!o_ptr->k_idx) continue;
- do_u16b(&i, flag);
- do_item(o_ptr, flag);
- }
- do_u16b(&sent, LS_SAVE); /* Sentinel */
- }
- /* Success */
- return (TRUE);
-}
-
-
-
-/*
- * Read the saved messages
- */
-static void do_messages(int flag) /* FIXME! We should be able to unify this better */
-{
- int i;
- char buf[128];
- byte color, type;
-
- s16b num;
-
- if (flag == LS_SAVE) num = message_num();
-
- /* Total */
- do_s16b(&num, flag);
-
- /* Read the messages */
- if (flag == LS_LOAD)
- {
- for (i = 0; i < num; i++)
- {
- /* Read the message */
- do_string(buf, 128, LS_LOAD);
- do_byte(&color, flag);
- do_byte(&type, flag);
-
- /* Save the message */
- message_add(type, buf, color);
- }
- }
- if (flag == LS_SAVE)
- {
- byte holder;
- 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);
- }
- }
-}
-
-/*
- * Handle dungeon
- *
- * The monsters/objects must be loaded in the same order
- * that they were stored, since the actual indexes matter.
- */
-static bool_ do_dungeon(int flag, bool_ no_companions)
-{
- int i;
-
- cave_type *c_ptr;
-
- /* Read specific */
- u16b tmp16b = 0;
-
- my_sentinel("Before do_dungeon", 324, flag);
-
- /* Header info */
- do_s16b(&dun_level, flag);
- do_byte(&dungeon_type, flag);
- do_s16b(&num_repro, flag);
- do_s16b(&p_ptr->py, flag);
- do_s16b(&p_ptr->px, flag);
- do_s16b(&cur_hgt, flag);
- do_s16b(&cur_wid, flag);
- do_s16b(&max_panel_rows, flag);
- do_s16b(&max_panel_cols, flag);
-
- do_u32b(&dungeon_flags1, flag);
- do_u32b(&dungeon_flags2, flag);
-
- /* Last teleportation */
- do_s16b(&last_teleportation_y, flag);
- do_s16b(&last_teleportation_y, flag);
-
- /* Spell effects */
- tmp16b = MAX_EFFECTS;
- do_u16b(&tmp16b, flag);
-
- if ((flag == LS_LOAD) && (tmp16b > MAX_EFFECTS))
- {
- quit("Too many spell effects");
- }
-
- for (i = 0; i < tmp16b; ++i)
- {
- do_s16b(&effects[i].type, flag);
- do_s16b(&effects[i].dam, flag);
- do_s16b(&effects[i].time, flag);
- do_u32b(&effects[i].flags, flag);
- do_s16b(&effects[i].cx, flag);
- do_s16b(&effects[i].cy, flag);
- do_s16b(&effects[i].rad, flag);
- }
-
- /* TO prevent bugs with evolving dungeons */
- for (i = 0; i < 100; i++)
- {
- do_s16b(&floor_type[i], flag);
- do_s16b(&fill_type[i], flag);
- }
-
- if ((flag == LS_LOAD) && (!dun_level && !p_ptr->inside_quest))
- {
- int xstart = 0;
- int ystart = 0;
- /* Init the wilderness */
- process_dungeon_file("w_info.txt", &ystart, &xstart, cur_hgt, cur_wid,
- TRUE, FALSE);
-
- /* Init the town */
- xstart = 0;
- ystart = 0;
- init_flags = 0;
- process_dungeon_file("t_info.txt", &ystart, &xstart, cur_hgt, cur_wid,
- TRUE, FALSE);
- }
-
- do_grid(flag);
-
- /*** Objects ***/
-
- if (flag == LS_SAVE) compact_objects(0);
- if (flag == LS_SAVE) compact_monsters(0);
- if (flag == LS_SAVE)
- {
- tmp16b = o_max;
-
- if (no_companions)
- {
- for (i = 1; i < o_max; i++)
- {
- object_type *o_ptr = &o_list[i];
-
- if (o_ptr->held_m_idx && (m_list[o_ptr->held_m_idx].status == MSTATUS_COMPANION)) tmp16b--;
- }
- }
-
- /* Item count */
- do_u16b(&tmp16b, flag);
-
- tmp16b = o_max;
- }
- else
- /* Read item count */
- do_u16b(&tmp16b, flag);
-
- /* Verify maximum */
- if ((flag == LS_LOAD) && (tmp16b > max_o_idx))
- {
- note(format("Too many (%d) object entries!", tmp16b));
- return (FALSE);
- }
-
- /* Dungeon items */
- for (i = 1; i < tmp16b; i++)
- {
- int o_idx;
-
- object_type *o_ptr;
-
- if (flag == LS_SAVE)
- {
- o_ptr = &o_list[i];
- /* Don't save objects held by companions when no_companions is set */
- if (no_companions && o_ptr->held_m_idx && (m_list[o_ptr->held_m_idx].status == MSTATUS_COMPANION)) continue;
-
- do_item(o_ptr, LS_SAVE);
- continue; /* Saving is easy */
- }
- /* Until the end of the loop, this is all LS_LOAD */
-
- /* Get a new record */
- o_idx = o_pop();
-
- /* Oops */
- if (i != o_idx)
- {
- note(format("Object allocation error (%d <> %d)", i, o_idx));
- return (FALSE);
- }
-
-
- /* Acquire place */
- o_ptr = &o_list[o_idx];
-
- /* Read the item */
- do_item(o_ptr, LS_LOAD);
-
- /* Monster */
- if (o_ptr->held_m_idx)
- {
- monster_type *m_ptr;
-
- /* Monster */
- m_ptr = &m_list[o_ptr->held_m_idx];
-
- /* Build a stack */
- o_ptr->next_o_idx = m_ptr->hold_o_idx;
-
- /* Place the object */
- m_ptr->hold_o_idx = o_idx;
- }
-
- /* Dungeon */
- else
- {
- /* Access the item location */
- c_ptr = &cave[o_ptr->iy][o_ptr->ix];
-
- /* Build a stack */
- o_ptr->next_o_idx = c_ptr->o_idx;
-
- /* Place the object */
- c_ptr->o_idx = o_idx;
- }
- }
-
- /*** Monsters ***/
-
- if (flag == LS_SAVE)
- {
- tmp16b = m_max;
-
- if (no_companions)
- {
- for (i = 1; i < m_max; i++)
- {
- monster_type *m_ptr = &m_list[i];
-
- if (m_ptr->status == MSTATUS_COMPANION) tmp16b--;
- }
- }
-
- /* Write the monster count */
- do_u16b(&tmp16b, flag);
-
- tmp16b = m_max;
- }
- else
- /* Read the monster count */
- do_u16b(&tmp16b, flag);
-
- /* Validate */
- if ((flag == LS_LOAD) && (tmp16b > max_m_idx))
- {
- note(format("Too many (%d) monster entries!", tmp16b));
- return (FALSE);
- }
-
- /* Read the monsters */
- for (i = 1; i < tmp16b; i++)
- {
- int m_idx;
- monster_type *m_ptr;
- monster_race *r_ptr;
-
- if (flag == LS_SAVE)
- {
- m_ptr = &m_list[i];
-
- /* Don't save companions when no_companions is set */
- if (no_companions && m_ptr->status == MSTATUS_COMPANION) continue;
-
- do_monster(m_ptr, LS_SAVE);
- continue; /* Easy to save a monster */
- }
- /* From here on, it's all LS_LOAD */
- /* Get a new record */
- m_idx = m_pop();
-
- /* Oops */
- if (i != m_idx)
- {
- note(format("Monster allocation error (%d <> %d)", i, m_idx));
- return (FALSE);
- }
-
- /* Acquire monster */
- m_ptr = &m_list[m_idx];
-
- /* Read the monster */
- do_monster(m_ptr, LS_LOAD);
-
- /* Access grid */
- c_ptr = &cave[m_ptr->fy][m_ptr->fx];
-
- /* Mark the location */
- c_ptr->m_idx = m_idx;
-
- /* Controlled ? */
- if (m_ptr->mflag & MFLAG_CONTROL)
- p_ptr->control = m_idx;
-
- /* Access race */
- r_ptr = &r_info[m_ptr->r_idx];
-
- /* Count XXX XXX XXX */
- r_ptr->cur_num++;
- }
-
- /* Read the kept monsters */
-
- tmp16b = (flag == LS_SAVE && !no_companions) ? max_m_idx : 0;
-
- /* Read the monster count */
- do_u16b(&tmp16b, flag);
-
- /* Hack -- verify */
- if ((flag == LS_LOAD) && (tmp16b > max_m_idx))
- {
- note(format("Too many (%d) monster entries!", tmp16b));
- return (FALSE);
- }
- for (i = 1; i < tmp16b; i++)
- {
- monster_type *m_ptr;
-
- /* Acquire monster */
- m_ptr = &km_list[i];
-
- /* Read the monster */
- do_monster(m_ptr, flag);
- }
-
- /*** Success ***/
-
- /* The dungeon is ready */
- if (flag == LS_LOAD) character_dungeon = TRUE;
-
- /* Success */
- return (TRUE);
-}
-
-/* Returns TRUE if we successfully load the dungeon */
-bool_ load_dungeon(char *ext)
-{
- char tmp[16];
- char name[1024];
- byte old_dungeon_type = dungeon_type;
- s16b old_dun = dun_level;
-
- /* Construct name */
- sprintf(tmp, "%s.%s", player_base, ext);
- path_build(name, 1024, ANGBAND_DIR_SAVE, tmp);
-
- /* Open the file */
- fff = my_fopen(name, "rb");
-
- if (fff == NULL)
- {
- dun_level = old_dun;
- dungeon_type = old_dungeon_type;
-
- my_fclose(fff);
- return (FALSE);
- }
-
- /* Read the dungeon */
- if (!do_dungeon(LS_LOAD, FALSE))
- {
- dun_level = old_dun;
- dungeon_type = old_dungeon_type;
-
- my_fclose(fff);
- return (FALSE);
- }
-
- dun_level = old_dun;
- dungeon_type = old_dungeon_type;
-
- /* Done */
- my_fclose(fff);
- return (TRUE);
-}
-
-void do_blocks(int flag)
-/* Handle blocked-allocation stuff for quests and lua stuff
- This depends on a dyn_tosave array of s32b's. Adjust as needed
- if other data structures are desirable. This also is not hooked
- in yet. Ideally, plug it near the end of the savefile.
- */
-{
- s16b numblks, n_iter = 0; /* How many blocks do we have? */
- do_s16b(&numblks, flag);
- while (n_iter < numblks)
- {
- /* do_s32b(dyn_tosave[n_iter], flag); */
- n_iter++;
- }
- my_sentinel("In blocked-allocation area", 37, flag);
-}
-
-void do_fate(int i, int flag)
-{
- if ((flag == LS_LOAD) && (i >= MAX_FATES)) i = MAX_FATES - 1;
-
- do_byte(&fates[i].fate, flag);
- do_byte(&fates[i].level, flag);
- do_byte(&fates[i].serious, flag);
- do_s16b(&fates[i].o_idx, flag);
- do_s16b(&fates[i].e_idx, flag);
- do_s16b(&fates[i].a_idx, flag);
- do_s16b(&fates[i].v_idx, flag);
- do_s16b(&fates[i].r_idx, flag);
- do_s16b(&fates[i].count, flag);
- do_s16b(&fates[i].time, flag);
- do_byte((byte*)&fates[i].know, flag);
-}
-
-/*
- * Actually read the savefile
- */
-static bool_ do_savefile_aux(int flag)
-{
- int i, j;
-
- byte tmp8u;
- u16b tmp16u;
- u32b tmp32u;
-
- bool_ *reals;
- u16b real_max = 0;
-
- /* Mention the savefile version */
- if (flag == LS_LOAD)
- {
- if (vernum < 100)
- {
- note(format("Savefile version %lu too old! ", vernum));
- return FALSE;
- }
- else
- {
- note(format("Loading version %lu savefile... ", vernum));
- }
- }
- if (flag == LS_SAVE)
- {
- sf_when = time((time_t *) 0); /* Note when file was saved */
- sf_xtra = 0L; /* What the hell is this? */
- sf_saves++; /* Increment the saves ctr */
- }
-
- /* Handle version bytes. FIXME! DG wants me to change this all around */
- if (flag == LS_LOAD)
- {
- u32b mt32b;
- byte mtbyte;
-
- /* Discard all this, we've already read it */
- do_u32b(&mt32b, flag);
- do_byte(&mtbyte, flag);
- }
- if (flag == LS_SAVE)
- {
- u32b saver;
- saver = SAVEFILE_VERSION;
- do_u32b(&saver, flag);
- tmp8u = (byte)rand_int(256);
- do_byte(&tmp8u, flag); /* 'encryption' */
- }
-
- /* Operating system info? Not really. This is just set to 0L */
- do_u32b(&sf_xtra, flag);
-
- /* Time of last save */
- do_u32b(&sf_when, flag);
-
- /* Number of past lives */
- do_u16b(&sf_lives, flag);
-
- /* Number of times saved */
- do_u16b(&sf_saves, flag);
-
- /* Game module */
- if (flag == LS_SAVE)
- strcpy(loaded_game_module, game_module);
- do_string(loaded_game_module, 80, 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;
- do_u16b(&tmp16u, flag);
-
- /* Incompatible save files */
- if ((flag == LS_LOAD) && (tmp16u > max_r_idx))
- {
- note(format("Too many (%u) monster races!", tmp16u));
- return (FALSE);
- }
-
- /* Read the available records */
- for (i = 0; i < tmp16u; i++)
- {
- /* Read the lore */
- 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);
-
- /* Incompatible save files */
- if ((flag == LS_LOAD) && (tmp16u > max_k_idx))
- {
- note(format("Too many (%u) object kinds!", tmp16u));
- return (FALSE);
- }
-
- /* 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();
-
- {
- u16b max_towns_ldsv;
- u16b max_quests_ldsv;
- if (flag == LS_SAVE) max_towns_ldsv = max_towns;
- /* Number of towns */
- do_u16b(&max_towns_ldsv, flag);
- /* Incompatible save files */
- if ((flag == LS_LOAD) && (max_towns_ldsv > max_towns))
- {
- note(format("Too many (%u) towns!", max_towns_ldsv));
- return (FALSE);
- }
- /* Min of random towns */
- if (flag == LS_SAVE) max_towns_ldsv = TOWN_RANDOM;
- do_u16b(&max_towns_ldsv, flag);
- /* Incompatible save files */
- if ((flag == LS_LOAD) && (max_towns_ldsv != TOWN_RANDOM))
- {
- note(format("Different random towns base (%u)!", max_towns_ldsv));
- return (FALSE);
- }
-
- for (i = 0; i < max_towns; i++)
- {
- do_byte((byte*)&town_info[i].destroyed, flag);
-
- if (i >= TOWN_RANDOM)
- {
- do_u32b(&town_info[i].seed, flag);
- do_byte(&town_info[i].numstores, flag);
- do_byte(&town_info[i].flags, flag);
-
- /* If the town is realy used create a sock */
- if ((town_info[i].flags & (TOWN_REAL)) && (flag == LS_LOAD))
- {
- create_stores_stock(i);
- }
- }
- }
-
- /* Number of dungeon */
- if (flag == LS_SAVE) max_towns_ldsv = max_d_idx;
- do_u16b(&max_towns_ldsv, flag);
-
- /* Incompatible save files */
- if ((flag == LS_LOAD) && (max_towns_ldsv > max_d_idx))
- {
- note(format("Too many dungeon types (%u)!", max_towns_ldsv));
- return (FALSE);
- }
-
- /* Number of towns per dungeon */
- if (flag == LS_SAVE) max_quests_ldsv = TOWN_DUNGEON;
- do_u16b(&max_quests_ldsv, flag);
- /* Incompatible save files */
- if ((flag == LS_LOAD) && (max_quests_ldsv > TOWN_DUNGEON))
- {
- note(format("Too many town per dungeons (%u)!", max_quests_ldsv));
- return (FALSE);
- }
-
- for (i = 0; i < max_towns_ldsv; i++)
- {
- for (j = 0; j < max_quests_ldsv; j++)
- {
- do_s16b(&(d_info[i].t_idx[j]), flag);
- do_s16b(&(d_info[i].t_level[j]), flag);
- }
- do_s16b(&(d_info[i].t_num), flag);
- }
-
- if (flag == LS_SAVE) max_quests_ldsv = MAX_Q_IDX_INIT;
- /* Number of quests */
- do_u16b(&max_quests_ldsv, flag);
-
- /* Incompatible save files */
- if ((flag == LS_LOAD) && (max_quests_ldsv > MAX_Q_IDX_INIT))
- {
- note(format("Too many (%u) quests!", max_quests_ldsv));
- return (FALSE);
- }
-
- for (i = 0; i < max_quests_ldsv; i++)
- {
- do_s16b(&quest[i].status, flag);
- for (j = 0; j < 4; j++)
- {
- do_s32b(&(quest[i].data[j]), flag);
- }
-
- /* Init the hooks */
- if ((flag == LS_LOAD) && (quest[i].type == HOOK_TYPE_C)) quest[i].init(i);
- }
-
- /* Position in the wilderness */
- do_s32b(&p_ptr->wilderness_x, flag);
- do_s32b(&p_ptr->wilderness_y, flag);
- do_byte((byte*)&p_ptr->wild_mode, flag);
- do_byte((byte*)&p_ptr->old_wild_mode, flag);
-
- {
- s32b wild_x_size, wild_y_size;
- if (flag == LS_SAVE)
- {
- wild_x_size = max_wild_x;
- wild_y_size = max_wild_y;
- }
- /* Size of the wilderness */
- do_s32b(&wild_x_size, flag);
- do_s32b(&wild_y_size, flag);
- /* Incompatible save files */
- if ((flag == LS_LOAD) &&
- ((wild_x_size > max_wild_x) || (wild_y_size > max_wild_y)))
- {
- note(format("Wilderness is too big (%u/%u)!",
- wild_x_size, wild_y_size));
- return (FALSE);
- }
- /* Wilderness seeds */
- for (i = 0; i < wild_x_size; i++)
- {
- for (j = 0; j < wild_y_size; j++)
- {
- do_u32b(&wild_map[j][i].seed, flag);
- do_u16b(&wild_map[j][i].entrance, flag);
- do_byte((byte*)&wild_map[j][i].known, flag);
- }
- }
- }
- }
- if ((flag == LS_LOAD) && (arg_fiddle)) note("Loaded Quests");
-
- /* Load the random artifacts. */
- if (flag == LS_SAVE) tmp16u = MAX_RANDARTS;
- do_u16b(&tmp16u, flag);
- if ((flag == LS_LOAD) && (tmp16u > MAX_RANDARTS))
- {
- note(format("Too many (%u) random artifacts!", tmp16u));
- return (FALSE);
- }
- for (i = 0; i < tmp16u; i++)
- {
- random_artifact *ra_ptr = &random_artifacts[i];
-
- do_string(ra_ptr->name_full, 80, flag);
- do_string(ra_ptr->name_short, 80, flag);
- do_byte(&ra_ptr->level, flag);
- do_byte(&ra_ptr->attr, flag);
- do_u32b(&ra_ptr->cost, flag);
- do_byte(&ra_ptr->activation, flag);
- do_byte(&ra_ptr->generated, flag);
- }
-
- /* Load the Artifacts */
- if (flag == LS_SAVE) tmp16u = max_a_idx;
- do_u16b(&tmp16u, flag);
- /* Incompatible save files */
- if ((flag == LS_LOAD) && (tmp16u > max_a_idx))
- {
- note(format("Too many (%u) artifacts!", tmp16u));
- return (FALSE);
- }
-
- /* Read the artifact flags */
- for (i = 0; i < tmp16u; i++)
- {
- 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;
- do_u16b(&tmp16u, flag);
-
- /* Incompatible save files */
- if ((flag == LS_LOAD) && (tmp16u > MAX_FATES))
- {
- note(format("Too many (%u) fates!", tmp16u));
- return (FALSE);
- }
-
- /* Read the fate flags */
- for (i = 0; i < tmp16u; i++)
- {
- do_fate(i, flag);
- }
- if ((flag == LS_LOAD) && arg_fiddle) note("Loaded Fates");
-
- /* Load the Traps */
- if (flag == LS_SAVE) tmp16u = max_t_idx;
- do_u16b(&tmp16u, flag);
-
- /* Incompatible save files */
- if ((flag == LS_LOAD) && (tmp16u > max_t_idx))
- {
- note(format("Too many (%u) traps!", tmp16u));
- return (FALSE);
- }
-
- /* fate flags */
- for (i = 0; i < tmp16u; i++)
- {
- 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;
- do_u16b(&tmp16u, flag);
-
- /* Incompatible save files */
- if ((flag == LS_LOAD) && (tmp16u > MAX_INSCRIPTIONS))
- {
- note(format("Too many (%u) inscriptions!", tmp16u));
- return (FALSE);
- }
-
- /* 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 */
- if (flag == LS_SAVE) tmp16u = PY_MAX_LEVEL;
- do_u16b(&tmp16u, flag);
- /* Incompatible save files */
- if ((flag == LS_LOAD) && (tmp16u > PY_MAX_LEVEL))
- {
- note(format("Too many (%u) hitpoint entries!", tmp16u));
- return (FALSE);
- }
-
- /* Read the player_hp array */
- for (i = 0; i < tmp16u; i++)
- {
- do_s16b(&player_hp[i], flag);
- }
-
- if (flag == LS_LOAD) morejunk();
-
- /* Read the pet command settings */
- do_byte(&p_ptr->pet_follow_distance, flag);
- do_byte(&p_ptr->pet_open_doors, flag);
- do_byte(&p_ptr->pet_pickup_items, flag);
-
- /* Read the inventory */
- if (!do_inventory(flag) && (flag == LS_LOAD)) /* do NOT reverse this ordering */
- {
- note("Unable to read inventory");
- return (FALSE);
- }
-
- /* Note that this forbids max_towns from shrinking, but that is fine */
- C_MAKE(reals, max_towns, bool_);
-
- /* Find the real towns */
- if (flag == LS_SAVE)
- {
- for (i = 1; i < max_towns; i++)
- {
- if (!(town_info[i].flags & (TOWN_REAL))) continue;
- reals[real_max++] = i;
- }
- }
- do_u16b(&real_max, flag);
- for (i = 0; i < real_max; i++)
- {
- do_byte((byte*)&reals[i], flag);
- }
-
- /* Read the stores */
- if (flag == LS_SAVE) tmp16u = max_st_idx;
- do_u16b(&tmp16u, flag);
-
- /* Ok now read the real towns */
- for (i = 0; i < real_max; i++)
- {
- int z = reals[i];
-
- /* Ultra paranoia */
- if (!town_info[z].stocked) create_stores_stock(z);
-
- for (j = 0; j < tmp16u; j++)
- do_store(&town_info[z].store[j], 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)
- {
- /* Dead players have no dungeon */
- if (flag == LS_LOAD) note("Restoring Dungeon...");
- if ((flag == LS_LOAD) && (!do_dungeon(LS_LOAD, FALSE)))
- {
- note("Error reading dungeon data");
- return (FALSE);
- }
- if (flag == LS_SAVE) do_dungeon(LS_SAVE, FALSE);
- my_sentinel("Before ghost data", 435, flag);
- my_sentinel("After ghost data", 320, flag);
- }
-
- {
- byte foo = 0;
- if (flag == LS_SAVE)
- {
- /*
- * Safety Padding. It's there
- * for a good reason. Trust me on
- * this. Keep this at the *END*
- * of the file, and do *NOT* try to
- * read it. Insert any new stuff before
- * this position.
- */
- do_byte(&foo, LS_SAVE);
- }
- }
-
- /* Success */
- return (TRUE);
-}
-
-
-/*
- * Actually read the savefile
- */
-errr rd_savefile(void)
-{
- errr err = 0;
-
- /* The savefile is a binary file */
- fff = my_fopen(savefile, "rb");
-
- /* Paranoia */
- if (!fff) return ( -1);
-
- /* Call the sub-function */
- err = !do_savefile_aux(LS_LOAD);
-
- /* Check for errors */
- if (ferror(fff)) err = -1;
-
- /* Close the file */
- my_fclose(fff);
-
- /* Result */
- return (err);
-}
-
-/*
- * Note that this function may not be needed at all.
- * It was taken out of load_player_aux(). Do we need it?
- */
-static void junkinit(void)
-{
- int i, j;
- p_ptr->arena_number = 0;
- p_ptr->inside_arena = 0;
- p_ptr->inside_quest = 0;
- p_ptr->exit_bldg = TRUE;
- p_ptr->exit_bldg = TRUE;
- p_ptr->town_num = 1;
- p_ptr->wilderness_x = 4;
- p_ptr->wilderness_y = 4;
- for (i = 0; i < max_wild_x; i++)
- {
- for (j = 0; j < max_wild_y; j++)
- {
- wild_map[j][i].seed = rand_int(0x10000000);
- }
- }
-}
-
-static void morejunk(void)
-{
- sp_ptr = &sex_info[p_ptr->psex]; /* Sex */
- rp_ptr = &race_info[p_ptr->prace]; /* Raceclass */
- rmp_ptr = &race_mod_info[p_ptr->pracem];
- cp_ptr = &class_info[p_ptr->pclass];
- spp_ptr = &class_info[p_ptr->pclass].spec[p_ptr->pspec];
-}
-
-static void do_grid(int flag)
-/* Does the grid, RLE, blahblah. RLE sucks. I hate it. */
-{
- int i = 0, y = 0, x = 0;
- byte count = 0;
- byte tmp8u = 0;
- s16b tmp16s = 0;
- cave_type *c_ptr;
- byte prev_char = 0;
- s16b prev_s16b = 0;
- int ymax = cur_hgt, xmax = cur_wid;
-
- int part; /* Which section of the grid we're on */
-
- for (part = 0; part < 9; part++) /* There are 8 fields to the grid, each stored
- in a seperate RLE data structure */
- {
- if (flag == LS_SAVE)
- {
- count = 0;
- prev_s16b = 0;
- prev_char = 0; /* Clear, prepare for RLE */
- for (y = 0; y < cur_hgt; y++)
- {
- for (x = 0; x < cur_wid; x++)
- {
- c_ptr = &cave[y][x];
- switch (part)
- {
- case 0:
- tmp16s = c_ptr->info;
- break;
-
- case 1:
- tmp8u = c_ptr->feat;
- break;
-
- case 2:
- tmp8u = c_ptr->mimic;
- break;
-
- case 3:
- tmp16s = c_ptr->special;
- break;
-
- case 4:
- tmp16s = c_ptr->special2;
- break;
-
- case 5:
- tmp16s = c_ptr->t_idx;
- break;
-
- case 6:
- tmp16s = c_ptr->inscription;
- break;
-
- case 7:
- tmp8u = c_ptr->mana;
- break;
-
- case 8:
- tmp16s = c_ptr->effect;
- break;
- }
- /* Flush a full run */
- if ((((part != 1) && (part != 2) && (part != 7)) &&
- (tmp16s != prev_s16b)) || (((part == 1) || (part == 2)
- || (part == 7)) &&
- (tmp8u != prev_char)) ||
- (count == MAX_UCHAR))
- {
- do_byte(&count, LS_SAVE);
- switch (part)
- {
- case 0:
- case 3:
- case 4:
- case 5:
- case 6:
- case 8:
- do_s16b(&prev_s16b, LS_SAVE);
- prev_s16b = tmp16s;
- break;
-
- case 1:
- case 2:
- case 7:
- do_byte(&prev_char, LS_SAVE);
- prev_char = tmp8u;
- break;
- }
- count = 1; /* Reset RLE */
- }
- else
- count++; /* Otherwise, keep going */
- }
- }
- /* Fallen off the end of the world, flush anything left */
- if (count)
- {
- do_byte(&count, LS_SAVE);
- switch (part)
- {
- case 0:
- case 3:
- case 4:
- case 5:
- case 6:
- case 8:
- do_s16b(&prev_s16b, LS_SAVE);
- break;
-
- case 1:
- case 2:
- case 7:
- do_byte(&prev_char, LS_SAVE);
- break;
- }
- }
- }
- if (flag == LS_LOAD)
- {
- x = 0;
- for (y = 0; y < ymax; )
- {
- do_byte(&count, LS_LOAD);
- switch (part)
- {
- case 0:
- case 3:
- case 4:
- case 5:
- case 6:
- case 8:
- do_s16b(&tmp16s, LS_LOAD);
- break;
-
- case 1:
- case 2:
- case 7:
- do_byte(&tmp8u, LS_LOAD);
- break;
- }
- for (i = count; i > 0; i--) /* RLE */
- {
- c_ptr = &cave[y][x];
- switch (part)
- {
- case 0:
- c_ptr->info = tmp16s;
- break;
-
- case 1:
- c_ptr->feat = tmp8u;
- break;
-
- case 2:
- c_ptr->mimic = tmp8u;
- break;
-
- case 3:
- c_ptr->special = tmp16s;
- break;
-
- case 4:
- c_ptr->special2 = tmp16s;
- break;
-
- case 5:
- c_ptr->t_idx = tmp16s;
- break;
-
- case 6:
- c_ptr->inscription = tmp16s;
- break;
-
- case 7:
- c_ptr->mana = tmp8u;
- break;
-
- case 8:
- c_ptr->effect = tmp16s;
- break;
- }
- if (++x >= xmax)
- {
- /* Wrap */
- x = 0;
- if ((++y) >= ymax) break;
- }
- }
- }
- }
- }
-}
-
-static void my_sentinel(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 */
-{
- if (flag == LS_SAVE)
- {
- do_u16b(&value, flag);
- return;
- }
- if (flag == LS_LOAD)
- {
- u16b found;
- do_u16b(&found, flag);
- if (found == value) /* All is good */
- return;
- /* All is bad */
- note(format("Savefile broken %s", place));
- return;
- }
- 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/loadsave.cc b/src/loadsave.cc
new file mode 100644
index 00000000..3c843a36
--- /dev/null
+++ b/src/loadsave.cc
@@ -0,0 +1,2630 @@
+#include "loadsave.hpp"
+#include "loadsave.h"
+
+#include "artifact_type.hpp"
+#include "birth.hpp"
+#include "cave_type.hpp"
+#include "dungeon_info_type.hpp"
+#include "ego_item_type.hpp"
+#include "game.hpp"
+#include "init1.hpp"
+#include "init2.hpp"
+#include "levels.hpp"
+#include "messages.hpp"
+#include "modules.hpp"
+#include "monster2.hpp"
+#include "monster_race.hpp"
+#include "monster_type.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_kind.hpp"
+#include "options.hpp"
+#include "player_class.hpp"
+#include "player_level_flag.hpp"
+#include "player_race.hpp"
+#include "player_race_mod.hpp"
+#include "player_type.hpp"
+#include "hooks.hpp"
+#include "skill_type.hpp"
+#include "store_type.hpp"
+#include "tables.hpp"
+#include "timer_type.hpp"
+#include "town_type.hpp"
+#include "util.hpp"
+#include "util.h"
+#include "wilderness_map.hpp"
+#include "variable.h"
+#include "variable.hpp"
+#include "xtra2.hpp"
+#include "z-rand.hpp"
+
+#include <boost/filesystem.hpp>
+#include <cassert>
+#include <fmt/format.h>
+#include <memory>
+
+static u32b vernum; /* Version flag */
+static FILE *fff; /* Local savefile ptr */
+
+/*
+ * Show information on the screen, one line at a time.
+ *
+ * Avoid the top two lines, to avoid interference with "msg_print()".
+ */
+static void note(cptr msg)
+{
+ static int y = 2;
+
+ /* Draw the message */
+ prt(msg, y, 0);
+
+ /* Advance one line (wrap if needed) */
+ if (++y >= 24) y = 2;
+
+ /* Flush it */
+ Term_fresh();
+}
+
+/**
+ * Load/save flag
+ */
+enum class ls_flag_t {
+ LOAD = 3,
+ SAVE = 7
+};
+
+/**
+ * Structure for loading/saving option values
+ */
+namespace {
+
+struct option_value {
+ std::string name;
+ bool_ value;
+};
+
+} // namespace (anonymous)
+
+
+/*
+ * Basic byte-level reading from savefile.
+ */
+static byte sf_get()
+{
+ byte c;
+
+ /* Get a character, decode the value */
+ c = getc(fff) & 0xFF;
+
+ /* Return the value */
+ return (c);
+}
+
+
+static void sf_put(byte v)
+{
+ putc((int)v, fff);
+}
+
+/*
+ * Size-aware read/write routines for the savefile, do all their
+ * work through sf_get and sf_put.
+ */
+static void do_byte(byte *v, ls_flag_t flag)
+{
+ switch (flag)
+ {
+ case ls_flag_t::LOAD:
+ {
+ *v = sf_get();
+ return;
+ }
+ case ls_flag_t::SAVE:
+ {
+ byte val = *v;
+ sf_put(val);
+ return;
+ }
+ }
+}
+
+static void do_char(char *c, ls_flag_t flag)
+{
+ do_byte((byte *) c, flag);
+}
+
+static void do_bool(bool_ *f, ls_flag_t flag)
+{
+ byte b = *f;
+ do_byte(&b, flag);
+ if (flag == ls_flag_t::LOAD)
+ {
+ *f = b;
+ }
+}
+
+static void do_std_bool(bool *x, ls_flag_t flag)
+{
+ switch (flag)
+ {
+ case ls_flag_t::LOAD:
+ {
+ *x = (sf_get() != 0);
+ return;
+ }
+ case ls_flag_t::SAVE:
+ {
+ byte val = (*x) ? 1 : 0;
+ sf_put(val);
+ return;
+ }
+ }
+}
+
+static void do_u16b(u16b *v, ls_flag_t flag)
+{
+ switch (flag)
+ {
+ case ls_flag_t::LOAD:
+ {
+ (*v) = sf_get();
+ (*v) |= ((u16b)(sf_get()) << 8);
+ return;
+ }
+ case ls_flag_t::SAVE:
+ {
+ u16b val;
+ val = *v;
+ sf_put((byte)(val & 0xFF));
+ sf_put((byte)((val >> 8) & 0xFF));
+ return;
+ }
+ }
+}
+
+static void do_s16b(s16b *ip, ls_flag_t flag)
+{
+ do_u16b((u16b *)ip, flag);
+}
+
+static void do_u32b(u32b *ip, ls_flag_t flag)
+{
+ switch(flag)
+ {
+ case ls_flag_t::LOAD:
+ {
+ (*ip) = sf_get();
+ (*ip) |= ((u32b)(sf_get()) << 8);
+ (*ip) |= ((u32b)(sf_get()) << 16);
+ (*ip) |= ((u32b)(sf_get()) << 24);
+ return;
+ }
+ case ls_flag_t::SAVE:
+ {
+ u32b val = *ip;
+ sf_put((byte)(val & 0xFF));
+ sf_put((byte)((val >> 8) & 0xFF));
+ sf_put((byte)((val >> 16) & 0xFF));
+ sf_put((byte)((val >> 24) & 0xFF));
+ return;
+ }
+ }
+}
+
+static void do_s32b(s32b *ip, ls_flag_t flag)
+{
+ do_u32b((u32b *)ip, flag);
+}
+
+static void save_std_string(std::string const *s)
+{
+ // Length prefix.
+ u32b saved_size = s->size();
+ do_u32b(&saved_size, ls_flag_t::SAVE);
+ // Save each character
+ for (auto c: *s)
+ {
+ sf_put(c);
+ }
+}
+
+static std::string load_std_string()
+{
+ // Length prefix.
+ u32b saved_size;
+ do_u32b(&saved_size, ls_flag_t::LOAD);
+ // Convert to size_t
+ std::size_t n = saved_size;
+ // Make sure we reserve space rather than resizing as we go.
+ std::string s;
+ s.reserve(n);
+ // Read each character
+ for (std::size_t i = 0; i < n; i++)
+ {
+ s += sf_get();
+ }
+ // Done
+ return s;
+}
+
+
+static void do_std_string(std::string &s, ls_flag_t flag)
+{
+ switch (flag)
+ {
+ case ls_flag_t::LOAD:
+ s = load_std_string();
+ break;
+ case ls_flag_t::SAVE:
+ save_std_string(&s);
+ break;
+ }
+}
+
+static void do_option_value(option_value *option_value, ls_flag_t flag)
+{
+ do_std_string(option_value->name, flag);
+ do_bool(&option_value->value, flag);
+}
+
+
+namespace {
+
+/**
+ * Load/save flag set
+ */
+template<std::size_t Tiers> void do_flag_set(flag_set<Tiers> *flags, ls_flag_t flag)
+{
+ for (std::size_t i = 0; i < flags->size(); i++)
+ {
+ do_u32b(&(*flags)[i], flag);
+ }
+}
+
+template<typename T, typename F> void do_vector(ls_flag_t flag, std::vector<T> &v, F f)
+{
+ u32b n = v.size();
+
+ do_u32b(&n, flag);
+
+ if (flag == ls_flag_t::LOAD)
+ {
+ v.clear(); // Make sure it's empty
+ v.reserve(n);
+ std::fill_n(std::back_inserter(v), n, T());
+ }
+
+ for (std::size_t i = 0; i < n; i++)
+ {
+ f(&v[i], flag);
+ }
+}
+
+template<typename A, typename F> void do_array(std::string const &what, ls_flag_t flag, A &array, std::size_t size, F f)
+{
+ // Save/load size.
+ u32b n = size;
+ do_u32b(&n, flag);
+
+ // Check that we don't overflow the array.
+ if (flag == ls_flag_t::LOAD)
+ {
+ if (n > size)
+ {
+ note(fmt::format("Too many {:s}: {:d} > {:d}! Game may act strangely or crash.", what, n, size).c_str());
+ }
+ }
+
+ // Load/save the contents of the array.
+ for (std::size_t i = 0; i < n; i++)
+ {
+ f(&array[i], flag);
+ }
+}
+
+static void do_bytes(ls_flag_t flag, std::uint8_t *buf, std::size_t n)
+{
+ for (std::size_t i = 0; i < n; i++)
+ {
+ do_byte(&buf[i], flag);
+ }
+};
+
+static void do_seed(seed_t *seed, ls_flag_t flag)
+{
+ uint8_t buf[seed_t::n_bytes];
+
+ if (flag == ls_flag_t::SAVE)
+ {
+ seed->to_bytes(buf);
+ }
+
+ do_bytes(flag, buf, sizeof(buf));
+
+ if (flag == ls_flag_t::LOAD)
+ {
+ *seed = seed_t::from_bytes(buf);
+ }
+}
+
+} // namespace (anonymous)
+
+
+/*
+ * Load/Save quick start data
+ */
+static void do_quick_start(ls_flag_t flag, birther &previous_char)
+{
+ do_s16b(&previous_char.race, flag);
+ do_s16b(&previous_char.rmod, flag);
+ do_s16b(&previous_char.pclass, flag);
+ do_s16b(&previous_char.spec, flag);
+ do_byte(&previous_char.quests, flag);
+ do_byte(&previous_char.god, flag);
+ do_s32b(&previous_char.grace, flag);
+ do_s32b(&previous_char.au, flag);
+
+ for (std::size_t i = 0; i < 6; i++)
+ {
+ do_s16b(&(previous_char.stat[i]), flag);
+ }
+ do_s16b(&previous_char.luck, flag);
+
+ do_bool(&previous_char.quick_ok, flag);
+}
+
+static void do_skill_modifier(skill_modifier *s, ls_flag_t flag)
+{
+ do_char(&s->basem, flag);
+ do_u32b(&s->base, flag);
+ do_char(&s->modm, flag);
+ do_s16b(&s->mod, flag);
+}
+
+static void do_skill_modifiers(skill_modifiers *skill_modifiers, ls_flag_t flag)
+{
+ do_vector(flag, skill_modifiers->modifiers, do_skill_modifier);
+}
+
+static void do_player_level_flag(player_level_flag *lflag, ls_flag_t flag)
+{
+ do_flag_set(&lflag->oflags, flag);
+ do_s16b(&lflag->pval, flag);
+}
+
+/*
+ * The special saved subrace
+ */
+static void do_subrace(ls_flag_t flag)
+{
+ auto &race_mod_info = game->edit_data.race_mod_info;
+
+ player_race_mod *sr_ptr = &race_mod_info[SUBRACE_SAVE];
+ int i;
+
+ do_std_string(sr_ptr->title, flag);
+ do_std_string(sr_ptr->description, flag);
+
+ do_bool(&sr_ptr->place, flag);
+
+ for (i = 0; i < 6; i++)
+ {
+ do_s16b(&sr_ptr->ps.adj[i], flag);
+ }
+
+ do_char(&sr_ptr->luck, flag);
+ do_s16b(&sr_ptr->mana, flag);
+
+ do_s16b(&sr_ptr->ps.mhp, flag);
+ do_s16b(&sr_ptr->ps.exp, flag);
+
+ do_char(&sr_ptr->infra, flag);
+
+ do_vector(flag, sr_ptr->ps.powers, do_s16b);
+
+ for (i = 0; i < BODY_MAX; i++)
+ {
+ do_char(&sr_ptr->body_parts[i], flag);
+ }
+
+ do_flag_set(&sr_ptr->flags, flag);
+
+ for (i = 0; i < PY_MAX_LEVEL + 1; i++)
+ {
+ do_player_level_flag(&sr_ptr->lflags[i], flag);
+ }
+
+ do_byte(&sr_ptr->g_attr, flag);
+ do_char(&sr_ptr->g_char, flag);
+
+ do_skill_modifiers(&sr_ptr->skill_modifiers, flag);
+}
+
+
+static void do_random_spell(random_spell *s_ptr, ls_flag_t flag)
+{
+ do_s16b(&s_ptr->mana, flag);
+ do_s16b(&s_ptr->fail, flag);
+ do_u32b(&s_ptr->proj_flags, flag);
+ do_byte(&s_ptr->GF, flag);
+ do_byte(&s_ptr->radius, flag);
+ do_byte(&s_ptr->dam_sides, flag);
+ do_byte(&s_ptr->dam_dice, flag);
+ do_byte(&s_ptr->level, flag);
+ do_std_bool(&s_ptr->untried, flag);
+}
+
+static void do_level_marker(level_marker *marker, ls_flag_t flag)
+{
+ std::string v;
+
+ if (flag == ls_flag_t::SAVE)
+ {
+ v = level_marker_values().stringify(*marker);
+ }
+
+ do_std_string(v, flag);
+
+ if (flag == ls_flag_t::LOAD)
+ {
+ bool valid = level_marker_values().parse(v.c_str(), marker);
+ if (!valid)
+ {
+ note(fmt::format("Bad level marker: {}!", v).c_str());
+ abort();
+ }
+ }
+}
+
+/*
+ * Misc. other data
+ */
+static bool_ do_extra(ls_flag_t flag)
+{
+ auto const &d_info = game->edit_data.d_info;
+ auto &s_info = game->s_info;
+
+ do_std_string(game->player_name, flag);
+
+ do_std_string(game->died_from, flag);
+
+ /* Handle the special levels info */
+ {
+ byte tmp8u = d_info.size();
+ u16b tmp16u = MAX_DUNGEON_DEPTH;
+
+ do_byte(&tmp8u, flag);
+
+ if (flag == ls_flag_t::LOAD)
+ {
+ if (tmp8u > d_info.size())
+ {
+ note(format("Too many dungeon types!", static_cast<int>(tmp8u)));
+ }
+ }
+
+ do_u16b(&tmp16u, flag);
+
+ if (flag == ls_flag_t::LOAD)
+ {
+ if (tmp16u > MAX_DUNGEON_DEPTH)
+ {
+ note(format("Too many (%d) max level by dungeon type!", static_cast<int>(tmp16u)));
+ }
+ }
+
+ /* Load the special levels history */
+ for (std::size_t i = 0; i < tmp8u; i++)
+ {
+ for (std::size_t j = 0; j < tmp16u; j++)
+ {
+ do_level_marker(&game->level_markers[j][i], flag);
+ }
+ }
+ }
+
+ do_std_bool(&game->generate_special_feeling, flag);
+
+ /* Load the quick start data */
+ do_quick_start(flag, game->previous_char);
+
+ /* Load/save the special subrace */
+ do_subrace(flag);
+
+ /* Race/Class/Gender/Spells */
+ do_s32b(&p_ptr->lives, flag);
+ do_byte(&p_ptr->prace, flag);
+ do_byte(&p_ptr->pracem, flag);
+ do_byte(&p_ptr->pclass, flag);
+ do_byte(&p_ptr->pspec, flag);
+ do_byte(&p_ptr->mimic_form, flag);
+ do_s16b(&p_ptr->mimic_level, flag);
+
+ do_byte(&p_ptr->hitdie, flag);
+ do_u16b(&p_ptr->expfact, flag);
+
+ /* Dump the stats (maximum and current) */
+ for (std::size_t i = 0; i < 6; ++i) do_s16b(&p_ptr->stat_max[i], flag);
+ for (std::size_t i = 0; i < 6; ++i) do_s16b(&p_ptr->stat_cur[i], flag);
+ for (std::size_t i = 0; i < 6; ++i) do_s16b(&p_ptr->stat_cnt[i], flag);
+ for (std::size_t i = 0; i < 6; ++i) do_s16b(&p_ptr->stat_los[i], flag);
+
+ // Skills
+ {
+ do_s16b(&p_ptr->skill_points, flag);
+ do_s16b(&p_ptr->skill_last_level, flag);
+ do_s16b(&p_ptr->melee_style, flag);
+ do_s16b(&p_ptr->use_piercing_shots, flag);
+
+ do_array("skills", flag, s_info, s_info.size(),
+ [](auto skill, auto flag) -> void {
+ do_s32b(&skill->value, flag);
+ do_s32b(&skill->mod, flag);
+ do_std_bool(&skill->dev, flag);
+ do_std_bool(&skill->hidden, flag);
+ }
+ );
+ }
+
+ // Abilities
+ do_vector(flag, p_ptr->abilities, do_u16b);
+
+ // Miscellaneous
+ do_s16b(&p_ptr->luck_base, flag);
+ do_s16b(&p_ptr->luck_max, flag);
+
+ do_s32b(&p_ptr->au, flag);
+
+ do_s32b(&p_ptr->max_exp, flag);
+ do_s32b(&p_ptr->exp, flag);
+ do_u16b(&p_ptr->exp_frac, flag);
+ do_s16b(&p_ptr->lev, flag);
+
+ do_s16b(&p_ptr->town_num, flag); /* -KMW- */
+
+ /* Write arena and rewards information -KMW- */
+ do_s16b(&p_ptr->inside_quest, flag);
+
+
+ /* Save/load spellbinder */
+ do_byte(&p_ptr->spellbinder.trigger, flag);
+ do_vector(flag, p_ptr->spellbinder.spell_idxs, do_u32b);
+
+ // Quest status
+ do_array("plot quests", flag, plots, MAX_PLOTS,
+ [](auto plot, auto flag) -> void {
+ do_s16b(plot, flag);
+ }
+ );
+
+ // Random quests
+ do_array("random quests", flag, random_quests, MAX_RANDOM_QUEST,
+ [](auto q, auto flag) -> void {
+ do_byte(&q->type, flag);
+ do_s16b(&q->r_idx, flag);
+ do_std_bool(&q->done, flag);
+ }
+ );
+
+ do_s16b(&p_ptr->oldpx, flag);
+ do_s16b(&p_ptr->oldpy, flag);
+
+ do_s16b(&p_ptr->mhp, flag);
+ do_s16b(&p_ptr->chp, flag);
+ do_u16b(&p_ptr->chp_frac, flag);
+ do_s16b(&p_ptr->hp_mod, flag);
+
+ do_s16b(&p_ptr->msane, flag);
+ do_s16b(&p_ptr->csane, flag);
+ do_u16b(&p_ptr->csane_frac, flag);
+
+ do_s16b(&p_ptr->msp, flag);
+ do_s16b(&p_ptr->csp, flag);
+ do_u16b(&p_ptr->csp_frac, flag);
+
+ /* Gods */
+ do_s32b(&p_ptr->grace, flag);
+ do_s32b(&p_ptr->grace_delay, flag);
+ do_bool(&p_ptr->praying, flag);
+ do_s16b(&p_ptr->melkor_sacrifice, flag);
+ do_byte(&p_ptr->pgod, flag);
+
+ do_s16b(&p_ptr->max_plv, flag);
+
+ // Max dungeon levels
+ {
+ byte tmp8u = d_info.size();
+
+ do_byte(&tmp8u, flag);
+
+ for (std::size_t i = 0; i < tmp8u; i++)
+ {
+ s16b tmp16s = max_dlv[i];
+
+ do_s16b(&tmp16s, flag);
+
+ if ((flag == ls_flag_t::LOAD) && (i <= d_info.size()))
+ {
+ max_dlv[i] = tmp16s;
+ }
+ }
+ }
+
+ /* Repair max player level??? */
+ if ((flag == ls_flag_t::LOAD) && (p_ptr->max_plv < p_ptr->lev))
+ {
+ p_ptr->max_plv = p_ptr->lev;
+ }
+
+ /* Help */
+ do_std_bool(&p_ptr->help.enabled, flag);
+ for (std::size_t i = 0; i < HELP_MAX; i++)
+ {
+ do_std_bool(&p_ptr->help.activated[i], flag);
+ }
+
+ /* More info */
+ do_s16b(&p_ptr->blind, flag);
+ do_s16b(&p_ptr->paralyzed, flag);
+ do_s16b(&p_ptr->confused, flag);
+ do_s16b(&p_ptr->food, flag);
+ do_s32b(&p_ptr->energy, flag);
+ do_s16b(&p_ptr->fast, flag);
+ do_s16b(&p_ptr->speed_factor, flag);
+ do_s16b(&p_ptr->slow, flag);
+ do_s16b(&p_ptr->afraid, flag);
+ do_s16b(&p_ptr->cut, flag);
+ do_s16b(&p_ptr->stun, flag);
+ do_s16b(&p_ptr->poisoned, flag);
+ do_s16b(&p_ptr->image, flag);
+ do_s16b(&p_ptr->protevil, flag);
+ do_s16b(&p_ptr->invuln, flag);
+ do_s16b(&p_ptr->hero, flag);
+ do_s16b(&p_ptr->shero, flag);
+ do_s16b(&p_ptr->shield, flag);
+ do_s16b(&p_ptr->shield_power, flag);
+ do_s16b(&p_ptr->shield_power_opt, flag);
+ do_s16b(&p_ptr->shield_power_opt2, flag);
+ do_s16b(&p_ptr->shield_opt, flag);
+ do_s16b(&p_ptr->blessed, flag);
+ do_s16b(&p_ptr->control, flag);
+ do_byte(&p_ptr->control_dir, 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);
+ do_s16b(&p_ptr->tim_project, flag);
+ do_s16b(&p_ptr->tim_project_dam, flag);
+ do_s16b(&p_ptr->tim_project_gf, flag);
+ do_s16b(&p_ptr->tim_project_rad, flag);
+ do_s16b(&p_ptr->tim_project_flag, flag);
+
+ do_s16b(&p_ptr->tim_magic_breath, flag);
+ do_s16b(&p_ptr->tim_water_breath, flag);
+
+ do_s16b(&p_ptr->tim_roots, flag);
+ do_s16b(&p_ptr->tim_roots_ac, flag);
+ do_s16b(&p_ptr->tim_roots_dam, flag);
+
+ do_s16b(&p_ptr->tim_invis, flag);
+ do_s16b(&p_ptr->word_recall, flag);
+ do_byte(&p_ptr->recall_dungeon, flag);
+ do_s16b(&p_ptr->see_infra, flag);
+ do_s16b(&p_ptr->tim_infra, flag);
+ do_s16b(&p_ptr->oppose_fire, flag);
+ do_s16b(&p_ptr->oppose_cold, flag);
+ do_s16b(&p_ptr->oppose_acid, flag);
+ do_s16b(&p_ptr->oppose_elec, flag);
+ do_s16b(&p_ptr->oppose_pois, flag);
+ do_s16b(&p_ptr->oppose_cc, flag);
+
+ do_s16b(&p_ptr->tim_esp, flag);
+ do_s16b(&p_ptr->tim_wraith, flag);
+ do_s16b(&p_ptr->tim_ffall, flag);
+ do_s16b(&p_ptr->tim_fly, flag);
+ do_s16b(&p_ptr->tim_poison, flag);
+ do_s16b(&p_ptr->tim_invisible, flag);
+ do_s16b(&p_ptr->tim_inv_pow, flag);
+ do_s16b(&p_ptr->tim_mimic, flag);
+ do_s16b(&p_ptr->lightspeed, flag);
+ do_s16b(&p_ptr->tim_lite, flag);
+ do_s16b(&p_ptr->tim_regen, flag);
+ do_s16b(&p_ptr->tim_regen_pow, flag);
+ do_s16b(&p_ptr->holy, flag);
+ do_s16b(&p_ptr->immov_cntr, flag);
+ do_s16b(&p_ptr->strike, flag);
+ do_s16b(&p_ptr->tim_reflect, flag);
+ do_s16b(&p_ptr->tim_deadly, flag);
+ do_s16b(&p_ptr->prob_travel, flag);
+ do_s16b(&p_ptr->disrupt_shield, flag);
+ do_s16b(&p_ptr->parasite, flag);
+ do_s16b(&p_ptr->parasite_r_idx, 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_array("corruptions", flag, p_ptr->corruptions, CORRUPTIONS_MAX,
+ [](auto corruption, auto flag) -> void {
+ do_bool(corruption, flag);
+ }
+ );
+
+ do_bool(&p_ptr->corrupt_anti_teleport_stopped, flag);
+
+ do_byte(&p_ptr->confusing, flag);
+ do_bool(&p_ptr->black_breath, flag);
+ do_bool(&fate_flag, flag);
+ do_bool(&ambush_flag, flag);
+ do_byte(&p_ptr->allow_one_death, flag);
+
+ do_s16b(&no_breeds, flag);
+
+ /* Auxilliary variables */
+ do_u32b(&p_ptr->mimic_extra, flag);
+ do_u32b(&p_ptr->antimagic_extra, flag);
+ do_u32b(&p_ptr->music_extra, flag);
+ do_u32b(&p_ptr->necro_extra, flag);
+ do_u32b(&p_ptr->necro_extra2, flag);
+
+ do_u16b(&p_ptr->body_monster, flag);
+ do_bool(&p_ptr->disembodied, flag);
+
+ /* Are we in astral mode? */
+ do_bool(&p_ptr->astral, flag);
+
+ // Powers
+ do_array("powers", flag, p_ptr->powers_mod, POWER_MAX,
+ [](auto pwr, auto flag) -> void {
+ do_bool(pwr, flag);
+ }
+ );
+
+ /* The tactic */
+ do_char(&p_ptr->tactic, flag);
+
+ /* The movement */
+ do_char(&p_ptr->movement, flag);
+
+ /* The comapnions killed */
+ do_s16b(&p_ptr->companion_killed, flag);
+
+ /* The fate */
+ do_bool(&p_ptr->no_mortal, flag);
+
+ /* Random spells */
+ do_vector(flag, p_ptr->random_spells, do_random_spell);
+
+ /* Random seed for object flavors. */
+ do_seed(&seed_flavor(), flag);
+
+ /* Special stuff */
+ do_u16b(&total_winner, flag);
+ do_u16b(&has_won, flag);
+ do_u16b(&noscore, flag);
+
+ /* Write death */
+ do_bool(&death, flag);
+
+ /* Level feeling */
+ do_s16b(&feeling, flag);
+
+ /* Turn of last "feeling" */
+ do_s32b(&old_turn, flag);
+
+ /* Current turn */
+ do_s32b(&turn, flag);
+
+ return TRUE;
+}
+
+
+/*
+ * Read a monster
+ */
+static void do_monster(monster_type *m_ptr, ls_flag_t flag)
+{
+ /* Read the monster race */
+ do_s16b(&m_ptr->r_idx, flag);
+
+ do_u16b(&m_ptr->ego, flag);
+
+ /* Read the other information */
+ do_byte(&m_ptr->fy, flag);
+ do_byte(&m_ptr->fx, flag);
+
+ do_s32b(&m_ptr->hp, flag);
+ do_s32b(&m_ptr->maxhp, flag);
+
+ do_s16b(&m_ptr->csleep, flag);
+ do_byte(&m_ptr->mspeed, flag);
+ do_byte(&m_ptr->energy, flag);
+ do_byte(&m_ptr->stunned, flag);
+ do_byte(&m_ptr->confused, flag);
+ do_byte(&m_ptr->monfear, flag);
+ do_u32b(&m_ptr->smart, flag);
+ do_s16b(&m_ptr->status, flag);
+ do_s16b(&m_ptr->possessor, flag);
+ do_byte(&m_ptr->speed, flag);
+ do_byte(&m_ptr->level, flag);
+ do_s16b(&m_ptr->ac, flag);
+ do_s32b(&m_ptr->exp, flag);
+ do_s16b(&m_ptr->target, flag);
+
+ do_s16b(&m_ptr->bleeding, flag);
+ do_s16b(&m_ptr->poisoned, flag);
+
+ do_s32b(&m_ptr->mflag, flag);
+
+ if (flag == ls_flag_t::LOAD)
+ {
+ m_ptr->mflag &= PERM_MFLAG_MASK;
+ }
+
+ /* Attacks */
+ do_array("attacks", flag, m_ptr->blow, 4,
+ [](auto blow, auto flag) {
+ do_byte(&blow->method, flag);
+ do_byte(&blow->effect, flag);
+ do_byte(&blow->d_dice, flag);
+ do_byte(&blow->d_side, flag);
+ }
+ );
+}
+
+
+
+/*
+ * Determine if an item can be wielded/worn (e.g. helmet, sword, bow, arrow)
+ */
+static bool_ wearable_p(object_type *o_ptr)
+{
+ /* Valid "tval" codes */
+ switch (o_ptr->tval)
+ {
+ case TV_WAND:
+ case TV_STAFF:
+ case TV_ROD:
+ case TV_ROD_MAIN:
+ case TV_SHOT:
+ case TV_ARROW:
+ case TV_BOLT:
+ case TV_BOOMERANG:
+ case TV_BOW:
+ case TV_DIGGING:
+ case TV_HAFTED:
+ case TV_POLEARM:
+ case TV_MSTAFF:
+ case TV_SWORD:
+ 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_SCROLL:
+ case TV_LITE:
+ case TV_POTION:
+ case TV_POTION2:
+ case TV_AMULET:
+ case TV_RING:
+ case TV_HYPNOS:
+ case TV_INSTRUMENT:
+ case TV_DAEMON_BOOK:
+ case TV_TOOL:
+ {
+ return (TRUE);
+ }
+ }
+
+ /* Nope */
+ return (FALSE);
+}
+
+
+/*
+ * rd/wr an object
+ */
+static void do_item(object_type *o_ptr, ls_flag_t flag)
+{
+ auto &k_info = game->edit_data.k_info;
+ auto &a_info = game->edit_data.a_info;
+ auto &e_info = game->edit_data.e_info;
+
+ byte old_dd;
+ byte old_ds;
+
+ /* Kind */
+ do_s16b(&o_ptr->k_idx, flag);
+
+ /* Location */
+ do_byte(&o_ptr->iy, flag);
+ do_byte(&o_ptr->ix, flag);
+
+ /* Type/Subtype */
+ do_byte(&o_ptr->tval, flag);
+ do_byte(&o_ptr->sval, flag);
+
+ /* Special pval */
+ do_s32b(&o_ptr->pval, flag);
+
+ /* Special pval */
+ do_s16b(&o_ptr->pval2, flag);
+
+ /* Special pval */
+ do_s32b(&o_ptr->pval3, flag);
+
+ do_byte(&o_ptr->discount, flag);
+ do_byte(&o_ptr->number, flag);
+ do_s32b(&o_ptr->weight, flag);
+
+ do_byte(&o_ptr->name1, flag);
+ do_s16b(&o_ptr->name2, flag);
+ do_s16b(&o_ptr->name2b, flag);
+ do_s16b(&o_ptr->timeout, flag);
+
+ do_s16b(&o_ptr->to_h, flag);
+ do_s16b(&o_ptr->to_d, flag);
+ do_s16b(&o_ptr->to_a, flag);
+
+ do_s16b(&o_ptr->ac, flag);
+
+ /* We do special processing of this flag when reading */
+ if (flag == ls_flag_t::LOAD)
+ {
+ do_byte(&old_dd, ls_flag_t::LOAD);
+ do_byte(&old_ds, ls_flag_t::LOAD);
+ }
+ if (flag == ls_flag_t::SAVE)
+ {
+ do_byte(&o_ptr->dd, ls_flag_t::SAVE);
+ do_byte(&o_ptr->ds, ls_flag_t::SAVE);
+ }
+
+ do_byte(&o_ptr->ident, flag);
+
+ do_byte(&o_ptr->marked, flag);
+
+ /* flags */
+ do_flag_set(&o_ptr->art_flags, flag);
+
+ /* obvious flags */
+ do_flag_set(&o_ptr->art_oflags, flag);
+
+ /* Monster holding object */
+ do_s16b(&o_ptr->held_m_idx, flag);
+
+ /* Special powers */
+ do_byte(&o_ptr->xtra1, flag);
+ do_s16b(&o_ptr->xtra2, flag);
+
+ do_byte(&o_ptr->elevel, flag);
+ do_s32b(&o_ptr->exp, flag);
+
+ /* Read the pseudo-id */
+ do_byte(&o_ptr->sense, flag);
+
+ /* Read the found info */
+ do_byte(&o_ptr->found, flag);
+ do_s16b(&o_ptr->found_aux1, flag);
+ do_s16b(&o_ptr->found_aux2, flag);
+ do_s16b(&o_ptr->found_aux3, flag);
+ do_s16b(&o_ptr->found_aux4, flag);
+
+ // Inscription
+ do_std_string(o_ptr->inscription, flag);
+
+ // Artifact name
+ do_std_string(o_ptr->artifact_name, flag);
+
+ /* Stick any more shared code before this. The rest
+ of this function is reserved for ls_flag_t::LOAD's
+ cleanup functions */
+
+ if (flag == ls_flag_t::SAVE) return;
+
+ /*********** END OF ls_flag_t::SAVE ***************/
+
+ /* Obtain the "kind" template */
+ object_kind *k_ptr = &k_info[o_ptr->k_idx];
+
+ /* Obtain tval/sval from k_info */
+ o_ptr->tval = k_ptr->tval;
+ if (o_ptr->tval != TV_RANDART) o_ptr->sval = k_ptr->sval;
+
+
+ /* Repair non "wearable" items */
+ if (!wearable_p(o_ptr))
+ {
+ /* Acquire correct fields */
+ o_ptr->to_h = k_ptr->to_h;
+ o_ptr->to_d = k_ptr->to_d;
+ o_ptr->to_a = k_ptr->to_a;
+
+ /* Acquire correct fields */
+ o_ptr->ac = k_ptr->ac;
+ o_ptr->dd = k_ptr->dd;
+ o_ptr->ds = k_ptr->ds;
+
+ /* All done */
+ return;
+ }
+
+
+ /* Paranoia */
+ if (o_ptr->name1)
+ {
+ /* Obtain the artifact info */
+ auto a_ptr = &a_info[o_ptr->name1];
+
+ /* Verify that artifact */
+ if (!a_ptr->name) o_ptr->name1 = 0;
+ }
+
+ /* Paranoia */
+ if (o_ptr->name2)
+ {
+ ego_item_type *e_ptr;
+
+ /* Obtain the ego-item info */
+ e_ptr = &e_info[o_ptr->name2];
+
+ /* Verify that ego-item */
+ if (!e_ptr->name) o_ptr->name2 = 0;
+ }
+
+
+ /* Acquire standard fields */
+ o_ptr->ac = k_ptr->ac;
+ o_ptr->dd = k_ptr->dd;
+ o_ptr->ds = k_ptr->ds;
+
+ /* Artifacts */
+ if (o_ptr->name1)
+ {
+ artifact_type *a_ptr;
+
+ /* Obtain the artifact info */
+ a_ptr = &a_info[o_ptr->name1];
+
+ /* Acquire new artifact fields */
+ o_ptr->ac = a_ptr->ac;
+ o_ptr->dd = a_ptr->dd;
+ o_ptr->ds = a_ptr->ds;
+
+ /* Acquire new artifact weight */
+ o_ptr->weight = a_ptr->weight;
+ }
+
+ /* Ego items */
+ if (o_ptr->name2)
+ {
+ o_ptr->dd = old_dd;
+ o_ptr->ds = old_ds;
+ }
+
+ if (!o_ptr->artifact_name.empty()) /* A random artifact */
+ {
+ o_ptr->dd = old_dd;
+ o_ptr->ds = old_ds;
+ }
+}
+
+static void do_cave_type(cave_type *c_ptr, ls_flag_t flag)
+{
+ do_u16b(&c_ptr->info, flag);
+ do_byte(&c_ptr->feat, flag);
+ do_byte(&c_ptr->mimic, flag);
+ do_s16b(&c_ptr->special, flag);
+ do_s16b(&c_ptr->special2, flag);
+ do_s16b(&c_ptr->inscription, flag);
+ do_byte(&c_ptr->mana, flag);
+ do_s16b(&c_ptr->effect, flag);
+}
+
+static void do_grid(ls_flag_t flag)
+{
+ for (int y = 0; y < cur_hgt; y++)
+ {
+ for (int x = 0; x < cur_wid; x++)
+ {
+ do_cave_type(&cave[y][x], flag);
+ }
+ }
+}
+
+static bool do_objects(ls_flag_t flag, bool no_companions)
+{
+ if (flag == ls_flag_t::SAVE)
+ {
+ // Compact everything before saving
+ compact_objects(0);
+ compact_monsters(0);
+ }
+
+ u16b n_objects = o_max;
+
+ if (flag == ls_flag_t::SAVE)
+ {
+ u16b tmp16u = n_objects;
+
+ if (no_companions)
+ {
+ for (int i = 1; i < o_max; i++)
+ {
+ object_type *o_ptr = &o_list[i];
+
+ if (o_ptr->held_m_idx && (m_list[o_ptr->held_m_idx].status == MSTATUS_COMPANION))
+ {
+ tmp16u--;
+ }
+ }
+ }
+
+ do_u16b(&tmp16u, flag);
+ }
+ else
+ {
+ do_u16b(&n_objects, flag);
+ }
+
+ /* Verify maximum */
+ if ((flag == ls_flag_t::LOAD) && (n_objects > max_o_idx))
+ {
+ note("Too many object entries!");
+ return false;
+ }
+
+ /* Dungeon items */
+ if (flag == ls_flag_t::SAVE)
+ {
+ for (std::size_t i = 1; i < n_objects; i++)
+ {
+ auto o_ptr = &o_list[i];
+ // Skip objects held by companions when no_companions is set
+ if (no_companions && o_ptr->held_m_idx && (m_list[o_ptr->held_m_idx].status == MSTATUS_COMPANION))
+ {
+ continue;
+ }
+
+ do_item(o_ptr, ls_flag_t::SAVE);
+ }
+ }
+ else if (flag == ls_flag_t::LOAD)
+ {
+ for (int i = 1; i < n_objects; i++)
+ {
+ /* Get a new record */
+ int o_idx = o_pop();
+
+ /* Oops */
+ if (i != o_idx)
+ {
+ note(format("Object allocation error (%d <> %d)", i, o_idx));
+ return false;
+ }
+
+ /* Acquire place */
+ auto o_ptr = &o_list[o_idx];
+
+ /* Read the item */
+ do_item(o_ptr, ls_flag_t::LOAD);
+
+ /* Monster */
+ if (o_ptr->held_m_idx)
+ {
+ /* Monster */
+ monster_type *m_ptr = &m_list[o_ptr->held_m_idx];
+
+ /* Place the object */
+ m_ptr->hold_o_idxs.push_back(o_idx);
+ }
+
+ /* Dungeon */
+ else
+ {
+ /* Access the item location */
+ auto c_ptr = &cave[o_ptr->iy][o_ptr->ix];
+
+ /* Place the object */
+ c_ptr->o_idxs.push_back(o_idx);
+ }
+ }
+ }
+
+ return true;
+}
+
+
+static bool do_monsters(ls_flag_t flag, bool no_companions)
+{
+ auto &r_info = game->edit_data.r_info;
+
+ u16b n_monsters = m_max;
+
+ if (flag == ls_flag_t::SAVE)
+ {
+ u16b tmp16u = m_max;
+
+ if (no_companions)
+ {
+ for (int i = 1; i < m_max; i++)
+ {
+ monster_type *m_ptr = &m_list[i];
+
+ if (m_ptr->status == MSTATUS_COMPANION)
+ {
+ tmp16u--;
+ }
+ }
+ }
+
+ do_u16b(&tmp16u, flag);
+ }
+ else
+ {
+ do_u16b(&n_monsters, flag);
+ }
+
+ /* Validate */
+ if ((flag == ls_flag_t::LOAD) && (n_monsters > max_m_idx))
+ {
+ note("Too many monster entries!");
+ return false;
+ }
+
+ /* Load/save the monsters */
+
+ if (flag == ls_flag_t::SAVE)
+ {
+ for (std::size_t i = 1; i < n_monsters; i++)
+ {
+ auto m_ptr = &m_list[i];
+
+ // Skip companions when no_companions is set
+ if (no_companions && m_ptr->status == MSTATUS_COMPANION)
+ {
+ continue;
+ }
+
+ do_monster(m_ptr, ls_flag_t::SAVE);
+ }
+ }
+ else if (flag == ls_flag_t::LOAD)
+ {
+ for (int i = 1; i < n_monsters; i++)
+ {
+ /* Get a new record */
+ int m_idx = m_pop();
+
+ /* Oops */
+ if (i != m_idx)
+ {
+ note(format("Monster allocation error (%d <> %d)", i, m_idx));
+ return false;
+ }
+
+ /* Acquire monster */
+ auto m_ptr = &m_list[m_idx];
+
+ /* Read the monster */
+ do_monster(m_ptr, ls_flag_t::LOAD);
+
+ /* Place in grid */
+ auto c_ptr = &cave[m_ptr->fy][m_ptr->fx];
+ c_ptr->m_idx = m_idx;
+
+ /* Controlled? */
+ if (m_ptr->mflag & MFLAG_CONTROL)
+ {
+ p_ptr->control = m_idx;
+ }
+
+ /* Count as an alive member of race */
+ auto r_ptr = &r_info[m_ptr->r_idx];
+ r_ptr->cur_num++;
+ }
+ }
+
+ /* Save/load pets */
+ {
+ const std::size_t sz =
+ (flag == ls_flag_t::SAVE && !no_companions) ? max_m_idx : 0;
+
+ do_array("pets", flag, km_list, sz,
+ [](auto m_ptr, auto flag) {
+ do_monster(m_ptr, flag);
+ }
+ );
+ }
+
+ return true;
+}
+
+/*
+ * Handle dungeon
+ *
+ * The monsters/objects must be loaded in the same order
+ * that they were stored, since the actual indexes matter.
+ */
+static bool_ do_dungeon(ls_flag_t flag, bool no_companions)
+{
+ /* Header info */
+ do_s16b(&dun_level, flag);
+ do_byte(&dungeon_type, flag);
+ do_s16b(&num_repro, flag);
+ do_s16b(&p_ptr->py, flag);
+ do_s16b(&p_ptr->px, flag);
+ do_s16b(&cur_hgt, flag);
+ do_s16b(&cur_wid, flag);
+ do_s16b(&max_panel_rows, flag);
+ do_s16b(&max_panel_cols, flag);
+
+ do_flag_set(&dungeon_flags, flag);
+
+ /* Last teleportation */
+ do_s16b(&last_teleportation_y, flag);
+ do_s16b(&last_teleportation_y, flag);
+
+ /* Spell effects */
+ do_array("spell effects", flag, effects, MAX_EFFECTS,
+ [](auto effect, auto flag) -> void {
+ do_s16b(&effect->type, flag);
+ do_s16b(&effect->dam, flag);
+ do_s16b(&effect->time, flag);
+ do_u32b(&effect->flags, flag);
+ do_s16b(&effect->cx, flag);
+ do_s16b(&effect->cy, flag);
+ do_s16b(&effect->rad, flag);
+ }
+ );
+
+ /* To prevent bugs with evolving dungeons */
+ for (std::size_t i = 0; i < 100; i++)
+ {
+ do_s16b(&floor_type[i], flag);
+ do_s16b(&fill_type[i], flag);
+ }
+
+ if ((flag == ls_flag_t::LOAD) && (!dun_level && !p_ptr->inside_quest))
+ {
+ int xstart = 0;
+ int ystart = 0;
+ /* Init the wilderness */
+ process_dungeon_file("w_info.txt", &ystart, &xstart, cur_hgt, cur_wid,
+ TRUE, FALSE);
+
+ /* Init the town */
+ xstart = 0;
+ ystart = 0;
+ init_flags = 0;
+ process_dungeon_file("t_info.txt", &ystart, &xstart, cur_hgt, cur_wid,
+ TRUE, FALSE);
+ }
+
+ do_grid(flag);
+
+ /*** Objects ***/
+ if (!do_objects(flag, no_companions))
+ {
+ return FALSE;
+ }
+
+ /*** Monsters ***/
+ if (!do_monsters(flag, no_companions))
+ {
+ return FALSE;
+ }
+
+ /*** Success ***/
+
+ /* The dungeon is ready */
+ if (flag == ls_flag_t::LOAD) character_dungeon = TRUE;
+
+ /* Success */
+ return (TRUE);
+}
+
+/* Save the current persistent dungeon -SC- */
+void save_dungeon()
+{
+ char tmp[16];
+ char name[1024], buf[5];
+
+ /* Save only persistent dungeons */
+ if (!get_dungeon_save(buf) || (!dun_level)) return;
+
+ /* Construct filename */
+ sprintf(tmp, "%s.%s", game->player_base.c_str(), buf);
+ path_build(name, 1024, ANGBAND_DIR_SAVE, tmp);
+
+ /* Open the file */
+ fff = my_fopen(name, "wb");
+
+ /* Save the dungeon */
+ do_dungeon(ls_flag_t::SAVE, true);
+
+ my_fclose(fff);
+}
+
+
+/*
+ * Read a store
+ */
+static void do_store(store_type *str, ls_flag_t flag)
+{
+ // Store state
+ do_s32b(&str->store_open, flag);
+ do_u16b(&str->owner, flag);
+ do_s32b(&str->last_visit, flag);
+
+ // Items in store
+ {
+ byte num = str->stock.size();
+
+ do_byte(&num, flag);
+
+ if (flag == ls_flag_t::SAVE)
+ {
+ for (std::size_t i = 0; i < num; i++)
+ {
+ do_item(&str->stock[i], ls_flag_t::SAVE);
+ }
+ }
+ else if (flag == ls_flag_t::LOAD)
+ {
+ for (std::size_t i = 0; i < num; i++)
+ {
+ object_type forge;
+ object_wipe(&forge);
+ do_item(&forge, ls_flag_t::LOAD);
+
+ if ((str->stock.size() < STORE_INVEN_MAX) && (str->stock.size() < str->stock_size))
+ {
+ object_type stock_obj;
+ object_copy(&stock_obj, &forge);
+ str->stock.push_back(stock_obj);
+ }
+ }
+ }
+ }
+}
+
+/*
+ * RNG state
+ */
+static void do_randomizer(ls_flag_t flag)
+{
+ std::string state;
+
+ if (flag == ls_flag_t::SAVE)
+ {
+ state = get_complex_rng_state();
+ }
+
+ do_std_string(state, flag);
+
+ if (flag == ls_flag_t::LOAD)
+ {
+ set_complex_rng_state(state);
+ }
+
+ /* Accept */
+ if (flag == ls_flag_t::LOAD)
+ {
+ set_complex_rng();
+ }
+}
+
+/*
+ * Handle options
+ *
+ * Normal options are stored as a set of 256 bit flags,
+ * plus a set of 256 bit masks to indicate which bit flags were defined
+ * at the time the savefile was created. This will allow new options
+ * to be added, and old options to be removed, at any time, without
+ * hurting old savefiles.
+ *
+ * The window options are stored in the same way, but note that each
+ * window gets 32 options, and their order is fixed by certain defines.
+ */
+static void do_options(ls_flag_t flag)
+{
+ int i, n;
+
+ u32b oflag[8];
+ u32b mask[8];
+
+ /*** Special info */
+
+ /* Read "delay_factor" */
+ do_byte(&options->delay_factor, flag);
+
+ /* Read "hitpoint_warn" */
+ do_byte(&options->hitpoint_warn, flag);
+
+ /*** Cheating options ***/
+ do_bool(&wizard, flag);
+ do_bool(&options->cheat_peek, flag);
+ do_bool(&options->cheat_hear, flag);
+ do_bool(&options->cheat_room, flag);
+ do_bool(&options->cheat_xtra, flag);
+ do_bool(&options->cheat_live, flag);
+
+ /*** Autosave options */
+ do_bool(&options->autosave_l, flag);
+ do_bool(&options->autosave_t, flag);
+ do_s16b(&options->autosave_freq, flag);
+
+ // Standard options
+ {
+ std::vector<option_value> option_values;
+
+ // If we're saving we need to map to a vector of key-value pairs.
+ if (flag == ls_flag_t::SAVE)
+ {
+ for (auto const &option: options->standard_options)
+ {
+ option_values.emplace_back(
+ option_value {
+ option.o_text,
+ *option.o_var
+ }
+ );
+ }
+ }
+
+ // Read/write the option values
+ do_vector(flag, option_values, do_option_value);
+
+ // If we're loading we need to set options based of the key-value pairs.
+ if (flag == ls_flag_t::LOAD)
+ {
+ // Go through all the options that were loaded.
+ for (auto const &option_value: option_values)
+ {
+ // We need to search through all the options
+ // that are actually in the game; we'll ignore
+ // saved options that are now gone.
+ const option_type *found_option;
+ for (auto const &option: options->standard_options)
+ {
+ if (option_value.name == option.o_text)
+ {
+ found_option = &option;
+ break;
+ }
+ }
+
+ // If we found the option, we'll set the value.
+ if (found_option)
+ {
+ *(*found_option).o_var = option_value.value;
+ }
+ }
+ }
+
+ }
+
+ if (flag == ls_flag_t::LOAD)
+ {
+ /*** Window Options ***/
+
+ /* Read the window flags */
+ for (n = 0; n < ANGBAND_TERM_MAX; n++)
+ {
+ do_u32b(&oflag[n], flag);
+ }
+
+ /* Read the window masks */
+ for (n = 0; n < ANGBAND_TERM_MAX; n++)
+ {
+ do_u32b(&mask[n], flag);
+ }
+
+ /* Analyze the options */
+ for (n = 0; n < ANGBAND_TERM_MAX; n++)
+ {
+ /* Analyze the options */
+ for (i = 0; i < 32; i++)
+ {
+ /* Process valid flags */
+ if (mask[n] & (1L << i))
+ {
+ /* Process valid flags */
+ if (window_mask[n] & (1L << i))
+ {
+ /* Set */
+ if (oflag[n] & (1L << i))
+ {
+ /* Set */
+ window_flag[n] |= (1L << i);
+ }
+
+ /* Clear */
+ else
+ {
+ /* Clear */
+ window_flag[n] &= ~(1L << i);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (flag == ls_flag_t::SAVE)
+ {
+ /*** Window options ***/
+
+ /* Dump the flags */
+ for (i = 0; i < ANGBAND_TERM_MAX; i++)
+ {
+ do_u32b(&window_flag[i], flag);
+ }
+
+ /* Dump the masks */
+ for (i = 0; i < ANGBAND_TERM_MAX; i++)
+ {
+ do_u32b(&window_mask[i], flag);
+ }
+ }
+}
+
+
+/*
+ * Handle player inventory. Note that the inventory is
+ * "re-sorted" later by "dungeon()".
+ */
+static bool_ do_inventory(ls_flag_t flag)
+{
+ auto const &a_info = game->edit_data.a_info;
+
+ if (flag == ls_flag_t::LOAD)
+ {
+ int slot = 0;
+
+ object_type forge;
+ object_type *q_ptr;
+
+ /* No items */
+ inven_cnt = 0;
+ equip_cnt = 0;
+
+ /* Read until done */
+ while (1)
+ {
+ u16b n;
+
+ /* Get the next item index */
+ do_u16b(&n, ls_flag_t::LOAD);
+
+ /* Nope, we reached the end */
+ if (n == 0xFFFF) break;
+
+ /* Get local object */
+ q_ptr = &forge;
+
+ /* Wipe the object */
+ object_wipe(q_ptr);
+
+ /* Read the item */
+ do_item(q_ptr, ls_flag_t::LOAD);
+
+ /* Hack -- verify item */
+ if (!q_ptr->k_idx) return (FALSE);
+
+ /* Wield equipment */
+ if (n >= INVEN_WIELD)
+ {
+ /* Copy object */
+ object_copy(&p_ptr->inventory[n], q_ptr);
+
+ /* Take care of item sets */
+ if (q_ptr->name1)
+ {
+ wield_set(q_ptr->name1, a_info[q_ptr->name1].set, TRUE);
+ }
+
+ /* One more item */
+ equip_cnt++;
+ }
+
+ /* Warning -- backpack is full */
+ else if (inven_cnt == INVEN_PACK)
+ {
+ /* Oops */
+ note("Too many items in the inventory!");
+
+ /* Fail */
+ return (FALSE);
+ }
+
+ /* Carry inventory */
+ else
+ {
+ /* Get a slot */
+ n = slot++;
+
+ /* Copy object */
+ object_copy(&p_ptr->inventory[n], q_ptr);
+
+ /* One more item */
+ inven_cnt++;
+ }
+ }
+ }
+ if (flag == ls_flag_t::SAVE)
+ {
+ for (u16b i = 0; i < INVEN_TOTAL; i++)
+ {
+ object_type *o_ptr = &p_ptr->inventory[i];
+ if (!o_ptr->k_idx) continue;
+ do_u16b(&i, flag);
+ do_item(o_ptr, flag);
+ }
+ // Sentinel
+ u16b sent = 0xFFFF;
+ do_u16b(&sent, ls_flag_t::SAVE);
+ }
+ /* Success */
+ return (TRUE);
+}
+
+
+static void do_message(message &msg, ls_flag_t flag)
+{
+ do_std_string(msg.text, flag);
+ do_u32b(&msg.count, flag);
+ do_byte(&msg.color, flag);
+}
+
+
+/*
+ * Read the saved messages
+ */
+static void do_messages(ls_flag_t flag)
+{
+ auto &messages = game->messages;
+
+ /* Save/load number of messages */
+ s16b num = messages.size();
+ do_s16b(&num, flag);
+
+ /* Read the messages */
+ for (int i = 0; i < num; i++)
+ {
+ message message;
+
+ if (flag == ls_flag_t::SAVE)
+ {
+ message = messages.at(i);
+ }
+
+ do_message(message, flag);
+
+ if (flag == ls_flag_t::LOAD)
+ {
+ messages.add(message);
+ }
+ }
+}
+
+/* Returns TRUE if we successfully load the dungeon */
+bool_ load_dungeon(char *ext)
+{
+ char tmp[16];
+ char name[1024];
+ byte old_dungeon_type = dungeon_type;
+ s16b old_dun = dun_level;
+
+ /* Construct name */
+ sprintf(tmp, "%s.%s", game->player_base.c_str(), ext);
+ path_build(name, 1024, ANGBAND_DIR_SAVE, tmp);
+
+ /* Open the file */
+ fff = my_fopen(name, "rb");
+
+ if (fff == NULL)
+ {
+ dun_level = old_dun;
+ dungeon_type = old_dungeon_type;
+
+ my_fclose(fff);
+ return (FALSE);
+ }
+
+ /* Read the dungeon */
+ if (!do_dungeon(ls_flag_t::LOAD, false))
+ {
+ dun_level = old_dun;
+ dungeon_type = old_dungeon_type;
+
+ my_fclose(fff);
+ return (FALSE);
+ }
+
+ dun_level = old_dun;
+ dungeon_type = old_dungeon_type;
+
+ /* Done */
+ my_fclose(fff);
+ return (TRUE);
+}
+
+/*
+ * Load/save timers.
+ */
+static void do_timers(ls_flag_t flag)
+{
+ for (auto &&t_ptr: game->timers)
+ {
+ do_std_bool(&t_ptr->m_enabled, flag);
+ do_s32b(&t_ptr->m_delay, flag);
+ do_s32b(&t_ptr->m_countdown, flag);
+ }
+}
+
+/*
+ * Load/save stores.
+ */
+static void do_stores(ls_flag_t flag)
+{
+ auto const &st_info = game->edit_data.st_info;
+
+ // Indexes for "real" towns.
+ std::vector<byte> reals;
+ reals.reserve(max_towns);
+
+ // Fill in the "real" towns if necessary.
+ if (flag == ls_flag_t::SAVE)
+ {
+ for (int i = 1; i < max_towns; i++)
+ {
+ if (!(town_info[i].flags & TOWN_REAL))
+ {
+ continue;
+ }
+ reals.emplace_back(i);
+ }
+ }
+
+ // Load/save
+ do_vector(flag, reals, do_byte);
+
+ /* Read the stores */
+ u16b n_stores = st_info.size();
+ do_u16b(&n_stores, flag);
+ assert(n_stores <= st_info.size());
+
+ for (auto const z: reals)
+ {
+ if (!town_info[z].stocked)
+ {
+ create_stores_stock(z);
+ }
+
+ for (int j = 0; j < n_stores; j++)
+ {
+ do_store(&town_info[z].store[j], flag);
+ }
+ }
+}
+
+/*
+ * Monster memory
+ */
+static bool do_monster_lore(ls_flag_t flag)
+{
+ auto &r_info = game->edit_data.r_info;
+
+ do_array("monster races", flag, r_info, r_info.size(),
+ [](auto r_ptr, auto flag) -> void {
+ do_s16b(&r_ptr->r_pkills, flag);
+ do_s16b(&r_ptr->max_num, flag);
+ do_bool(&r_ptr->on_saved, flag);
+ }
+ );
+
+ return true;
+}
+
+
+/*
+ * Object memory
+ */
+static bool do_object_lore(ls_flag_t flag)
+{
+ auto &k_info = game->edit_data.k_info;
+
+ do_array("object kinds", flag, k_info, k_info.size(),
+ [](auto k_ptr, auto flag) -> void {
+ do_bool(&k_ptr->aware, flag);
+ do_bool(&k_ptr->tried, flag);
+ do_bool(&k_ptr->artifact, flag);
+ }
+ );
+
+ return true;
+}
+
+
+static bool do_towns(ls_flag_t flag)
+{
+ auto &d_info = game->edit_data.d_info;
+
+ u16b max_towns_ldsv = max_towns;
+
+ do_u16b(&max_towns_ldsv, flag);
+
+ if ((flag == ls_flag_t::LOAD) && (max_towns_ldsv > max_towns))
+ {
+ note("Too many towns!");
+ return false;
+ }
+
+ if (flag == ls_flag_t::SAVE)
+ {
+ max_towns_ldsv = TOWN_RANDOM;
+ }
+
+ do_u16b(&max_towns_ldsv, flag);
+
+ if ((flag == ls_flag_t::LOAD) && (max_towns_ldsv != TOWN_RANDOM))
+ {
+ note("Different random towns base!");
+ return false;
+ }
+
+ for (std::size_t i = 0; i < max_towns; i++)
+ {
+ auto town = &town_info[i];
+
+ do_bool(&town->destroyed, flag);
+
+ if (i >= TOWN_RANDOM)
+ {
+ do_seed(&town->seed, flag);
+ do_byte(&town->flags, flag);
+
+ // Create stock if necessary
+ if ((town_info->flags & TOWN_REAL) && (flag == ls_flag_t::LOAD))
+ {
+ create_stores_stock(i);
+ }
+ }
+ }
+
+ if (flag == ls_flag_t::SAVE)
+ {
+ max_towns_ldsv = d_info.size();
+ }
+
+ do_u16b(&max_towns_ldsv, flag);
+
+ if ((flag == ls_flag_t::LOAD) && (max_towns_ldsv > d_info.size()))
+ {
+ note("Too many dungeon types!");
+ return false;
+ }
+
+ // Town quest entrances
+ u16b max_quests_ldsv = TOWN_DUNGEON;
+ do_u16b(&max_quests_ldsv, flag);
+
+ if ((flag == ls_flag_t::LOAD) && (max_quests_ldsv > TOWN_DUNGEON))
+ {
+ note("Too many town per dungeons!");
+ return false;
+ }
+
+ for (std::size_t i = 0; i < max_towns_ldsv; i++)
+ {
+ for (std::size_t j = 0; j < max_quests_ldsv; j++)
+ {
+ do_s16b(&(d_info[i].t_idx[j]), flag);
+ do_s16b(&(d_info[i].t_level[j]), flag);
+ }
+ do_s16b(&(d_info[i].t_num), flag);
+ }
+
+ return true;
+}
+
+static bool do_quests(ls_flag_t flag)
+{
+ do_array("quests", flag, quest, MAX_Q_IDX,
+ [](auto q, auto flag) {
+ // Load/save the data
+ do_s16b(&q->status, flag);
+ for (auto &quest_data : q->data)
+ {
+ do_s32b(&quest_data, flag);
+ }
+ // Initialize if necessary
+ if ((flag == ls_flag_t::LOAD) && (q->init != NULL))
+ {
+ q->init();
+ }
+ }
+ );
+
+ return true;
+}
+
+static bool do_wilderness(ls_flag_t flag)
+{
+ auto &wilderness = game->wilderness;
+
+ // Player position and "mode" wrt. wilderness
+ do_s32b(&p_ptr->wilderness_x, flag);
+ do_s32b(&p_ptr->wilderness_y, flag);
+ do_bool(&p_ptr->wild_mode, flag);
+ do_bool(&p_ptr->old_wild_mode, flag);
+
+ // Size of the wilderness
+ u16b wild_x_size = wilderness.width();
+ u16b wild_y_size = wilderness.height();
+ do_u16b(&wild_x_size, flag);
+ do_u16b(&wild_y_size, flag);
+
+ if (flag == ls_flag_t::LOAD)
+ {
+ if ((wild_x_size > wilderness.width()) || (wild_y_size > wilderness.height()))
+ {
+ note("Wilderness is too big!");
+ return false;
+ }
+ }
+
+ // Save/load wilderness tile state
+ for (std::size_t x = 0; x < wild_x_size; x++)
+ {
+ for (std::size_t y = 0; y < wild_y_size; y++)
+ {
+ auto w = &wilderness(x, y);
+ do_seed(&w->seed, flag);
+ do_u16b(&w->entrance, flag);
+ do_bool(&w->known, flag);
+ }
+ }
+
+ return true;
+}
+
+static void do_randart(random_artifact *ra_ptr, ls_flag_t flag)
+{
+ do_std_string(ra_ptr->name_full, flag);
+ do_std_string(ra_ptr->name_short, flag);
+ do_byte(&ra_ptr->level, flag);
+ do_byte(&ra_ptr->attr, flag);
+ do_u32b(&ra_ptr->cost, flag);
+ do_byte(&ra_ptr->activation, flag);
+ do_byte(&ra_ptr->generated, flag);
+}
+
+static bool do_randarts(ls_flag_t flag)
+{
+ do_vector(flag, game->random_artifacts, do_randart);
+ return true;
+}
+
+static bool do_artifacts(ls_flag_t flag)
+{
+ auto &a_info = game->edit_data.a_info;
+
+ do_array("artifacts", flag, a_info, a_info.size(),
+ [](auto a_ptr, auto flag) {
+ do_byte(&a_ptr->cur_num, flag);
+ }
+ );
+
+ return true;
+}
+
+static bool do_fates(ls_flag_t flag)
+{
+ do_array("fates", flag, fates, MAX_FATES,
+ [](auto fate, auto flag) {
+ do_byte(&fate->fate, flag);
+ do_byte(&fate->level, flag);
+ do_byte(&fate->serious, flag);
+ do_s16b(&fate->o_idx, flag);
+ do_s16b(&fate->e_idx, flag);
+ do_s16b(&fate->a_idx, flag);
+ do_s16b(&fate->v_idx, flag);
+ do_s16b(&fate->r_idx, flag);
+ do_s16b(&fate->count, flag);
+ do_s16b(&fate->time, flag);
+ do_bool(&fate->know, flag);
+ }
+ );
+
+ return true;
+}
+
+static bool do_floor_inscriptions(ls_flag_t flag)
+{
+ do_array("inscriptions", flag, p_ptr->inscriptions, MAX_INSCRIPTIONS,
+ [](auto i_ptr, auto flag) {
+ do_std_bool(i_ptr, flag);
+ }
+ );
+
+ return true;
+}
+
+static bool do_player_hd(ls_flag_t flag)
+{
+ auto &player_hp = game->player_hp;
+
+ do_array("hit dice entries", flag, player_hp, PY_MAX_LEVEL,
+ [](auto hp_ptr, auto flag) {
+ do_s16b(hp_ptr, flag);
+ }
+ );
+
+ return true;
+}
+
+
+/*
+ * Actually read the savefile
+ */
+static bool_ do_savefile_aux(ls_flag_t flag)
+{
+ auto &class_info = game->edit_data.class_info;
+ auto const &race_info = game->edit_data.race_info;
+ auto const &race_mod_info = game->edit_data.race_mod_info;
+
+ /* Mention the savefile version */
+ if (flag == ls_flag_t::LOAD)
+ {
+ if (vernum != SAVEFILE_VERSION)
+ {
+ note("Incompatible save file version");
+ return FALSE;
+ }
+ }
+
+ /* Handle version bytes */
+ if (flag == ls_flag_t::LOAD)
+ {
+ /* Discard all this, we've already read it */
+ u32b mt32b;
+ do_u32b(&mt32b, flag);
+ }
+ if (flag == ls_flag_t::SAVE)
+ {
+ u32b saver;
+ saver = SAVEFILE_VERSION;
+ do_u32b(&saver, flag);
+ }
+
+ /* Game module */
+ {
+ std::string loaded_game_module;
+
+ if (flag == ls_flag_t::SAVE)
+ {
+ loaded_game_module = game_module;
+ }
+ do_std_string(loaded_game_module, flag);
+
+ // Check for incompatible module
+ if (flag == ls_flag_t::LOAD)
+ {
+ if (!module_savefile_loadable(loaded_game_module))
+ {
+ note(fmt::format("Bad game module. Savefile was saved with module '{:s}' but game is '{:s}'.",
+ loaded_game_module,
+ game_module).c_str());
+ return FALSE;
+ }
+ }
+ }
+
+ /* Timers */
+ do_timers(flag);
+
+ /* Read RNG state */
+ do_randomizer(flag);
+
+ /* Automatizer state */
+ do_bool(&automatizer_enabled, flag);
+
+ /* Then the options */
+ do_options(flag);
+
+ /* Then the "messages" */
+ do_messages(flag);
+
+ if (!do_monster_lore(flag))
+ {
+ return FALSE;
+ }
+
+ if (!do_object_lore(flag))
+ {
+ return FALSE;
+ }
+
+ if (!do_towns(flag))
+ {
+ return FALSE;
+ }
+
+ if (!do_quests(flag))
+ {
+ return FALSE;
+ }
+
+ if (!do_wilderness(flag))
+ {
+ return FALSE;
+ }
+
+ if (!do_randarts(flag))
+ {
+ return FALSE;
+ }
+
+ if (!do_artifacts(flag))
+ {
+ return FALSE;
+ }
+
+ if (!do_fates(flag))
+ {
+ return FALSE;
+ }
+
+ if (!do_floor_inscriptions(flag))
+ {
+ return FALSE;
+ }
+
+ if (!do_extra(flag))
+ {
+ return FALSE;
+ }
+
+ if (!do_player_hd(flag))
+ {
+ return FALSE;
+ }
+
+ if (flag == ls_flag_t::LOAD)
+ {
+ // Make sure that the auxiliary pointers for player
+ // class, race, etc. point to the right places.
+ rp_ptr = &race_info[p_ptr->prace];
+ rmp_ptr = &race_mod_info[p_ptr->pracem];
+ cp_ptr = &class_info[p_ptr->pclass];
+ spp_ptr = &class_info[p_ptr->pclass].spec[p_ptr->pspec];
+ }
+
+ /* Read the pet command settings */
+ do_byte(&p_ptr->pet_follow_distance, 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))
+ {
+ if (flag == ls_flag_t::LOAD)
+ {
+ note("Unable to read inventory");
+ return FALSE;
+ }
+ }
+
+ /* Stores */
+ do_stores(flag);
+
+ /* I'm not dead yet... */
+ if (!death)
+ {
+ /* Dead players have no dungeon */
+ if (flag == ls_flag_t::LOAD)
+ {
+ note("Restoring Dungeon...");
+ }
+
+ if ((flag == ls_flag_t::LOAD) && (!do_dungeon(ls_flag_t::LOAD, false)))
+ {
+ note("Error reading dungeon data");
+ return FALSE;
+ }
+
+ if (flag == ls_flag_t::SAVE)
+ {
+ do_dungeon(ls_flag_t::SAVE, false);
+ }
+ }
+
+ /* Success */
+ return TRUE;
+}
+
+
+
+/*
+ * Actually read the savefile
+ */
+static errr rd_savefile()
+{
+ errr err = 0;
+
+ /* The savefile is a binary file */
+ fff = my_fopen(savefile, "rb");
+
+ /* Paranoia */
+ if (!fff) return ( -1);
+
+ /* Call the sub-function */
+ err = !do_savefile_aux(ls_flag_t::LOAD);
+
+ /* Check for errors */
+ if (ferror(fff)) err = -1;
+
+ /* Close the file */
+ my_fclose(fff);
+
+ /* Result */
+ return (err);
+}
+
+
+/*
+ * Attempt to Load a "savefile"
+ *
+ * On multi-user systems, you may only "read" a savefile if you will be
+ * allowed to "write" it later, this prevents painful situations in which
+ * the player loads a savefile belonging to someone else, and then is not
+ * allowed to save his game when he quits.
+ *
+ * We return "TRUE" if the savefile was usable, and we set the global
+ * flag "character_loaded" if a real, living, character was loaded.
+ *
+ * Note that we always try to load the "current" savefile, even if
+ * there is no such file, so we must check for "empty" savefile names.
+ */
+bool_ load_player()
+{
+ errr err = 0;
+
+ cptr what = "generic";
+
+ /* Paranoia */
+ turn = 0;
+
+ /* Paranoia */
+ death = FALSE;
+
+
+ /* Allow empty savefile name */
+ if (!savefile[0]) return (TRUE);
+
+
+ /* XXX XXX XXX Fix this */
+
+ /* Verify the existance of the savefile */
+ if (!boost::filesystem::exists(savefile))
+ {
+ /* Give a message */
+ msg_format("Savefile does not exist: %s", savefile);
+ msg_print(NULL);
+
+ /* Allow this */
+ return (TRUE);
+ }
+
+ /* Okay */
+ if (!err)
+ {
+ /* Open the savefile */
+ int fd = fd_open(savefile, O_RDONLY);
+
+ /* No file */
+ if (fd < 0) err = -1;
+
+ /* Message (below) */
+ if (err) what = "Cannot open savefile";
+
+ /* Close the file */
+ if (!err) fd_close(fd);
+ }
+
+ /* Process file */
+ if (!err)
+ {
+ /* Open the file XXX XXX XXX XXX Should use Angband file interface */
+ fff = my_fopen(savefile, "rb");
+
+ /* Read the first four bytes */
+ do_u32b(&vernum, ls_flag_t::LOAD);
+
+ my_fclose(fff);
+
+ }
+
+ /* Process file */
+ if (!err)
+ {
+ /* Clear screen */
+ Term_clear();
+
+ /* Attempt to load */
+ err = rd_savefile();
+
+ /* Message (below) */
+ if (err) what = "Cannot parse savefile";
+ }
+
+ /* Paranoia */
+ if (!err)
+ {
+ /* Invalid turn */
+ if (!turn) err = -1;
+
+ /* Message (below) */
+ if (err) what = "Broken savefile";
+ }
+
+
+ /* Okay */
+ if (!err)
+ {
+ /* Player is dead */
+ if (death)
+ {
+ /* Player is no longer "dead" */
+ death = FALSE;
+
+ /* Cheat death (unless the character retired) */
+ if (arg_wizard && !total_winner)
+ {
+ /* A character was loaded */
+ character_loaded = TRUE;
+
+ /* Done */
+ return (TRUE);
+ }
+
+ /* Forget turns */
+ turn = old_turn = 0;
+
+ /* Done */
+ return (TRUE);
+ }
+
+ /* A character was loaded */
+ character_loaded = TRUE;
+
+ /* Still alive */
+ if (p_ptr->chp >= 0)
+ {
+ /* Reset cause of death */
+ game->died_from = "(alive and well)";
+ }
+
+ /* Success */
+ return (TRUE);
+ }
+
+
+ /* Message */
+ msg_format("Error (%s) reading savefile (version " FMTu32b ").",
+ what, vernum);
+ msg_print(NULL);
+
+ /* Oops */
+ return (FALSE);
+}
+
+
+
+/*
+ * Medium level player saver
+ */
+static bool_ save_player_aux(char *name)
+{
+ bool_ ok = FALSE;
+ int fd = -1;
+ int mode = 0644;
+
+ /* No file yet */
+ fff = NULL;
+
+ /* Create the savefile */
+ fd = fd_make(name, mode);
+
+ /* File is okay */
+ if (fd >= 0)
+ {
+ /* Close the "fd" */
+ fd_close(fd);
+
+ /* Open the savefile */
+ fff = my_fopen(name, "wb");
+
+ /* Successful open */
+ if (fff)
+ {
+ /* Write the savefile */
+ if (do_savefile_aux(ls_flag_t::SAVE)) ok = TRUE;
+
+ /* Attempt to close it */
+ if (my_fclose(fff)) ok = FALSE;
+ }
+
+ /* "broken" savefile */
+ if (!ok)
+ {
+ /* Remove "broken" files */
+ fd_kill(name);
+ }
+ }
+
+ /* Failure */
+ if (!ok) return (FALSE);
+
+ /* Success */
+ return (TRUE);
+}
+
+/*
+ * Attempt to save the player in a savefile
+ */
+bool_ save_player()
+{
+ int result = FALSE;
+ char safe[1024];
+
+ /* New savefile */
+ strcpy(safe, savefile);
+ strcat(safe, ".new");
+
+ /* Remove it */
+ fd_kill(safe);
+
+ /* Attempt to save the player */
+ if (save_player_aux(safe))
+ {
+ char temp[1024];
+
+ /* Old savefile */
+ strcpy(temp, savefile);
+ strcat(temp, ".old");
+
+ /* Remove it */
+ fd_kill(temp);
+
+ /* Preserve old savefile */
+ fd_move(savefile, temp);
+
+ /* Activate new savefile */
+ fd_move(safe, savefile);
+
+ /* Remove preserved savefile */
+ fd_kill(temp);
+
+ /* Hack -- Pretend the character was loaded */
+ character_loaded = TRUE;
+
+ /* Success */
+ result = TRUE;
+ }
+
+ save_savefile_names();
+
+ /* Return the result */
+ return (result);
+}
diff --git a/src/loadsave.h b/src/loadsave.h
new file mode 100644
index 00000000..52782dac
--- /dev/null
+++ b/src/loadsave.h
@@ -0,0 +1,15 @@
+#pragma once
+
+#include "h-basic.h"
+
+// C linkage required for these functions since main-* code uses them.
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void save_dungeon();
+bool_ save_player();
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/src/loadsave.hpp b/src/loadsave.hpp
new file mode 100644
index 00000000..d28d437e
--- /dev/null
+++ b/src/loadsave.hpp
@@ -0,0 +1,6 @@
+#pragma once
+
+#include "h-basic.h"
+
+bool_ load_dungeon(char *ext);
+bool_ load_player();
diff --git a/src/lua/.cvsignore b/src/lua/.cvsignore
deleted file mode 100644
index 0b086004..00000000
--- a/src/lua/.cvsignore
+++ /dev/null
@@ -1,2 +0,0 @@
-tolua
-host
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 <string.h>
-
-#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 <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-
-/* 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; i<n; i++)
- lua_register(L, l[i].name, l[i].func);
-}
-
-
-LUALIB_API void luaL_verror (lua_State *L, const char *fmt, ...) {
- char buff[500];
- va_list argp;
- va_start(argp, fmt);
- vsprintf(buff, fmt, argp);
- va_end(argp);
- lua_error(L, buff);
-}
-
-
-/*
-** {======================================================
-** Generic Buffer manipulation
-** =======================================================
-*/
-
-
-#define buffempty(B) ((B)->p == (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 <stddef.h>
-#include <stdio.h>
-
-#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 <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#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<n; i++) /* push arg[1...n] */
- lua_rawgeti(L, 2, i+1);
- status = lua_call(L, n, LUA_MULTRET);
- if (err != 0) { /* restore old error method */
- lua_pushvalue(L, err);
- lua_setglobal(L, LUA_ERRORMESSAGE);
- }
- if (status != 0) { /* error in call? */
- if (strchr(options, 'x'))
- lua_pushnil(L); /* return nil to signal the error */
- else
- lua_error(L, NULL); /* propagate error without additional messages */
- return 1;
- }
- if (strchr(options, 'p')) /* pack results? */
- lua_error(L, "deprecated option `p' in `call'");
- return lua_gettop(L) - oldtop; /* results are already on the stack */
-}
-
-
-static int luaB_tostring (lua_State *L) {
- char buff[64];
- switch (lua_type(L, 1)) {
- case LUA_TNUMBER:
- lua_pushstring(L, lua_tostring(L, 1));
- return 1;
- case LUA_TSTRING:
- lua_pushvalue(L, 1);
- return 1;
- case LUA_TTABLE:
- sprintf(buff, "table: %p", lua_topointer(L, 1));
- break;
- case LUA_TFUNCTION:
- sprintf(buff, "function: %p", lua_topointer(L, 1));
- break;
- case LUA_TUSERDATA:
- sprintf(buff, "userdata(%d): %p", lua_tag(L, 1), lua_touserdata(L, 1));
- break;
- case LUA_TNIL:
- lua_pushstring(L, "nil");
- return 1;
- default:
- luaL_argerror(L, 1, "value expected");
- }
- lua_pushstring(L, buff);
- return 1;
-}
-
-
-static int luaB_foreachi (lua_State *L) {
- int n, i;
- luaL_checktype(L, 1, LUA_TTABLE);
- luaL_checktype(L, 2, LUA_TFUNCTION);
- n = lua_getn(L, 1);
- for (i=1; i<=n; i++) {
- lua_pushvalue(L, 2); /* function */
- lua_pushnumber(L, i); /* 1st argument */
- lua_rawgeti(L, 1, i); /* 2nd argument */
- lua_rawcall(L, 2, 1);
- if (!lua_isnil(L, -1))
- return 1;
- lua_pop(L, 1); /* remove nil result */
- }
- return 0;
-}
-
-
-static int luaB_foreach (lua_State *L) {
- luaL_checktype(L, 1, LUA_TTABLE);
- luaL_checktype(L, 2, LUA_TFUNCTION);
- lua_pushnil(L); /* first index */
- for (;;) {
- if (lua_next(L, 1) == 0)
- return 0;
- lua_pushvalue(L, 2); /* function */
- lua_pushvalue(L, -3); /* key */
- lua_pushvalue(L, -3); /* value */
- lua_rawcall(L, 2, 1);
- if (!lua_isnil(L, -1))
- return 1;
- lua_pop(L, 2); /* remove value and result */
- }
-}
-
-
-static int luaB_assert (lua_State *L) {
- luaL_checkany(L, 1);
- if (lua_isnil(L, 1))
- luaL_verror(L, "assertion failed! %.90s", luaL_opt_string(L, 2, ""));
- return 0;
-}
-
-
-static int luaB_getn (lua_State *L) {
- luaL_checktype(L, 1, LUA_TTABLE);
- lua_pushnumber(L, lua_getn(L, 1));
- return 1;
-}
-
-
-static int luaB_tinsert (lua_State *L) {
- int v = lua_gettop(L); /* last argument: to be inserted */
- int n, pos;
- luaL_checktype(L, 1, LUA_TTABLE);
- n = lua_getn(L, 1);
- if (v == 2) /* called with only 2 arguments */
- pos = n+1;
- else
- pos = luaL_check_int(L, 2); /* 2nd argument is the position */
- lua_pushstring(L, "n");
- lua_pushnumber(L, n+1);
- lua_rawset(L, 1); /* t.n = n+1 */
- for (; n>=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<n; pos++) {
- lua_rawgeti(L, 1, pos+1);
- lua_rawseti(L, 1, pos); /* a[pos] = a[pos+1] */
- }
- lua_pushstring(L, "n");
- lua_pushnumber(L, n-1);
- lua_rawset(L, 1); /* t.n = n-1 */
- lua_pushnil(L);
- lua_rawseti(L, 1, n); /* t[n] = nil */
- return 1;
-}
-
-
-
-
-/*
-** {======================================================
-** Quicksort
-** (based on `Algorithms in MODULA-3', Robert Sedgewick;
-** Addison-Wesley, 1993.)
-*/
-
-
-static void set2 (lua_State *L, int i, int j) {
- lua_rawseti(L, 1, i);
- lua_rawseti(L, 1, j);
-}
-
-static int sort_comp (lua_State *L, int a, int b) {
- /* WARNING: the caller (auxsort) must ensure stack space */
- if (!lua_isnil(L, 2)) { /* function? */
- int res;
- lua_pushvalue(L, 2);
- lua_pushvalue(L, a-1); /* -1 to compensate function */
- lua_pushvalue(L, b-2); /* -2 to compensate function and `a' */
- lua_rawcall(L, 2, 1);
- res = !lua_isnil(L, -1);
- lua_pop(L, 1);
- return res;
- }
- else /* a < b? */
- return lua_lessthan(L, a, b);
-}
-
-static void auxsort (lua_State *L, int l, int u) {
- while (l < u) { /* for tail recursion */
- int i, j;
- /* sort elements a[l], a[(l+u)/2] and a[u] */
- lua_rawgeti(L, 1, l);
- lua_rawgeti(L, 1, u);
- if (sort_comp(L, -1, -2)) /* a[u] < a[l]? */
- set2(L, l, u); /* swap a[l] - a[u] */
- else
- lua_pop(L, 2);
- if (u-l == 1) break; /* only 2 elements */
- i = (l+u)/2;
- lua_rawgeti(L, 1, i);
- lua_rawgeti(L, 1, l);
- if (sort_comp(L, -2, -1)) /* a[i]<a[l]? */
- set2(L, i, l);
- else {
- lua_pop(L, 1); /* remove a[l] */
- lua_rawgeti(L, 1, u);
- if (sort_comp(L, -1, -2)) /* a[u]<a[i]? */
- set2(L, i, u);
- else
- lua_pop(L, 2);
- }
- if (u-l == 2) break; /* only 3 elements */
- lua_rawgeti(L, 1, i); /* Pivot */
- lua_pushvalue(L, -1);
- lua_rawgeti(L, 1, u-1);
- set2(L, i, u-1);
- /* a[l] <= P == a[u-1] <= a[u], only need to sort from l+1 to u-2 */
- i = l; j = u-1;
- for (;;) { /* invariant: a[l..i] <= P <= a[j..u] */
- /* repeat ++i until a[i] >= 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 (j<l) lua_error(L, "invalid order function for sorting");
- lua_pop(L, 1); /* remove a[j] */
- }
- if (j<i) {
- lua_pop(L, 3); /* pop pivot, a[i], a[j] */
- break;
- }
- set2(L, i, j);
- }
- lua_rawgeti(L, 1, u-1);
- lua_rawgeti(L, 1, i);
- set2(L, u-1, i); /* swap pivot (a[u-1]) with a[i] */
- /* a[l..i-1] <= a[i] == P <= a[i+1..u] */
- /* adjust so that smaller "half" is in [j..i] and larger one in [l..u] */
- if (i-l < u-i) {
- j=l; i=i-1; l=i+2;
- }
- else {
- j=i+1; i=u; u=j-2;
- }
- auxsort(L, j, i); /* call recursively the smaller one */
- } /* repeat the routine for the larger one */
-}
-
-static int luaB_sort (lua_State *L) {
- int n;
- luaL_checktype(L, 1, LUA_TTABLE);
- n = lua_getn(L, 1);
- if (!lua_isnull(L, 2)) /* is there a 2nd argument? */
- luaL_checktype(L, 2, LUA_TFUNCTION);
- lua_settop(L, 2); /* make sure there is two arguments */
- auxsort(L, 1, n);
- return 0;
-}
-
-/* }====================================================== */
-
-
-
-/*
-** {======================================================
-** Deprecated functions to manipulate global environment.
-** =======================================================
-*/
-
-
-#define num_deprecated 4
-
-static const struct luaL_reg deprecated_names [num_deprecated] = {
- {"foreachvar", luaB_foreach},
- {"nextvar", luaB_next},
- {"rawgetglobal", luaB_rawget},
- {"rawsetglobal", luaB_rawset}
-};
-
-
-#ifdef LUA_DEPRECATEDFUNCS
-
-/*
-** call corresponding function inserting `globals' as first argument
-*/
-static int deprecated_func (lua_State *L) {
- lua_insert(L, 1); /* upvalue is the function to be called */
- lua_getglobals(L);
- lua_insert(L, 2); /* table of globals is 1o argument */
- lua_rawcall(L, lua_gettop(L)-1, LUA_MULTRET);
- return lua_gettop(L); /* return all results */
-}
-
-
-static void deprecated_funcs (lua_State *L) {
- int i;
- for (i=0; i<num_deprecated; i++) {
- lua_pushcfunction(L, deprecated_names[i].func);
- lua_pushcclosure(L, deprecated_func, 1);
- lua_setglobal(L, deprecated_names[i].name);
- }
-}
-
-
-#else
-
-/*
-** gives an explicit error in any attempt to call a deprecated function
-*/
-static int deprecated_func (lua_State *L) {
- luaL_verror(L, "function `%.20s' is deprecated", lua_tostring(L, -1));
- return 0; /* to avoid warnings */
-}
-
-
-static void deprecated_funcs (lua_State *L) {
- int i;
- for (i=0; i<num_deprecated; i++) {
- lua_pushstring(L, deprecated_names[i].name);
- lua_pushcclosure(L, deprecated_func, 1);
- lua_setglobal(L, deprecated_names[i].name);
- }
-}
-
-#endif
-
-/* }====================================================== */
-
-static const struct luaL_reg base_funcs[] = {
- {LUA_ALERT, luaB__ALERT},
- {LUA_ERRORMESSAGE, luaB__ERRORMESSAGE},
- {"call", luaB_call},
- {"collectgarbage", luaB_collectgarbage},
- {"copytagmethods", luaB_copytagmethods},
- {"dofile", luaB_dofile},
- {"dostring", luaB_dostring},
- {"error", luaB_error},
- {"foreach", luaB_foreach},
- {"foreachi", luaB_foreachi},
- {"gcinfo", luaB_gcinfo},
- {"getglobal", luaB_getglobal},
- {"gettagmethod", luaB_gettagmethod},
- {"globals", luaB_globals},
- {"newtag", luaB_newtag},
- {"next", luaB_next},
- {"print", luaB_print},
- {"rawget", luaB_rawget},
- {"rawset", luaB_rawset},
- {"rawgettable", luaB_rawget}, /* for compatibility */
- {"rawsettable", luaB_rawset}, /* for compatibility */
- {"setglobal", luaB_setglobal},
- {"settag", luaB_settag},
- {"settagmethod", luaB_settagmethod},
- {"tag", luaB_tag},
- {"tonumber", luaB_tonumber},
- {"tostring", luaB_tostring},
- {"type", luaB_type},
- {"assert", luaB_assert},
- {"getn", luaB_getn},
- {"sort", luaB_sort},
- {"tinsert", luaB_tinsert},
- {"tremove", luaB_tremove}
-};
-
-
-
-LUALIB_API void lua_baselibopen (lua_State *L) {
- luaL_openl(L, base_funcs);
- lua_pushstring(L, LUA_VERSION);
- lua_setglobal(L, "_VERSION");
- deprecated_funcs(L);
-}
-
diff --git a/src/lua/lcode.c b/src/lua/lcode.c
deleted file mode 100644
index 89de4a55..00000000
--- a/src/lua/lcode.c
+++ /dev/null
@@ -1,701 +0,0 @@
-/*
-** $Id: lcode.c,v 1.4 2004/06/04 13:42:10 neil Exp $
-** Code generator for Lua
-** See Copyright Notice in lua.h
-*/
-
-
-#include "stdlib.h"
-
-#include "lua.h"
-
-#include "lcode.h"
-#include "ldo.h"
-#include "llex.h"
-#include "lmem.h"
-#include "lobject.h"
-#include "lopcodes.h"
-#include "lparser.h"
-
-
-void luaK_error (LexState *ls, const char *msg) {
- luaX_error(ls, msg, ls->t.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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#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 <stdlib.h>
-
-#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; e<TM_N; e++) {
- int t;
- for (t=0; t<=L->last_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; i<g->size; 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 <setjmp.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#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; n<nup; n++) /* copy upvalues as extra arguments */
- *(L->top++) = 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 <stdlib.h>
-
-#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; i<f->nlocvars && 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; i<f->nkstr; i++)
- strmark(f->kstr[i]);
- for (i=0; i<f->nkproto; i++)
- protomark(f->kproto[i]);
- for (i=0; i<f->nlocvars; i++) /* mark local-variable names */
- strmark(f->locvars[i].varname);
- }
-}
-
-
-static void markstack (lua_State *L, GCState *st) {
- StkId o;
- for (o=L->stack; o<L->top; o++)
- markobject(st, o);
-}
-
-
-static void marklock (lua_State *L, GCState *st) {
- int i;
- for (i=0; i<L->refSize; 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; e<TM_N; e++) {
- int t;
- for (t=0; t<=L->last_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; i<f->nupvalues; 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; i<h->size; 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; i<n; i++) {
- struct Ref *r = &L->refArray[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; i<L->strt.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; i<L->udt.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 <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include "lua.h"
-
-#include "lauxlib.h"
-#include "luadebug.h"
-#include "lualib.h"
-
-
-#ifndef OLD_ANSI
-#include <errno.h>
-#include <locale.h>
-#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; i<sizeof(iolibtag)/sizeof(iolibtag[0]); i++) {
- /* put `ctrl' as upvalue for these functions */
- lua_pushvalue(L, -1);
- lua_pushcclosure(L, iolibtag[i].func, 1);
- lua_setglobal(L, iolibtag[i].name);
- }
- /* create references to variable names */
- lua_pushstring(L, filenames[INFILE]);
- ctrl->ref[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 <ctype.h>
-#include <stdio.h>
-#include <string.h>
-
-#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", "", "..", "...", "==", ">=", "<=", "~=", "", "", "<eof>"};
-
-
-void luaX_init (lua_State *L) {
- int i;
- for (i=0; i<NUM_RESERVED; i++) {
- TString *ts = luaS_new(L, token2string[i]);
- ts->marked = (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 <limits.h>
-#include <stddef.h>
-
-
-
-/*
-** 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<<SIZE_U)-1)
-#define MAXARG_S (MAXARG_U>>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<<SIZE_A)-1)
-#else
-#define MAXARG_A MAX_INT
-#endif
-
-#if SIZE_B < BITS_INT-1
-#define MAXARG_B ((1<<SIZE_B)-1)
-#else
-#define MAXARG_B MAX_INT
-#endif
-
-
-/* maximum stack size in a function */
-#ifndef MAXSTACK
-#define MAXSTACK 250
-#endif
-
-#if MAXSTACK > MAXARG_B
-#undef MAXSTACK
-#define MAXSTACK MAXARG_B
-#endif
-
-
-/* maximum number of local variables */
-#ifndef MAXLOCALS
-#define MAXLOCALS 200 /* arbitrary limit (<MAXSTACK) */
-#endif
-#if MAXLOCALS>=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) */
-#endif
-#if MAXVARSLH>=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) */
-#endif
-#if MAXPARAMS>=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 <stdlib.h>
-
-#include "lua.h"
-
-#include "ldo.h"
-#include "lmem.h"
-#include "lobject.h"
-#include "lstate.h"
-
-
-
-
-#ifdef LUA_DEBUG
-/*
-** {======================================================================
-** Controlled version for realloc.
-** =======================================================================
-*/
-
-
-#include <assert.h>
-#include <limits.h>
-#include <string.h>
-
-#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<MARKSIZE;i++)
- assert(*(((char *)b)+HEADER+size+i) == MARK+i); /* corrupted block? */
- memdebug_numblocks--;
- memdebug_total -= size;
- return b;
-}
-
-
-static void freeblock (void *block) {
- if (block) {
- size_t size = *blocksize(block);
- block = checkblock(block);
- memset(block, -1, size+HEADER+MARKSIZE); /* erase block */
- (free)(block); /* free original block */
- }
-}
-
-
-static void *debug_realloc (void *block, size_t size) {
- if (size == 0) {
- freeblock(block);
- return NULL;
- }
- else if (memdebug_total+size > 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<MARKSIZE;i++)
- *(newblock+HEADER+size+i) = (char)(MARK+i);
- return newblock+HEADER;
- }
-}
-
-
-/* }====================================================================== */
-#endif
-
-
-
-/*
-** Real ISO (ANSI) systems do not need these tests;
-** but some systems (Sun OS) are not that ISO...
-*/
-#ifdef OLD_ANSI
-#define realloc(b,s) ((b) == NULL ? malloc(s) : (realloc)(b, s))
-#define free(b) if (b) (free)(b)
-#endif
-
-
-void *luaM_growaux (lua_State *L, void *block, size_t nelems,
- int inc, size_t size, const char *errormsg, size_t limit) {
- size_t newn = nelems+inc;
- if (nelems >= 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 <stddef.h>
-
-#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 <ctype.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#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 <assert.h>
-#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)<<n))<<p)
-
-/* creates a mask with `n' 0 bits at position `p' */
-#define MASK0(n,p) (~MASK1(n,p))
-
-/*
-** the following macros help to manipulate instructions
-*/
-
-#define CREATE_0(o) ((Instruction)(o))
-#define GET_OPCODE(i) ((OpCode)((i)&MASK1(SIZE_OP,0)))
-#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,0)) | (Instruction)(o)))
-
-#define CREATE_U(o,u) ((Instruction)(o) | ((Instruction)(u)<<POS_U))
-#define GETARG_U(i) ((int)((i)>>POS_U))
-#define SETARG_U(i,u) ((i) = (((i)&MASK0(SIZE_U,POS_U)) | \
- ((Instruction)(u)<<POS_U)))
-
-#define CREATE_S(o,s) CREATE_U((o),(s)+MAXARG_S)
-#define GETARG_S(i) (GETARG_U(i)-MAXARG_S)
-#define SETARG_S(i,s) SETARG_U((i),(s)+MAXARG_S)
-
-
-#define CREATE_AB(o,a,b) ((Instruction)(o) | ((Instruction)(a)<<POS_A) \
- | ((Instruction)(b)<<POS_B))
-#define GETARG_A(i) ((int)((i)>>POS_A))
-#define SETARG_A(i,a) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \
- ((Instruction)(a)<<POS_A)))
-#define GETARG_B(i) ((int)(((i)>>POS_B) & MASK1(SIZE_B,0)))
-#define SETARG_B(i,b) ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \
- ((Instruction)(b)<<POS_B)))
-
-
-/*
-** K = U argument used as index to `kstr'
-** J = S argument used as jump offset (relative to pc of next instruction)
-** L = unsigned argument used as index of local variable
-** N = U argument used as index to `knum'
-*/
-
-typedef enum {
-/*----------------------------------------------------------------------
-name args stack before stack after side effects
-------------------------------------------------------------------------*/
-OP_END,/* - - (return) no results */
-OP_RETURN,/* U v_n-v_x(at u) (return) returns v_x-v_n */
-
-OP_CALL,/* A B v_n-v_1 f(at a) r_b-r_1 f(v1,...,v_n) */
-OP_TAILCALL,/* A B v_n-v_1 f(at a) (return) f(v1,...,v_n) */
-
-OP_PUSHNIL,/* U - nil_1-nil_u */
-OP_POP,/* U a_u-a_1 - */
-
-OP_PUSHINT,/* S - (Number)s */
-OP_PUSHSTRING,/* K - KSTR[k] */
-OP_PUSHNUM,/* N - KNUM[n] */
-OP_PUSHNEGNUM,/* N - -KNUM[n] */
-
-OP_PUSHUPVALUE,/* U - Closure[u] */
-
-OP_GETLOCAL,/* L - LOC[l] */
-OP_GETGLOBAL,/* K - VAR[KSTR[k]] */
-
-OP_GETTABLE,/* - i t t[i] */
-OP_GETDOTTED,/* K t t[KSTR[k]] */
-OP_GETINDEXED,/* L t t[LOC[l]] */
-OP_PUSHSELF,/* K t t t[KSTR[k]] */
-
-OP_CREATETABLE,/* U - newarray(size = u) */
-
-OP_SETLOCAL,/* L x - LOC[l]=x */
-OP_SETGLOBAL,/* K x - VAR[KSTR[k]]=x */
-OP_SETTABLE,/* A B v a_a-a_1 i t (pops b values) t[i]=v */
-
-OP_SETLIST,/* A B v_b-v_1 t t t[i+a*FPF]=v_i */
-OP_SETMAP,/* U v_u k_u - v_1 k_1 t t t[k_i]=v_i */
-
-OP_ADD,/* - y x x+y */
-OP_ADDI,/* S x x+s */
-OP_SUB,/* - y x x-y */
-OP_MULT,/* - y x x*y */
-OP_DIV,/* - y x x/y */
-OP_POW,/* - y x x^y */
-OP_CONCAT,/* U v_u-v_1 v1..-..v_u */
-OP_MINUS,/* - x -x */
-OP_NOT,/* - x (x==nil)? 1 : nil */
-
-OP_JMPNE,/* J y x - (x~=y)? PC+=s */
-OP_JMPEQ,/* J y x - (x==y)? PC+=s */
-OP_JMPLT,/* J y x - (x<y)? PC+=s */
-OP_JMPLE,/* J y x - (x<y)? PC+=s */
-OP_JMPGT,/* J y x - (x>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 <stdio.h>
-#include <string.h>
-
-#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), "<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; i<fs->nupvalues; 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; i<func->nupvalues; 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), "<eof> 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, "<name> 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, "<expression> 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, "<statement> 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, "<name> 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 <stdio.h>
-
-#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 <string.h>
-
-#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; i<newsize; i++) newhash[i] = NULL;
- /* rehash */
- for (i=0; i<tb->size; 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 <ctype.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#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<l; i++)
- luaL_putchar(&b, tolower((unsigned char)(s[i])));
- luaL_pushresult(&b);
- return 1;
-}
-
-
-static int str_upper (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<l; i++)
- luaL_putchar(&b, toupper((unsigned char)(s[i])));
- luaL_pushresult(&b);
- return 1;
-}
-
-static int str_rep (lua_State *L) {
- size_t l;
- luaL_Buffer b;
- const char *s = luaL_check_lstr(L, 1, &l);
- int n = luaL_check_int(L, 2);
- luaL_buffinit(L, &b);
- while (n-- > 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, 0<pos && (size_t)pos<=l, 2, "out of range");
- lua_pushnumber(L, (unsigned char)s[pos-1]);
- return 1;
-}
-
-
-static int str_char (lua_State *L) {
- int n = lua_gettop(L); /* number of arguments */
- int i;
- luaL_Buffer b;
- luaL_buffinit(L, &b);
- for (i=1; i<=n; i++) {
- int c = luaL_check_int(L, i);
- luaL_arg_check(L, (unsigned char)c == c, i, "invalid value");
- luaL_putchar(&b, (unsigned char)c);
- }
- luaL_pushresult(&b);
- return 1;
-}
-
-
-
-/*
-** {======================================================
-** PATTERN MATCHING
-** =======================================================
-*/
-
-#ifndef MAX_CAPTURES
-#define MAX_CAPTURES 32 /* arbitrary limit */
-#endif
-
-
-struct Capture {
- const char *src_end; /* end ('\0') of source string */
- int level; /* total number of captures (finished or unfinished) */
- struct {
- const char *init;
- long len; /* -1 signals unfinished capture */
- } capture[MAX_CAPTURES];
-};
-
-
-#define ESC '%'
-#define SPECIALS "^$*+?.([%-"
-
-
-static int check_capture (lua_State *L, int l, struct Capture *cap) {
- l -= '1';
- if (!(0 <= l && l < cap->level && 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)<cap->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 (s<cap->src_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 = s<cap->src_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; i<cap->level; 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++<cap.src_end && !anchor);
- }
- lua_pushnil(L); /* not found */
- return 1;
-}
-
-
-static void add_s (lua_State *L, luaL_Buffer *b, struct Capture *cap) {
- if (lua_isstring(L, 3)) {
- const char *news = lua_tostring(L, 3);
- size_t l = lua_strlen(L, 3);
- size_t i;
- for (i=0; i<l; i++) {
- if (news[i] != ESC)
- luaL_putchar(b, news[i]);
- else {
- i++; /* skip ESC */
- if (!isdigit((unsigned char)news[i]))
- luaL_putchar(b, news[i]);
- else {
- int level = check_capture(L, news[i], cap);
- luaL_addlstring(b, cap->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 (; i<t->size; 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; i<size; i++) {
- if (ttype(&v[i].val) != LUA_TNIL)
- realuse++;
- }
- return realuse;
-}
-
-
-static void rehash (lua_State *L, Hash *t) {
- int oldsize = t->size;
- 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; i<oldsize; i++) {
- Node *old = nold+i;
- if (ttype(&old->val) != 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 <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-
-#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; i<p->nkstr; 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 <stdio.h>
-#include <string.h>
-
-#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; i<TM_N; i++)
- luaT_gettm(L, tag, i) = NULL;
- L->TMtable[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; e<TM_N; e++) {
- if (luaT_validevent(tagto, e))
- luaT_gettm(L, tagto, e) = luaT_gettm(L, tagfrom, e);
- }
- return tagto;
-}
-
-
-int luaT_tag (const TObject *o) {
- int t = ttype(o);
- switch (t) {
- case LUA_TUSERDATA: return tsvalue(o)->u.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 <stddef.h>
-
-
-/* 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 <stdio.h>
-#include <string.h>
-
-#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; i<n; i++)
- {
- tf->locvars[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; i<n; i++)
- tf->kstr[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; i<n; i++)
- tf->kproto[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<VERSION0) /* check last major change */
- luaO_verror(L,"`%.99s' too old:\n"
- " read version %d.%d; expected at least %d.%d",
- ZNAME(Z),V(version),V(VERSION));
- swap=(luaU_endianess()!=ezgetc(L,Z)); /* need to swap bytes? */
- TESTSIZE(sizeof(int));
- TESTSIZE(sizeof(size_t));
- TESTSIZE(sizeof(Instruction));
- TESTSIZE(SIZE_INSTRUCTION);
- TESTSIZE(SIZE_OP);
- TESTSIZE(SIZE_B);
- TESTSIZE(sizeof(Number));
- f=LoadNumber(L,Z,swap);
- if ((long)f!=(long)tf) /* disregard errors in last bit of fraction */
- luaO_verror(L,"unknown number format in `%.99s':\n"
- " read " NUMBER_FMT "; expected " NUMBER_FMT, ZNAME(Z),f,tf);
- return swap;
-}
-
-static Proto* LoadChunk (lua_State* L, ZIO* Z)
-{
- return LoadFunction(L,Z,LoadHeader(L,Z));
-}
-
-/*
-** load one chunk from a file or buffer
-** return main if ok and NULL at EOF
-*/
-Proto* luaU_undump (lua_State* L, ZIO* Z)
-{
- Proto* tf=NULL;
- int c=zgetc(Z);
- if (c==ID_CHUNK)
- tf=LoadChunk(L,Z);
- c=zgetc(Z);
- if (c!=EOZ)
- luaO_verror(L,"`%.99s' apparently contains more than one chunk",ZNAME(Z));
- return tf;
-}
-
-/*
-** find byte order
-*/
-int luaU_endianess (void)
-{
- int x=1;
- return *(char*)&x;
-}
diff --git a/src/lua/lundump.h b/src/lua/lundump.h
deleted file mode 100644
index ec394f46..00000000
--- a/src/lua/lundump.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
-** $Id: lundump.h,v 1.3 2001/11/26 23:00:26 darkgod Exp $
-** load pre-compiled Lua chunks
-** See Copyright Notice in lua.h
-*/
-
-#ifndef lundump_h
-#define lundump_h
-
-#include "lobject.h"
-#include "lzio.h"
-
-/* load one chunk */
-Proto* luaU_undump (lua_State* L, ZIO* Z);
-
-/* find byte order */
-int luaU_endianess (void);
-
-/* definitions for headers of binary files */
-#define VERSION 0x40 /* last format change was in 4.0 */
-#define VERSION0 0x40 /* last major change was in 4.0 */
-#define ID_CHUNK 27 /* binary files start with ESC... */
-#define SIGNATURE "Lua" /* ...followed by this signature */
-
-/* formats for error messages */
-#define SOURCE_FMT "<%d:%.99s>"
-#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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#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+i<L->top; 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<a) */
- top -= 2;
- if (!luaV_lessthan(L, top+1, top, top+2)) dojump(pc, i);
- break;
- }
- case OP_JMPGT: { /* a > b === (b<a) */
- top -= 2;
- if (luaV_lessthan(L, top+1, top, top+2)) dojump(pc, i);
- break;
- }
- case OP_JMPGE: { /* a >= b === !(a<b) */
- top -= 2;
- if (!luaV_lessthan(L, top, top+1, top+2)) dojump(pc, i);
- break;
- }
- case OP_JMPT: {
- if (ttype(--top) != LUA_TNIL) dojump(pc, i);
- break;
- }
- case OP_JMPF: {
- if (ttype(--top) == LUA_TNIL) dojump(pc, i);
- break;
- }
- case OP_JMPONT: {
- if (ttype(top-1) == LUA_TNIL) top--;
- else dojump(pc, i);
- break;
- }
- case OP_JMPONF: {
- if (ttype(top-1) != LUA_TNIL) top--;
- else dojump(pc, i);
- break;
- }
- case OP_JMP: {
- dojump(pc, i);
- break;
- }
- case OP_PUSHNILJMP: {
- ttype(top++) = LUA_TNIL;
- pc++;
- break;
- }
- case OP_FORPREP: {
- if (tonumber(top-1))
- lua_error(L, "`for' step must be a number");
- if (tonumber(top-2))
- lua_error(L, "`for' limit must be a number");
- if (tonumber(top-3))
- lua_error(L, "`for' initial value must be a number");
- if (nvalue(top-1) > 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 <stdio.h>
-#include <string.h>
-
-#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 <stdio.h>
-
-
-
-/* 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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-
-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<argc; ++i)
- {
- if (*argv[i] == '-')
- {
- switch (argv[i][1])
- {
- case 'v': version(); return 0;
- case 'h': help(); return 0;
- case 'p': setfield(L,t,"p",""); break;
- case 'P': setfield(L,t,"P",""); break;
- case 'o': setfield(L,t,"o",argv[++i]); break;
- case 'n': setfield(L,t,"n",argv[++i]); break;
- case 'H': setfield(L,t,"H",argv[++i]); break;
- default: error(argv[i]); break;
- }
- }
- else
- {
- setfield(L,t,"f",argv[i]);
- break;
- }
- }
- lua_pop(L,1);
- }
-
-#if 1
- {
- int tolua_tolualua_open(lua_State* L);
- tolua_tolualua_open(L);
- }
-#else
- {
- int i;
- char* p;
- char path[BUFSIZ];
- char* files[] = {
- "basic.lua",
- "feature.lua",
- "verbatim.lua",
- "code.lua",
- "typedef.lua",
- "container.lua",
- "package.lua",
- "module.lua",
- "define.lua",
- "enumerate.lua",
- "declaration.lua",
- "variable.lua",
- "array.lua",
- "function.lua",
- "operator.lua",
- "class.lua",
- "clean.lua",
- "doit.lua",
- NULL
- };
- strcpy(path,argv[0]);
- p = strrchr(path,'/');
- p = (p==NULL) ? path : p+1;
- for (i=0; files[i]; ++i)
- {
- sprintf(p,"%s",files[i]);
- lua_dofile(L,path);
- }
- }
-
-#endif
- return 0;
-}
diff --git a/src/lua/tolua.h b/src/lua/tolua.h
deleted file mode 100644
index ab86976c..00000000
--- a/src/lua/tolua.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/* tolua - Support code for Lua bindings.
-** Written by Waldemar Celes (celes@tecgraf.puc-rio.br)
-** TeCGraf/PUC-Rio
-** http://www.tecgraf.puc-rio.br/~celes/tolua
-** Jul 1998
-** $Id: tolua.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_h
-#define tolua_h
-
-#define TOLUA_VERSION "tolua 4.0a - angband"
-
-
-#include <stdlib.h> /* 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 <stdio.h>
-
-/* 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 <string.h>
-#include <stdlib.h>
-
-long tolua_getnumber (lua_State* L, int narg, long def)
-{
- return lua_gettop(L)<abs(narg) ? def : lua_tonumber(L,narg);
-}
-
-const char* tolua_getstring (lua_State* L, int narg, const char* def)
-{
- return lua_gettop(L)<abs(narg) ? def : lua_tostring(L,narg);
-}
-
-void* tolua_getuserdata (lua_State* L, int narg, void* def)
-{
- return lua_gettop(L)<abs(narg) ? def : lua_touserdata(L,narg);
-}
-
-void* tolua_getusertype (lua_State* L, int narg, void* def)
-{
- return lua_gettop(L)<abs(narg) ? def : lua_touserdata(L,narg);
-}
-
-int tolua_getvalue (lua_State* L, int narg, int def)
-{
- return lua_gettop(L)<abs(narg) ? def : narg;
-}
-
-int tolua_getbool (lua_State* L, int narg, int def)
-{
- return lua_gettop(L)<abs(narg) ?
- def :
- lua_isnil(L,narg) ? 0 : lua_tonumber(L,narg)!=0;
-}
-
-long tolua_getfieldnumber (lua_State* L, int lo, int index, long def)
-{
- long v;
- lua_pushnumber(L,index);
- lua_gettable(L,lo);
- v = lua_isnil(L,-1) ? def : lua_tonumber(L,-1);
- lua_pop(L,1);
- return v;
-}
-
-const char* tolua_getfieldstring
-(lua_State* L, int lo, int index, const char* def)
-{
- const char* v;
- lua_pushnumber(L,index);
- lua_gettable(L,lo);
- v = lua_isnil(L,-1) ? def : lua_tostring(L,-1);
- lua_pop(L,1);
- return v;
-}
-
-void* tolua_getfielduserdata (lua_State* L, int lo, int index, void* def)
-{
- void* v;
- lua_pushnumber(L,index);
- lua_gettable(L,lo);
- v = lua_isnil(L,-1) ? def : lua_touserdata(L,-1);
- lua_pop(L,1);
- return v;
-}
-
-void* tolua_getfieldusertype (lua_State* L, int lo, int index, void* def)
-{
- void* v;
- lua_pushnumber(L,index);
- lua_gettable(L,lo);
- v = lua_isnil(L,-1) ? def : lua_touserdata(L,-1);
- lua_pop(L,1);
- return v;
-}
-
-int tolua_getfieldvalue (lua_State* L, int lo, int index, int def)
-{
- int v;
- lua_pushnumber(L,index);
- lua_gettable(L,lo);
- v = lua_isnil(L,-1) ? def : lo;
- lua_pop(L,1);
- return v;
-}
-
-int tolua_getfieldbool (lua_State* L, int lo, int index, int def)
-{
- int v;
- lua_pushnumber(L,index);
- lua_gettable(L,lo);
- v = lua_isnil(L,-1) ? 0 : lua_tonumber(L,-1)!=0;
- lua_pop(L,1);
- return v;
-}
-
-void tolua_pushnumber (lua_State* L, long value)
-{
- lua_pushnumber(L,value);
-}
-
-void tolua_pushstring (lua_State* L, const char* value)
-{
- if (value == NULL)
- lua_pushnil(L);
- else
- lua_pushstring(L,value);
-}
-
-void tolua_pushuserdata (lua_State* L, void* value)
-{
- if (value == NULL)
- lua_pushnil(L);
- else
- lua_pushuserdata(L,value);
-}
-
-void tolua_pushusertype (lua_State* L, void* value, int tag)
-{
- if (value == NULL)
- lua_pushnil(L);
- else
- lua_pushusertag(L,value,tag);
-}
-
-void tolua_pushvalue (lua_State* L, int lo)
-{
- lua_pushvalue(L,lo);
-}
-
-void tolua_pushbool (lua_State* L, int value)
-{
- if (value)
- lua_pushnumber(L,(long)value);
- else
- lua_pushnil(L);
-}
-
-void tolua_pushfieldnumber (lua_State* L, int lo, int index, long v)
-{
- lua_pushnumber(L,index);
- tolua_pushnumber(L,v);
- lua_settable(L,lo);
-}
-
-void tolua_pushfieldstring (lua_State* L, int lo, int index, char* v)
-{
- lua_pushnumber(L,index);
- tolua_pushstring(L,v);
- lua_settable(L,lo);
-}
-
-void tolua_pushfielduserdata (lua_State* L, int lo, int index, void* v)
-{
- lua_pushnumber(L,index);
- tolua_pushuserdata(L,v);
- lua_settable(L,lo);
-}
-
-void tolua_pushfieldusertype (lua_State* L, int lo, int index, void* v, int tag)
-{
- lua_pushnumber(L,index);
- tolua_pushusertype(L,v,tag);
- lua_settable(L,lo);
-}
-
-void tolua_pushfieldvalue (lua_State* L, int lo, int index, int v)
-{
- lua_pushnumber(L,index);
- lua_pushvalue(L,v);
- lua_settable(L,lo);
-}
-
-void tolua_pushfieldbool (lua_State* L, int lo, int index, int v)
-{
- lua_pushnumber(L,index);
- tolua_pushbool(L,v);
- lua_settable(L,lo);
-}
-
diff --git a/src/lua/tolua_lb.c b/src/lua/tolua_lb.c
deleted file mode 100644
index 5fd4c337..00000000
--- a/src/lua/tolua_lb.c
+++ /dev/null
@@ -1,160 +0,0 @@
-/* tolua
-** Support code for Lua bindings.
-** Written by Waldemar Celes
-** TeCGraf/PUC-Rio
-** Jul 1998
-** $Id: tolua_lb.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_rg.h"
-#include "tolua_tm.h"
-#include "tolua_tt.h"
-
-
-int tolua_open (lua_State* L)
-{
- int tolua_tolua_open (lua_State* L);
- /* check if alread opened */
- toluaI_getregistry(L,"TOLUA");
- if (lua_isnil(L,-1))
- {
- lua_pushnumber(L,1);
- toluaI_setregistry(L,"TOLUA");
- toluaI_tt_init(L);
- toluaI_tm_init(L);
- lua_getglobal(L,"foreach");
- toluaI_setregistry(L,"tolua_orig_foreach");
- tolua_tolua_open(L); /* opens tolua own binding */
- }
- lua_pop(L,1);
- return 1;
-}
-
-void tolua_using (lua_State* L, int module)
-{
- toluaI_tm_using(L,module);
-}
-
-void tolua_class (lua_State* L, int derived, int base)
-{
- int tag = lua_newtag(L); /* new tag of instances of that class */
- toluaI_tm_setclass(L,derived);
- toluaI_tm_linstance(L,tag,derived);
- lua_pushvalue(L,derived);
- lua_pushstring(L,".base");
- lua_pushvalue(L,base);
- lua_rawset(L,-3);
- lua_pushstring(L,".itag");
- lua_pushnumber(L,tag);
- lua_rawset(L,-3);
- lua_pop(L,1);
-}
-
-void tolua_instance (lua_State* L, int instance, int classobj)
-{
- int tag;
- lua_pushvalue(L,classobj);
- lua_pushstring(L,".itag");
- lua_gettable(L,-2);
- tag = (int) lua_tonumber(L,-1);
- lua_pop(L,2); /* number and table */
- if (tag==0)
- tolua_error(L,"unregistered 'classobj' in function 'tolua_instance'.");
- lua_pushvalue(L,instance);
- lua_settag(L,tag);
- lua_pop(L,1);
-}
-
-static int filter (lua_State* L)
-{
- int n = 1; /* name */
- int v = 2; /* value */
- int f = lua_gettop(L); /* function */
- /* do not pass string fields starting with a dot */
- if (!lua_isstring(L,n) || *lua_tostring(L,n)!='.')
- {
- lua_pushvalue(L,f);
- lua_pushvalue(L,n);
- lua_pushvalue(L,v);
- lua_call(L,2,1);
- }
- else
- lua_pushnil(L);
- return 1;
-}
-
-void tolua_foreach (lua_State* L, int lo, int f)
-{
- if (toluaI_tt_isusertype(L,lo))
- {
- toluaI_tm_pushmate(L,lo);
- if (lua_isnil(L,-1))
- return; /* no field in mate table */
- else
- lo = lua_gettop(L);
- }
- toluaI_getregistry(L,"tolua_orig_foreach");
- lua_pushvalue(L,lo);
- lua_pushvalue(L,f);
- lua_pushcclosure(L,filter,1);
- lua_call(L,2,1);
-}
-
-const char* tolua_type (lua_State* L, int lo)
-{
- return toluaI_tt_getobjtype(L,lo);
-}
-
-int tolua_tag (lua_State* L, char* type)
-{
- return toluaI_tt_gettag(L,type);
-}
-
-int tolua_base (lua_State* L, int lo)
-{
- if (toluaI_tt_isusertype(L,lo))
- {
- toluaI_tm_pushclass(L,lo);
- return lua_gettop(L);
- }
- else if (lua_istable(L,lo))
- {
- lua_pushvalue(L,lo);
- lua_pushstring(L,".base");
- lua_rawget(L,-2);
- return -1;
- }
- else
- return 0;
-}
-
-int tolua_cast (lua_State* L, int lo, char* type)
-{
- if (lua_isuserdata(L,lo))
- {
- tolua_pushusertype(L,lua_touserdata(L,lo),toluaI_tt_gettag(L,type));
- return -1;
- }
- else
- return 0;
-}
-
-void tolua_takeownership (lua_State* L, int lo)
-{
- if (toluaI_tt_isusertype(L,lo))
- {
- /* force garbage collection to avoid C to reuse a to-be-collected address */
- lua_setgcthreshold(L,0);
- tolua_doclone(L,lua_touserdata(L,lo),lua_tag(L,lo));
- }
- else
- tolua_error(L,"cannot take ownership of specified obejct.");
-}
-
diff --git a/src/lua/tolua_rg.c b/src/lua/tolua_rg.c
deleted file mode 100644
index 4337e9f9..00000000
--- a/src/lua/tolua_rg.c
+++ /dev/null
@@ -1,243 +0,0 @@
-/* tolua: register functions
-** Support code for Lua bindings.
-** Written by Waldemar Celes
-** TeCGraf/PUC-Rio
-** Jul 1998
-** $Id: tolua_rg.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 <stdio.h>
-
-#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 <string.h>
-
-
-
-/* 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 <stdio.h>
-#include <string.h>
-#include <assert.h>
-
-/* 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(lo))
- return "[no object]";
- else
- return gettype(L,lua_tag(L,lo));
-}
-
-int toluaI_tt_gettag (lua_State* L, char* type)
-{
- int tag;
- toluaI_getregistry(L,"tolua_tbl_itag");
- lua_pushstring(L,type);
- lua_gettable(L,-2);
- tag = (int)lua_tonumber(L,-1);
- lua_pop(L,2);
- return tag;
-}
-
-static int basetag (lua_State* L, int hierarchy, int tag)
-{
- int btag;
- lua_pushnumber(L,tag);
- lua_gettable(L,hierarchy);
- btag = (int)lua_tonumber(L,-1);
- lua_pop(L,1);
- return btag;
-}
-
-static int istype (lua_State* L, int lo, int tag)
-{
- int otag = lua_tag(L,lo);
- if (tag==otag) /* check simplest case */
- return 1;
- else if (lua_isnil(L,lo) &&
- tag!=LUA_TNUMBER &&
- tag!=LUA_TTABLE &&
- tag!=LUA_TFUNCTION
- )
- return 1;
- else if ((tag==LUA_TSTRING && lua_isstring(L,lo)) || /* check convertions */
- (tag==LUA_TNUMBER && lua_isnumber(L,lo))
- )
- return 1;
- else if (tag==LUA_TUSERDATA && lua_isuserdata(L,lo)) /* pointer to void* */
- return 1;
- else if (tag==toluaI_tt_gettag(L,"bool") && otag==LUA_TNUMBER)
- return 1;
- else
- {
- /* if requested type is const, the non-const is an alternative type */
- int tag2;
- int tbl_hierarchy;
- toluaI_getregistry(L,"tolua_tbl_const");
- lua_pushnumber(L,tag);
- lua_gettable(L,-2);
- tag2 = (int)lua_tonumber(L,-1);
- lua_pop(L,2);
- if (tag2 && tag2==otag)
- return 1;
- /* check for base classes */
- toluaI_getregistry(L,"tolua_tbl_hierarchy");
- tbl_hierarchy = lua_gettop(L);
- otag = basetag(L,tbl_hierarchy,otag);
- while (otag)
- {
- if (tag==otag || (tag2 && tag2==otag))
- break;
- otag = basetag(L,tbl_hierarchy,otag);
- }
- lua_pop(L,1);
- return otag!=0;
- }
-}
-
-void toluaI_tt_init (lua_State* L)
-{
- lua_newtable(L); toluaI_setregistry(L,"tolua_tbl_itype");
- lua_newtable(L); toluaI_setregistry(L,"tolua_tbl_itag");
- lua_newtable(L); toluaI_setregistry(L,"tolua_tbl_const");
- lua_newtable(L); toluaI_setregistry(L,"tolua_tbl_hierarchy");
-
- /* set and register basic Lua type tag */
-#if 0
- lua_pushnumber(L,LUA_TNIL); toluaI_setregistry(L,"tolua_tag_nil");
- lua_pushnumber(L,LUA_TNUMBER); toluaI_setregistry(L,"tolua_tag_number");
- lua_pushnumber(L,LUA_TSTRING); toluaI_setregistry(L,"tolua_tag_string");
- lua_pushnumber(L,LUA_TUSERDATA); toluaI_setregistry(L,"tolua_tag_userdata");
- lua_pushnumber(L,LUA_TTABLE); toluaI_setregistry(L,"tolua_tag_table");
- lua_pushnumber(L,LUA_TFUNCTION); toluaI_setregistry(L,"tolua_tag_function");
-
- toluaI_tt_register(L,toluaI_tt_gettag(L,"tolua_tag_nil"),"nil");
- toluaI_tt_register(L,toluaI_tt_gettag(L,"tolua_tag_number"),"number");
- toluaI_tt_register(L,toluaI_tt_gettag(L,"tolua_tag_string"),"string");
- toluaI_tt_register(L,toluaI_tt_gettag(L,"tolua_tag_userdata"),"userdata");
- toluaI_tt_register(L,toluaI_tt_gettag(L,"tolua_tag_table"),"table");
- toluaI_tt_register(L,toluaI_tt_gettag(L,"tolua_tag_function"),"function");
-#else
- toluaI_tt_register(L,LUA_TNIL,"nil");
- toluaI_tt_register(L,LUA_TNUMBER,"number");
- toluaI_tt_register(L,LUA_TSTRING,"string");
- toluaI_tt_register(L,LUA_TUSERDATA,"userdata");
- toluaI_tt_register(L,LUA_TTABLE,"table");
- toluaI_tt_register(L,LUA_TFUNCTION,"function");
- toluaI_tt_register(L,lua_newtag(L),"bool");
-#endif
-}
-
-
-void toluaI_tt_register (lua_State* L, int tag, char* type)
-{
- toluaI_getregistry(L,"tolua_tbl_itype");
- lua_pushnumber(L,tag);
- lua_pushstring(L,type);
- lua_settable(L,-3);
-
- toluaI_getregistry(L,"tolua_tbl_itag");
- lua_pushstring(L,type);
- lua_pushnumber(L,tag);
- lua_settable(L,-3);
-
- lua_pop(L,2);
-}
-
-
-void toluaI_tt_class (lua_State* L, int lo, char* derived, char* base)
-{
- char* cderived = toluaI_tt_concat("const ",derived);
- int tag = toluaI_tt_gettag(L,derived);
- int ctag = toluaI_tt_gettag(L,cderived);
- toluaI_tm_instance(L,tag,lo);
- toluaI_tm_instance(L,ctag,lo);
- if (*base != 0)
- {
- char* cbase = toluaI_tt_concat("const ",base);
- int btag = toluaI_tt_gettag(L,base);
- int cbtag = toluaI_tt_gettag(L,cbase);
- toluaI_tt_sethierarchy(L,tag,btag);
- toluaI_tt_sethierarchy(L,ctag,cbtag);
- }
-}
-
-void toluaI_tt_sethierarchy (lua_State* L, int tag, int btag)
-{
- toluaI_getregistry(L,"tolua_tbl_hierarchy");
- lua_pushnumber(L,tag);
- lua_pushnumber(L,btag);
- lua_settable(L,-3);
- lua_pop(L,1);
-}
-
-char* toluaI_tt_concat (const char* s1, const char* s2)
-{
- static char s[BUFSIZ];
- assert(strlen(s1)+strlen(s2)<BUFSIZ);
- return strcat(strcpy(s,s1),s2);
-}
-
-void tolua_usertype (lua_State* L, char* type)
-{
- /* check if type is already registered */
- toluaI_getregistry(L,"tolua_tbl_itag");
- lua_pushstring(L,type);
- lua_gettable(L,-2);
- if (lua_isnil(L,-1))
- {
- char *ctype = toluaI_tt_concat("const ",type);
- int tag = lua_newtag(L);
- int ctag = lua_newtag(L);
- toluaI_tt_register(L,tag,type);
- toluaI_tt_register(L,ctag,ctype);
- /* set const table */
- toluaI_getregistry(L,"tolua_tbl_const");
- lua_pushnumber(L,ctag);
- lua_pushnumber(L,tag);
- lua_settable(L,-3);
- lua_pop(L,1);
- }
- lua_pop(L,2);
-}
-
-int toluaI_tt_isusertype (lua_State* L, int lo)
-{
- if (lua_isuserdata(L,lo) &&
- toluaI_tt_gettag(L,"tolua_tag_userdata")!=lua_tag(L,lo)
- )
- {
- int status;
- toluaI_getregistry(L,"tolua_tbl_itype");
- lua_pushnumber(L,lua_tag(L,lo));
- lua_gettable(L,-2);
- status = !lua_isnil(L,-1);
- lua_pop(L,2);
- return status;
- }
- return 0;
-}
-
-#if 0
-void tolua_settag (lua_State* L, char* type, int* tag)
-{
- toluaI_getregistry(L,"tolua_tbl_itag");
- lua_pushstring(L,type);
- lua_gettable(L,-2);
- *tag = (int) lua_tonumber(L,-1);
- lua_pop(L,2);
-}
-#endif
-
-int tolua_istype (lua_State* L, int narg, int tag, int def)
-{
- if (lua_gettop(L)<abs(narg))
- {
- if (def==0)
- {
- toluaI_eh_set(L,narg,toluaI_tt_getobjtype(L,narg),gettype(L,tag));
- return 0;
- }
- }
- else
- {
- if (!istype(L,narg,tag))
- {
- toluaI_eh_set(L,narg,toluaI_tt_getobjtype(L,narg),gettype(L,tag));
- return 0;
- }
- }
- return 1;
-}
-
-int tolua_arrayistype (lua_State* L, int narg, int tag, int dim, int def)
-{
- int i;
- for (i=0; i<dim; ++i)
- {
- int tf;
- lua_pushnumber(L,i+1);
- lua_gettable(L,narg);
- tf = lua_gettop(L);
- if (!istype(L,tf,tag) && (!def || !lua_isnil(L,tf)))
- {
- static char t1[BUFSIZ], t2[BUFSIZ];
- sprintf(t1,"array of %s",toluaI_tt_getobjtype(L,tf));
- sprintf(t2,"array of %s (dimension=%d)",gettype(L,tag),dim);
- toluaI_eh_set(L,narg,t1,t2);
- return 0;
- }
- lua_pop(L,1);
- }
- return 1;
-}
-
-int tolua_isnoobj (lua_State* L, int narg)
-{
- 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 @@
-$[
-$<basic.lua>
-$<feature.lua>
-$<verbatim.lua>
-$<code.lua>
-$<typedef.lua>
-$<container.lua>
-$<package.lua>
-$<module.lua>
-$<define.lua>
-$<enumerate.lua>
-$<declaration.lua>
-$<variable.lua>
-$<array.lua>
-$<function.lua>
-$<operator.lua>
-$<class.lua>
-$<clean.lua>
-$<doit.lua>
-$]
-
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
deleted file mode 100644
index 67b75ee6..00000000
--- a/src/lua_bind.c
+++ /dev/null
@@ -1,691 +0,0 @@
-/* File: lua_bind.c */
-
-/* Purpose: various lua bindings */
-
-/*
- * Copyright (c) 2001 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 "lua.h"
-#include "tolua.h"
-extern lua_State *L;
-
-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
- */
-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);
-}
-
-/*
- * 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)
-{
- 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];
-
- object_desc(buf, o_ptr, pref, mode);
- return (buf);
-}
-
-/*
- * Monsters
- */
-
-void find_position(int y, int x, int *yy, int *xx)
-{
- int attempts = 500;
-
- do
- {
- scatter(yy, xx, y, x, 6);
- }
- 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);
-}
-
-/*
- * 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)
- strncpy(quest[q_idx].desc[d], desc, 79);
-}
-
-/*
- * Misc
- */
-bool_ get_com_lua(cptr prompt, int *com)
-{
- char c;
-
- if (!get_com(prompt, &c)) return (FALSE);
- *com = c;
- 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);
-}
-
-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]);
-}
-
-/* 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 tmp;
-
- tmp = lvl - ((school_spells[s].skill_level - 1) * (SKILL_STEP / 10));
-
- if (tmp >= (SKILL_STEP / 10)) /* We require at least one spell level */
- tmp += bonus;
-
- tmp = (tmp * (max * (SKILL_STEP / 10)) / (SKILL_MAX / 10));
-
- if (tmp < 0) /* Shift all negative values, so they map to appropriate integer */
- tmp -= SKILL_STEP / 10 - 1;
-
- /* Now, we can safely divide */
- lvl = tmp / (SKILL_STEP / 10);
-
- if (lvl < min)
- lvl = min;
-
- return lvl;
-}
-
-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);
-}
-
-/* Cave */
-cave_type *lua_get_cave(int y, int x)
-{
- return (&(cave[y][x]));
-}
-
-void set_target(int y, int x)
-{
- target_who = -1;
- target_col = x;
- target_row = y;
-}
-
-void get_target(int dir, int *y, int *x)
-{
- int ty, tx;
-
- /* Use the given direction */
- tx = p_ptr->px + (ddx[dir] * 100);
- ty = p_ptr->py + (ddy[dir] * 100);
-
- /* Hack -- Use an actual "target" */
- if ((dir == 5) && target_okay())
- {
- tx = target_col;
- ty = target_row;
- }
- *y = ty;
- *x = tx;
-}
-
-/* Level gen */
-void get_map_size(char *name, int *ysize, int *xsize)
-{
- *xsize = 0;
- *ysize = 0;
- init_flags = INIT_GET_SIZE;
- process_dungeon_file(name, ysize, xsize, cur_hgt, cur_wid, TRUE, TRUE);
-}
-
-void load_map(char *name, int *y, int *x)
-{
- /* Set the correct monster hook */
- set_mon_num_hook();
-
- /* Prepare allocation table */
- get_mon_num_prep();
-
- init_flags = INIT_CREATE_DUNGEON;
- 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
- */
-
-/*
- * Hook for bounty monster selection.
- */
-static bool_ lua_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)) return (FALSE);
-
- /* Accept only monsters that can be generated */
- if (r_ptr->flags9 & RF9_SPECIAL_GENE) return (FALSE);
- if (r_ptr->flags9 & RF9_NEVER_GENE) return (FALSE);
-
- /* Reject pets */
- if (r_ptr->flags7 & RF7_PET) return (FALSE);
-
- /* Reject friendly creatures */
- if (r_ptr->flags7 & RF7_FRIENDLY) return (FALSE);
-
- /* Accept only monsters that are not breeders */
- if (r_ptr->flags4 & RF4_MULTIPLY) return (FALSE);
-
- /* Forbid joke monsters */
- if (r_ptr->flags8 & RF8_JOKEANGBAND) return (FALSE);
-
- /* Accept only monsters that are not good */
- if (r_ptr->flags3 & RF3_GOOD) return (FALSE);
-
- /* The rest are acceptable */
- return (TRUE);
-}
-
-int lua_get_new_bounty_monster(int lev)
-{
- int r_idx;
-
- /*
- * Set up the hooks -- no bounties on uniques or monsters
- * with no corpses
- */
- get_mon_num_hook = lua_mon_hook_bounty;
- get_mon_num_prep();
-
- /* Set up the quest monster. */
- r_idx = get_mon_num(lev);
-
- /* Undo the filters */
- get_mon_num_hook = NULL;
- get_mon_num_prep();
-
- return r_idx;
-}
-
-/*
- * Some misc functions
- */
-char *lua_input_box(cptr title, int max)
-{
- static char buf[80];
- int wid, hgt;
-
- strcpy(buf, "");
- Term_get_size(&wid, &hgt);
- if (!input_box(title, hgt / 2, wid / 2, buf, (max > 79) ? 79 : max))
- return "";
- return buf;
-}
-
-char lua_msg_box(cptr title)
-{
- int wid, hgt;
-
- Term_get_size(&wid, &hgt);
- 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);
-}
-
-/*
- * 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);
-}
-
-/*
- * 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);
- 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;
-}
diff --git a/src/lua_bind.cc b/src/lua_bind.cc
new file mode 100644
index 00000000..3ca43716
--- /dev/null
+++ b/src/lua_bind.cc
@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 2001 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 "lua_bind.hpp"
+
+#include "cmd7.hpp"
+#include "corrupt.hpp"
+#include "game.hpp"
+#include "init1.hpp"
+#include "monster2.hpp"
+#include "player_type.hpp"
+#include "range.hpp"
+#include "skills.hpp"
+#include "skill_type.hpp"
+#include "spell_type.hpp"
+#include "spells2.hpp"
+#include "spells5.hpp"
+#include "tables.hpp"
+#include "timer_type.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+
+#include <cassert>
+#include <functional>
+
+/*
+ * Misc
+ */
+
+/* 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)
+{
+ s32b tmp;
+
+ 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;
+
+ tmp = (tmp * (max * (SKILL_STEP / 10)) / (SKILL_MAX / 10));
+
+ if (tmp < 0) /* Shift all negative values, so they map to appropriate integer */
+ tmp -= SKILL_STEP / 10 - 1;
+
+ /* Now, we can safely divide */
+ lvl = tmp / (SKILL_STEP / 10);
+
+ if (lvl < min)
+ lvl = min;
+
+ return lvl;
+}
+
+/* static */ s32b get_level_device(spell_type *spell, s32b max, s32b min, s32b device_skill, std::function<s32b(spell_type *, s32b, s32b, s32b, s32b)> lua_get_level_ = lua_get_level)
+{
+ /* No max specified ? assume 50 */
+ if (max <= 0) {
+ max = 50;
+ }
+ /* No min specified ? */
+ if (min <= 0) {
+ min = 1;
+ }
+
+ int lvl = device_skill + (get_level_use_stick * SKILL_STEP);
+
+ /* Sticks are limited */
+ if (lvl - ((spell_type_skill_level(spell) + 1) * SKILL_STEP) >= get_level_max_stick * 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
+ -- The loss of information should be negligible since 1 skill = 1000 internally
+ */
+ lvl = lvl / 10;
+ lvl = lua_get_level_(spell, lvl, max, min, 0);
+
+ return lvl;
+}
+
+static s32b get_level_device_1(spell_type *spell, s32b max, s32b min)
+{
+ auto const &s_info = game->s_info;
+
+ // Must be in "device" mode.
+ assert(get_level_use_stick > -1);
+ // Delegate
+ auto device_skill = s_info[SKILL_DEVICE].value;
+ return get_level_device(spell, max, min, device_skill);
+}
+
+static s32b get_level_school_1(spell_type *spell, s32b max, s32b min)
+{
+ // Delegate
+ s32b level;
+ bool_ na;
+ get_level_school(spell, max, min, &level, &na);
+ // Note: It is tempting to add an assertion here for "na == FALSE" here,
+ // but there are cases where we haven't actually checked if the spell is
+ // really castable before calling this function (indirectly). Thus we
+ // MUST NOT assert anything about "na" as the code currently stands.
+ return level;
+}
+
+int get_mana(s32b s)
+{
+ // Does not make sense in "device" mode.
+ assert(get_level_use_stick == -1);
+ // Extract the spell's mana range.
+ spell_type *spell = spell_at(s);
+ range_type mana_range;
+ spell_type_mana_range(spell, &mana_range);
+ // Scale
+ return get_level_school_1(spell, mana_range.max, mana_range.min);
+}
+
+/** 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_school_1(s_ptr, 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 (!(p_ptr->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 spell_chance_device(spell_type *spell_ptr)
+{
+ // Device parameters initialized?
+ assert(get_level_use_stick > -1);
+
+ // Calculate the chance.
+ int level = get_level_device_1(spell_ptr, 50, 1);
+ s32b chance = spell_type_failure_rate(spell_ptr);
+
+ /* Reduce failure rate by "effective" level adjustment */
+ chance -= (level - 1);
+
+ /* Extract the minimum failure rate */
+ int minfail = 15 - get_skill_scale(SKILL_DEVICE, 25);
+
+ /* Return the chance */
+ return clamp_failure_chance(chance, minfail);
+}
+
+s32b spell_chance_book(s32b s)
+{
+ // Must NOT be a device!
+ assert(get_level_use_stick < 0);
+ // Delegate
+ return spell_chance_school(s);
+}
+
+static s32b get_level_full(s32b s, s32b max, s32b min)
+{
+ auto spell = spell_at(s);
+ /** Ahah shall we use Magic device instead ? */
+ if (get_level_use_stick > -1) {
+ return get_level_device_1(spell, max, min);
+ } else {
+ return get_level_school_1(spell, max, min);
+ }
+}
+
+s32b get_level(s32b s, s32b max)
+{
+ return get_level_full(s, max, 0);
+}
+
+s32b get_level_s(int sp, int max)
+{
+ return get_level_full(sp, max, 1);
+}
+
+/* Level gen */
+void get_map_size(const char *name, int *ysize, int *xsize)
+{
+ *xsize = 0;
+ *ysize = 0;
+ init_flags = INIT_GET_SIZE;
+ process_dungeon_file(name, ysize, xsize, cur_hgt, cur_wid, TRUE, TRUE);
+}
+
+void load_map(const char *name, int *y, int *x)
+{
+ /* Set the correct monster hook */
+ set_mon_num_hook();
+
+ /* Prepare allocation table */
+ get_mon_num_prep();
+
+ init_flags = INIT_CREATE_DUNGEON;
+ process_dungeon_file(name, y, x, cur_hgt, cur_wid, TRUE, TRUE);
+}
+
+void increase_mana(int delta)
+{
+ p_ptr->csp += delta;
+ p_ptr->redraw |= PR_FRAME;
+
+ 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;
+
+void timer_aggravate_evil_enable()
+{
+ TIMER_AGGRAVATE_EVIL->enable();
+}
+
+void timer_aggravate_evil_callback()
+{
+ 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);
+ }
+}
diff --git a/src/lua_bind.hpp b/src/lua_bind.hpp
new file mode 100644
index 00000000..39fc2159
--- /dev/null
+++ b/src/lua_bind.hpp
@@ -0,0 +1,32 @@
+#pragma once
+
+#include "h-basic.h"
+#include "spell_type_fwd.hpp"
+#include "timer_type_fwd.hpp"
+
+/** Calculate spell failure rate for a device, i.e. a wand or staff. */
+s32b spell_chance_device(spell_type *spell_ptr);
+
+/** Calculate spell failure rate for a spell book. */
+s32b spell_chance_book(s32b s);
+
+
+s32b lua_get_level(struct spell_type *spell, s32b lvl, s32b max, s32b min, s32b bonus);
+int get_mana(s32b s);
+s32b get_power(s32b s);
+s32b get_level(s32b s, s32b max);
+s32b get_level_s(int sp, int max);
+void get_level_school(struct spell_type *spell, s32b max, s32b min, s32b *level, bool_ *na);
+
+extern s32b get_level_max_stick;
+extern s32b get_level_use_stick;
+
+void get_map_size(const char *name, int *ysize, int *xsize);
+void load_map(const char *name, int *y, int *x);
+
+void increase_mana(int delta);
+
+extern timer_type *TIMER_AGGRAVATE_EVIL;
+
+void timer_aggravate_evil_enable();
+void timer_aggravate_evil_callback();
diff --git a/src/magic_power.hpp b/src/magic_power.hpp
new file mode 100644
index 00000000..b02c6c14
--- /dev/null
+++ b/src/magic_power.hpp
@@ -0,0 +1,15 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * Powers, used by Mindcrafters and Necromancers
+ */
+struct magic_power
+{
+ int min_lev;
+ int mana_cost;
+ int fail;
+ cptr name;
+ cptr desc;
+};
diff --git a/src/maid-x11.c b/src/maid-x11.c
deleted file mode 100755
index 86df2119..00000000
--- a/src/maid-x11.c
+++ /dev/null
@@ -1,855 +0,0 @@
-/* File: maid-x11.c */
-
-/*
- * Copyright (c) 1997 Ben Harrison, and others
- *
- * 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.
- */
-
-#if defined(USE_X11) || defined(USE_XAW)
-
-/*
- * This file defines some "XImage" manipulation functions for X11.
- *
- * Original code by Desvignes Sebastien (desvigne@solar12.eerie.fr).
- *
- * BMP format support by Denis Eropkin (denis@dream.homepage.ru).
- *
- * Major fixes and cleanup by Ben Harrison (benh@phial.com).
- *
- * This file is designed to be "included" by "main-x11.c" or "main-xaw.c",
- * which will have already "included" several relevant header files.
- */
-
-#ifndef IsModifierKey
-
-/*
- * Keysym macros, used on Keysyms to test for classes of symbols
- * These were stolen from one of the X11 header files
- *
- * Also appears in "main-x11.c".
- */
-
-#define IsKeypadKey(keysym) \
-(((unsigned)(keysym) >= XK_KP_Space) && ((unsigned)(keysym) <= XK_KP_Equal))
-
-#define IsCursorKey(keysym) \
-(((unsigned)(keysym) >= XK_Home) && ((unsigned)(keysym) < XK_Select))
-
-#define IsPFKey(keysym) \
-(((unsigned)(keysym) >= XK_KP_F1) && ((unsigned)(keysym) <= XK_KP_F4))
-
-#define IsFunctionKey(keysym) \
-(((unsigned)(keysym) >= XK_F1) && ((unsigned)(keysym) <= XK_F35))
-
-#define IsMiscFunctionKey(keysym) \
-(((unsigned)(keysym) >= XK_Select) && ((unsigned)(keysym) < XK_KP_Space))
-
-#define IsModifierKey(keysym) \
-(((unsigned)(keysym) >= XK_Shift_L) && ((unsigned)(keysym) <= XK_Hyper_R))
-
-#endif /* IsModifierKey */
-
-
-/*
- * Checks if the keysym is a special key or a normal key
- * Assume that XK_MISCELLANY keysyms are special
- *
- * Also appears in "main-x11.c".
- */
-#define IsSpecialKey(keysym) \
-((unsigned)(keysym) >= 0xFF00)
-
-
-/*
- * Hack -- Convert an RGB value to an X11 Pixel, or die.
- */
-static unsigned long create_pixel(Display *dpy, byte red, byte green, byte blue)
-{
- Colormap cmap = DefaultColormapOfScreen(DefaultScreenOfDisplay(dpy));
-
- char cname[8];
-
- XColor xcolour;
-
- /* Build the color */
-
- xcolour.red = red * 255 + red;
- xcolour.green = green * 255 + green;
- xcolour.blue = blue * 255 + blue;
- xcolour.flags = DoRed | DoGreen | DoBlue;
-
- /* Attempt to Allocate the Parsed color */
- if (!(XAllocColor(dpy, cmap, &xcolour)))
- {
- quit_fmt("Couldn't allocate bitmap color '%s'\n", cname);
- }
-
- return (xcolour.pixel);
-}
-
-
-
-#ifdef USE_GRAPHICS
-
-/*
- * The Win32 "BITMAPFILEHEADER" type.
- */
-typedef struct BITMAPFILEHEADER
-{
- u16b bfType;
- u32b bfSize;
- u16b bfReserved1;
- u16b bfReserved2;
- u32b bfOffBits;
-}
-BITMAPFILEHEADER;
-
-
-/*
- * The Win32 "BITMAPINFOHEADER" type.
- */
-typedef struct BITMAPINFOHEADER
-{
- u32b biSize;
- u32b biWidth;
- u32b biHeight;
- u16b biPlanes;
- u16b biBitCount;
- u32b biCompresion;
- u32b biSizeImage;
- u32b biXPelsPerMeter;
- u32b biYPelsPerMeter;
- u32b biClrUsed;
- u32b biClrImportand;
-}
-BITMAPINFOHEADER;
-
-/*
- * The Win32 "RGBQUAD" type.
- */
-typedef struct RGBQUAD
-{
- unsigned char b, g, r;
- unsigned char filler;
-}
-RGBQUAD;
-
-
-/*** Helper functions for system independent file loading. ***/
-
-static byte get_byte(FILE *fff)
-{
- /* Get a character, and return it */
- return (getc(fff) & 0xFF);
-}
-
-static void rd_byte(FILE *fff, byte *ip)
-{
- *ip = get_byte(fff);
-}
-
-static void rd_u16b(FILE *fff, u16b *ip)
-{
- (*ip) = get_byte(fff);
- (*ip) |= ((u16b)(get_byte(fff)) << 8);
-}
-
-static void rd_u32b(FILE *fff, u32b *ip)
-{
- (*ip) = get_byte(fff);
- (*ip) |= ((u32b)(get_byte(fff)) << 8);
- (*ip) |= ((u32b)(get_byte(fff)) << 16);
- (*ip) |= ((u32b)(get_byte(fff)) << 24);
-}
-
-
-/*
- * Read a Win32 BMP file.
- *
- * This function replaces the old ReadRaw and RemapColors functions.
- *
- * Assumes that the bitmap has a size such that no padding is needed in
- * various places. Currently only handles bitmaps with 3 to 256 colors.
- */
-static XImage *ReadBMP(Display *dpy, char *Name)
-{
- Visual *visual = DefaultVisual(dpy, DefaultScreen(dpy));
-
- int depth = DefaultDepth(dpy, DefaultScreen(dpy));
-
- FILE *f;
-
- BITMAPFILEHEADER fileheader;
- BITMAPINFOHEADER infoheader;
-
- XImage *Res = NULL;
-
- char *Data;
-
- int ncol;
-
- int total;
-
- int i, j;
-
- u32b x, y;
-
- unsigned long clr_pixels[256];
-
-
- /* Open the BMP file */
- f = fopen(Name, "r");
-
- /* No such file */
- if (f == NULL)
- {
- return (NULL);
- }
-
- /* Read the "BITMAPFILEHEADER" */
- rd_u16b(f, &(fileheader.bfType));
- rd_u32b(f, &(fileheader.bfSize));
- rd_u16b(f, &(fileheader.bfReserved1));
- rd_u16b(f, &(fileheader.bfReserved2));
- rd_u32b(f, &(fileheader.bfOffBits));
-
- /* Read the "BITMAPINFOHEADER" */
- rd_u32b(f, &(infoheader.biSize));
- rd_u32b(f, &(infoheader.biWidth));
- rd_u32b(f, &(infoheader.biHeight));
- rd_u16b(f, &(infoheader.biPlanes));
- rd_u16b(f, &(infoheader.biBitCount));
- rd_u32b(f, &(infoheader.biCompresion));
- rd_u32b(f, &(infoheader.biSizeImage));
- rd_u32b(f, &(infoheader.biXPelsPerMeter));
- rd_u32b(f, &(infoheader.biYPelsPerMeter));
- rd_u32b(f, &(infoheader.biClrUsed));
- rd_u32b(f, &(infoheader.biClrImportand));
-
- /* Verify the header */
- if (feof(f) ||
- (fileheader.bfType != 19778) ||
- (infoheader.biSize != 40))
- {
- quit_fmt("Incorrect BMP file format %s", Name);
- }
-
- /* The two headers above occupy 54 bytes total */
- /* The "bfOffBits" field says where the data starts */
- /* The "biClrUsed" field does not seem to be reliable */
- /* Compute number of colors recorded */
- ncol = (fileheader.bfOffBits - 54) / 4;
-
- for (i = 0; i < ncol; i++)
- {
- RGBQUAD clrg;
-
- /* Read an "RGBQUAD" */
- rd_byte(f, &(clrg.b));
- rd_byte(f, &(clrg.g));
- rd_byte(f, &(clrg.r));
- rd_byte(f, &(clrg.filler));
-
- /* Analyze the color */
- clr_pixels[i] = create_pixel(dpy, clrg.r, clrg.g, clrg.b);
- }
-
- /* Determine total bytes needed for image */
- i = 1;
- j = (depth - 1) >> 2;
- while (j >>= 1) i <<= 1;
- total = infoheader.biWidth * infoheader.biHeight * i;
-
- /* Allocate image memory */
- C_MAKE(Data, total, char);
-
- Res = XCreateImage(dpy, visual, depth, ZPixmap, 0 /*offset*/,
- Data, infoheader.biWidth, infoheader.biHeight,
- 8 /*bitmap_pad*/, 0 /*bytes_per_line*/);
-
- /* Failure */
- if (Res == NULL)
- {
- C_KILL(Data, total, char);
- fclose(f);
- return (NULL);
- }
-
- for (y = 0; y < infoheader.biHeight; y++)
- {
- int y2 = infoheader.biHeight - y - 1;
-
- for (x = 0; x < infoheader.biWidth; x++)
- {
- int ch = getc(f);
-
- /* Verify not at end of file XXX XXX */
- if (feof(f)) quit_fmt("Unexpected end of file in %s", Name);
-
- if (infoheader.biBitCount == 24)
- {
- int c2 = getc(f);
- int c3 = getc(f);
-
- /* Verify not at end of file XXX XXX */
- if (feof(f)) quit_fmt("Unexpected end of file in %s", Name);
-
- XPutPixel(Res, x, y2, create_pixel(dpy, ch, c2, c3));
- }
- else if (infoheader.biBitCount == 8)
- {
- XPutPixel(Res, x, y2, clr_pixels[ch]);
- }
- else if (infoheader.biBitCount == 4)
- {
- XPutPixel(Res, x, y2, clr_pixels[ch / 16]);
- x++;
- XPutPixel(Res, x, y2, clr_pixels[ch % 16]);
- }
- else
- {
- /* Technically 1 bit is legal too */
- quit_fmt("Illegal biBitCount %d in %s",
- infoheader.biBitCount, Name);
- }
- }
- }
-
- fclose(f);
-
- return Res;
-}
-
-
-/* ========================================================*/
-/* Code for smooth icon rescaling from Uwe Siems, Jan 2000 */
-/* ========================================================*/
-
-/*
- * to save ourselves some labour, define a maximum expected icon width here:
- */
-#define MAX_ICON_WIDTH 32
-
-
-/* some static variables for composing and decomposing pixel values into
- * red, green and blue values
- */
-static unsigned long redMask, greenMask, blueMask;
-static int redShift, greenShift, blueShift;
-
-
-/*
- * Use smooth rescaling?
- */
-static bool_ smoothRescaling = TRUE;
-
-
-/*
- * GetScaledRow reads a scan from the given XImage, scales it smoothly
- * and returns the red, green and blue values in arrays.
- * The values in this arrays must be divided by a certain value that is
- * calculated in ScaleIcon.
- * x, y is the position, iw is the input width and ow the output width
- * redScan, greenScan and blueScan must be sufficiently sized
- */
-static void GetScaledRow(XImage *Im, int x, int y, int iw, int ow,
- unsigned long *redScan, unsigned long *greenScan,
- unsigned long *blueScan)
-{
- int xi, si, sifrac, ci, cifrac, addWhole, addFrac;
- unsigned long pix;
- int prevRed, prevGreen, prevBlue, nextRed, nextGreen, nextBlue;
- bool_ getNextPix;
-
- if (iw == ow)
- {
- /* unscaled */
- for (xi = 0; xi < ow; xi++)
- {
- pix = XGetPixel(Im, x + xi, y);
- redScan [xi] = (pix >> redShift) & redMask;
- greenScan [xi] = (pix >> greenShift) & greenMask;
- blueScan [xi] = (pix >> blueShift) & blueMask;
- }
- }
- else if (iw < ow)
- {
- /* scaling by subsampling (grow) */
- iw--;
- ow--;
- /* read first pixel: */
- pix = XGetPixel(Im, x, y);
- nextRed = (pix >> redShift) & redMask;
- nextGreen = (pix >> greenShift) & greenMask;
- nextBlue = (pix >> blueShift) & blueMask;
- prevRed = nextRed;
- prevGreen = nextGreen;
- prevBlue = nextBlue;
- /* si and sifrac give the subsampling position: */
- si = x;
- sifrac = 0;
- /* getNextPix tells us, that we need the next pixel */
- getNextPix = TRUE;
-
- for (xi = 0; xi <= ow; xi++)
- {
- if (getNextPix)
- {
- prevRed = nextRed;
- prevGreen = nextGreen;
- prevBlue = nextBlue;
- if (xi < ow)
- {
- /* only get next pixel if in same icon */
- pix = XGetPixel(Im, si + 1, y);
- nextRed = (pix >> redShift) & redMask;
- nextGreen = (pix >> greenShift) & greenMask;
- nextBlue = (pix >> blueShift) & blueMask;
- }
- }
-
- /* calculate subsampled color values: */
- /* division by ow occurs in ScaleIcon */
- redScan [xi] = prevRed * (ow - sifrac) + nextRed * sifrac;
- greenScan [xi] = prevGreen * (ow - sifrac) + nextGreen * sifrac;
- blueScan [xi] = prevBlue * (ow - sifrac) + nextBlue * sifrac;
-
- /* advance sampling position: */
- sifrac += iw;
- if (sifrac >= ow)
- {
- si++;
- sifrac -= ow;
- getNextPix = TRUE;
- }
- else
- {
- getNextPix = FALSE;
- }
-
- }
- }
- else
- {
- /* scaling by averaging (shrink) */
- /* width of an output pixel in input pixels: */
- addWhole = iw / ow;
- addFrac = iw % ow;
- /* start position of the first output pixel: */
- si = x;
- sifrac = 0;
- /* get first input pixel: */
- pix = XGetPixel(Im, x, y);
- nextRed = (pix >> redShift) & redMask;
- nextGreen = (pix >> greenShift) & greenMask;
- nextBlue = (pix >> blueShift) & blueMask;
- for (xi = 0; xi < ow; xi++)
- {
- /* find endpoint of the current output pixel: */
- ci = si + addWhole;
- cifrac = sifrac + addFrac;
- if (cifrac >= ow)
- {
- ci++;
- cifrac -= ow;
- }
- /* take fraction of current input pixel (starting segment): */
- redScan[xi] = nextRed * (ow - sifrac);
- greenScan[xi] = nextGreen * (ow - sifrac);
- blueScan[xi] = nextBlue * (ow - sifrac);
- si++;
- /* add values for whole pixels: */
- while (si < ci)
- {
- pix = XGetPixel(Im, si, y);
- redScan[xi] += ((pix >> redShift) & redMask) * ow;
- greenScan[xi] += ((pix >> greenShift) & greenMask) * ow;
- blueScan[xi] += ((pix >> blueShift) & blueMask) * ow;
- si++;
- }
- /* add fraction of current input pixel (ending segment): */
- if (xi < ow - 1)
- {
- /* only get next pixel if still in icon: */
- pix = XGetPixel(Im, si, y);
- nextRed = (pix >> redShift) & redMask;
- nextGreen = (pix >> greenShift) & greenMask;
- nextBlue = (pix >> blueShift) & blueMask;
- }
- sifrac = cifrac;
- if (sifrac > 0)
- {
- redScan[xi] += nextRed * sifrac;
- greenScan[xi] += nextGreen * sifrac;
- blueScan[xi] += nextBlue * sifrac;
- }
- }
- }
-}
-
-
-/*
- * PutRGBScan takes arrays for red, green and blue and writes pixel values
- * according to this values in the XImage-structure. w is the number of
- * pixels to write and div is the value by which all red/green/blue values
- * are divided first.
- */
-static void PutRGBScan(XImage *Im, int x, int y, int w, int div,
- unsigned long *redScan, unsigned long *greenScan,
- unsigned long *blueScan)
-{
- int xi;
- unsigned long pix;
- unsigned long adj = div / 2;
- for (xi = 0; xi < w; xi++)
- {
- pix = (((((redScan[xi] + adj) / div) & redMask) << redShift) +
- ((((greenScan[xi] + adj) / div) & greenMask) << greenShift) +
- ((((blueScan[xi] + adj) / div) & blueMask) << blueShift));
- XPutPixel(Im, x + xi, y, pix);
- }
-}
-
-
-/*
- * ScaleIcon transfers an area from XImage ImIn, locate (x1,y1) to ImOut,
- * locate (x2, y2).
- * Source size is (ix, iy) and destination size is (ox, oy).
- * It does this by getting icon scan line from GetScaledScan and handling
- * them the same way as pixels are handled in GetScaledScan.
- * This even allows icons to be scaled differently in horizontal and
- * vertical directions (eg. shrink horizontal, grow vertical).
- */
-static void ScaleIcon(XImage *ImIn, XImage *ImOut,
- int x1, int y1, int x2, int y2,
- int ix, int iy, int ox, int oy)
-{
- int div;
- int xi, yi, si, sifrac, ci, cifrac, addWhole, addFrac;
-
- /* buffers for pixel rows: */
- unsigned long prevRed [MAX_ICON_WIDTH];
- unsigned long prevGreen [MAX_ICON_WIDTH];
- unsigned long prevBlue [MAX_ICON_WIDTH];
- unsigned long nextRed [MAX_ICON_WIDTH];
- unsigned long nextGreen [MAX_ICON_WIDTH];
- unsigned long nextBlue [MAX_ICON_WIDTH];
- unsigned long tempRed [MAX_ICON_WIDTH];
- unsigned long tempGreen [MAX_ICON_WIDTH];
- unsigned long tempBlue [MAX_ICON_WIDTH];
-
- bool_ getNextRow;
-
- /* get divider value for the horizontal scaling: */
- if (ix == ox)
- div = 1;
- else if (ix < ox)
- div = ox - 1;
- else
- div = ix;
-
- if (iy == oy)
- {
- /* no scaling needed vertically: */
- for (yi = 0; yi < oy; yi++)
- {
- GetScaledRow(ImIn, x1, y1 + yi, ix, ox,
- tempRed, tempGreen, tempBlue);
- PutRGBScan(ImOut, x2, y2 + yi, ox, div,
- tempRed, tempGreen, tempBlue);
- }
- }
- else if (iy < oy)
- {
- /* scaling by subsampling (grow): */
- iy--;
- oy--;
- div *= oy;
- /* get first row: */
- GetScaledRow(ImIn, x1, y1, ix, ox, nextRed, nextGreen, nextBlue);
- /* si and sifrac give the subsampling position: */
- si = y1;
- sifrac = 0;
- /* getNextRow tells us, that we need the next row */
- getNextRow = TRUE;
- for (yi = 0; yi <= oy; yi++)
- {
- if (getNextRow)
- {
- for (xi = 0; xi < ox; xi++)
- {
- prevRed[xi] = nextRed[xi];
- prevGreen[xi] = nextGreen[xi];
- prevBlue[xi] = nextBlue[xi];
- }
- if (yi < oy)
- {
- /* only get next row if in same icon */
- GetScaledRow(ImIn, x1, si + 1, ix, ox,
- nextRed, nextGreen, nextBlue);
- }
- }
-
- /* calculate subsampled color values: */
- /* division by oy occurs in PutRGBScan */
- for (xi = 0; xi < ox; xi++)
- {
- tempRed[xi] = (prevRed[xi] * (oy - sifrac) +
- nextRed[xi] * sifrac);
- tempGreen[xi] = (prevGreen[xi] * (oy - sifrac) +
- nextGreen[xi] * sifrac);
- tempBlue[xi] = (prevBlue[xi] * (oy - sifrac) +
- nextBlue[xi] * sifrac);
- }
-
- /* write row to output image: */
- PutRGBScan(ImOut, x2, y2 + yi, ox, div,
- tempRed, tempGreen, tempBlue);
-
- /* advance sampling position: */
- sifrac += iy;
- if (sifrac >= oy)
- {
- si++;
- sifrac -= oy;
- getNextRow = TRUE;
- }
- else
- {
- getNextRow = FALSE;
- }
-
- }
- }
- else
- {
- /* scaling by averaging (shrink) */
- div *= iy;
- /* height of a output row in input rows: */
- addWhole = iy / oy;
- addFrac = iy % oy;
- /* start position of the first output row: */
- si = y1;
- sifrac = 0;
- /* get first input row: */
- GetScaledRow(ImIn, x1, y1, ix, ox, nextRed, nextGreen, nextBlue);
- for (yi = 0; yi < oy; yi++)
- {
- /* find endpoint of the current output row: */
- ci = si + addWhole;
- cifrac = sifrac + addFrac;
- if (cifrac >= oy)
- {
- ci++;
- cifrac -= oy;
- }
- /* take fraction of current input row (starting segment): */
- for (xi = 0; xi < ox; xi++)
- {
- tempRed[xi] = nextRed[xi] * (oy - sifrac);
- tempGreen[xi] = nextGreen[xi] * (oy - sifrac);
- tempBlue[xi] = nextBlue[xi] * (oy - sifrac);
- }
- si++;
- /* add values for whole pixels: */
- while (si < ci)
- {
- GetScaledRow(ImIn, x1, si, ix, ox,
- nextRed, nextGreen, nextBlue);
- for (xi = 0; xi < ox; xi++)
- {
- tempRed[xi] += nextRed[xi] * oy;
- tempGreen[xi] += nextGreen[xi] * oy;
- tempBlue[xi] += nextBlue[xi] * oy;
- }
- si++;
- }
- /* add fraction of current input row (ending segment): */
- if (yi < oy - 1)
- {
- /* only get next row if still in icon: */
- GetScaledRow(ImIn, x1, si, ix, ox,
- nextRed, nextGreen, nextBlue);
- }
- sifrac = cifrac;
- for (xi = 0; xi < ox; xi++)
- {
- tempRed[xi] += nextRed[xi] * sifrac;
- tempGreen[xi] += nextGreen[xi] * sifrac;
- tempBlue[xi] += nextBlue[xi] * sifrac;
- }
- /* write row to output image: */
- PutRGBScan(ImOut, x2, y2 + yi, ox, div,
- tempRed, tempGreen, tempBlue);
- }
- }
-}
-
-
-
-static XImage *ResizeImageSmooth(Display *dpy, XImage *Im,
- int ix, int iy, int ox, int oy)
-{
- Visual *visual = DefaultVisual(dpy, DefaultScreen(dpy));
-
- int width1, height1, width2, height2;
- int x1, x2, y1, y2;
-
- XImage *Tmp;
-
- char *Data;
-
- width1 = Im->width;
- height1 = Im->height;
-
- width2 = ox * width1 / ix;
- height2 = oy * height1 / iy;
-
- Data = (char *)malloc(width2 * height2 * Im->bits_per_pixel / 8);
-
- Tmp = XCreateImage(dpy, visual,
- Im->depth, ZPixmap, 0, Data, width2, height2,
- 32, 0);
-
- /* compute values for decomposing pixel into color values: */
- redMask = Im->red_mask;
- redShift = 0;
- while ((redMask & 1) == 0)
- {
- redShift++;
- redMask >>= 1;
- }
- greenMask = Im->green_mask;
- greenShift = 0;
- while ((greenMask & 1) == 0)
- {
- greenShift++;
- greenMask >>= 1;
- }
- blueMask = Im->blue_mask;
- blueShift = 0;
- while ((blueMask & 1) == 0)
- {
- blueShift++;
- blueMask >>= 1;
- }
-
- /* scale each icon: */
- for (y1 = 0, y2 = 0; (y1 < height1) && (y2 < height2); y1 += iy, y2 += oy)
- {
- for (x1 = 0, x2 = 0; (x1 < width1) && (x2 < width2); x1 += ix, x2 += ox)
- {
- ScaleIcon(Im, Tmp, x1, y1, x2, y2,
- ix, iy, ox, oy);
- }
- }
-
- return Tmp;
-}
-
-/*
- * Resize an image. XXX XXX XXX
- *
- * Also appears in "main-xaw.c".
- */
-static XImage *ResizeImage(Display *dpy, XImage *Im,
- int ix, int iy, int ox, int oy)
-{
- Visual *visual = DefaultVisual(dpy, DefaultScreen(dpy));
-
- int width1, height1, width2, height2;
- int x1, x2, y1, y2, Tx, Ty;
- int *px1, *px2, *dx1, *dx2;
- int *py1, *py2, *dy1, *dy2;
-
- XImage *Tmp;
-
- char *Data;
-
- if (smoothRescaling && (ix != ox || iy != oy) &&
- visual->class == TrueColor)
- {
- return ResizeImageSmooth(dpy, Im, ix, iy, ox, oy);
- }
-
- width1 = Im->width;
- height1 = Im->height;
-
- width2 = ox * width1 / ix;
- height2 = oy * height1 / iy;
-
- Data = (char *)malloc(width2 * height2 * Im->bits_per_pixel / 8);
-
- Tmp = XCreateImage(dpy, visual,
- Im->depth, ZPixmap, 0, Data, width2, height2,
- 32, 0);
-
- if (ix > ox)
- {
- px1 = &x1;
- px2 = &x2;
- dx1 = &ix;
- dx2 = &ox;
- }
- else
- {
- px1 = &x2;
- px2 = &x1;
- dx1 = &ox;
- dx2 = &ix;
- }
-
- if (iy > oy)
- {
- py1 = &y1;
- py2 = &y2;
- dy1 = &iy;
- dy2 = &oy;
- }
- else
- {
- py1 = &y2;
- py2 = &y1;
- dy1 = &oy;
- dy2 = &iy;
- }
-
- Ty = *dy1 / 2;
-
- for (y1 = 0, y2 = 0; (y1 < height1) && (y2 < height2); )
- {
- Tx = *dx1 / 2;
-
- for (x1 = 0, x2 = 0; (x1 < width1) && (x2 < width2); )
- {
- XPutPixel(Tmp, x2, y2, XGetPixel(Im, x1, y1));
-
- (*px1)++;
-
- Tx -= *dx2;
- if (Tx < 0)
- {
- Tx += *dx1;
- (*px2)++;
- }
- }
-
- (*py1)++;
-
- Ty -= *dy2;
- if (Ty < 0)
- {
- Ty += *dy1;
- (*py2)++;
- }
- }
-
- return Tmp;
-}
-
-#endif /* USE_GRAPHICS */
-
-#endif /* USE_X11 || USE_XAW */
diff --git a/src/main-crb.c b/src/main-crb.c
deleted file mode 100644
index a4a1a742..00000000
--- a/src/main-crb.c
+++ /dev/null
@@ -1,6402 +0,0 @@
-/* File: main-crb.c */
-
-/*
- * Copyright (c) 1997 Ben Harrison, Keith Randall, Peter Ammon, Ron Anderson
- * and others
- *
- * 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.
- */
-
-
-/*
- * This file helps Angband work with Macintosh computers running OS X,
- * or OS 8/9 with CarbonLib system extention.
- *
- * To use this file, use an appropriate "Makefile" or "Project File", which
- * should define "MACINTOSH".
- *
- * The official compilation uses the CodeWarrior Pro compiler.
- *
- * If you are never going to use "graphics" (especially if you are not
- * compiling support for graphics anyway) then you can delete the "pict"
- * resources with id "1001", "1002", "1003" and "1004" with no dangerous
- * side effects.
- *
- *
- * This file assumes that you will be using a PPC Mac running OS X
- * or OS 8/9 (8.6 or greater) with CarbonLib system extention enabled.
- * In fact, the game will refuse to run unless these features are available.
- *
- * MACH_O_CARBON code pushes the system requirement a bit further, and
- * I don't think it works on System 8, even with CarbonLib, because it uses
- * the Bundle services, but I may be wrong.
- *
- * Note that the "preference" file is now a simple XML text file
- * called "<program name>.plist" in case of PEF Carbon, and "<Java-style
- * program id defined in Info.plist>.plist" for Mach-O Carbon, which contains
- * key-value paris, so it no longer has to check version stamp to validate
- * its contents.
- *
- *
- * Note that "init1.c", "init2.c", "load1.c", "load2.c", and "birth.c"
- * should probably be "unloaded" as soon as they are no longer needed,
- * to save space, but I do not know how to do this. XXX XXX XXX
- *
- * Stange bug -- The first "ClipRect()" call crashes if the user closes
- * all the windows, switches to another application, switches back, and
- * re-opens the main window, for example, using "command-a". XXX XXX XXX
- *
- *
- * Initial framework (and most code) by Ben Harrison (benh@phial.com).
- *
- * Some code adapted from "MacAngband 2.6.1" by Keith Randall
- *
- * Initial PowerMac port by Maarten Hazewinkel (mmhazewi@cs.ruu.nl).
- *
- * Most Apple Event code provided by Steve Linberg (slinberg@crocker.com).
- *
- * Most of the graphics code is adapted from an extremely minimal subset of
- * the "Sprite World II" package, an amazing (and free) animation package.
- *
- * Carbon code adapted from works by Peter Ammon and Ron Anderson.
- *
- * (List of changes made by "pelpel" follow)
- * Some API calls are updated to OS 8.x-- ones.
- *
- * Pixmap locking code in Term_pict_map() follows Carbon Porting Guide
- * by Apple.
- *
- * The idle loop in TERM_XTRA_DELAY is rewritten to sleep on WaitNextEvent
- * for a couple of reasons.
- *
- * CheckEvent now really blocks whenever asked to wait.
- *
- * The unused buffer GWorld is completely removed. It has long been pure waste
- * of memory.
- *
- * The default font-size combination was changed because the old one, Monaco
- * at 12 points causes the redraw artefact problem on OS X.
- *
- * Characters in the ASCII mode are clipped by their bounding rects to reduce
- * redraw artefacts that were quite annoying in certain font-point combos.
- *
- * Transparency effect now avoids double bitblts whenever possible.
- *
- * Old tiles were drawn in a wrong fashion by the USE_TRANSPARENCY code.
- *
- * ASCII and the two graphics modes are now controlled by single graf_mode
- * variable. arg_* and use_* variables are set when requested mode is
- * successfully initialised.
- *
- * Most of the menus are now loaded from resources.
- *
- * Moved TileWidth and TileHeight menus into Special. There were too many menus.
- *
- * Added support for 32x32 tiles, now for [V] only.
- *
- * Related to the above, globe_init no longer loads tile images twice if
- * a tileset doesn't have corresponding masks.
- *
- * Added support for POSIX-style pathnames, for Mach-O Carbon (gcc, CW >= 7).
- * We can finally live without Pascal strings to handle files this way.
- *
- * (Mach-O Carbon) Graphics tiles are moved out of the resource fork into
- * bundle-based data fork files.
- *
- * Changed size-related menu code, because they no longer function because
- * some APIs have been changed to return Unicode in some cases.
- *
- * Changed the transparency code again, this time using Ron Anderson's code,
- * which makes more sound assumption about background colour and is more
- * efficient.
- *
- * The old asynchronous sound player could try to lock the same handle more
- * than once, load same sound resource already in use, or unlock and release
- * currently playing sound.
- *
- * hook_quit() now releases memory-related resources dynamically allocated by
- * the graphics and sound code.
- *
- * Important Resources in the resource file:
- *
- * FREF 130 = ANGBAND_CREATOR / 'APPL' (application)
- * FREF 129 = ANGBAND_CREATOR / 'SAVE' (save file)
- * FREF 130 = ANGBAND_CREATOR / 'TEXT' (generic text file)
- * FREF 131 = ANGBAND_CREATOR / 'DATA' (binary image file, score file)
- *
- * DLOG 128 = "About Angband..."
- *
- * ALRT 128 = unused (?)
- * ALRT 129 = "Warning..."
- *
- * DITL 128 = body for DLOG 128
- * DITL 129 = body for ALRT 129
- * DITL 130 = body for ALRT 130
- *
- * ICON 128 = "warning" icon
- *
- * 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, -)
- * MENU 132 = Size ()
- * MENU 133 = Windows ()
- * MENU 134 = Special (Sound, Graphics, TileWidth, TileHeight, -, Fiddle,
- * Wizard)
- * Graphics have following submenu attached:
- * MENU 144 = Graphics (None, 8x8, 16x16, 32x32, enlarge tiles)
- * TileWidth and TileHeight submenus are filled in by this program.
- * MENU 145 = TileWidth ()
- * MENU 146 = TileHeight ()
- *
- * On CFM(PEF) Carbon only:
- * PICT 1001 = Graphics tile set (8x8)
- * PICT 1002 = Graphics tile set (16x16 images)
- * PICT 1004 = Graphics tile set (32x32)
- *
- * Mach-O Carbon now uses data fork resources:
- * 8x8.png = Graphics tile set (8x8)
- * 16x16.png = Graphics tile set (16x16 images)
- * 32x32.png = Graphics tile set (32x32)
- * These files should go into the Resources subdirectory of an application
- * bundle.
- *
- * STR# 128 = "Please select the "lib" folder"
- *
- * plst 0 can be empty, but required for single binary Carbon apps on OS X
- * Isn't necessary for Mach-O Carbon.
- *
- *
- * File name patterns:
- * all 'APEX' files have a filename of the form "*:apex:*" (?)
- * all 'DATA' files have a filename of the form "*:data:*"
- * all 'SAVE' files have a filename of the form "*:save:*"
- * all 'USER' files have a filename of the form "*:user:*" (?)
- *
- * Perhaps we should attempt to set the "_ftype" flag inside this file,
- * to avoid nasty file type information being spread all through the
- * rest of the code. (?) This might require adding hooks into the
- * "fd_open()" and "my_fopen()" functions in "util.c". XXX XXX XXX
- *
- *
- * Reasons for each header file:
- *
- * angband.h = Angband header file
- *
- * Types.h = (included anyway)
- * Gestalt.h = gestalt code
- * QuickDraw.h = (included anyway)
- * OSUtils.h = (included anyway)
- * Files.h = file code
- * Fonts.h = font code
- * Menus.h = menu code
- * Dialogs.h = dialog code
- * Windows.h = (included anyway)
- * Palettes.h = palette code
- * ToolUtils.h = HiWord() / LoWord()
- * Events.h = event code
- * Resources.h = resource code
- * Controls.h = button code
- * SegLoad.h = ExitToShell(), AppFile, etc
- * Memory.h = NewPtr(), etc
- * QDOffscreen.h = GWorld code
- * Sound.h = Sound code
- * Navigation.h = save file / lib locating dialogues
- * CFPreferences.h = Preferences
- * CFNumber.h = read/write short values from/to preferences
- */
-
-/*
- * Yet another main-xxx.c for Carbon (pelpel) - revision 11d
- *
- * Since I'm using CodeWarrior, the traditional header files are
- * #include'd below.
- *
- * I also compiled Angband 3.0.2 successfully with OS X's gcc.
- * Please follow these instructions if you are interested.
- *
- * ---(developer CD gcc + makefile porting notes, for Angband 3.0.2)-------
- * 1. Compiling the binary
- *
- * If you try this on OS X + gcc, please use makefile.std, replacing
- * main.c and main.o with main-crb.c and main-crb.o, removing all main-xxx.c
- * and main-xxx.o from SRCS and OBJS, and, and use these settings:
- *
- * COPTS = -Wall -O1 -g -fpascal-strings
- * INCLUDES =
- * 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).
- *
- * You might wish to disable some SET_UID features for various reasons:
- * to have user folder within the lib folder, savefile names etc.
- *
- * For the best compatibility with the Classic ports and my PEF Carbon
- * ports, my_fopen, fd_make and fd_open [in util.c] should call
- * (void)fsetfileinfo(buf, _fcreator, _ftype);
- * when a file is successfully opened. Or you'll see odd icons for some files
- * in the lib folder. In order to do so, extern.h should contain these lines,
- * within #ifdef MACH_O_CARBON:
- * extern int fsetfileinfo(char *path, u32b fcreator, u32b ftype);
- * extern u32b _fcreator;
- * extern u32b _ftype;
- * And enable the four FILE_TYPE macros in h-config.h for defined(MACH_O_CARBON)
- * in addition to defined(MACINTOSH) && !defined(applec), i.e.
- * #if defined(MACINTOSH) && !defined(applec) || defined(MACH_O_CARBON)
- *
- * This is a very good way to spot bugs in use of these macros, btw.
- *
- * 2. Installation
- *
- * The "angband" binary must be arranged this way for it to work:
- *
- * lib/ <- the lib folder
- * Angband (OS X).app/
- * Contents/
- * MacOS/
- * angband <- the binary you've just compiled
- * Info.plist <- to be explained below
- * Resources/
- * Angband.icns
- * Data.icns
- * Edit.icns
- * Save.icns
- * 8x8.png <- 8x8 tiles
- * 16x16.png <- 16x16 tiles
- * angband.rsrc <- see below
- *
- * 3. Preparing Info.plist
- *
- * Info.plist is an XML file describing some attributes of an application,
- * and this is appropriate for Angband:
- *
- * <?xml version="1.0" encoding="UTF-8"?>
- * <plist version="1.0">
- * <dict>
- * <key>CFBundleName</key><string>Angband</string>
- * <key>CFBundleDisplayName</key><string>Angband (OS X)</string>
- * <key>CFBundleExecutable</key><string>angband</string>
- * <key>CFBundlePackageType</key><string>APPL</string>
- * <key>CFBundleSignature</key><string>A271</string>
- * <key>CFBundleVersion</key><string>3.0.2</string>
- * <key>CFBundleShortVersionString</key><string>3.0.2</string>
- * <key>CFBundleIconFile</key><string>Angband</string>
- * <key>CFBundleIdentifier</key><string>net.thangorodrim.Angband</string>
- * <key>CFBundleInfoDictionaryVersion</key><string>6.0</string>
- * <key>CFBundleDocumentTypes</key>
- * <array>
- * <dict>
- * <key>CFBundleTypeExtentions</key><array><string>*</string></array>
- * <key>CFBundleTypeIconFile</key><string>Save</string>
- * <key>CFBundleTypeName</key><string>Angband saved game</string>
- * <key>CFBundleTypeOSTypes</key><array><string>SAVE</string></array>
- * <key>CFBundleTypeRole</key><string>Editor</string>
- * </dict>
- * <dict>
- * <key>CFBundleTypeExtentions</key><array><string>*</string></array>
- * <key>CFBundleTypeIconFile</key><string>Edit</string>
- * <key>CFBundleTypeName</key><string>Angband game data</string>
- * <key>CFBundleTypeOSTypes</key><array><string>TEXT</string></array>
- * <key>CFBundleTypeRole</key><string>Editor</string>
- * </dict>
- * <dict>
- * <key>CFBundleTypeExtentions</key><array><string>raw</string></array>
- * <key>CFBundleTypeIconFile</key><string>Data</string>
- * <key>CFBundleTypeName</key><string>Angband game data</string>
- * <key>CFBundleTypeOSTypes</key><array><string>DATA</string></array>
- * <key>CFBundleTypeRole</key><string>Editor</string>
- * </dict>
- * </array>
- * </dict>
- * </plist>
- *
- * 4. Menu, diaglogue and gfx resources
- *
- * The binary assumes angband.rsrc should be in the traditional resource
- * mangager format. Please run this command to create it from its textual
- * description:
- *
- * Rez -i /Developer/Headers/FlatCarbon -d MACH_O -o angband.rsrc Angband.r
- *
- * The command is in /Developer/Tools. You might wish to include it in your
- * PATH.
- *
- * It's better to comment out the definitions of BNDL and plst resources
- * before you do that. I think you can DeRez the resulting tome.rsrc and
- * feed it to the Interface Builder to produce a set of compatible .nib files,
- * but this file also needs to be updated to understand .nib... On the other
- * hand, I really don't like to hardcode UI definitions in C.
- *
- * Graphics resources are moved out of the resource fork and become ordinary
- * PNG files. Make sure to set its resolution to 72 dpi (<- VERY important)
- * while keeping vertical and horizontal scaling factor to 100% (<- VERY
- * important), when you convert tiles in any formats to PNG. This means
- * that the real size of an image must shrink or grow when you change it's dpi.
- *
- * Sound resources are a bit more complicated.
- * The easiest way is:
- * 1) Grab recent Mac Angband binary.
- * 2) Run this command:
- * DeRez -only 'snd ' (Angband binary) > sound.r
- * 3) And specify sound.r files in addition to Angband.r when you run Rez.
- *
- * ---(end of OS X + gcc porting note)--------------------------------------
- *
- * Code adapted from Peter Ammon's work on 2.8.3 and some modifications
- * are made when Apple's Carbon Porting Guide says they are absolutely
- * necessary. Other arbirary changes are mostly because of my hatred
- * of deep nestings and indentations. The code for controlling graphics modes
- * have been thoroughly revised simply because I didn't like it (^ ^;).
- * A bonus of this is that graphics settings can be loaded from Preferences
- * quite easily.
- *
- * I also took Ron Anderson's (minimising the use of local-global coordinate
- * conversions). Some might say his QuickTime multimedia is the most
- * significant achievement... Play your favourite CD instead, if you really
- * miss that (^ ^;) I might consider incorporating it if it makes use of
- * event notification.
- *
- * I replaced some old API calls with new (OS 8.x--) ones, especially
- * when I felt Apple is strongly against their continued usage.
- *
- * Similarly, USE_SFL_CODE should be always active, so I removed ifdef's
- * just to prevent accidents, as well as to make the code a bit cleaner.
- *
- * On the contrary, I deliberately left traditional resource interfaces.
- * Whatever Apple might say, I abhor file name extentions. And keeping two
- * different sets of resources for Classic and Carbon is just too much for
- * a personal project XXX
- *
- * Because Carbon forbids the use of 68K code, ANGBAND_LITE_MAC sections
- * are removed.
- *
- * Because the default font-size combination causes redraw artefact problem
- * (some characters, even in monospace fonts, have negative left bearings),
- * I introduced rather crude hack to clip all character drawings within
- * their bounding rects. If you don't like this, please comment out the line
- * #define CLIP_HACK
- * below.
- *
- * The check for return values of AEProcessAppleEvent is removed,
- * because it results in annoying dialogues on OS X, also because
- * Apple says it isn't usually necessary.
- *
- * Because the always_pict code is *so* slow, I changed the graphics
- * mode selection a bit to use higher_pict when a user chooses a fixed
- * width font and doesn't changes tile width / height.
- *
- * Added support for David Gervais' 32x32 tiles.
- *
- * Replaced transparency effect code by Ron Anderson's.
- *
- * Added support for gcc & make compilation. They come free with OS X
- * (on the developer CD). This means that it can be compiled as a bundle.
- *
- * For Mach-O Carbon binary, moved graphics tiles out of the
- * resource fork and made them plain PNG files, to be stored in the application
- * bundle's "Resources" subdirectory.
- *
- * For Mach-O Carbon binary, provided a compile-time option (USE_QT_SOUND) to
- * move sound effect samples out of the resource fork and use *.wav files in
- * the bundle's "Resources" subdirectory. The "*" part must match the names in
- * angband_sound_name (variable.c) exactly. This doesn't hurt performance
- * a lot in [V] (it's got ~25 sound events), but problematic in [Z]-based
- * ones (they have somewhere around 70 sound events).
- *
- * You still can use the resource file that comes with the ext-mac archive
- * on the Angband FTP server, with these additions:
- * - MENUs 131--134 and 144--146, as described above
- * - MBAR 128: just a array of 128 through 134
- * - plst 0 : can be empty, although Apple recommends us to fill it in.
- * - STR# 128 : something like "Please select your lib folder"
- *
- * Since this involves considerable amount of work, I attached
- * a plain text resource definition (= Rez format) .
- * I heavily commented on the file, hoping it could be easily adapted
- * to future versions of Angband as well as variants.
- * I omitted sound effects and graphic tiles to make it reasonably small.
- * Please copy them from any recent Mac binaries - you can use, say ZAngband
- * ones for Vanilla or [V]-based variants quite safely. T.o.M.E. uses fairly
- * extended 16x16 tileset and it is maintained actively. IIRC Thangorodrim
- * compile page has an intruction explaining how to convert tiles for
- * use on the Mac... It can be tricky, depending on your choice of
- * graphics utility. Remember setting resolution to 72 pixels per inch,
- * while keeping vertical/horizontal scale factor to 100% and dump the
- * result as a PICT from resource.
- *
- * To build Carbonised Angband with CodeWarrior, copy your PPC project
- * and
- * - replace main-mac.c in the project with this file (in the link order tab)
- * - remove InterfaceLib and MathLib
- * - add CarbonLib (found in Carbon SDK or CW's UniversalInterfaces) --
- * if you have compiler/linker errors, you'll need Carbon SDK 1.1 or greater
- * - replace MSL C.PPC.Lib with MSL C.Carbon.Lib (both found in
- * MSL:MSL_C:MSL_MacOS:Lib:PPC)
- * - leave MSL RuntimePPC.Lib as it is
- * - don't forget to update resource file, as described above
- * - as in Classic targets, you may have to include <unistd.h> and
- * <fcntl.h>. The most convinient place for them is the first
- * #ifdef MACINTOSH in h-system.h
- * - check variant dependent ifdef's explained below, and add
- * appropriate one(s) in your A-mac-h.pch.
- */
-
-
-/*
- * Force Carbon-compatible APIs
- */
-#ifndef MACH_O_CARBON
-
-/* Can be CodeWarrior or MPW */
-# define TARGET_API_MAC_CARBON 1
-
-#else
-
-/*
-* Must be Mach-O Carbon target with OS X gcc.
-* No need to set TARGET_API_MAC_CARBON to 1 here, but I assume it should
-* be able to make efficient use of BSD functions, hence:
-*/
-# define USE_MALLOC
-/* Not yet */
-/* # define USE_NIB */
-
-#endif /* !MACH_O_CARBON */
-
-
-#include "angband.h"
-
-#if defined(MACINTOSH) || defined(MACH_O_CARBON)
-
-/*
- * Check and create if needed the directory dirpath
- */
-bool_ private_check_user_directory(cptr dirpath)
-{
- /* Is this used anywhere else in *bands? */
- struct stat stat_buf;
-
- int ret;
-
- /* See if it already exists */
- ret = stat(dirpath, &stat_buf);
-
- /* It does */
- if (ret == 0)
- {
- /* Now we see if it's a directory */
- if ((stat_buf.st_mode & S_IFMT) == S_IFDIR) return (TRUE);
-
- /*
- * Something prevents us from create a directory with
- * the same pathname
- */
- return (FALSE);
- }
-
- /* No - this maybe the first time. Try to create a directory */
- else
- {
- /* Create the ~/.ToME directory */
- ret = mkdir(dirpath, 0700);
-
- /* An error occured */
- if (ret == -1) return (FALSE);
-
- /* Success */
- return (TRUE);
- }
-}
-
-/*
- * Check existence of ".ToME/" directory in the user's
- * home directory or try to create it if it doesn't exist.
- * Returns FALSE if all the attempts fail.
- */
-static bool_ check_create_user_dir(void)
-{
- char dirpath[1024];
- char versionpath[1024];
- char savepath[1024];
-#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);
- strcpy(versionpath, dirpath);
- strcat(versionpath, USER_PATH_VERSION);
- strcpy(savepath, versionpath);
- strcat(savepath, "/save");
-#ifdef PRIVATE_USER_PATH_DATA
- 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);
-}
-
-
-/*
- * Variant-dependent features:
- *
- * #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 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.
- *
- * For [Z], you also have to say -- #define inkey_flag (p_ptr->inkey_flag)
- * but before that, please, please consider using main-mac-carbon.c in [Z],
- * 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'
-
-/* Default creator signature */
-#ifndef ANGBAND_CREATOR
-# define ANGBAND_CREATOR 'A271'
-#endif
-
-
-/*
- * Use rewritten asynchronous sound player
- */
-#define USE_ASYNC_SOUND
-
-
-/*
- * A rather crude fix to reduce amount of redraw artefacts.
- * Some fixed width fonts (i.e. Monaco) has characters with negative
- * left bearings, so Term_wipe_mac or overwriting cannot completely
- * erase them. This could be introduced to Classic Mac OS ports too,
- * but since I've never heard any complaints and I don't like to
- * make 68K ports even slower, I won't do so there.
- */
-#define CLIP_HACK /* */
-
-/*
- * To cope with pref file related problems. It no longer has to be acculate,
- * because preferences are stored in plist.
- */
-#define PREF_VER_MAJOR VERSION_MAJOR
-#define PREF_VER_MINOR VERSION_MINOR
-#define PREF_VER_PATCH VERSION_PATCH
-#define PREF_VER_EXTRA VERSION_EXTRA
-
-
-/*
- * In OS X + gcc, use <Carbon/Carbon.h>, <CoreServices/CoreServices.h> and
- * <CoreFoundation/CoreFoundation.h> for ALL of these, including the Apple
- * Event ones. <QuickTime/QuickTime.h> is used by the tile loading code.
- */
-#ifdef MACH_O_CARBON
-
-#include <Carbon/Carbon.h>
-#include <QuickTime/QuickTime.h>
-#include <CoreServices/CoreServices.h>
-#include <CoreFoundation/CoreFoundation.h>
-
-#else /* MACH_O_CARBON */
-
-#include <Types.h>
-#include <Gestalt.h>
-#include <QuickDraw.h>
-#include <Files.h>
-#include <Fonts.h>
-#include <Menus.h>
-#include <Dialogs.h>
-#include <Windows.h>
-#include <Palettes.h>
-#include <ToolUtils.h>
-#include <Events.h>
-#include <SegLoad.h>
-#include <Resources.h>
-#include <Controls.h>
-#include <Memory.h>
-#include <QDOffscreen.h>
-#include <Sound.h>
-#include <Navigation.h>
-#include <CFPreferences.h>
-#include <CFNumber.h>
-#include <AppleEvents.h>
-#include <EPPC.h>
-#include <Folders.h>
-
-#endif /* MACH_O_CARBON */
-
-/* MacOSX == Unix == Good */
-#ifdef USE_MACOSX
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <dirent.h>
-#endif
-
-
-/*
- * Use "malloc()" instead of "NewPtr()"
- */
-/* #define USE_MALLOC */
-
-
-/*
- * Information about each of the 256 available colors
- */
-static RGBColor color_info[256];
-
-
-#ifdef MACH_O_CARBON
-
-/*
- * Creator signature and file type - Didn't I say that I abhor file name
- * extentions? Names and metadata are entirely different set of notions.
- */
-OSType _fcreator;
-OSType _ftype;
-
-#endif /* MACH_O_CARBON */
-
-
-/*
- * Forward declare
- */
-typedef struct term_data term_data;
-
-/*
- * Extra "term" data
- */
-struct term_data
-{
- term *t;
-
- Rect r;
-
- WindowPtr w;
-
-
- short padding;
-
- short pixelDepth;
-
- GWorldPtr theGWorld; /* not used ... */
-
- GDHandle theGDH;
-
- GDHandle mainSWGDH; /* not used ... */
-
- Str15 title;
-
- s16b oops;
-
- s16b keys;
-
- s16b last;
-
- s16b mapped;
-
- s16b rows;
- s16b cols;
-
- s16b font_id;
- s16b font_size;
- s16b font_face;
- s16b font_mono;
-
- s16b font_o_x;
- s16b font_o_y;
- s16b font_wid;
- s16b font_hgt;
-
- s16b tile_o_x;
- s16b tile_o_y;
- s16b tile_wid;
- s16b tile_hgt;
-
- s16b size_wid;
- s16b size_hgt;
-
- s16b size_ow1;
- s16b size_oh1;
- s16b size_ow2;
- s16b size_oh2;
-};
-
-
-
-
-/*
- * Forward declare -- see below
- */
-static bool_ CheckEvents(bool_ wait);
-
-
-#ifndef MACH_O_CARBON
-
-/*
- * Hack -- location of the main directory
- */
-static short app_vol;
-static long app_dir;
-
-#endif /* !MACH_O_CARBON */
-
-
-/*
- * Delay handling of double-clicked savefiles
- */
-Boolean open_when_ready = FALSE;
-
-/*
- * Delay handling of pre-emptive "quit" event
- */
-Boolean quit_when_ready = FALSE;
-
-
-/*
- * Aqua automatically supplies the Quit menu.
- */
-static Boolean is_aqua = FALSE;
-
-/*
- * Version of Mac OS - for version specific bug workarounds (; ;)
- */
-static long mac_os_version;
-
-
-/*
- * Hack -- game in progress
- */
-static int game_in_progress = 0;
-
-
-/*
- * Only do "SetPort()" when needed
- */
-static WindowPtr active = NULL;
-
-
-/*
- * Maximum number of terms
- */
-#define MAX_TERM_DATA 8
-
-
-/*
- * An array of term_data's
- */
-static term_data data[MAX_TERM_DATA];
-
-
-/*
- * Note when "open"/"new" become valid
- */
-static bool_ initialized = FALSE;
-
-
-
-/*
- * Convert a C string to a pascal string in place
- *
- * This function may be defined elsewhere, but since it is so
- * small, it is not worth finding the proper function name for
- * all the different platforms.
- */
-static void ctopstr(StringPtr src)
-{
- int i;
- byte len;
-
- /* Hack -- pointer */
- char *s = (char*)(src);
-
- len = strlen(s);
-
- /* Hack -- convert the string */
- for (i = len; i > 1; i--) s[i] = s[i - 1];
-
- /* Hack -- terminate the string */
- s[0] = len;
-}
-
-
-#ifdef MACH_O_CARBON
-
-/* Carbon File Manager utilities by pelpel */
-
-/*
- * (Carbon)
- * Convert a pathname to a corresponding FSSpec.
- * Returns noErr on success.
- */
-static OSErr path_to_spec(const char *path, FSSpec *spec)
-{
- OSErr err;
- FSRef ref;
-
- /* Convert pathname to FSRef ... */
- err = FSPathMakeRef(path, &ref, NULL);
- if (err != noErr) return (err);
-
- /* ... then FSRef to FSSpec */
- err = FSGetCatalogInfo(&ref, kFSCatInfoNone, NULL, NULL, spec, NULL);
-
- /* Inform caller of success or failure */
- return (err);
-}
-
-
-/*
- * (Carbon)
- * Convert a FSSpec to a corresponding pathname.
- * Returns noErr on success.
- */
-static OSErr spec_to_path(const FSSpec *spec, char *buf, size_t size)
-{
- OSErr err;
- FSRef ref;
-
- /* Convert FSSpec to FSRef ... */
- err = FSpMakeFSRef(spec, &ref);
- if (err != noErr) return (err);
-
- /* ... then FSRef to pathname */
- err = FSRefMakePath(&ref, buf, size);
-
- /* Inform caller of success or failure */
- return (err);
-}
-
-
-/*
- * (Carbon) [via path_to_spec]
- * Set creator and filetype of a file specified by POSIX-style pathname.
- * Returns 0 on success, -1 in case of errors.
- */
-int fsetfileinfo(char *pathname, OSType fcreator, OSType ftype)
-{
- OSErr err;
- FSSpec spec;
- FInfo info;
-
- /* Convert pathname to FSSpec */
- if (path_to_spec(pathname, &spec) != noErr) return ( -1);
-
- /* Obtain current finder info of the file */
- if (FSpGetFInfo(&spec, &info) != noErr) return ( -1);
-
- /* Overwrite creator and type */
- info.fdCreator = fcreator;
- info.fdType = ftype;
- err = FSpSetFInfo(&spec, &info);
-
- /* Inform caller of success or failure */
- return ((err == noErr) ? 0 : -1);
-}
-
-
-#else /* MACH_O_CARBON */
-
-/*
-* Convert refnum+vrefnum+fname into a full file name
-* Store this filename in 'buf' (make sure it is long enough)
-* Note that 'fname' looks to be a "pascal" string
-*/
-static void refnum_to_name(char *buf, long refnum, short vrefnum, char *fname)
-{
- DirInfo pb;
- Str255 name;
- int err;
- int i, j;
-
- char res[1000];
-
- i = 999;
-
- res[i] = 0;
- i--;
- for (j = 1; j <= fname[0]; j++)
- {
- res[i - fname[0] + j] = fname[j];
- }
- i -= fname[0];
-
- pb.ioCompletion = NULL;
- pb.ioNamePtr = name;
- pb.ioVRefNum = vrefnum;
- pb.ioDrParID = refnum;
- pb.ioFDirIndex = -1;
-
- while (1)
- {
- pb.ioDrDirID = pb.ioDrParID;
- err = PBGetCatInfoSync((CInfoPBPtr) & pb);
- res[i] = ':';
- i--;
- for (j = 1; j <= name[0]; j++)
- {
- res[i - name[0] + j] = name[j];
- }
- i -= name[0];
-
- if (pb.ioDrDirID == fsRtDirID) break;
- }
-
- /* Extract the result */
- for (j = 0, i++; res[i]; j++, i++) buf[j] = res[i];
- buf[j] = 0;
-}
-
-
-/*
-* Convert a pascal string in place
-*
-* This function may be defined elsewhere, but since it is so
-* small, it is not worth finding the proper function name for
-* all the different platforms.
-*/
-static void ptocstr(StringPtr src)
-{
- int i;
-
- /* Hack -- pointer */
- char *s = (char*)(src);
-
- /* Hack -- convert the string */
- for (i = s[0]; i; i--, s++) s[0] = s[1];
-
- /* Hack -- terminate the string */
- s[0] = '\0';
-}
-
-
-/*
-* Utility routines by Steve Linberg
-*
-* The following three routines (pstrcat, pstrinsert, and PathNameFromDirID)
-* were taken from the Think Reference section called "Getting a Full Pathname"
-* (under the File Manager section). We need PathNameFromDirID to get the
-* full pathname of the opened savefile, making no assumptions about where it
-* is.
-*
-* I had to hack PathNameFromDirID a little for MetroWerks, but it's awfully
-* nice.
-*/
-static void pstrcat(StringPtr dst, StringPtr src)
-{
- /* copy string in */
- BlockMove(src + 1, dst + *dst + 1, *src);
-
- /* adjust length byte */
- *dst += *src;
-}
-
-
-/*
-* pstrinsert - insert string 'src' at beginning of string 'dst'
-*/
-static void pstrinsert(StringPtr dst, StringPtr src)
-{
- /* make room for new string */
- BlockMove(dst + 1, dst + *src + 1, *dst);
-
- /* copy new string in */
- BlockMove(src + 1, dst + 1, *src);
-
- /* adjust length byte */
- *dst += *src;
-}
-
-
-static void PathNameFromDirID(long dirID, short vRefNum, StringPtr fullPathName)
-{
- CInfoPBRec block;
- Str255 directoryName;
- OSErr err;
-
- fullPathName[0] = '\0';
-
- block.dirInfo.ioDrParID = dirID;
- block.dirInfo.ioNamePtr = directoryName;
-
- while (1)
- {
- block.dirInfo.ioVRefNum = vRefNum;
- block.dirInfo.ioFDirIndex = -1;
- block.dirInfo.ioDrDirID = block.dirInfo.ioDrParID;
- err = PBGetCatInfoSync(&block);
- pstrcat(directoryName, (StringPtr)"\p:");
- pstrinsert(fullPathName, directoryName);
- if (block.dirInfo.ioDrDirID == 2) break;
- }
-}
-
-#endif /* MACH_O_CARBON */
-
-
-
-
-/*
- * Center a rectangle inside another rectangle
- *
- * Consider using RepositionWindow() whenever possible
- */
-static void center_rect(Rect *r, Rect *s)
-{
- int centerx = (s->left + s->right) / 2;
- int centery = (2 * s->top + s->bottom) / 3;
- int dx = centerx - (r->right - r->left) / 2 - r->left;
- int dy = centery - (r->bottom - r->top) / 2 - r->top;
- r->left += dx;
- r->right += dx;
- r->top += dy;
- r->bottom += dy;
-}
-
-
-/*
- * Activate a given window, if necessary
- */
-static void activate(WindowPtr w)
-{
- /* Activate */
- if (active != w)
- {
- /* Activate */
- if (w) SetPort(GetWindowPort(w));
-
- /* Remember */
- active = w;
- }
-}
-
-
-/*
- * Display a warning message
- */
-static void mac_warning(cptr warning)
-{
- Str255 text;
- int len, i;
-
- /* Limit of 250 chars */
- len = strlen(warning);
- if (len > 250) len = 250;
-
- /* Make a "Pascal" string */
- text[0] = len;
- for (i = 0; i < len; i++) text[i + 1] = warning[i];
-
- /* Prepare the dialog box values */
- ParamText(text, "\p", "\p", "\p");
-
- /* Display the Alert, wait for Okay */
- Alert(129, 0L);
-}
-
-
-
-/*** Some generic functions ***/
-
-/*
- * Hack -- activate a color (0 to 255)
- */
-static void term_data_color(term_data *td, int a)
-{
- /* Activate the color */
- if (td->last != a)
- {
- /* Activate the color */
- RGBForeColor(&color_info[a]);
-
- /* Memorize color */
- td->last = a;
- }
-}
-
-
-/*
- * Hack -- Apply and Verify the "font" info
- *
- * This should usually be followed by "term_data_check_size()"
- *
- * XXX XXX To force (re)initialisation of td->tile_wid and td->tile_hgt
- * you have to reset them to zero before this function is called.
- * XXX XXX This is automatic when the program starts because the term_data
- * array is WIPE'd by term_data_hack, but isn't in the other cases, i.e.
- * font, font style and size changes.
- */
-static void term_data_check_font(term_data *td)
-{
- int i;
-
- FontInfo info;
-
- WindowPtr old = active;
-
-
- /* Activate */
- activate(td->w);
-
- /* Instantiate font */
- TextFont(td->font_id);
- TextSize(td->font_size);
- TextFace(td->font_face);
-
- /* Extract the font info */
- GetFontInfo(&info);
-
- /* Assume monospaced */
- td->font_mono = TRUE;
-
- /* Extract the font sizing values XXX XXX XXX */
- td->font_wid = CharWidth('@'); /* info.widMax; */
- td->font_hgt = info.ascent + info.descent;
- td->font_o_x = 0;
- td->font_o_y = info.ascent;
-
- /* Check important characters */
- for (i = 33; i < 127; i++)
- {
- /* Hack -- notice non-mono-space */
- if (td->font_wid != CharWidth(i)) td->font_mono = FALSE;
-
- /* Hack -- collect largest width */
- if (td->font_wid < CharWidth(i)) td->font_wid = CharWidth(i);
- }
-
- /* Set default offsets */
- td->tile_o_x = td->font_o_x;
- td->tile_o_y = td->font_o_y;
-
- /* Set default tile size */
- if (td->tile_wid == 0) td->tile_wid = td->font_wid;
- if (td->tile_hgt == 0) td->tile_hgt = td->font_hgt;
-
- /* Re-activate the old window */
- activate(old);
-}
-
-
-/*
- * Hack -- Apply and Verify the "size" info
- */
-static void term_data_check_size(term_data *td)
-{
- if (td == &data[0])
- {
-#ifndef ALLOW_BIG_SCREEN
-
- /* Forbid resizing of the Angband window */
- td->cols = 80;
- td->rows = 24;
-
-#else
-
- /* Enforce minimal size */
- if (td->cols < 80) td->cols = 80;
- if (td->rows < 24) td->rows = 24;
-
-#endif /* !ALLOW_BIG_SCREEN */
- }
-
- /* Information windows can be much smaller */
- else
- {
- if (td->cols < 1) td->cols = 1;
- if (td->rows < 1) td->rows = 1;
- }
-
- /* Enforce maximal sizes */
- if (td->cols > 255) td->cols = 255;
- if (td->rows > 255) td->rows = 255;
-
- /* Minimal tile size */
- if (td->tile_wid < td->font_wid) td->tile_wid = td->font_wid;
- if (td->tile_hgt < td->font_hgt) td->tile_hgt = td->font_hgt;
-
- /* Default tile offsets */
- td->tile_o_x = (td->tile_wid - td->font_wid) / 2;
- td->tile_o_y = (td->tile_hgt - td->font_hgt) / 2;
-
- /* Minimal tile offsets */
- if (td->tile_o_x < 0) td->tile_o_x = 0;
- if (td->tile_o_y < 0) td->tile_o_y = 0;
-
- /* Apply font offsets */
- td->tile_o_x += td->font_o_x;
- td->tile_o_y += td->font_o_y;
-
- /* Calculate full window size */
- td->size_wid = td->cols * td->tile_wid + td->size_ow1 + td->size_ow2;
- td->size_hgt = td->rows * td->tile_hgt + td->size_oh1 + td->size_oh2;
-
- {
- BitMap tScreen;
-
- /* Get current screen */
- (void)GetQDGlobalsScreenBits(&tScreen);
-
- /* Verify the top */
- if (td->r.top > tScreen.bounds.bottom - td->size_hgt)
- {
- td->r.top = tScreen.bounds.bottom - td->size_hgt;
- }
-
- /* Verify the top */
- if (td->r.top < tScreen.bounds.top + GetMBarHeight())
- {
- td->r.top = tScreen.bounds.top + GetMBarHeight();
- }
-
- /* Verify the left */
- if (td->r.left > tScreen.bounds.right - td->size_wid)
- {
- td->r.left = tScreen.bounds.right - td->size_wid;
- }
-
- /* Verify the left */
- if (td->r.left < tScreen.bounds.left)
- {
- td->r.left = tScreen.bounds.left;
- }
- }
-
- /* Calculate bottom right corner */
- td->r.right = td->r.left + td->size_wid;
- td->r.bottom = td->r.top + td->size_hgt;
-
- /* Assume no graphics */
- td->t->higher_pict = FALSE;
- td->t->always_pict = FALSE;
-
-
- /* Handle graphics */
- if (use_graphics)
- {
- /* Use higher pict whenever possible */
- if (td->font_mono) td->t->higher_pict = TRUE;
-
- /* Use always_pict only when necessary */
- else td->t->always_pict = TRUE;
- }
-
- /* Fake mono-space */
- if (!td->font_mono ||
- (td->font_wid != td->tile_wid) ||
- (td->font_hgt != td->tile_hgt))
- {
- /*
- * Handle fake monospace
- *
- * pelpel: This is SLOW. Couldn't we use CharExtra
- * and SpaceExtra for monospaced fonts?
- */
- if (td->t->higher_pict) td->t->higher_pict = FALSE;
- td->t->always_pict = TRUE;
- }
-}
-
-
-/*
- * Hack -- resize a term_data
- *
- * This should normally be followed by "term_data_redraw()"
- */
-static void term_data_resize(term_data *td)
-{
- /*
- * Actually resize the window
- *
- * ResizeWindow is the preferred API call, but it cannot
- * be used here.
- */
- SizeWindow(td->w, td->size_wid, td->size_hgt, 0);
-}
-
-
-
-/*
- * Hack -- redraw a term_data
- *
- * Note that "Term_redraw()" calls "TERM_XTRA_CLEAR"
- */
-static void term_data_redraw(term_data *td)
-{
- term *old = Term;
- Rect tRect;
-
- /* Activate the term */
- Term_activate(td->t);
-
- /* Redraw the contents */
- Term_redraw();
-
- /* Flush the output */
- Term_fresh();
-
- /* Restore the old term */
- Term_activate(old);
-
- /* No need to redraw */
- ValidWindowRect(td->w, GetPortBounds(GetWindowPort(td->w), &tRect));
-}
-
-
-/*
- * Graphics support
- */
-
-/* Set by Term_xtra_mac_react */
-#ifdef MACH_O_CARBON
-static CFStringRef pict_id; /* PICT id of image tiles */
-#else
-static int pict_id; /* PICT id of image tiles */
-#endif /* MACH_O_CARBON */
-
-static int graf_width; /* Width of a tile in pixels */
-static int graf_height; /* Height of a tile in pixels */
-
-/* Calculated by PICT loading code */
-static int pict_cols; /* Number of columns in tiles */
-static int pict_rows; /* Number of rows in tiles */
-
-/* Available graphics modes */
-#define GRAF_MODE_NONE 0 /* plain ASCII */
-#define GRAF_MODE_8X8 1 /* 8x8 tiles */
-#define GRAF_MODE_16X16 2 /* 16x16 tiles */
-#define GRAF_MODE_32X32 3 /* 32x32 tiles */
-
-static int graf_mode = GRAF_MODE_NONE; /* current graphics mode */
-static int graf_mode_req = GRAF_MODE_NONE; /* requested graphics mode */
-
-#define TR_NONE 0 /* No transparency */
-#define TR_OVER 1 /* Overwriting with transparent black pixels */
-static int transparency_mode = TR_NONE; /* types of transparency effect */
-
-
-/*
- * Forward Declare
- */
-typedef struct FrameRec FrameRec;
-
-/*
- * Frame
- *
- * - GWorld for the frame image
- * - Handle to pix map (saved for unlocking/locking)
- * - Pointer to color pix map (valid only while locked)
- */
-struct FrameRec
-{
- GWorldPtr framePort;
- PixMapHandle framePixHndl;
- PixMapPtr framePix;
-};
-
-
-/*
- * The global picture data
- */
-static FrameRec *frameP = NULL;
-
-
-/*
- * Lock a frame
- */
-static void BenSWLockFrame(FrameRec *srcFrameP)
-{
- PixMapHandle pixMapH;
-
- pixMapH = GetGWorldPixMap(srcFrameP->framePort);
- (void)LockPixels(pixMapH);
- HLockHi((Handle)pixMapH);
- srcFrameP->framePixHndl = pixMapH;
- srcFrameP->framePix = (PixMapPtr)(*(Handle)pixMapH);
-}
-
-
-/*
- * Unlock a frame
- */
-static void BenSWUnlockFrame(FrameRec *srcFrameP)
-{
- if (srcFrameP->framePort != NULL)
- {
- HUnlock((Handle)srcFrameP->framePixHndl);
- UnlockPixels(srcFrameP->framePixHndl);
- }
-
- srcFrameP->framePix = NULL;
-}
-
-
-
-#ifdef MACH_O_CARBON
-
-/* Moving graphics resources into data fork -- pelpel */
-
-/*
- * (Carbon, Bundle)
- * Given base and type names of a resource, find a file in the
- * current application bundle and return its FSSpec in the third argument.
- * Returns true on success, false otherwise.
- * e.g. get_resource_spec(CFSTR("8x8"), CFSTR("png"), &spec);
- */
-static Boolean get_resource_spec(
- CFStringRef base_name, CFStringRef type_name, FSSpec *spec)
-{
- CFURLRef res_url;
- FSRef ref;
-
- /* Find the tile resource specified in the current bundle */
- res_url = CFBundleCopyResourceURL(
- CFBundleGetMainBundle(), base_name, type_name, NULL);
-
- /* Oops */
- if (res_url == NULL) return (false);
-
- /* Convert CFURL to FSRef */
- (void)CFURLGetFSRef(res_url, &ref);
-
- /* Convert FSRef to FSSpec */
- (void)FSGetCatalogInfo(&ref, kFSCatInfoNone, NULL, NULL, spec, NULL);
-
- /* Free allocated CF data */
- CFRelease(res_url);
-
- /* Success */
- return (true);
-}
-
-
-/*
- * (QuickTime)
- * Create a off-screen GWorld from contents of a file specified by a FSSpec.
- *
- * Globals referenced: data[0], graf_height, graf_width
- * Globals updated: pict_rows, pict_cols.
- */
-static OSErr create_gworld_from_spec(
- GWorldPtr *tile_gw, FSSpec *tile_spec)
-{
- OSErr err;
- GraphicsImportComponent gi;
- GWorldPtr gw, tmp_gw;
- GDHandle gdh, tmp_gdh;
- Rect r;
- SInt16 depth;
-
- /* See if QuickTime understands the file format */
- err = GetGraphicsImporterForFile(tile_spec, &gi);
-
- /* Oops */
- if (err != noErr) return (err);
-
- /* Get depth */
- depth = data[0].pixelDepth;
-
- /* Get GDH */
- gdh = data[0].theGDH;
-
- /* Retrieve the rect of the image */
- err = GraphicsImportGetNaturalBounds(gi, &r);
-
- /* Adjust it, so that the upper left corner becomes (0, 0) */
- OffsetRect(&r, -r.left, -r.top);
-
- /* Calculate and set numbers of rows and columns */
- pict_rows = r.bottom / graf_height;
- pict_cols = r.right / graf_width;
-
- /* Create a GWorld */
- err = NewGWorld(&gw, depth, &r, NULL, gdh, noNewDevice);
-
- /* Oops */
- if (err != noErr) return (err);
-
- /* Save the pointer to the GWorld */
- *tile_gw = gw;
-
- /* Save the current GWorld */
- GetGWorld(&tmp_gw, &tmp_gdh);
-
- /* Activate the newly created GWorld */
- (void)GraphicsImportSetGWorld(gi, gw, NULL);
-
- /* Prevent pixmap from moving while drawing */
- (void)LockPixels(GetGWorldPixMap(gw));
-
- /* Clear the pixels */
- EraseRect(&r);
-
- /* Draw the image into it */
- (void)GraphicsImportDraw(gi);
-
- /* Release the lock*/
- UnlockPixels(GetGWorldPixMap(gw));
-
- /* Restore GWorld */
- SetGWorld(tmp_gw, tmp_gdh);
-
- /* Close the image importer */
- CloseComponent(gi);
-
- /* Success */
- return (noErr);
-}
-
-#else /* MACH_O_CARBON */
-
-static OSErr BenSWCreateGWorldFromPict(
- GWorldPtr *pictGWorld, PicHandle pictH)
-{
- OSErr err;
- GWorldPtr saveGWorld;
- GDHandle saveGDevice;
- GWorldPtr tempGWorld;
- Rect pictRect;
- short depth;
- GDHandle theGDH;
-
- tempGWorld = NULL;
-
- /* Reset */
- *pictGWorld = NULL;
-
- /* Get depth */
- depth = data[0].pixelDepth;
-
- /* Get GDH */
- theGDH = data[0].theGDH;
-
- /* Obtain size rectangle */
- pictRect = (**pictH).picFrame;
- OffsetRect(&pictRect, -pictRect.left, -pictRect.top);
-
- /* Calculate and set numbers of rows and columns */
- pict_rows = pictRect.bottom / graf_height;
- pict_cols = pictRect.right / graf_width;
-
- /* Create a GWorld */
- err = NewGWorld(&tempGWorld, depth, &pictRect, nil, theGDH, noNewDevice);
-
- /* Oops */
- if (err != noErr) return (err);
-
- /* Save pointer */
- *pictGWorld = tempGWorld;
-
- /* Save GWorld */
- GetGWorld(&saveGWorld, &saveGDevice);
-
- /* Activate */
- SetGWorld(tempGWorld, nil);
-
- /* Dump the pict into the GWorld */
- (void)LockPixels(GetGWorldPixMap(tempGWorld));
- EraseRect(&pictRect);
- DrawPicture(pictH, &pictRect);
- UnlockPixels(GetGWorldPixMap(tempGWorld));
-
- /* Restore GWorld */
- SetGWorld(saveGWorld, saveGDevice);
-
- /* Success */
- return (0);
-}
-
-#endif /* MACH_O_CARBON */
-
-
-/*
- * Init the global "frameP"
- */
-static errr globe_init(void)
-{
- OSErr err;
-
- GWorldPtr tempPictGWorldP;
-
-#ifdef MACH_O_CARBON
- FSSpec pict_spec;
-#else
- PicHandle newPictH;
-#endif /* MACH_O_CARBON */
-
-
- /* Use window XXX XXX XXX */
- SetPort(GetWindowPort(data[0].w));
-
-
-#ifdef MACH_O_CARBON
-
- /* Get the tile resources */
- if (!get_resource_spec(pict_id, CFSTR("png"), &pict_spec)) return ( -1);
-
- /* Create GWorld */
- err = create_gworld_from_spec(&tempPictGWorldP, &pict_spec);
-
-#else /* MACH_O_CARBON */
-
- /* Get the pict resource */
- if ((newPictH = GetPicture(pict_id)) == 0) return ( -1);
-
- /* Create GWorld */
- err = BenSWCreateGWorldFromPict(&tempPictGWorldP, newPictH);
-
- /* Release resource */
- ReleaseResource((Handle)newPictH);
-
-#endif /* MACH_O_CARBON */
-
- /* Error */
- if (err != noErr) return (err);
-
- /* Create the frame */
- frameP = (FrameRec*)NewPtrClear((Size)sizeof(FrameRec));
-
- /* Analyze result */
- if (frameP == NULL) return ( -1);
-
- /* Save GWorld */
- frameP->framePort = tempPictGWorldP;
-
- /* Lock it */
- BenSWLockFrame(frameP);
-
- /* Success */
- return (noErr);
-}
-
-
-/*
- * Nuke the global "frameP"
- */
-static errr globe_nuke(void)
-{
- /* Dispose */
- if (frameP)
- {
- /* Unlock */
- BenSWUnlockFrame(frameP);
-
- /* Dispose of the GWorld */
- DisposeGWorld(frameP->framePort);
-
- /* Dispose of the memory */
- DisposePtr((Ptr)frameP);
-
- /* Forget */
- frameP = NULL;
- }
-
- /* Flush events */
- FlushEvents(everyEvent, 0);
-
- /* Success */
- return (0);
-}
-
-
-#ifdef USE_ASYNC_SOUND
-
-/*
- * Asynchronous sound player - completely revised (beta)
- */
-#if defined(USE_QT_SOUND) && !defined(MACH_O_CARBON)
-# undef USE_QT_SOUND
-#endif /* USE_QT_SOUND && !MACH_O_CARBON */
-
-/*
- * How many sound channels will be pooled
- *
- * Was: 20, but I don't think we need 20 sound effects playing
- * simultaneously :) -- pelpel
- */
-#define MAX_CHANNELS 8
-
-/*
- * A pool of sound channels
- */
-static SndChannelPtr channels[MAX_CHANNELS];
-
-/*
- * Status of the channel pool
- */
-static Boolean channel_initialised = FALSE;
-
-/*
- * Data handles containing sound samples
- */
-static SndListHandle samples[SOUND_MAX];
-
-/*
- * Reference counts of sound samples
- */
-static SInt16 sample_refs[SOUND_MAX];
-
-#define SOUND_VOLUME_MIN 0 /* Default minimum sound volume */
-#define SOUND_VOLUME_MAX 255 /* Default maximum sound volume */
-#define VOLUME_MIN 0 /* Minimum sound volume in % */
-#define VOLUME_MAX 100 /* Maximum sound volume in % */
-#define VOLUME_INC 5 /* Increment sound volume in % */
-
-/*
- * I'm just too lazy to write a panel for this XXX XXX
- */
-static int sound_volume = SOUND_VOLUME_MAX;
-
-
-#ifdef USE_QT_SOUND
-
-/*
- * QuickTime sound, by Ron Anderson
- *
- * I didn't choose to use Windows-style .ini files (Ron wrote a parser
- * for it, but...), nor did I use lib/xtra directory, hoping someone
- * would code plist-based configuration code in the future -- pelpel
- */
-
-/*
- * (QuickTime)
- * Load sound effects from data-fork resources. They are wav files
- * with the same names as angband_sound_name[] (variable.c)
- *
- * Globals referenced: angband_sound_name[]
- * Globals updated: samples[] (they can be *huge*)
- */
-static void load_sounds(void)
-{
- OSErr err;
- int i;
-
- /* Start QuickTime */
- err = EnterMovies();
-
- /* Error */
- if (err != noErr) return;
-
- /*
- * This loop may take a while depending on the count and size of samples
- * to load.
- *
- * We should use a progress dialog for this.
- */
- for (i = 1; i < SOUND_MAX; i++)
- {
- /* Apple APIs always give me headacke :( */
- CFStringRef name;
- FSSpec spec;
- SInt16 file_id;
- SInt16 res_id;
- Str255 movie_name;
- Movie movie;
- Track track;
- Handle h;
- Boolean res;
-
- /* Allocate CFString with the name of sound event to be processed */
- name = CFStringCreateWithCString(NULL, angband_sound_name[i],
- kTextEncodingUS_ASCII);
-
- /* Error */
- if (name == NULL) continue;
-
- /* Find sound sample resource with the same name */
- res = get_resource_spec(name, CFSTR("wav"), &spec);
-
- /* Free the reference to CFString */
- CFRelease(name);
-
- /* Error */
- if (!res) continue;
-
- /* Open the sound file */
- err = OpenMovieFile(&spec, &file_id, fsRdPerm);
-
- /* Error */
- if (err != noErr) continue;
-
- /* Create Movie from the file */
- err = NewMovieFromFile(&movie, file_id, &res_id, movie_name,
- newMovieActive, NULL);
-
- /* Error */
- if (err != noErr) goto close_file;
-
- /* Get the first track of the movie */
- track = GetMovieIndTrackType(movie, 1, AudioMediaCharacteristic,
- movieTrackCharacteristic | movieTrackEnabledOnly );
-
- /* Error */
- if (track == NULL) goto close_movie;
-
- /* Allocate a handle to store sample */
- h = NewHandle(0);
-
- /* Error */
- if (h == NULL) goto close_track;
-
- /* Dump the sample into the handle */
- err = PutMovieIntoTypedHandle(movie, track, soundListRsrc, h, 0,
- GetTrackDuration(track), 0L, NULL);
-
- /* Success */
- if (err == noErr)
- {
- /* Store the handle in the sample list */
- samples[i] = (SndListHandle)h;
- }
-
- /* Failure */
- else
- {
- /* Free unused handle */
- DisposeHandle(h);
- }
-
- /* Free the track */
-close_track:
- DisposeMovieTrack(track);
-
- /* Free the movie */
-close_movie:
- DisposeMovie(movie);
-
- /* Close the movie file */
-close_file:
- CloseMovieFile(file_id);
- }
-
- /* Stop QuickTime */
- ExitMovies();
-}
-
-#else /* USE_QT_SOUND */
-
-/*
-* Return a handle of 'snd ' resource given Angband sound event number,
-* or NULL if it isn't found.
-*
-* Globals referenced: angband_sound_name[] (variable.c)
-*/
-static SndListHandle find_sound(int num)
-{
-Str255 sound;
-
-/* Get the proper sound name */
-strnfmt((char*)sound + 1, 255, "%.16s.wav", angband_sound_name[num]);
-sound[0] = strlen((char*)sound + 1);
-
-/* Obtain resource XXX XXX XXX */
-return ((SndListHandle)GetNamedResource('snd ', sound));
-}
-
-#endif /* USE_QT_SOUND */
-
-
-/*
- * Clean up sound support - to be called when the game exits.
- *
- * Globals referenced: channels[], samples[], sample_refs[].
- */
-static void cleanup_sound(void)
-{
- int i;
-
- /* No need to clean it up */
- if (!channel_initialised) return;
-
- /* Dispose channels */
- for (i = 0; i < MAX_CHANNELS; i++)
- {
- /* Drain sound commands and free the channel */
- SndDisposeChannel(channels[i], TRUE);
- }
-
- /* Free sound data */
- for (i = 1; i < SOUND_MAX; i++)
- {
- /* Still locked */
- if ((sample_refs[i] > 0) && (samples[i] != NULL))
- {
- /* Unlock it */
- HUnlock((Handle)samples[i]);
- }
-
-#ifndef USE_QT_SOUND
-
- /* Release it */
- if (samples[i]) ReleaseResource((Handle)samples[i]);
-
-#else
-/* Free handle */
- if (samples[i]) DisposeHandle((Handle)samples[i]);
-
-#endif /* !USE_QT_SOUND */
- }
-}
-
-
-/*
- * Play sound effects asynchronously -- pelpel
- *
- * I don't believe those who first started using the previous implementations
- * imagined this is *much* more complicated as it may seem. Anyway,
- * introduced round-robin scheduling of channels and made it much more
- * paranoid about HLock/HUnlock.
- *
- * XXX XXX de-refcounting, HUnlock and ReleaseResource should be done
- * using channel's callback procedures, which set global flags, and
- * a procedure hooked into CheckEvents does housekeeping. On the other
- * hand, this lazy reclaiming strategy keeps things simple (no interrupt
- * time code) and provides a sort of cache for sound data.
- *
- * Globals referenced: channel_initialised, channels[], samples[],
- * sample_refs[].
- * Globals updated: channel_initialised, channels[], sample_refs[].
- * Only in !USE_QT_SOUND, samples[].
- */
-static void play_sound(int num, int vol)
-{
- OSErr err;
- int i;
- int prev_num;
- SndListHandle h;
- SndChannelPtr chan;
- SCStatus status;
-
- static int next_chan;
- static SInt16 channel_occupants[MAX_CHANNELS];
- static SndCommand volume_cmd, quiet_cmd;
-
-
- /* Initialise sound channels */
- if (!channel_initialised)
- {
- for (i = 0; i < MAX_CHANNELS; i++)
- {
- /* Paranoia - Clear occupant table */
- /* channel_occupants[i] = 0; */
-
- /* Create sound channel for all sounds to play from */
- err = SndNewChannel(&channels[i], sampledSynth, initMono, NULL);
-
- /* Error */
- if (err != noErr)
- {
- /* Free channels */
- while (--i >= 0)
- {
- SndDisposeChannel(channels[i], TRUE);
- }
-
- /* Notify error */
- plog("Cannot initialise sound channels!");
-
- /* Cancel request */
- use_sound = arg_sound = FALSE;
-
- /* Failure */
- return;
- }
- }
-
- /* First channel to use */
- next_chan = 0;
-
- /* Prepare volume command */
- volume_cmd.cmd = volumeCmd;
- volume_cmd.param1 = 0;
- volume_cmd.param2 = 0;
-
- /* Prepare quiet command */
- quiet_cmd.cmd = quietCmd;
- quiet_cmd.param1 = 0;
- quiet_cmd.param2 = 0;
-
- /* Initialisation complete */
- channel_initialised = TRUE;
- }
-
- /* Paranoia */
- if ((num <= 0) || (num >= SOUND_MAX)) return;
-
- /* Prepare volume command */
- volume_cmd.param2 = (SInt16)((vol << 4) | vol);
-
- /* Channel to use (round robin) */
- chan = channels[next_chan];
-
- /* See if the resource is already in use */
- if (sample_refs[num] > 0)
- {
- /* Resource in use */
- h = samples[num];
-
- /* Increase the refcount */
- sample_refs[num]++;
- }
-
- /* Sound is not currently in use */
- else
- {
- /* Get handle for the sound */
-#ifdef USE_QT_SOUND
- h = samples[num];
-#else
- h = find_sound(num);
-#endif /* USE_QT_SOUND */
-
- /* Sample not available */
- if (h == NULL) return;
-
-#ifndef USE_QT_SOUND
-
- /* Load resource */
- LoadResource((Handle)h);
-
- /* Remember it */
- samples[num] = h;
-
-#endif /* !USE_QT_SOUND */
-
- /* Lock the handle */
- HLock((Handle)h);
-
- /* Initialise refcount */
- sample_refs[num] = 1;
- }
-
- /* Poll the channel */
- err = SndChannelStatus(chan, sizeof(SCStatus), &status);
-
- /* It isn't available */
- if ((err != noErr) || status.scChannelBusy)
- {
- /* Shut it down */
- SndDoImmediate(chan, &quiet_cmd);
- }
-
- /* Previously played sound on this channel */
- prev_num = channel_occupants[next_chan];
-
- /* Process previously played sound */
- if (prev_num != 0)
- {
- /* Decrease refcount */
- sample_refs[prev_num]--;
-
- /* We can free it now */
- if (sample_refs[prev_num] <= 0)
- {
- /* Unlock */
- HUnlock((Handle)samples[prev_num]);
-
-#ifndef USE_QT_SOUND
-
- /* Release */
- ReleaseResource((Handle)samples[prev_num]);
-
- /* Forget handle */
- samples[prev_num] = NULL;
-
-#endif /* !USE_QT_SOUND */
-
- /* Paranoia */
- sample_refs[prev_num] = 0;
- }
- }
-
- /* Remember this sound as the current occupant of the channel */
- channel_occupants[next_chan] = num;
-
- /* Set up volume for channel */
- SndDoImmediate(chan, &volume_cmd);
-
- /* Play new sound asynchronously */
- SndPlay(chan, h, TRUE);
-
- /* Schedule next channel (round robin) */
- next_chan++;
- if (next_chan >= MAX_CHANNELS) next_chan = 0;
-}
-
-#endif /* USE_ASYNC_SOUND */
-
-
-
-
-/*** Support for the "z-term.c" package ***/
-
-
-/*
- * Initialize a new Term
- *
- * Note also the "window type" called "noGrowDocProc", which might be more
- * appropriate for the main "screen" window.
- *
- * Note the use of "srcCopy" mode for optimized screen writes.
- */
-static void Term_init_mac(term *t)
-{
- term_data *td = (term_data*)(t->data);
- WindowAttributes wattrs;
- OSStatus err;
-
- static RGBColor black = {0x0000, 0x0000, 0x0000};
- static RGBColor white = {0xFFFF, 0xFFFF, 0xFFFF};
-
-#ifndef ALLOW_BIG_SCREEN
-
- /* Every window has close and collapse boxes */
- wattrs = kWindowCloseBoxAttribute | kWindowCollapseBoxAttribute;
-
- /* Information windows are resizable */
- if (td != &data[0]) wattrs |= kWindowResizableAttribute;
-
-#else
-
- /* Big screen - every window has close, collapse and resize boxes */
- wattrs = kWindowCloseBoxAttribute |
- kWindowCollapseBoxAttribute |
- kWindowResizableAttribute;
-
-#endif /* !ALLOW_BIG_SCREEN */
-
- /* Make the window */
- err = CreateNewWindow(
- kDocumentWindowClass,
- wattrs,
- &td->r,
- &td->w);
-
- /*
- * XXX XXX Although the original main-mac.c doesn't perform error
- * checking, it should be done here.
- */
-
- /* Set window title */
- SetWTitle(td->w, td->title);
-
- /* Activate the window */
- activate(td->w);
-
- /* Erase behind words */
- TextMode(srcCopy);
-
- /* Apply and Verify */
- term_data_check_font(td);
- term_data_check_size(td);
-
- /* Resize the window */
- term_data_resize(td);
-
-
- /* Prepare the colors (real colors) */
- RGBBackColor(&black);
- RGBForeColor(&white);
-
- /* Block */
- {
- Rect globalRect;
- GDHandle mainGDH;
- GDHandle currentGDH;
- GWorldPtr windowGWorld;
- PixMapHandle basePixMap;
-
- /* Obtain the global rect */
- GetWindowBounds((WindowRef)td->w, kWindowContentRgn, &globalRect);
-
- /* Obtain the proper GDH */
- mainGDH = GetMaxDevice(&globalRect);
-
- /* Extract GWorld and GDH */
- GetGWorld(&windowGWorld, &currentGDH);
-
- /* Obtain base pixmap */
- basePixMap = (**mainGDH).gdPMap;
-
- /* Save pixel depth */
- td->pixelDepth = (**basePixMap).pixelSize;
-
- /* Save Window GWorld - unused */
- td->theGWorld = windowGWorld;
-
- /* Save Window GDH */
- td->theGDH = currentGDH;
-
- /* Save main GDH - unused */
- td->mainSWGDH = mainGDH;
- }
-
- {
- Rect portRect;
-
- /* Get current Rect */
- GetPortBounds(GetWindowPort(td->w), &portRect);
-
- /* Clip to the window */
- ClipRect(&portRect);
-
- /* Erase the window */
- EraseRect(&portRect);
-
- /* Invalidate the window */
- InvalWindowRect(td->w, &portRect);
- }
-
- /*
- * A certain release of OS X fails to display windows at proper
- * locations (_ _#)
- */
- if ((mac_os_version >= 0x1000) && (mac_os_version < 0x1010))
- {
- /* Hack - Make sure the window is displayed at (r.left,r.top) */
- MoveWindow(td->w, td->r.left, td->r.top, 1);
- }
-
- /* Display the window if needed */
- if (td->mapped)
- {
- TransitionWindow(td->w,
- kWindowZoomTransitionEffect, kWindowShowTransitionAction, NULL);
- }
-
- /* Hack -- set "mapped" flag */
- t->mapped_flag = td->mapped;
-
- /* Forget color */
- td->last = -1;
-}
-
-
-
-/*
- * Nuke an old Term
- */
-static void Term_nuke_mac(term *t)
-{
- /* XXX */
-}
-
-
-
-/*
- * Unused
- */
-static errr Term_user_mac(int n)
-{
- /* Success */
- return (0);
-}
-
-
-
-/*
- * React to changes
- */
-static errr Term_xtra_mac_react(void)
-{
- term_data *td = (term_data*)(Term->data);
-
- int i;
-
-
- /* Reset color */
- td->last = -1;
-
- /* Update colors */
- for (i = 0; i < 256; i++)
- {
- u16b rv, gv, bv;
-
- /* Extract the R,G,B data */
- rv = angband_color_table[i][1];
- gv = angband_color_table[i][2];
- bv = angband_color_table[i][3];
-
- /* Save the actual color */
- color_info[i].red = (rv | (rv << 8));
- color_info[i].green = (gv | (gv << 8));
- color_info[i].blue = (bv | (bv << 8));
- }
-
-
- /* Handle sound */
- if (use_sound != arg_sound)
- {
- /* Apply request */
- use_sound = arg_sound;
- }
-
-
- /* Handle graphics */
- if (graf_mode_req != graf_mode)
- {
- /* dispose old GWorld's if present */
- globe_nuke();
-
- /*
- * Setup parameters according to request
- *
- * In [Z], you have to set use_graphics and arg_graphics to
- * GRAPHICS_NONE, GRAPHICS_ORIGINAL or GRAPHICS_ADAM_BOLT, and
- * comment ANGBAND_GRAF out.
- */
- switch (graf_mode_req)
- {
- /* ASCII - no graphics whatsoever */
- case GRAF_MODE_NONE:
- {
- use_graphics = arg_graphics = FALSE;
- transparency_mode = TR_NONE;
- break;
- }
-
- /*
- * 8x8 tiles (PICT id 1001)
- * no transparency effect
- * "old" graphics definitions
- */
- case GRAF_MODE_8X8:
- {
- use_graphics = arg_graphics = TRUE;
- ANGBAND_GRAF = "old";
- transparency_mode = TR_NONE;
-#ifdef MACH_O_CARBON
- pict_id = CFSTR("8x8");
-#else
- pict_id = 1001;
-#endif /* MACH_O_CARBON */
- graf_width = graf_height = 8;
- break;
- }
-
- /*
- * 16x16 tiles (images: PICT id 1002, masks: PICT id 1003)
- * with transparency effect
- * "new" graphics definitions
- */
- case GRAF_MODE_16X16:
- {
- use_graphics = arg_graphics = TRUE;
- ANGBAND_GRAF = "new";
- transparency_mode = TR_OVER;
-#ifdef MACH_O_CARBON
- pict_id = CFSTR("16x16");
-#else
- pict_id = 1002;
-#endif /* MACH_O_CARBON */
- graf_width = graf_height = 16;
- break;
- }
-
- /*
- * 32x32 tiles (images: PICT id 1004)
- * with transparency effect
- * "david" graphics definitions
- * Vanilla-specific
- */
- case GRAF_MODE_32X32:
- {
- use_graphics = arg_graphics = TRUE;
- ANGBAND_GRAF = "david";
- transparency_mode = TR_OVER;
-#ifdef MACH_O_CARBON
- pict_id = CFSTR("32x32");
-#else
- pict_id = 1004;
-#endif /* MACH_O_CARBON */
- graf_width = graf_height = 32;
- break;
- }
- }
-
- /* load tiles and setup GWorlds if tiles are requested */
- if ((graf_mode_req != GRAF_MODE_NONE) && (globe_init() != 0))
- {
- /* Oops */
- plog("Cannot initialize graphics!");
-
- /* reject request */
- graf_mode_req = GRAF_MODE_NONE;
-
- /* reset graphics flags */
- use_graphics = arg_graphics = FALSE;
-
- /* reset transparency mode */
- transparency_mode = TR_NONE;
- }
-
- /* update current graphics mode */
- graf_mode = graf_mode_req;
-
- /* Apply and Verify */
- term_data_check_size(td);
-
- /* Resize the window */
- term_data_resize(td);
-
- /* Reset visuals */
-#ifndef ANG281_RESET_VISUALS
- reset_visuals(TRUE);
-#else
- reset_visuals();
-#endif /* !ANG281_RESET_VISUALS */
- }
-
- /* Success */
- return (0);
-}
-
-
-/*
- * Do a "special thing"
- */
-static errr Term_xtra_mac(int n, int v)
-{
- term_data *td = (term_data*)(Term->data);
-
- Rect r;
-
- /* Analyze */
- switch (n)
- {
- /* Make a noise */
- case TERM_XTRA_NOISE:
- {
- /* Make a noise */
- SysBeep(1);
-
- /* Success */
- return (0);
- }
-
- /* Make a sound */
- case TERM_XTRA_SOUND:
- {
-#ifndef USE_ASYNC_SOUND
-
- /*
- * This may not be your choice, but much safer and much less
- * resource hungry. Existing implementations can quite easily
- * crash, by starting asynchronous playing and immediately
- * unlocking and releasing the sound data just started playing...
- * -- pelpel
- */
- Handle handle;
- Str255 sound;
-
- /* Get the proper sound name */
- strnfmt((char*)sound + 1, 255, "%.16s.wav", angband_sound_name[v]);
- sound[0] = strlen((char*)sound + 1);
-
- /* Obtain resource XXX XXX XXX */
- handle = GetNamedResource('snd ', sound);
-
- /* Oops -- it is a failure, but we return 0 anyway */
- if (handle == NULL) return (0);
-
- /* Load and Lock */
- LoadResource(handle);
- HLock(handle);
-
- /* Play sound (wait for completion) */
- SndPlay(NULL, (SndListHandle)handle, FALSE);
-
- /* Unlock and release */
- HUnlock(handle);
- ReleaseResource(handle);
-
-#else /* !USE_ASYNC_SOUND */
-
- /* Play sound */
- play_sound(v, sound_volume);
-
-#endif /* !USE_ASYNC_SOUND */
-
- /* Success */
- return (0);
- }
-
- /* Process random events */
- case TERM_XTRA_BORED:
- {
- /* Process an event */
- (void)CheckEvents(FALSE);
-
- /* Success */
- return (0);
- }
-
- /* Process pending events */
- case TERM_XTRA_EVENT:
- {
- /* Process an event */
- (void)CheckEvents(v);
-
- /* Success */
- return (0);
- }
-
- /* Flush all pending events (if any) */
- case TERM_XTRA_FLUSH:
- {
- /* Hack -- flush all events */
- while (CheckEvents(FALSE)) /* loop */;
-
- /* Success */
- return (0);
- }
-
- /* Hack -- Change the "soft level" */
- case TERM_XTRA_LEVEL:
- {
- /* Activate if requested */
- if (v) activate(td->w);
-
- /* Success */
- return (0);
- }
-
- /* Clear the screen */
- case TERM_XTRA_CLEAR:
- {
- Rect portRect;
-
- /* Get current Rect */
- GetPortBounds(GetWindowPort(td->w), &portRect);
-
- /* No clipping XXX XXX XXX */
- ClipRect(&portRect);
-
- /* Erase the window */
- EraseRect(&portRect);
-
- /* Set the color */
- term_data_color(td, TERM_WHITE);
-
- /* Frame the window in white */
- MoveTo(0, 0);
- LineTo(0, td->size_hgt - 1);
- LineTo(td->size_wid - 1, td->size_hgt - 1);
- LineTo(td->size_wid - 1, 0);
-
- /* Clip to the new size */
- r.left = portRect.left + td->size_ow1;
- r.top = portRect.top + td->size_oh1;
- r.right = portRect.right - td->size_ow2;
- r.bottom = portRect.bottom - td->size_oh2;
- ClipRect(&r);
-
- /* Success */
- return (0);
- }
-
- /* React to changes */
- case TERM_XTRA_REACT:
- {
- /* React to changes */
- return (Term_xtra_mac_react());
- }
-
- /* Delay (milliseconds) */
- case TERM_XTRA_DELAY:
- {
- /*
- * WaitNextEvent relinquishes CPU as well as
- * induces a screen refresh on OS X
- */
-
- /* If needed */
- if (v > 0)
- {
- EventRecord tmp;
- UInt32 ticks;
-
- /* Convert millisecs to ticks */
- ticks = (v * 60L) / 1000;
-
- /*
- * Hack? - Put the programme into sleep.
- * No events match ~everyEvent, so nothing
- * should be lost in Angband's event queue.
- * Even if ticks are 0, it's worth calling for
- * the above mentioned reasons.
- */
- WaitNextEvent((EventMask)~everyEvent, &tmp, ticks, nil);
- }
-
- /* Success */
- return (0);
- }
-
- /* Rename main window */
- case TERM_XTRA_RENAME_MAIN_WIN:
- {
- char *s = strdup(angband_term_name[0]);
-
- ctopstr((StringPtr)s);
- SetWTitle(data[0].w, (StringPtr)s);
-
- free(s);
- return (0);
- }
-
-/* MacOSX == Unix == Good */
-#ifdef USE_MACOSX
- /* Get Delay of some milliseconds */
- case TERM_XTRA_GET_DELAY:
- {
- int ret;
- struct timeval tv;
-
- ret = gettimeofday(&tv, NULL);
- Term_xtra_long = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
-
- return ret;
- }
-
- /* Subdirectory scan */
- case TERM_XTRA_SCANSUBDIR:
- {
- DIR *directory;
- struct dirent *entry;
-
- scansubdir_max = 0;
-
- directory = opendir(scansubdir_dir);
- if (!directory)
- return 1;
-
- while ((entry = readdir(directory)))
- {
- char file[PATH_MAX + NAME_MAX + 2];
- struct stat filedata;
-
- file[PATH_MAX + NAME_MAX] = 0;
- strncpy(file, scansubdir_dir, PATH_MAX);
- strncat(file, "/", 2);
- strncat(file, entry->d_name, NAME_MAX);
- if (!stat(file, &filedata) && S_ISDIR((filedata.st_mode)))
- {
- string_free(scansubdir_result[scansubdir_max]);
- scansubdir_result[scansubdir_max] = string_make(entry->d_name);
- ++scansubdir_max;
- }
- }
-
- closedir(directory);
- return 0;
- }
-#endif
- }
-
- /* Oops */
- return (1);
-}
-
-
-
-/*
- * Low level graphics (Assumes valid input).
- * Draw a "cursor" at (x,y), using a "yellow box".
- * We are allowed to use "Term_what()" to determine
- * the current screen contents (for inverting, etc).
- */
-static errr Term_curs_mac(int x, int y)
-{
- Rect r;
-
- term_data *td = (term_data*)(Term->data);
-
- /* Set the color */
- term_data_color(td, TERM_YELLOW);
-
- /* Frame the grid */
- r.left = x * td->tile_wid + td->size_ow1;
- r.right = r.left + td->tile_wid;
- r.top = y * td->tile_hgt + td->size_oh1;
- r.bottom = r.top + td->tile_hgt;
-
-#ifdef USE_DOUBLE_TILES
-
- /* Mogami's bigtile patch */
-
- /* Adjust it if double width tiles are requested */
- if (use_bigtile &&
- (x + 1 < Term->wid) &&
- (Term->old->a[y][x + 1] == 255))
- {
- r.right += td->tile_wid;
- }
-
-#endif /* USE_DOUBLE_TILES */
-
- FrameRect(&r);
-
- /* Success */
- return (0);
-}
-
-
-/*
- * Low level graphics (Assumes valid input)
- *
- * Erase "n" characters starting at (x,y)
- */
-static errr Term_wipe_mac(int x, int y, int n)
-{
- Rect r;
-
- term_data *td = (term_data*)(Term->data);
-
-
- /* Erase the block of characters */
- r.left = x * td->tile_wid + td->size_ow1;
- r.right = r.left + n * td->tile_wid;
- r.top = y * td->tile_hgt + td->size_oh1;
- r.bottom = r.top + td->tile_hgt;
- EraseRect(&r);
-
- /* Success */
- return (0);
-}
-
-
-/*
- * Low level graphics. Assumes valid input.
- *
- * Draw several ("n") chars, with an attr, at a given location.
- */
-static errr Term_text_mac(int x, int y, int n, byte a, const char *cp)
-{
- int xp, yp;
-
-#ifdef CLIP_HACK
- Rect r;
-#endif /* CLIP_HACK */
-
- term_data *td = (term_data*)(Term->data);
-
-
- /* Set the color */
- term_data_color(td, a);
-
-#ifdef CLIP_HACK
- /* Hack - only draw within the bounding rect */
- r.left = x * td->tile_wid + td->size_ow1;
- r.right = r.left + n * td->tile_wid;
- r.top = y * td->tile_hgt + td->size_oh1;
- r.bottom = r.top + td->tile_hgt;
- ClipRect(&r);
-
- /* Hack - clear the content of the bounding rect */
- EraseRect(&r);
-#endif /* CLIP_HACK */
-
- /* Starting pixel */
- xp = x * td->tile_wid + td->tile_o_x + td->size_ow1;
- yp = y * td->tile_hgt + td->tile_o_y + td->size_oh1;
-
- /* Move to the correct location */
- MoveTo(xp, yp);
-
- /* Draw the character */
- if (n == 1) DrawChar(*cp);
-
- /* Draw the string */
- else DrawText(cp, 0, n);
-
-#ifdef CLIP_HACK
- /* Obtain current window's rect */
- GetPortBounds(GetWindowPort(td->w), &r);
-
- /* Clip to the window again */
- ClipRect(&r);
-#endif /* CLIP_HACK */
-
- /* Success */
- return (0);
-}
-
-
-/*
- * Low level graphics (Assumes valid input)
- *
- * Erase "n" characters starting at (x,y)
- */
-static errr Term_pict_mac(int x, int y, int n, const byte *ap, const char *cp,
- const byte *tap, const char *tcp,
- const byte *eap, const char *ecp)
-{
- int i;
- Rect dst_r;
- GrafPtr port;
- PixMapHandle pixmap_h;
-
-#ifdef CLIP_HACK
- Rect portRect;
-#endif /* CLIP_HACK */
-
- term_data *td = (term_data*)(Term->data);
-
- static RGBColor black = {0x0000, 0x0000, 0x0000};
- static RGBColor white = {0xFFFF, 0xFFFF, 0xFFFF};
-
-
-#ifdef CLIP_HACK
- /* Remember current window's rect */
- GetPortBounds(GetWindowPort(td->w), &portRect);
-#endif /* CLIP_HACK */
-
- /* Destination rectangle */
- dst_r.left = x * td->tile_wid + td->size_ow1;
-#ifndef USE_DOUBLE_TILES
- dst_r.right = dst_r.left + td->tile_wid;
-#endif /* !USE_DOUBLE_TILES */
- dst_r.top = y * td->tile_hgt + td->size_oh1;
- dst_r.bottom = dst_r.top + td->tile_hgt;
-
- /* Scan the input */
- for (i = 0; i < n; i++)
- {
- bool_ done = FALSE;
-
- byte a = *ap++;
- char c = *cp++;
-
- byte ta = *tap++;
- char tc = *tcp++;
- byte ea = *eap++;
- char ec = *ecp++;
- bool_ has_overlay = (ea && ec);
-
-
-#ifdef USE_DOUBLE_TILES
-
- /* Hack -- a filler for double-width tile */
- if (use_bigtile && (a == 255))
- {
- /* Advance */
- dst_r.left += td->tile_wid;
-
- /* Ignore */
- continue;
- }
-
- /* Prepare right side of rectagle now */
- dst_r.right = dst_r.left + td->tile_wid;
-
-#endif /* USE_DOUBLE_TILES */
-
- /* Graphics -- if Available and Needed */
- if (use_graphics && ((byte)a & 0x80) && ((byte)c & 0x80))
- {
- int col, row;
- Rect src_r;
- int t_col, t_row;
- Rect terrain_r;
- int e_col, e_row;
- Rect ego_r;
-
- /* Row and Col */
- row = ((byte)a & 0x7F) % pict_rows;
- col = ((byte)c & 0x7F) % pict_cols;
-
- /* Source rectangle */
- src_r.left = col * graf_width;
- src_r.top = row * graf_height;
- src_r.right = src_r.left + graf_width;
- src_r.bottom = src_r.top + graf_height;
-
- /* Row and Col */
- t_row = ((byte)ta & 0x7F) % pict_rows;
- t_col = ((byte)tc & 0x7F) % pict_cols;
-
- /* Source rectangle */
- terrain_r.left = t_col * graf_width;
- terrain_r.top = t_row * graf_height;
- terrain_r.right = terrain_r.left + graf_width;
- terrain_r.bottom = terrain_r.top + graf_height;
-
- /* If there's an overlay */
- if (has_overlay)
- {
- /* Row and Col */
- e_row = ((byte)ea & 0x7F) % pict_rows;
- e_col = ((byte)ec & 0x7F) % pict_cols;
-
- /* Source rectangle */
- ego_r.left = e_col * graf_width;
- ego_r.top = e_row * graf_height;
- ego_r.right = ego_r.left + graf_width;
- ego_r.bottom = ego_r.top + graf_height;
- }
-
- /* Hardwire CopyBits */
- RGBBackColor(&white);
- RGBForeColor(&black);
-
-#ifdef USE_DOUBLE_TILES
-
- /* Double width tiles */
- if (use_bigtile) dst_r.right += td->tile_wid;
-
-#endif /* USE_DOUBLE_TILES */
-
- /*
- * OS X requires locking and unlocking of window port
- * when we draw directly to its pixmap.
- * The Lock/Unlock protocol is described in the Carbon
- * Porting Guide.
- */
-
- /* Obtain current window's graphic port */
- port = GetWindowPort(td->w);
-
- /* Lock pixels, so we can use handle safely */
- LockPortBits(port);
-
- /* Get Pixmap handle */
- pixmap_h = GetPortPixMap(port);
-
- /* Transparency effect */
- switch (transparency_mode)
- {
- /* No transparency effects */
- case TR_NONE:
- default:
- {
- /* Draw the picture */
- CopyBits((BitMap*)frameP->framePix,
- (BitMap*)*pixmap_h,
- &src_r, &dst_r, srcCopy, NULL);
-
- break;
- }
-
- /* Overwriting with transparent black pixels */
- case TR_OVER:
- {
- /* Draw the terrain */
- CopyBits((BitMap*)frameP->framePix,
- (BitMap*)*pixmap_h,
- &terrain_r, &dst_r, srcCopy, NULL);
-
- /* Make black pixels transparent */
- RGBBackColor(&black);
-
- /* Draw mon/obj if there's one */
- if ((row != t_row) || (col != t_col))
- CopyBits((BitMap*)frameP->framePix,
- (BitMap*)*pixmap_h,
- &src_r, &dst_r, transparent, NULL);
-
- /* Draw overlay if there's one */
- if (has_overlay)
- {
- CopyBits((BitMap*)frameP->framePix,
- (BitMap*)*pixmap_h,
- &ego_r, &dst_r, transparent, NULL);
- }
-
- break;
- }
- }
-
- /* Release the lock and dispose the PixMap handle */
- UnlockPortBits(port);
-
- /* Restore colors */
- RGBBackColor(&black);
- RGBForeColor(&white);
-
- /* Forget color */
- td->last = -1;
-
- /* Done */
- done = TRUE;
- }
-
- /* Normal */
- if (!done)
- {
- int xp, yp;
-
-#ifdef CLIP_HACK
- /* Hack - avoid writing outside of dst_r */
- ClipRect(&dst_r);
- /* Some characters do not match dst_r, therefore we have to... */
-#endif /* CLIP_HACK */
-
- /* Erase */
- EraseRect(&dst_r);
-
- /* Set the color */
- term_data_color(td, a);
-
- /* Starting pixel */
- xp = dst_r.left + td->tile_o_x;
- yp = dst_r.top + td->tile_o_y;
-
- /* Move to the correct location */
- MoveTo(xp, yp);
-
- /* Draw the character */
- DrawChar(c);
-
-#ifdef CLIP_HACK
- /* Clip to the window - inefficient (; ;) XXX XXX */
- ClipRect(&portRect);
-#endif /* CLIP_HACK */
- }
-
- /* Advance */
- dst_r.left += td->tile_wid;
-#ifndef USE_DOUBLE_TILES
- dst_r.right += td->tile_wid;
-#endif /* !USE_DOUBLE_TILES */
- }
-
- /* Success */
- return (0);
-}
-
-
-
-
-
-/*
- * Create and initialize window number "i"
- */
-static void term_data_link(int i)
-{
- term *old = Term;
-
- term_data *td = &data[i];
-
- /* Only once */
- if (td->t) return;
-
- /* Require mapped */
- if (!td->mapped) return;
-
- /* Allocate */
- MAKE(td->t, term);
-
- /* Initialize the term */
- term_init(td->t, td->cols, td->rows, td->keys);
-
- /* Use a "software" cursor */
- td->t->soft_cursor = TRUE;
-
- /* Erase with "white space" */
- td->t->attr_blank = TERM_WHITE;
- td->t->char_blank = ' ';
-
- /* Prepare the init/nuke hooks */
- td->t->init_hook = Term_init_mac;
- td->t->nuke_hook = Term_nuke_mac;
-
- /* Prepare the function hooks */
- td->t->user_hook = Term_user_mac;
- td->t->xtra_hook = Term_xtra_mac;
- td->t->wipe_hook = Term_wipe_mac;
- td->t->curs_hook = Term_curs_mac;
- 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);
-
- /* Activate it */
- Term_activate(td->t);
-
- /* Global pointer */
- angband_term[i] = td->t;
-
- /* Activate old */
- Term_activate(old);
-}
-
-
-
-
-#ifdef MACH_O_CARBON
-
-/*
- * (Carbon, Bundle)
- * Return a POSIX pathname of the lib directory, or NULL if it can't be
- * located. Caller must supply a buffer along with its size in bytes,
- * where returned pathname will be stored.
- * I prefer use of goto's to several nested if's, if they involve error
- * handling. Sorry if you are offended by their presence. Modern
- * languages have neater constructs for this kind of jobs -- pelpel
- */
-static char *locate_lib(char *buf, size_t size)
-{
- CFURLRef main_url = NULL;
- CFStringRef main_str = NULL;
- char *p;
- char *res = NULL;
-
- /* Obtain the URL of the main bundle */
- main_url = CFBundleCopyBundleURL(CFBundleGetMainBundle());
-
- /* Oops */
- if (main_url == NULL) goto ret;
-
- /* Convert it to POSIX pathname */
- main_str = CFURLCopyFileSystemPath(main_url, kCFURLPOSIXPathStyle);
-
- /* Oops */
- if (main_str == NULL) goto ret;
-
- /* Convert it again from darn unisomething encoding to ASCII */
- if (CFStringGetCString(main_str, buf, size, kTextEncodingUS_ASCII) == FALSE)
- goto ret;
-
- /*
- * Paranoia - bounds check
- */
- if (strlen(buf) + 25 + 1 > size) goto ret;
-
- /* Location of the data */
- strcat(buf, "/Contents/Resources/");
-
- /* Set result */
- res = buf;
-
-ret:
-
- /* Release objects allocated and implicitly retained by the program */
- if (main_str) CFRelease(main_str);
- if (main_url) CFRelease(main_url);
-
- /* pathname of the lib folder or NULL */
- return (res);
-}
-
-
-#else /* MACH_O_CARBON */
-
-/*
-* Set the "current working directory" (also known as the "default"
-* volume/directory) to the location of the current application.
-*
-* Original code by: Maarten Hazewinkel (mmhazewi@cs.ruu.nl)
-*
-* Completely rewritten to use Carbon Process Manager. It retrieves the
-* volume and direcotry of the current application and simply stores it
-* in the (static) global variables app_vol and app_dir, but doesn't
-* mess with the "current working directory", because it has long been
-* an obsolete (and arcane!) feature.
-*/
-static void SetupAppDir(void)
-{
- OSErr err;
- ProcessSerialNumber curPSN;
- ProcessInfoRec procInfo;
- FSSpec cwdSpec;
-
- /* Initialise PSN info for the current process */
- curPSN.highLongOfPSN = 0;
- curPSN.lowLongOfPSN = kCurrentProcess;
-
- /* Fill in mandatory fields */
- procInfo.processInfoLength = sizeof(ProcessInfoRec);
- procInfo.processName = nil;
- procInfo.processAppSpec = &cwdSpec;
-
- /* Obtain current process information */
- err = GetProcessInformation(&curPSN, &procInfo);
-
- /* Oops */
- if (err != noErr)
- {
- mac_warning("Unable to get process information");
-
- /* Quit without writing anything */
- ExitToShell();
- }
-
- /* Extract and save the Vol and Dir */
- app_vol = cwdSpec.vRefNum;
- app_dir = cwdSpec.parID;
-}
-
-#endif /* MACH_O_CARBON */
-
-
-
-
-/*
- * Using Core Foundation's Preferences services -- pelpel
- *
- * Requires OS 8.6 or greater with CarbonLib 1.1 or greater. Or OS X,
- * of course.
- *
- * Without this, we can support older versions of OS 8 as well
- * (with CarbonLib 1.0.4).
- *
- * Frequent allocation/deallocation of small chunks of data is
- * far from my liking, but since this is only called at the
- * beginning and the end of a session, I hope this hardly matters.
- */
-
-
-/*
- * Store "value" as the value for preferences item name
- * pointed by key
- */
-static void save_pref_short(const char *key, short value)
-{
- CFStringRef cf_key;
- CFNumberRef cf_value;
-
- /* allocate and initialise the key */
- cf_key = CFStringCreateWithCString(NULL, key, kTextEncodingUS_ASCII);
-
- /* allocate and initialise the value */
- cf_value = CFNumberCreate(NULL, kCFNumberShortType, &value);
-
- if ((cf_key != NULL) && (cf_value != NULL))
- {
- /* Store the key-value pair in the applications preferences */
- CFPreferencesSetAppValue(
- cf_key,
- cf_value,
- kCFPreferencesCurrentApplication);
- }
-
- /*
- * Free CF data - the reverse order is a vain attempt to
- * minimise memory fragmentation.
- */
- if (cf_value) CFRelease(cf_value);
- if (cf_key) CFRelease(cf_key);
-}
-
-
-/*
- * Load preference value for key, returns TRUE if it succeeds with
- * vptr updated appropriately, FALSE otherwise.
- */
-static bool_ query_load_pref_short(const char *key, short *vptr)
-{
- CFStringRef cf_key;
- CFNumberRef cf_value;
-
- /* allocate and initialise the key */
- cf_key = CFStringCreateWithCString(NULL, key, kTextEncodingUS_ASCII);
-
- /* Oops */
- if (cf_key == NULL) return (FALSE);
-
- /* Retrieve value for the key */
- cf_value = CFPreferencesCopyAppValue(
- cf_key,
- kCFPreferencesCurrentApplication);
-
- /* Value not found */
- if (cf_value == NULL)
- {
- CFRelease(cf_key);
- return (FALSE);
- }
-
- /* Convert the value to short */
- CFNumberGetValue(
- cf_value,
- kCFNumberShortType,
- vptr);
-
- /* Free CF data */
- CFRelease(cf_value);
- CFRelease(cf_key);
-
- /* Success */
- return (TRUE);
-}
-
-
-/*
- * Update short data pointed by vptr only if preferences
- * value for key is located.
- */
-static void load_pref_short(const char *key, short *vptr)
-{
- short tmp;
-
- if (query_load_pref_short(key, &tmp)) *vptr = tmp;
- return;
-}
-
-
-/*
- * Save preferences to preferences file for current host+current user+
- * current application.
- */
-static void cf_save_prefs()
-{
- int i;
-
- /* Version stamp */
- save_pref_short("version.major", PREF_VER_MAJOR);
- save_pref_short("version.minor", PREF_VER_MINOR);
- save_pref_short("version.patch", PREF_VER_PATCH);
- save_pref_short("version.extra", PREF_VER_EXTRA);
-
- /* Gfx settings */
- save_pref_short("arg.arg_sound", arg_sound);
- save_pref_short("arg.graf_mode", graf_mode);
-#ifdef USE_DOUBLE_TILES
- save_pref_short("arg.big_tile", use_bigtile);
-#endif /* USE_DOUBLE_TILES */
-
- /* Windows */
- for (i = 0; i < MAX_TERM_DATA; i++)
- {
- term_data *td = &data[i];
-
- save_pref_short(format("term%d.font_mono", i), td->font_mono);
- save_pref_short(format("term%d.font_o_x", i), td->font_o_x);
- save_pref_short(format("term%d.font_o_y", i), td->font_o_y);
- save_pref_short(format("term%d.font_wid", i), td->font_wid);
- save_pref_short(format("term%d.font_hgt", i), td->font_hgt);
- save_pref_short(format("term%d.tile_o_x", i), td->tile_o_x);
- save_pref_short(format("term%d.tile_o_y", i), td->tile_o_y);
- save_pref_short(format("term%d.right", i), td->r.right);
- save_pref_short(format("term%d.bottom", i), td->r.bottom);
- save_pref_short(format("term%d.ow1", i), td->size_ow1);
- save_pref_short(format("term%d.oh1", i), td->size_oh1);
- save_pref_short(format("term%d.ow2", i), td->size_ow2);
- save_pref_short(format("term%d.oh2", i), td->size_oh2);
-
- save_pref_short(format("term%d.mapped", i), td->mapped);
-
- save_pref_short(format("term%d.font_id", i), td->font_id);
- save_pref_short(format("term%d.font_size", i), td->font_size);
- save_pref_short(format("term%d.font_face", i), td->font_face);
-
- save_pref_short(format("term%d.tile_wid", i), td->tile_wid);
- save_pref_short(format("term%d.tile_hgt", i), td->tile_hgt);
-
- save_pref_short(format("term%d.cols", i), td->cols);
- save_pref_short(format("term%d.rows", i), td->rows);
- save_pref_short(format("term%d.left", i), td->r.left);
- save_pref_short(format("term%d.top", i), td->r.top);
- }
-
- /*
- * Make sure preferences are persistent
- */
- CFPreferencesAppSynchronize(
- kCFPreferencesCurrentApplication);
-}
-
-
-/*
- * Load preferences from preferences file for current host+current user+
- * current application.
- */
-static void cf_load_prefs()
-{
- bool_ ok;
- short pref_major, pref_minor, pref_patch, pref_extra;
- int i;
-
- /* Assume nothing is wrong, yet */
- ok = TRUE;
-
- /* Load version information */
- ok &= query_load_pref_short("version.major", &pref_major);
- ok &= query_load_pref_short("version.minor", &pref_minor);
- ok &= query_load_pref_short("version.patch", &pref_patch);
- ok &= query_load_pref_short("version.extra", &pref_extra);
-
- /* Any of the above failed */
- if (!ok)
- {
- /* This may be the first run */
- mac_warning("Preferences are not found.");
-
- /* Ignore the rest */
- 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;
-
- /* sound */
- if (query_load_pref_short("arg.arg_sound", &pref_tmp))
- arg_sound = pref_tmp;
-
- /* graphics */
- if (query_load_pref_short("arg.graf_mode", &pref_tmp))
- graf_mode_req = pref_tmp;
-
-#ifdef USE_DOUBLE_TILES
-
- /* double-width tiles */
- if (query_load_pref_short("arg.big_tile", &pref_tmp))
- {
- use_bigtile = pref_tmp;
- }
-
-#endif /* USE_DOUBLE_TILES */
-
- }
-
- /* Windows */
- for (i = 0; i < MAX_TERM_DATA; i++)
- {
- term_data *td = &data[i];
-
- load_pref_short(format("term%d.mapped", i), &td->mapped);
-
- load_pref_short(format("term%d.font_id", i), &td->font_id);
- load_pref_short(format("term%d.font_size", i), &td->font_size);
- load_pref_short(format("term%d.font_face", i), &td->font_face);
-
- load_pref_short(format("term%d.tile_wid", i), &td->tile_wid);
- load_pref_short(format("term%d.tile_hgt", i), &td->tile_hgt);
-
- load_pref_short(format("term%d.cols", i), &td->cols);
- load_pref_short(format("term%d.rows", i), &td->rows);
- load_pref_short(format("term%d.left", i), &td->r.left);
- load_pref_short(format("term%d.top", i), &td->r.top);
-
- load_pref_short(format("term%d.font_mono", i), &td->font_mono);
- load_pref_short(format("term%d.font_o_x", i), &td->font_o_x);
- load_pref_short(format("term%d.font_o_y", i), &td->font_o_y);
- load_pref_short(format("term%d.font_wid", i), &td->font_wid);
- load_pref_short(format("term%d.font_hgt", i), &td->font_hgt);
- load_pref_short(format("term%d.tile_o_x", i), &td->tile_o_x);
- load_pref_short(format("term%d.tile_o_y", i), &td->tile_o_y);
- load_pref_short(format("term%d.right", i), &td->r.right);
- load_pref_short(format("term%d.bottom", i), &td->r.bottom);
- load_pref_short(format("term%d.ow1", i), &td->size_ow1);
- load_pref_short(format("term%d.oh1", i), &td->size_oh1);
- load_pref_short(format("term%d.ow2", i), &td->size_ow2);
- load_pref_short(format("term%d.oh2", i), &td->size_oh2);
- }
-}
-
-
-
-
-/*
- * Hack -- default data for a window
- */
-static void term_data_hack(term_data *td)
-{
- short fid;
-
- /* Default to Monaco font */
- GetFNum("\pmonaco", &fid);
-
- /* Wipe it */
- WIPE(td, term_data);
-
- /* No color */
- td->last = -1;
-
- /* Default borders */
- td->size_ow1 = 2;
- td->size_ow2 = 2;
- td->size_oh1 = 2;
- td->size_oh2 = 2;
-
- /* Start hidden */
- td->mapped = FALSE;
-
- /* Default font */
- td->font_id = fid;
-
- /* Default font size - was 12 */
- td->font_size = 14;
-
- /* Default font face */
- td->font_face = 0;
-
- /* Default size */
- td->rows = 24;
- td->cols = 80;
-
- /* Default position */
- td->r.left = 10;
- td->r.top = 40;
-
- /* Minimal keys */
- td->keys = 16;
-}
-
-
-/*
- * Read the preference file, Create the windows.
- *
- * We attempt to use "FindFolder()" to track down the preference file.
- */
-static void init_windows(void)
-{
- int i, b = 0;
-
- term_data *td;
-
-
- /*** Default values ***/
-
- /* Initialize (backwards) */
- for (i = MAX_TERM_DATA; i-- > 0; )
- {
- int n;
-
- cptr s;
-
- /* Obtain */
- td = &data[i];
-
- /* Defaults */
- term_data_hack(td);
-
- /* Obtain title */
- s = angband_term_name[i];
-
- /* Get length */
- n = strlen(s);
-
- /* Maximal length */
- if (n > 15) n = 15;
-
- /* Copy the title */
- strncpy((char*)(td->title) + 1, s, n);
-
- /* Save the length */
- td->title[0] = n;
-
- /* Tile the windows */
- td->r.left += (b * 30);
- td->r.top += (b * 30);
-
- /* Tile */
- b++;
- }
-
-
- /*** Load preferences ***/
-
- cf_load_prefs();
-
-
- /*** Instantiate ***/
-
- /* Main window */
- td = &data[0];
-
- /* Many keys */
- td->keys = 1024;
-
- /* Start visible */
- td->mapped = TRUE;
-
- /* Link (backwards, for stacking order) */
- for (i = MAX_TERM_DATA; i-- > 0; )
- {
- term_data_link(i);
- }
-
- /* Main window */
- td = &data[0];
-
- /* Main window */
- Term_activate(td->t);
-}
-
-
-/*
- * Save preferences
- */
-static void save_pref_file(void)
-{
- cf_save_prefs();
-}
-
-
-
-
-#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
- */
-static void handle_open_when_ready(void)
-{
- /* Check the flag XXX XXX XXX make a function for this */
- if (open_when_ready && initialized && !game_in_progress)
- {
- /* Forget */
- open_when_ready = FALSE;
-
- /* Game is in progress */
- game_in_progress = 1;
-
- /* Wait for it */
- pause_line(23);
-
- /* 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);
-
- /* Quit */
- quit(NULL);
- }
-}
-
-
-
-
-/*
- * Menus
- *
- * 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, ..., -, ... }
- * Size (132) = { ... }
- * Window (133) = { Angband, Term-1/Mirror, Term-2/Recall, Term-3/Choice,
- * Term-4, Term-5, Term-6, Term-7 }
- * Special (134) = { Sound, Graphics, TileWidth, TileHeight, -,
- * Fiddle, Wizard }
- */
-
-/* Apple menu */
-#define MENU_APPLE 128
-#define ITEM_ABOUT 1
-
-/* 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 */
-
-/* Edit menu */
-#define MENU_EDIT 130
-#define ITEM_UNDO 1
-#define ITEM_CUT 3
-#define ITEM_COPY 4
-#define ITEM_PASTE 5
-#define ITEM_CLEAR 6
-
-/* Font menu */
-#define MENU_FONT 131
-#define ITEM_BOLD 1
-#define ITEM_WIDE 2
-
-/* Size menu */
-#define MENU_SIZE 132
-
-/* Windows menu */
-#define MENU_WINDOWS 133
-
-/* Special menu */
-#define MENU_SPECIAL 134
-#define ITEM_SOUND 1
-#define ITEM_GRAPH 2
-# define SUBMENU_GRAPH 144
-# define ITEM_NONE 1
-# define ITEM_8X8 2
-# define ITEM_16X16 3
-# define ITEM_32X32 4
-# define ITEM_BIGTILE 6
-#define ITEM_TILEWIDTH 3
-# define SUBMENU_TILEWIDTH 145
-#define ITEM_TILEHEIGHT 4
-# define SUBMENU_TILEHEIGHT 146
-#define ITEM_FIDDLE 6
-#define ITEM_WIZARD 7
-
-
-/*
- * I HATE UNICODE! We've never wanted it. Some multi-national companies
- * made it up as their internationalisation "solution". So I won't use
- * any such API's -- pelpel
- */
-#define NSIZES 32
-static byte menu_size_values[NSIZES];
-static byte menu_tilewidth_values[NSIZES];
-static byte menu_tileheight_values[NSIZES];
-
-/*
- * Initialize the menus
- *
- * Fixed top level menus are now loaded all at once by GetNewMBar().
- * Although this simplifies the function a bit, we have to make sure
- * that resources have all the expected entries defined XXX XXX
- */
-static void init_menubar(void)
-{
- int i, n;
-
- Rect r;
-
- WindowPtr tmpw;
-
- MenuRef m;
-
-#ifdef USE_NIB
-
- /* The new way - loading main menu using Interface Builder services */
- {
- IBNibRef nib;
- OSStatus err;
-
- /* Create a nib reference to the main nib file */
- err = CreateNibReference(CFSTR("main"), &nib);
-
- /* Fatal error - missing Main.nib */
- if (err != noErr) quit("Cannot find Main.nib in the bundle!");
-
- /* Unarchive the menu bar and make it ready to use */
- err = SetMenuBarFromNib(nib, CFSTR("MainMenu"));
-
- /* Fatal error - couldn't insert menu bar */
- if (err != noErr) quit("Cannot prepare menu bar!");
-
- /* Dispose of the nib reference because we don't need it any longer */
- DisposeNibReference(nib);
- }
-
-#else /* USE_NIB */
-
- /* The old way - loading main menu from Resource Manager resource */
- {
- Handle mbar;
-
- /* Load menubar from resources */
- mbar = GetNewMBar(128);
-
- /* Whoops! */
- if (mbar == nil) quit("Cannot find menubar('MBAR') id 128!");
-
- /* Insert them into the current menu list */
- SetMenuBar(mbar);
-
- /* Free handle */
- DisposeHandle(mbar);
- }
-
-#endif /* USE_NIB */
-
-
- /* Apple menu (id 128) - we don't have to do anything */
-
-#ifndef USE_NIB
-
- /* File menu (id 129) - Aqua provides Quit menu for us */
- if (is_aqua)
- {
- /* Get a handle to the file menu */
- m = GetMenuHandle(MENU_FILE);
-
- /* Nuke the quit menu since Aqua does that for us */
- DeleteMenuItem(m, ITEM_QUIT);
-
-#ifndef HAS_SCORE_MENU
-
- /* Hack - because the above leaves a separator as the last item */
- DeleteMenuItem(m, ITEM_QUIT - 1);
-
-#endif /* !HAS_SCORE_MENU */
- }
-
-#endif /* !USE_NIB */
-
-
- /* Edit menu (id 130) - we don't have to do anything */
-
-
- /*
- * Font menu (id 131) - append names of mono-spaced fonts
- * followed by all available ones
- */
- m = GetMenuHandle(MENU_FONT);
-
- /* Fake window */
- r.left = r.right = r.top = r.bottom = 0;
-
- /* Make the fake window so that we can retrieve font info */
- (void)CreateNewWindow(
- kDocumentWindowClass,
- kWindowNoAttributes,
- &r,
- &tmpw);
-
- /* Activate the "fake" window */
- SetPort(GetWindowPort(tmpw));
-
- /* Default mode */
- TextMode(0);
-
- /* Default size */
- TextSize(12);
-
- /* Add the fonts to the menu */
- AppendResMenu(m, 'FONT');
-
- /* Size of menu */
- n = CountMenuItems(m);
-
- /* Scan the menu */
- for (i = n; i >= 4; i--)
- {
- Str255 tmpName;
- short fontNum;
-
- /* Acquire the font name */
- GetMenuItemText(m, i, tmpName);
-
- /* Acquire the font index */
- GetFNum(tmpName, &fontNum);
-
- /* Apply the font index */
- TextFont(fontNum);
-
- /* Remove non-mono-spaced fonts */
- if ((CharWidth('i') != CharWidth('W')) || (CharWidth('W') == 0))
- {
- /* Delete the menu item */
- DeleteMenuItem(m, i);
- }
- }
-
- /* Destroy the fake window */
- DisposeWindow(tmpw);
-
- /* Add a separator */
- AppendMenu(m, "\p-");
-
- /* Add the fonts to the menu */
- AppendResMenu(m, 'FONT');
-
-
-#ifndef USE_NIB
-
- /* Size menu (id 132) */
- m = GetMenuHandle(MENU_SIZE);
-
- /* Add some sizes (stagger choices) */
- for (i = 8, n = 1; i <= 32; i += ((i / 16) + 1), n++)
- {
- Str15 buf;
-
- /* Textual size */
- strnfmt((char*)buf + 1, 15, "%d", i);
- buf[0] = strlen((char*)buf + 1);
-
- /* Add the item */
- AppendMenu(m, buf);
-
- /* Remember its value, for we can't be sure it's in ASCII */
- menu_size_values[n] = i;
- }
-
-#endif /* !USE_NIB */
-
-
- /* Windows menu (id 133) */
- m = GetMenuHandle(MENU_WINDOWS);
-
- /* Default choices */
- for (i = 0; i < MAX_TERM_DATA; i++)
- {
- Str15 buf;
-
- /* Describe the item */
- strnfmt((char*)buf + 1, 15, "%.15s", angband_term_name[i]);
- buf[0] = strlen((char*)buf + 1);
-
- /* Add the item */
- AppendMenu(m, buf);
-
- /* Command-Key shortcuts */
- if (i < 8) SetItemCmd(m, i + 1, I2D(i));
- }
-
-
-#ifndef USE_NIB
-
- /* Special menu (id 134) */
- m = GetMenuHandle(MENU_SPECIAL);
-
- /* Insert Graphics submenu (id 144) */
- {
- MenuHandle submenu;
-
- /* Get the submenu */
- submenu = GetMenu(SUBMENU_GRAPH);
-
- /* Insert it */
- SetMenuItemHierarchicalMenu(m, ITEM_GRAPH, submenu);
- }
-
- /* Insert TileWidth submenu (id 145) */
- {
- MenuHandle submenu;
-
- /* Get the submenu */
- submenu = GetMenu(SUBMENU_TILEWIDTH);
-
- /* Add some sizes */
- for (i = 4, n = 1; i <= 32; i++, n++)
- {
- Str15 buf;
-
- /* Textual size */
- strnfmt((char*)buf + 1, 15, "%d", i);
- buf[0] = strlen((char*)buf + 1);
-
- /* Append item */
- AppendMenu(submenu, buf);
-
- /* Remember its value, for we can't be sure it's in ASCII */
- menu_tilewidth_values[n] = i;
- }
-
- /* Insert it */
- SetMenuItemHierarchicalMenu(m, ITEM_TILEWIDTH, submenu);
- }
-
- /* Insert TileHeight submenu (id 146) */
- {
- MenuHandle submenu;
-
- /* Get the submenu */
- submenu = GetMenu(SUBMENU_TILEHEIGHT);
-
-
- /* Add some sizes */
- for (i = 4, n = 1; i <= 32; i++, n++)
- {
- Str15 buf;
-
- /* Textual size */
- strnfmt((char*)buf + 1, 15, "%d", i);
- buf[0] = strlen((char*)buf + 1);
-
- /* Append item */
- AppendMenu(submenu, buf);
-
- /* Remember its value, for we can't be sure it's in ASCII */
- menu_tileheight_values[n] = i;
- }
-
- /* Insert it */
- SetMenuItemHierarchicalMenu(m, ITEM_TILEHEIGHT, submenu);
- }
-
-#endif /* !USE_NIB */
-
- /* Update the menu bar */
- DrawMenuBar();
-}
-
-
-/*
- * Prepare the menus
- *
- * It is very important that the player not be allowed to "save" the game
- * unless the "inkey_flag" variable is set, indicating that the game is
- * waiting for a new command. XXX XXX XXX
- */
-
-static void setup_menus(void)
-{
- int i, n;
-
- short value;
-
- Str255 s;
-
- MenuHandle m;
-
- term_data *td = NULL;
-
-
- /* Relevant "term_data" */
- for (i = 0; i < MAX_TERM_DATA; i++)
- {
- /* Unused */
- if (!data[i].t) continue;
-
- /* Notice the matching window */
- if (data[i].w == FrontWindow()) td = &data[i];
- }
-
-
- /* File menu */
- m = GetMenuHandle(MENU_FILE);
-
- /* Get menu size */
- n = CountMenuItems(m);
-
- /* Reset menu */
- for (i = 1; i <= n; i++)
- {
- /* Reset */
- DisableMenuItem(m, i);
- 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)
- {
- EnableMenuItem(m, ITEM_CLOSE);
- }
-
- /* Enable "save" */
- if (initialized && character_generated && inkey_flag)
- {
- EnableMenuItem(m, ITEM_SAVE);
- }
-
-#ifdef HAS_SCORE_MENU
-
- /* Enable "score" */
- if (initialized && character_generated && !character_icky)
- {
- EnableMenuItem(m, ITEM_SCORE);
- }
-
-#endif /* HAS_SCORE_MENU */
-
- /* Enable "quit" */
- if (!is_aqua)
- {
- if (!initialized || !character_generated || inkey_flag)
- {
- EnableMenuItem(m, ITEM_QUIT);
- }
- }
-
-
- /* Edit menu */
- m = GetMenuHandle(MENU_EDIT);
-
- /* Get menu size */
- n = CountMenuItems(m);
-
- /* Reset menu */
- for (i = 1; i <= n; i++)
- {
- /* Reset */
- DisableMenuItem(m, i);
- CheckMenuItem(m, i, FALSE);
- }
-
- /* Enable "edit" options if "needed" */
- if (!td)
- {
- EnableMenuItem(m, ITEM_UNDO);
- EnableMenuItem(m, ITEM_CUT);
- EnableMenuItem(m, ITEM_COPY);
- EnableMenuItem(m, ITEM_PASTE);
- EnableMenuItem(m, ITEM_CLEAR);
- }
-
-
- /* Font menu */
- m = GetMenuHandle(MENU_FONT);
-
- /* Get menu size */
- n = CountMenuItems(m);
-
- /* Reset menu */
- for (i = 1; i <= n; i++)
- {
- /* Reset */
- DisableMenuItem(m, i);
- CheckMenuItem(m, i, FALSE);
- }
-
- /* Hack -- look cute XXX XXX */
- /* SetItemStyle(m, ITEM_BOLD, bold); */
-
- /* Hack -- look cute XXX XXX */
- /* SetItemStyle(m, ITEM_WIDE, extend); */
-
- /* Active window */
- if (initialized && td)
- {
- /* Enable "bold" */
- EnableMenuItem(m, ITEM_BOLD);
-
- /* Enable "extend" */
- EnableMenuItem(m, ITEM_WIDE);
-
- /* Check the appropriate "bold-ness" */
- if (td->font_face & bold) CheckMenuItem(m, ITEM_BOLD, TRUE);
-
- /* Check the appropriate "wide-ness" */
- if (td->font_face & extend) CheckMenuItem(m, ITEM_WIDE, TRUE);
-
- /* Analyze fonts */
- for (i = 4; i <= n; i++)
- {
- /* Enable it */
- EnableMenuItem(m, i);
-
- /* Analyze font */
- GetMenuItemText(m, i, s);
- GetFNum(s, &value);
-
- /* Check active font */
- if (td->font_id == value) CheckMenuItem(m, i, TRUE);
- }
- }
-
-
- /* Size menu */
- m = GetMenuHandle(MENU_SIZE);
-
- /* Get menu size */
- n = CountMenuItems(m);
-
- /* Reset menu */
- for (i = 1; i <= n; i++)
- {
- /* Reset */
- DisableMenuItem(m, i);
- CheckMenuItem(m, i, FALSE);
- }
-
- /* Active window */
- if (initialized && td)
- {
- /* Analyze sizes */
- for (i = 1; i <= n; i++)
- {
- /* Analyze size */
- value = menu_size_values[i];
-
- /* Enable the "real" sizes */
- if (RealFont(td->font_id, value)) EnableMenuItem(m, i);
-
- /* Check the current size */
- if (td->font_size == value) CheckMenuItem(m, i, TRUE);
- }
- }
-
-
- /* Windows menu */
- m = GetMenuHandle(MENU_WINDOWS);
-
- /* Get menu size */
- n = CountMenuItems(m);
-
- /* Check active windows */
- for (i = 1; i <= n; i++)
- {
- /* Check if needed */
- CheckMenuItem(m, i, data[i - 1].mapped);
- }
-
-
- /* Special menu */
- m = GetMenuHandle(MENU_SPECIAL);
-
- /* Get menu size */
- n = CountMenuItems(m);
-
- /* Reset menu */
- for (i = 1; i <= n; i++)
- {
- /* Reset */
- DisableMenuItem(m, i);
- CheckMenuItem(m, i, FALSE);
- }
-
- /* Item "arg_sound" */
- EnableMenuItem(m, ITEM_SOUND);
- CheckMenuItem(m, ITEM_SOUND, arg_sound);
-
- /* Item "Graphics" */
- EnableMenuItem(m, ITEM_GRAPH);
- {
- MenuRef submenu;
-
- /* Graphics submenu */
- (void)GetMenuItemHierarchicalMenu(m, ITEM_GRAPH, &submenu);
-
- /* Get menu size */
- n = CountMenuItems(submenu);
-
- /* Reset menu */
- for (i = 1; i <= n; i++)
- {
- /* Reset */
- DisableMenuItem(submenu, i);
- CheckMenuItem(submenu, i, FALSE);
- }
-
- /* Item "None" */
- EnableMenuItem(submenu, ITEM_NONE);
- CheckMenuItem(submenu, ITEM_NONE, (graf_mode == GRAF_MODE_NONE));
-
- /* Item "8x8" */
- EnableMenuItem(submenu, ITEM_8X8);
- CheckMenuItem(submenu, ITEM_8X8, (graf_mode == GRAF_MODE_8X8));
-
- /* Item "16x16" */
- EnableMenuItem(submenu, ITEM_16X16);
- CheckMenuItem(submenu, ITEM_16X16, (graf_mode == GRAF_MODE_16X16));
-
- /* Item "32x32" */
- /*EnableMenuItem(submenu, ITEM_32X32);
- CheckMenuItem(submenu, ITEM_32X32, (graf_mode == GRAF_MODE_32X32));*/
-
-#ifdef USE_DOUBLE_TILES
-
- /* Item "Big tiles" */
- if (inkey_flag) EnableMenuItem(submenu, ITEM_BIGTILE);
- CheckMenuItem(submenu, ITEM_BIGTILE, use_bigtile);
-
-#endif /* USE_DOUBLE_TILES */
-
- }
-
- /* Item "TileWidth" */
- EnableMenuItem(m, ITEM_TILEWIDTH);
- {
- MenuRef submenu;
-
- /* TileWidth submenu */
- (void)GetMenuItemHierarchicalMenu(m, ITEM_TILEWIDTH, &submenu);
-
- /* Get menu size */
- n = CountMenuItems(submenu);
-
- /* Reset menu */
- for (i = 1; i <= n; i++)
- {
- /* Reset */
- DisableMenuItem(submenu, i);
- CheckMenuItem(submenu, i, FALSE);
- }
-
- /* Active window */
- if (initialized && td)
- {
- /* Analyze sizes */
- for (i = 1; i <= n; i++)
- {
- /* Analyze size */
- value = menu_tilewidth_values[i];
-
- /* Enable */
- if (value >= td->font_wid) EnableMenuItem(submenu, i);
-
- /* Check the current size */
- if (td->tile_wid == value) CheckMenuItem(submenu, i, TRUE);
- }
- }
- }
-
- /* Item "TileHeight" */
- EnableMenuItem(m, ITEM_TILEHEIGHT);
- {
- MenuRef submenu;
-
- /* TileWidth submenu */
- (void)GetMenuItemHierarchicalMenu(m, ITEM_TILEHEIGHT, &submenu);
-
- /* Get menu size */
- n = CountMenuItems(submenu);
-
- /* Reset menu */
- for (i = 1; i <= n; i++)
- {
- /* Reset */
- DisableMenuItem(submenu, i);
- CheckMenuItem(submenu, i, FALSE);
- }
-
- /* Active window */
- if (initialized && td)
- {
- /* Analyze sizes */
- for (i = 1; i <= n; i++)
- {
- /* Analyze size */
- value = menu_tileheight_values[i];
-
- /* Enable */
- if (value >= td->font_hgt) EnableMenuItem(submenu, i);
-
- /* Check the current size */
- if (td->tile_hgt == value) CheckMenuItem(submenu, i, TRUE);
- }
- }
- }
-
- /* 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);
-
-
- /* TileHeight menu */
- m = GetMenuHandle(SUBMENU_TILEHEIGHT);
-
- /* Get menu size */
- n = CountMenuItems(m);
-
- /* Reset menu */
- for (i = 1; i <= n; i++)
- {
- /* Reset */
- DisableMenuItem(m, i);
- CheckMenuItem(m, i, FALSE);
- }
-}
-
-
-/*
- * Process a menu selection (see above)
- *
- * Hack -- assume that invalid menu selections are disabled above,
- * which I have been informed may not be reliable. XXX XXX XXX
- */
-static void menu(long mc)
-{
- int i;
-
- int menuid, selection;
-
- static unsigned char s[1000];
-
- short fid;
-
- term_data *td = NULL;
-
- WindowPtr old_win;
-
-
- /* Analyze the menu command */
- menuid = HiWord(mc);
- selection = LoWord(mc);
-
-
- /* Find the window */
- for (i = 0; i < MAX_TERM_DATA; i++)
- {
- /* Skip dead windows */
- if (!data[i].t) continue;
-
- /* Notice matches */
- if (data[i].w == FrontWindow()) td = &data[i];
- }
-
-
- /* Branch on the menu */
- switch (menuid)
- {
- /* Apple Menu */
- case MENU_APPLE:
- {
- /* About Angband... */
- if (selection == ITEM_ABOUT)
- {
- DialogPtr dialog;
- short item_hit;
-
- /* Get the about dialogue */
- dialog = GetNewDialog(128, 0, (WindowPtr) - 1);
-
- /* Move it to the middle of the screen */
- RepositionWindow(
- GetDialogWindow(dialog),
- NULL,
- kWindowCenterOnMainScreen);
-
- /* Show the dialog */
- TransitionWindow(GetDialogWindow(dialog),
- kWindowZoomTransitionEffect,
- kWindowShowTransitionAction,
- NULL);
-
- /* Wait for user to click on it */
- ModalDialog(0, &item_hit);
-
- /* Free the dialogue */
- DisposeDialog(dialog);
- break;
- }
-
- break;
- }
-
- /* File Menu */
- case MENU_FILE:
- {
- 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:
- {
- /* No window */
- if (!td) break;
-
- /* Not Mapped */
- td->mapped = FALSE;
-
- /* Not Mapped */
- td->t->mapped_flag = FALSE;
-
- /* Hide the window */
- TransitionWindow(td->w,
- kWindowZoomTransitionEffect,
- kWindowHideTransitionAction,
- NULL);
-
- break;
- }
-
- /* Save */
- case ITEM_SAVE:
- {
- /* Hack -- Forget messages */
- 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;
- }
-
-#ifdef HAS_SCORE_MENU
-
- /* 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_APEX,
- "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;
-
- /* Done */
- break;
- }
-
-#endif /* HAS_SCORE_MENU */
-
- /* Quit (with save) */
- case ITEM_QUIT:
- {
- /* Save the game (if necessary) */
- if (game_in_progress && character_generated)
- {
- /* Hack -- Forget messages */
- 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);
- break;
- }
- }
- break;
- }
-
- /* Edit menu */
- case MENU_EDIT:
- {
- /* Unused */
- break;
- }
-
- /* Font menu */
- case MENU_FONT:
- {
- /* Require a window */
- if (!td) break;
-
- /* Memorize old */
- old_win = active;
-
- /* Activate */
- activate(td->w);
-
- /* Toggle the "bold" setting */
- if (selection == ITEM_BOLD)
- {
- /* Toggle the setting */
- if (td->font_face & bold)
- {
- td->font_face &= ~bold;
- }
- else
- {
- td->font_face |= bold;
- }
-
- /* Hack - clear tile size info XXX XXX */
- td->tile_wid = td->tile_hgt = 0;
-
- /* Apply and Verify */
- term_data_check_font(td);
- term_data_check_size(td);
-
- /* Resize and Redraw */
- term_data_resize(td);
- term_data_redraw(td);
-
- break;
- }
-
- /* Toggle the "wide" setting */
- if (selection == ITEM_WIDE)
- {
- /* Toggle the setting */
- if (td->font_face & extend)
- {
- td->font_face &= ~extend;
- }
- else
- {
- td->font_face |= extend;
- }
-
- /* Hack - clear tile size info XXX XXX */
- td->tile_wid = td->tile_hgt = 0;
-
- /* Apply and Verify */
- term_data_check_font(td);
- term_data_check_size(td);
-
- /* Resize and Redraw */
- term_data_resize(td);
- term_data_redraw(td);
-
- break;
- }
-
- /* Get a new font name */
- GetMenuItemText(GetMenuHandle(MENU_FONT), selection, s);
- GetFNum(s, &fid);
-
- /* Save the new font id */
- td->font_id = fid;
-
- /* Current size is bad for new font */
- if (!RealFont(td->font_id, td->font_size))
- {
- /* Find similar size */
- for (i = 1; i <= 32; i++)
- {
- /* Adjust smaller */
- if (td->font_size - i >= 8)
- {
- if (RealFont(td->font_id, td->font_size - i))
- {
- td->font_size -= i;
- break;
- }
- }
-
- /* Adjust larger */
- if (td->font_size + i <= 128)
- {
- if (RealFont(td->font_id, td->font_size + i))
- {
- td->font_size += i;
- break;
- }
- }
- }
- }
-
- /* Hack - clear tile size info XXX XXX */
- td->tile_wid = td->tile_hgt = 0;
-
- /* Apply and Verify */
- term_data_check_font(td);
- term_data_check_size(td);
-
- /* Resize and Redraw */
- term_data_resize(td);
- term_data_redraw(td);
-
- /* Restore the window */
- activate(old_win);
-
- break;
- }
-
- /* Size menu */
- case MENU_SIZE:
- {
- if (!td) break;
-
- /* Save old */
- old_win = active;
-
- /* Activate */
- activate(td->w);
-
- td->font_size = menu_size_values[selection];
-
- /* Hack - clear tile size info XXX XXX */
- td->tile_wid = td->tile_hgt = 0;
-
- /* Apply and Verify */
- term_data_check_font(td);
- term_data_check_size(td);
-
- /* Resize and Redraw */
- term_data_resize(td);
- term_data_redraw(td);
-
- /* Restore */
- activate(old_win);
-
- break;
- }
-
- /* Window menu */
- case MENU_WINDOWS:
- {
- /* Parse */
- i = selection - 1;
-
- /* Check legality of choice */
- if ((i < 0) || (i >= MAX_TERM_DATA)) break;
-
- /* Obtain the window */
- td = &data[i];
-
- /* Mapped */
- td->mapped = TRUE;
-
- /* Link */
- term_data_link(i);
-
- /* Mapped (?) */
- td->t->mapped_flag = TRUE;
-
- /* Show the window */
- TransitionWindow(td->w,
- kWindowZoomTransitionEffect,
- kWindowShowTransitionAction,
- NULL);
-
- /* Bring to the front */
- SelectWindow(td->w);
-
- break;
- }
-
- /* Special menu */
- case MENU_SPECIAL:
- {
- switch (selection)
- {
- case ITEM_SOUND:
- {
- /* Toggle arg_sound */
- arg_sound = !arg_sound;
-
- /* React to changes */
- Term_xtra(TERM_XTRA_REACT, 0);
-
- break;
- }
-
- case ITEM_FIDDLE:
- {
- arg_fiddle = !arg_fiddle;
-
- break;
- }
-
- case ITEM_WIZARD:
- {
- arg_wizard = !arg_wizard;
-
- break;
- }
- }
-
- break;
- }
-
- /* Graphics submenu */
- case SUBMENU_GRAPH:
- {
- switch (selection)
- {
- case ITEM_NONE:
- {
- graf_mode_req = GRAF_MODE_NONE;
-
- break;
- }
-
- case ITEM_8X8:
- {
- graf_mode_req = GRAF_MODE_8X8;
-
- break;
- }
-
- case ITEM_16X16:
- {
- graf_mode_req = GRAF_MODE_16X16;
-
- break;
- }
-
- case ITEM_32X32:
- {
- graf_mode_req = GRAF_MODE_32X32;
-
- break;
- }
-
-#ifdef USE_DOUBLE_TILES
-
- case ITEM_BIGTILE:
- {
- term *old = Term;
- term_data *td = &data[0];
-
- /* Toggle "use_bigtile" */
- use_bigtile = !use_bigtile;
- arg_bigtile = use_bigtile;
-
- /* Activate */
- Term_activate(td->t);
-
- /* Resize the term */
- Term_resize(td->cols, td->rows);
-
- /* Activate old */
- Term_activate(old);
-
- break;
- }
-
-#endif /* USE_DOUBLE_TILES */
-
- }
-
- /* Hack -- Force redraw */
- Term_key_push(KTRL('R'));
-
- break;
- }
-
- /* TileWidth menu */
- case SUBMENU_TILEWIDTH:
- {
- if (!td) break;
-
- /* Save old */
- old_win = active;
-
- /* Activate */
- activate(td->w);
-
- /* Analyse value */
- td->tile_wid = menu_tilewidth_values[selection];
-
- /* Apply and Verify */
- term_data_check_size(td);
-
- /* Resize and Redraw */
- term_data_resize(td);
- term_data_redraw(td);
-
- /* Restore */
- activate(old_win);
-
- break;
- }
-
- /* TileHeight menu */
- case SUBMENU_TILEHEIGHT:
- {
- if (!td) break;
-
- /* Save old */
- old_win = active;
-
- /* Activate */
- activate(td->w);
-
- /* Analyse value */
- td->tile_hgt = menu_tileheight_values[selection];
-
- /* Apply and Verify */
- term_data_check_size(td);
-
- /* Resize and Redraw */
- term_data_resize(td);
- term_data_redraw(td);
-
- /* Restore */
- activate(old_win);
-
- break;
- }
- }
-
-
- /* Clean the menu */
- HiliteMenu(0);
-}
-
-
-/*
- * Check for extra required parameters -- From "Maarten Hazewinkel"
- */
-static OSErr CheckRequiredAEParams(const AppleEvent *theAppleEvent)
-{
- OSErr aeError;
- DescType returnedType;
- Size actualSize;
-
- aeError = AEGetAttributePtr(
- theAppleEvent, keyMissedKeywordAttr, typeWildCard,
- &returnedType, NULL, 0, &actualSize);
-
- if (aeError == errAEDescNotFound) return (noErr);
-
- if (aeError == noErr) return (errAEParamMissed);
-
- return (aeError);
-}
-
-
-/*
- * Apple Event Handler -- Open Application
- */
-static OSErr AEH_Start(const AppleEvent *theAppleEvent, AppleEvent *reply,
- SInt32 handlerRefCon)
-{
- return (CheckRequiredAEParams(theAppleEvent));
-}
-
-
-/*
- * Apple Event Handler -- Quit Application
- */
-static OSErr AEH_Quit(const AppleEvent *theAppleEvent, AppleEvent *reply,
- SInt32 handlerRefCon)
-{
- /* Quit later */
- quit_when_ready = TRUE;
-
- /* Check arguments */
- return (CheckRequiredAEParams(theAppleEvent));
-}
-
-
-/*
- * Apple Event Handler -- Print Documents
- */
-static OSErr AEH_Print(const AppleEvent *theAppleEvent, AppleEvent *reply,
- SInt32 handlerRefCon)
-{
- return (errAEEventNotHandled);
-}
-
-
-/*
- * Apple Event Handler by Steve Linberg (slinberg@crocker.com).
- *
- * The old method of opening savefiles from the finder does not work
- * on the Power Macintosh, because CountAppFiles and GetAppFiles,
- * used to return information about the selected document files when
- * an application is launched, are part of the Segment Loader, which
- * is not present in the RISC OS due to the new memory architecture.
- *
- * The "correct" way to do this is with AppleEvents. The following
- * code is modeled on the "Getting Files Selected from the Finder"
- * snippet from Think Reference 2.0. (The prior sentence could read
- * "shamelessly swiped & hacked")
- */
-static OSErr AEH_Open(const AppleEvent *theAppleEvent, AppleEvent* reply,
- SInt32 handlerRefCon)
-{
- FSSpec myFSS;
- AEDescList docList;
- OSErr err;
- Size actualSize;
- AEKeyword keywd;
- DescType returnedType;
- char msg[128];
- FInfo myFileInfo;
-
- /* Put the direct parameter (a descriptor list) into a docList */
- err = AEGetParamDesc(
- theAppleEvent, keyDirectObject, typeAEList, &docList);
- if (err) return err;
-
- /*
- * We ignore the validity check, because we trust the FInder, and we only
- * allow one savefile to be opened, so we ignore the depth of the list.
- */
- err = AEGetNthPtr(
- &docList, 1L, typeFSS, &keywd, &returnedType,
- (Ptr) & myFSS, sizeof(myFSS), &actualSize);
- if (err) return err;
-
- /* Only needed to check savefile type below */
- err = FSpGetFInfo(&myFSS, &myFileInfo);
- if (err)
- {
- strnfmt(msg, 128, "Argh! FSpGetFInfo failed with code %d", err);
- mac_warning(msg);
- return err;
- }
-
- /* Ignore non 'SAVE' files */
- if (myFileInfo.fdType != 'SAVE') return noErr;
-
-#ifdef MACH_O_CARBON
-
- /* Extract a file name */
- (void)spec_to_path(&myFSS, savefile, sizeof(savefile));
-
-#else
-
- /* XXX XXX XXX Extract a file name */
- PathNameFromDirID(myFSS.parID, myFSS.vRefNum, (StringPtr)savefile);
- pstrcat((StringPtr)savefile, (StringPtr)&myFSS.name);
-
- /* Convert the string */
- ptocstr((StringPtr)savefile);
-
-#endif /* MACH_O_CARBON */
-
- /* Delay actual open */
- open_when_ready = TRUE;
-
- /* Dispose */
- err = AEDisposeDesc(&docList);
-
- /* Success */
- return noErr;
-}
-
-
-/*
- * Handle quit_when_ready, by Peter Ammon,
- * slightly modified to check inkey_flag.
- */
-static void quit_calmly(void)
-{
- /* Quit immediately if game's not started */
- if (!game_in_progress || !character_generated) quit(NULL);
-
- /* Save the game and Quit (if it's safe) */
- if (inkey_flag)
- {
- /* Hack -- Forget messages */
- 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);
- }
-
- /* Wait until inkey_flag is set */
-}
-
-
-/*
- * Macintosh modifiers (event.modifier & ccc):
- * cmdKey, optionKey, shiftKey, alphaLock, controlKey
- *
- *
- * Macintosh Keycodes (0-63 normal, 64-95 keypad, 96-127 extra):
- *
- * Return:36
- * Delete:51
- *
- * Period:65
- * Star:67
- * Plus:69
- * Clear:71
- * Slash:75
- * Enter:76
- * Minus:78
- * Equal:81
- * 0-7:82-89
- * 8-9:91-92
- *
- * backslash/vertical bar (Japanese keyboard):93
- *
- * F5: 96
- * F6: 97
- * F7: 98
- * F3:99
- * F8:100
- * F10:101
- * F11:103
- * F13:105
- * F14:107
- * F9:109
- * F12:111
- * F15:113
- * Help:114
- * Home:115
- * PgUp:116
- * Del:117
- * F4: 118
- * End:119
- * F2:120
- * PgDn:121
- * F1:122
- * Lt:123
- * Rt:124
- * Dn:125
- * Up:126
- */
-
-
-/*
- * Check for Events, return TRUE if we process any
- *
- * Now it really waits for events if wait set to true, to prevent
- * undesirable monopoly of CPU. The side-effect is that you cannot do
- * while (CheckEvents(TRUE)); without discretion.
- */
-static bool_ CheckEvents(bool_ wait)
-{
- EventRecord event;
-
- WindowPtr w;
-
- Rect r;
-
- UInt32 sleep_ticks;
-
- int ch, ck;
-
- int mc, ms, mo, mx;
-
- int i;
-
- term_data *td = NULL;
-
-
- /*
- * With the wait mode blocking for available event / timeout,
- * the non-wait mode should actually call WaitNextEvent,
- * because of those event draining loops. Or we had to
- * implement yet another mode.
- */
-
- /* Handles the quit_when_ready flag */
- if (quit_when_ready) quit_calmly();
-
- /* Blocking call to WaitNextEvent - should use MAX_INT XXX XXX */
- if (wait) sleep_ticks = 0x7FFFFFFFL;
-
- /* Non-blocking */
- else sleep_ticks = 0L;
-
- /* Get an event (or null) */
- WaitNextEvent(everyEvent, &event, sleep_ticks, nil);
-
- /* Hack -- Nothing is ready yet */
- if (event.what == nullEvent) return (FALSE);
-
-
- /* Analyze the event */
- switch (event.what)
- {
-
-#if 0
-
- case activateEvt:
- {
- w = (WindowPtr)event.message;
-
- activate(w);
-
- break;
- }
-
-#endif
-
- case updateEvt:
- {
- /* Extract the window */
- w = (WindowPtr)event.message;
-
- /* Find the window */
- for (i = 0; i < MAX_TERM_DATA; i++)
- {
- /* Skip dead windows */
- if (!data[i].t) continue;
-
- /* Notice matches */
- if (data[i].w == w) td = &data[i];
- }
-
- /* Hack XXX XXX XXX */
- BeginUpdate(w);
- EndUpdate(w);
-
- /* Redraw the window */
- if (td) term_data_redraw(td);
-
- break;
- }
-
- case keyDown:
- case autoKey:
- {
- /* Extract some modifiers */
- mc = (event.modifiers & controlKey) ? TRUE : FALSE;
- ms = (event.modifiers & shiftKey) ? TRUE : FALSE;
- mo = (event.modifiers & optionKey) ? TRUE : FALSE;
- mx = (event.modifiers & cmdKey) ? TRUE : FALSE;
-
- /* Keypress: (only "valid" if ck < 96) */
- ch = (event.message & charCodeMask) & 255;
-
- /* Keycode: see table above */
- ck = ((event.message & keyCodeMask) >> 8) & 255;
-
- /* Command + "normal key" -> menu action */
- if (mx && (ck < 64))
- {
-#ifdef MENU_SHORTCUTS
- /* Hack -- Prepare the menus */
- setup_menus();
-
- /* Run the Menu-Handler */
- menu(MenuKey(ch));
-
- /* Turn off the menus */
- HiliteMenu(0);
-
- /* Done */
- break;
-#else
- /* Begin special trigger */
- Term_keypress(31);
-
- /* Send some modifier keys */
- if (mc) Term_keypress('C');
- if (ms) Term_keypress('S');
- if (mo) Term_keypress('O');
- if (mx) Term_keypress('X');
-
- /* Enqueue the keypress */
- Term_keypress(ch);
-
- /* Terminate the trigger */
- Term_keypress(13);
-#endif
- }
-
- /* Hide the mouse pointer */
- ObscureCursor();
-
- /* Normal key -> simple keypress */
- if ((ck < 64) || (ck == 93))
- {
- /* Enqueue the keypress */
- Term_keypress(ch);
- }
-
- /* Keypad keys -> trigger plus simple keypress */
- else if (!mc && !ms && !mo && !mx && (ck < 96))
- {
- /* Hack -- "enter" is confused */
- if (ck == 76) ch = '\n';
-
- /* Begin special trigger */
- Term_keypress(31);
-
- /* Send the "keypad" modifier */
- Term_keypress('K');
-
- /* Send the "ascii" keypress */
- Term_keypress(ch);
-
- /* Terminate the trigger */
- Term_keypress(13);
- }
-
- /* Bizarre key -> encoded keypress */
- else if (ck <= 127)
- {
- /* Begin special trigger */
- Term_keypress(31);
-
- /* Send some modifier keys */
- if (mc) Term_keypress('C');
- if (ms) Term_keypress('S');
- if (mo) Term_keypress('O');
- if (mx) Term_keypress('X');
-
- /* Downshift and encode the keycode */
- Term_keypress(I2D((ck - 64) / 10));
- Term_keypress(I2D((ck - 64) % 10));
-
- /* Terminate the trigger */
- Term_keypress(13);
- }
-
- break;
- }
-
- case mouseDown:
- {
- int code;
-
- /* Analyze click location */
- code = FindWindow(event.where, &w);
-
- /* Find the window */
- for (i = 0; i < MAX_TERM_DATA; i++)
- {
- /* Skip dead windows */
- if (!data[i].t) continue;
-
- /* Notice matches */
- if (data[i].w == w) td = &data[i];
- }
-
- /* Analyze */
- switch (code)
- {
- case inMenuBar:
- {
- setup_menus();
- menu(MenuSelect(event.where));
- HiliteMenu(0);
- break;
- }
-
- case inDrag:
- {
- WindowPtr old_win;
- BitMap tBitMap;
- Rect pRect;
-
- r = GetQDGlobalsScreenBits(&tBitMap)->bounds;
- r.top += 20; /* GetMBarHeight() XXX XXX XXX */
- InsetRect(&r, 4, 4);
- DragWindow(w, event.where, &r);
-
- /* Oops */
- if (!td) break;
-
- /* Save */
- old_win = active;
-
- /* Activate */
- activate(td->w);
-
- /* Analyze */
- GetWindowBounds(
- (WindowRef)td->w,
- kWindowContentRgn,
- &pRect);
- td->r.left = pRect.left;
- td->r.top = pRect.top;
-
- /* Apply and Verify */
- term_data_check_size(td);
-
- /* Restore */
- activate(old_win);
-
- break;
- }
-
- case inGoAway:
- {
- /* Oops */
- if (!td) break;
-
- /* Track the go-away box */
- if (TrackGoAway(w, event.where))
- {
- /* Not Mapped */
- td->mapped = FALSE;
-
- /* Not Mapped */
- td->t->mapped_flag = FALSE;
-
- /* Hide the window */
- TransitionWindow(td->w,
- kWindowZoomTransitionEffect,
- kWindowHideTransitionAction,
- NULL);
- }
-
- break;
- }
-
- case inGrow:
- {
- int x, y;
-
- Rect nr;
-
- term *old = Term;
-
- /* Oops */
- if (!td) break;
-
-#ifndef ALLOW_BIG_SCREEN
-
- /* Minimum and maximum sizes */
- r.left = 20 * td->tile_wid + td->size_ow1;
- r.right = 80 * td->tile_wid + td->size_ow1 + td->size_ow2 + 1;
- r.top = 1 * td->tile_hgt + td->size_oh1;
- r.bottom = 24 * td->tile_hgt + td->size_oh1 + td->size_oh2 + 1;
-
- /* Grow the rectangle */
- if (!ResizeWindow(w, event.where, &r, NULL)) break;
-#else
-
- /* Grow the rectangle */
- if (!ResizeWindow(w, event.where, NULL, NULL)) break;
-
-#endif /* !ALLOW_BIG_SCREEN */
-
-
- /* Obtain geometry of resized window */
- GetWindowBounds(w, kWindowContentRgn, &nr);
-
- /* Extract the new size in pixels */
- y = nr.bottom - nr.top - td->size_oh1 - td->size_oh2;
- x = nr.right - nr.left - td->size_ow1 - td->size_ow2;
-
- /* Extract a "close" approximation */
- td->rows = y / td->tile_hgt;
- td->cols = x / td->tile_wid;
-
- /* Apply and Verify */
- term_data_check_size(td);
-
- /* Activate */
- Term_activate(td->t);
-
- /* Hack -- Resize the term */
- Term_resize(td->cols, td->rows);
-
- /* Resize and Redraw */
- term_data_resize(td);
- term_data_redraw(td);
-
- /* Restore */
- Term_activate(old);
-
- break;
- }
-
- case inContent:
- {
- SelectWindow(w);
-
- break;
- }
- }
-
- break;
- }
-
- /* OS Event -- From "Maarten Hazewinkel" */
- case osEvt:
- {
- switch ((event.message >> 24) & 0x000000FF)
- {
- case suspendResumeMessage:
-
- /* Resuming: activate the front window */
- if (event.message & resumeFlag)
- {
- Cursor tempCursor;
- SetPort(GetWindowPort(FrontWindow()));
- SetCursor(GetQDGlobalsArrow(&tempCursor));
- }
-
- /* Suspend: deactivate the front window */
- else
- {
- /* Nothing */
- }
-
- break;
- }
-
- break;
- }
-
- /* From "Steve Linberg" and "Maarten Hazewinkel" */
- case kHighLevelEvent:
- {
- /* Process apple events */
- (void)AEProcessAppleEvent(&event);
-
- /* 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);
- }
-
- /* Handle "open_when_ready" */
- else if (open_when_ready)
- {
- handle_open_when_ready();
- }
-
- break;
- }
-
- }
-
-
- /* Something happened */
- return (TRUE);
-}
-
-
-/*** Some Hooks for various routines ***/
-
-
-/*
- * Mega-Hack -- emergency lifeboat
- */
-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
-
- /* Alternative method */
- free(v);
-
-#else
-
- /* Dispose */
- DisposePtr(v);
-
-#endif
-
- /* Success */
- return (NULL);
-}
-
-/*
- * Hook to "allocate" memory
- */
-static void *hook_ralloc(size_t size)
-{
-
-#ifdef USE_MALLOC
-
- /* Make a new pointer */
- return (malloc(size));
-
-#else
-
- /* Make a new pointer */
- return (NewPtr(size));
-
-#endif
-
-}
-
-/*
- * Hook to handle "out of memory" errors
- */
-static void *hook_rpanic(size_t size)
-{
- /* void *mem = NULL; */
-
- /* Free the lifeboat */
- if (lifeboat)
- {
- /* Free the lifeboat */
- DisposePtr(lifeboat);
-
- /* Forget the lifeboat */
- lifeboat = NULL;
-
- /* Mega-Hack -- Warning */
- mac_warning("Running out of Memory!\rAbort this process now!");
-
- /* Mega-Hack -- Never leave this function */
- while (TRUE) CheckEvents(TRUE);
- }
-
- /* Mega-Hack -- Crash */
- return (NULL);
-}
-
-
-/*
- * Hook to tell the user something important
- */
-static void hook_plog(cptr str)
-{
- /* Warning message */
- mac_warning(str);
-}
-
-
-/*
- * Hook to tell the user something, and then quit
- */
-static void hook_quit(cptr str)
-{
- /* Warning if needed */
- if (str) mac_warning(str);
-
-#ifdef USE_ASYNC_SOUND
-
- /* Clean up sound support */
- cleanup_sound();
-
-#endif /* USE_ASYNC_SOUND */
-
- /* Dispose of graphic tiles */
- if (frameP)
- {
- /* Unlock */
- BenSWUnlockFrame(frameP);
-
- /* Dispose of the GWorld */
- DisposeGWorld(frameP->framePort);
-
- /* Dispose of the memory */
- DisposePtr((Ptr)frameP);
- }
-
- /* Write a preference file */
- save_pref_file();
-
- /* All done */
- ExitToShell();
-}
-
-
-/*
- * Hook to tell the user something, and then crash
- */
-static void hook_core(cptr str)
-{
- /* XXX Use the debugger */
- /* DebugStr(str); */
-
- /* Warning */
- if (str) mac_warning(str);
-
- /* Warn, then save player */
- mac_warning("Fatal error.\rI will now attempt to save and quit.");
-
- /* Attempt to save */
- if (!save_player()) mac_warning("Warning -- save failed!");
-
- /* Quit */
- quit(NULL);
-}
-
-
-
-/*** Main program ***/
-
-
-/*
- * Init some stuff
- *
- * XXX XXX XXX Hack -- This function attempts to "fix" the nasty
- * "Macintosh Save Bug" by using "absolute" path names, since on
- * System 7 machines anyway, the "current working directory" often
- * "changes" due to background processes, invalidating any "relative"
- * path names. Note that the Macintosh is limited to 255 character
- * path names, so be careful about deeply embedded directories...
- *
- * XXX XXX XXX Hack -- This function attempts to "fix" the nasty
- * "missing lib folder bug" by allowing the user to help find the
- * "lib" folder by hand if the "application folder" code fails...
- *
- *
- * The problem description above no longer applies, but I left it here,
- * modified for Carbon, to allow the game proceeds when a user doesn't
- * placed the Angband binary and the lib folder in the same place for
- * whatever reasons. -- pelpel
- */
-static void init_stuff(void)
-{
- Rect r;
- BitMap tBitMap;
- Rect screenRect;
- Point topleft;
-
- char path[1024];
-
- OSErr err = noErr;
- NavDialogOptions dialogOptions;
- FSSpec theFolderSpec;
- NavReplyRecord theReply;
-
-
- /* Fake rectangle */
- r.left = 0;
- r.top = 0;
- r.right = 344;
- r.bottom = 188;
-
- /* Center it */
- screenRect = GetQDGlobalsScreenBits(&tBitMap)->bounds;
- center_rect(&r, &screenRect);
-
- /* Extract corner */
- topleft.v = r.top;
- topleft.h = r.left;
-
- /* Default to the "lib" folder with the application */
-#ifdef MACH_O_CARBON
- if (locate_lib(path, sizeof(path)) == NULL) quit(NULL);
-#else
- refnum_to_name(path, app_dir, app_vol, (char*)("\plib:"));
-#endif
-
-
- /* Check until done */
- while (1)
- {
- /* Prepare the paths */
- init_file_paths(path);
-
- /* Build the filename */
- path_build(path, 1024, ANGBAND_DIR_FILE, "news.txt");
-
- /* Attempt to open and close that file */
- if (0 == fd_close(fd_open(path, O_RDONLY))) break;
-
- /* Warning */
- plog_fmt("Unable to open the '%s' file.", path);
-
- /* Warning */
- plog("The Angband 'lib' folder is probably missing or misplaced.");
-
- /* Ask the user to choose the lib folder */
- err = NavGetDefaultDialogOptions(&dialogOptions);
-
- /* Paranoia */
- if (err != noErr) quit(NULL);
-
- /* Set default location option */
- dialogOptions.dialogOptionFlags |= kNavSelectDefaultLocation;
-
- /* Clear preview option */
- dialogOptions.dialogOptionFlags &= ~(kNavAllowPreviews);
-
- /* Forbit selection of multiple files */
- dialogOptions.dialogOptionFlags &= ~(kNavAllowMultipleFiles);
-
- /* 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);
-
- /* Assume the player doesn't want to go on */
- if ((err != noErr) || !theReply.validRecord) quit(NULL);
-
- /* Retrieve FSSpec from the reply */
- {
- AEKeyword theKeyword;
- DescType actualType;
- Size actualSize;
-
- /* Get a pointer to selected folder */
- err = AEGetNthPtr(
- &(theReply.selection), 1, typeFSS, &theKeyword,
- &actualType, &theFolderSpec, sizeof(FSSpec), &actualSize);
-
- /* Paranoia */
- if (err != noErr) quit(NULL);
- }
-
- /* Free navitagor reply */
- err = NavDisposeReply(&theReply);
-
- /* Paranoia */
- if (err != noErr) quit(NULL);
-
- /* Extract textual file name for given file */
-#ifdef MACH_O_CARBON
- if (spec_to_path(&theFolderSpec, path, sizeof(path)) != noErr)
- {
- quit(NULL);
- }
-#else /* MACH_O_CARBON */
-refnum_to_name(
- path,
- theFolderSpec.parID,
- theFolderSpec.vRefNum,
- (char *)theFolderSpec.name);
-#endif /* MACH_O_CARBON */
- }
-}
-
-
-/*
- * Macintosh Main loop
- */
-int main(void)
-{
- int i;
- long response;
- OSStatus err;
- EventRecord tempEvent;
- UInt32 numberOfMasters = 10;
-
- /* Get more Masters -- it is not recommended by Apple, should go away */
- MoreMasterPointers(numberOfMasters);
-
- /* Check for existence of Carbon */
- err = Gestalt(gestaltCarbonVersion, &response);
-
- if (err != noErr) quit("This program requires Carbon API");
-
- /* See if we are running on Aqua */
- err = Gestalt(gestaltMenuMgrAttr, &response);
-
- /* Cache the result */
- if ((err == noErr) &&
- (response & gestaltMenuMgrAquaLayoutMask)) is_aqua = TRUE;
-
- /*
- * Remember Mac OS version, in case we have to cope with version-specific
- * problems
- */
- (void)Gestalt(gestaltSystemVersion, &mac_os_version);
-
-
- /* Set up the Macintosh */
- InitCursor();
-
- /* Flush events */
- FlushEvents(everyEvent, 0);
-
- /* Flush events some more (?) */
- if (EventAvail(everyEvent, &tempEvent)) FlushEvents(everyEvent, 0);
-
-
- /* Install the start event hook (ignore error codes) */
- AEInstallEventHandler(
- kCoreEventClass,
- kAEOpenApplication,
- NewAEEventHandlerUPP(AEH_Start),
- 0L,
- FALSE);
-
- /* Install the quit event hook (ignore error codes) */
- AEInstallEventHandler(
- kCoreEventClass,
- kAEQuitApplication,
- NewAEEventHandlerUPP(AEH_Quit),
- 0L,
- FALSE);
-
- /* Install the print event hook (ignore error codes) */
- AEInstallEventHandler(
- kCoreEventClass,
- kAEPrintDocuments,
- NewAEEventHandlerUPP(AEH_Print),
- 0L,
- FALSE);
-
- /* Install the open event hook (ignore error codes) */
- AEInstallEventHandler(
- kCoreEventClass,
- kAEOpenDocuments,
- NewAEEventHandlerUPP(AEH_Open),
- 0L,
- FALSE);
-
-
-#ifndef MACH_O_CARBON
-
- /* Find the current application */
- SetupAppDir();
-
-#endif /* !MACH_O_CARBON */
-
- /* Mark ourself as the file creator */
- _fcreator = ANGBAND_CREATOR;
-
- /* Default to saving a "text" file */
- _ftype = 'TEXT';
-
-
- /* Hook in some "z-virt.c" hooks */
- rnfree_aux = hook_rnfree;
- ralloc_aux = hook_ralloc;
- rpanic_aux = hook_rpanic;
-
- /* Hooks in some "z-util.c" hooks */
- plog_aux = hook_plog;
- quit_aux = hook_quit;
- core_aux = hook_core;
-
-
- /* Initialize colors */
- for (i = 0; i < 256; i++)
- {
- u16b rv, gv, bv;
-
- /* Extract the R,G,B data */
- rv = angband_color_table[i][1];
- gv = angband_color_table[i][2];
- bv = angband_color_table[i][3];
-
- /* Save the actual color */
- color_info[i].red = (rv | (rv << 8));
- color_info[i].green = (gv | (gv << 8));
- color_info[i].blue = (bv | (bv << 8));
- }
-
-
- /* Show the "watch" cursor */
- SetCursor(*(GetCursor(watchCursor)));
-
- /* Prepare the menubar */
- init_menubar();
-
- /* Prepare the windows */
- init_windows();
-
- /* Hack -- process all events */
- while (CheckEvents(FALSE)) /* loop */;
-
- /* Reset the cursor */
- {
- Cursor tempCursor;
-
- SetCursor(GetQDGlobalsArrow(&tempCursor));
- }
-
- /* Mega-Hack -- Allocate a "lifeboat" */
- lifeboat = NewPtr(16384);
-
-#ifdef USE_QT_SOUND
-
- /* Load sound effect resources */
- load_sounds();
-
-#endif /* USE_QT_SOUND */
-
- /* Note the "system" */
- ANGBAND_SYS = "mac";
-
- if (check_create_user_dir() == FALSE)
- quit("Cannot create directory " PRIVATE_USER_PATH);
-
- /* Initialize */
- init_stuff();
-
- /* Initialize */
- init_angband();
-
-
- /* Hack -- process all events */
- while (CheckEvents(FALSE)) /* loop */;
-
-
- /* We are now initialized */
- initialized = TRUE;
-
-
- /* 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;
-
- /* Wait for keypress */
- pause_line(23);
-
- /* flush input - Warning: without this, _system_ would hang */
- flush();
-
- /* Play the game - note the value of the argument */
- play_game(FALSE);
-
- /* Quit */
- quit(NULL);
-
- /* Since it's a int function */
- return (0);
-#endif /* !SAVEFILE_SCREEN */
-}
-
-#endif /* MACINTOSH || MACH_O_CARBON */
-
diff --git a/src/main-gcu.c b/src/main-gcu.c
index 57c41703..ac41272c 100644
--- a/src/main-gcu.c
+++ b/src/main-gcu.c
@@ -38,11 +38,10 @@
* Consider the use of "savetty()" and "resetty()". XXX XXX XXX
*/
+#include "main.h"
+#include "util.h"
+#include "variable.h"
-#include "angband.h"
-
-
-#ifdef USE_GCU
#include <limits.h>
@@ -82,7 +81,7 @@
# if defined(_POSIX_VERSION)
# define USE_TPOSIX
# else
-# if defined(USG) || defined(linux) || defined(SOLARIS)
+# if defined(linux)
# define USE_TERMIO
# else
# define USE_TCHARS
@@ -122,11 +121,6 @@
#include <unistd.h>
#include <dirent.h>
-/* /me pffts Solaris */
-#ifndef NAME_MAX
-#define NAME_MAX _POSIX_NAME_MAX
-#endif
-
/*
@@ -451,7 +445,7 @@ static errr Term_xtra_gcu_alive(int v)
keymap_norm();
/* Restore modes */
- nocbreak();
+ noraw();
echo();
nl();
@@ -482,7 +476,7 @@ static errr Term_xtra_gcu_alive(int v)
/* (void)wrefresh(curscr); */
/* Restore the settings */
- cbreak();
+ raw();
noecho();
nonl();
@@ -561,60 +555,6 @@ static void Term_nuke_gcu(term *t)
}
-
-
-#ifdef USE_GETCH
-
-/*
- * Process events, with optional wait
- */
-static errr Term_xtra_gcu_event(int v)
-{
- int i, k;
-
- /* Wait */
- if (v)
- {
- /* Paranoia -- Wait for it */
- nodelay(stdscr, FALSE);
-
- /* Get a keypress */
- i = getch();
-
- /* Mega-Hack -- allow graceful "suspend" */
- for (k = 0; (k < 10) && (i == ERR); k++) i = getch();
-
- /* Broken input is special */
- if (i == ERR) abort();
- if (i == EOF) abort();
- }
-
- /* Do not wait */
- else
- {
- /* Do not wait for it */
- nodelay(stdscr, TRUE);
-
- /* Check for keypresses */
- i = getch();
-
- /* Wait for it next time */
- nodelay(stdscr, FALSE);
-
- /* None ready */
- if (i == ERR) return (1);
- if (i == EOF) return (1);
- }
-
- /* Enqueue the keypress */
- Term_keypress(i);
-
- /* Success */
- return (0);
-}
-
-#else /* USE_GETCH */
-
/*
* Process events (with optional wait)
*/
@@ -663,7 +603,6 @@ static errr Term_xtra_gcu_event(int v)
return (0);
}
-#endif /* USE_GETCH */
/*
* React to changes
@@ -721,14 +660,6 @@ static errr Term_xtra_gcu(int n, int v)
(void)wrefresh(td->win);
return (0);
-#ifdef USE_CURS_SET
-
- /* Change the cursor visibility */
- case TERM_XTRA_SHAPE:
- curs_set(v);
- return (0);
-
-#endif
/* Suspend/Resume curses */
case TERM_XTRA_ALIVE:
@@ -743,53 +674,6 @@ static errr Term_xtra_gcu(int n, int v)
while (!Term_xtra_gcu_event(FALSE));
return (0);
- /* Delay */
- case TERM_XTRA_DELAY:
- usleep(1000 * v);
- return (0);
-
- /* Get Delay of some milliseconds */
- case TERM_XTRA_GET_DELAY:
- {
- int ret;
- struct timeval tv;
-
- ret = gettimeofday(&tv, NULL);
- Term_xtra_long = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
-
- return ret;
- }
-
- /* Subdirectory scan */
- case TERM_XTRA_SCANSUBDIR:
- {
- DIR *directory;
- struct dirent *entry;
-
- scansubdir_max = 0;
-
- directory = opendir(scansubdir_dir);
- if (!directory)
- return 1;
-
- while ((entry = readdir(directory)))
- {
- char file[PATH_MAX + NAME_MAX + 2];
- struct stat filedata;
-
- file[PATH_MAX + NAME_MAX] = 0;
- strncpy(file, scansubdir_dir, PATH_MAX);
- strncat(file, "/", 2);
- strncat(file, entry->d_name, NAME_MAX);
- if (!stat(file, &filedata) && S_ISDIR((filedata.st_mode)))
- {
- string_free(scansubdir_result[scansubdir_max]);
- scansubdir_result[scansubdir_max] = string_make(entry->d_name);
- ++scansubdir_max;
- }
- }
- }
-
/* React to events */
case TERM_XTRA_REACT:
Term_xtra_gcu_react();
@@ -817,41 +701,13 @@ static errr Term_curs_gcu(int x, int y)
/*
- * Erase a grid of space
- * Hack -- try to be "semi-efficient".
- */
-static errr Term_wipe_gcu(int x, int y, int n)
-{
- term_data *td = (term_data *)(Term->data);
-
- /* Place cursor */
- wmove(td->win, y, x);
-
- /* Clear to end of line */
- if (x + n >= td->t.wid)
- {
- wclrtoeol(td->win);
- }
-
- /* Clear some characters */
- else
- {
- while (n-- > 0) waddch(td->win, ' ');
- }
-
- /* Success */
- return (0);
-}
-
-
-/*
* Place some text on the screen using an attribute
*/
static errr Term_text_gcu(int x, int y, int n, byte a, cptr s)
{
term_data *td = (term_data *)(Term->data);
- int i, pic;
+ int i;
#ifdef A_COLOR
/* Set the color */
@@ -864,41 +720,6 @@ static errr Term_text_gcu(int x, int y, int n, byte a, cptr s)
/* Draw each character */
for (i = 0; i < n; i++)
{
-#ifdef USE_GRAPHICS
- /* Special character */
- if (use_graphics && (s[i] & 0x80))
- {
- /* Determine picture to use */
- switch (s[i] & 0x7F)
- {
-
-#ifdef ACS_CKBOARD
- /* Wall */
- case '#':
- pic = ACS_CKBOARD;
- break;
-#endif /* ACS_CKBOARD */
-
-#ifdef ACS_BOARD
- /* Mineral vein */
- case '%':
- pic = ACS_BOARD;
- break;
-#endif /* ACS_BOARD */
-
- /* XXX */
- default:
- pic = '?';
- break;
- }
-
- /* Draw the picture */
- waddch(td->win, pic);
-
- /* Next character */
- continue;
- }
-#endif
/* Draw a normal character */
waddch(td->win, (byte)s[i]);
@@ -934,17 +755,12 @@ static errr term_data_init_gcu(term_data *td, int rows, int cols, int y, int x)
/* Avoid bottom right corner */
t->icky_corner = TRUE;
- /* Erase with "white space" */
- t->attr_blank = TERM_WHITE;
- t->char_blank = ' ';
-
/* Set some hooks */
t->init_hook = Term_init_gcu;
t->nuke_hook = Term_nuke_gcu;
/* Set some more hooks */
t->text_hook = Term_text_gcu;
- t->wipe_hook = Term_wipe_gcu;
t->curs_hook = Term_curs_gcu;
t->xtra_hook = Term_xtra_gcu;
@@ -977,7 +793,7 @@ static void hook_quit(cptr str)
*
* Someone should really check the semantics of "initscr()"
*/
-errr init_gcu(int argc, char **argv)
+int init_gcu(int argc, char **argv)
{
int i;
@@ -995,7 +811,7 @@ errr init_gcu(int argc, char **argv)
continue;
}
- plog_fmt("Ignoring option: %s", argv[i]);
+ fprintf(stderr, "Ignoring option: %s", argv[i]);
}
@@ -1003,17 +819,11 @@ errr init_gcu(int argc, char **argv)
keymap_norm_prepare();
-#if defined(USG)
- /* Initialize for USG Unix */
- if (initscr() == NULL) return ( -1);
-#else
/* Initialize for other systems */
if (initscr() == (WINDOW*)ERR) return ( -1);
-#endif
/* Activate hooks */
quit_aux = hook_quit;
- core_aux = hook_quit;
/* Require standard size screen */
if ((LINES < 24) || (COLS < 80))
@@ -1022,12 +832,6 @@ errr init_gcu(int argc, char **argv)
}
-#ifdef USE_GRAPHICS
-
- /* Set graphics flag */
- use_graphics = arg_graphics;
-
-#endif
#ifdef A_COLOR
@@ -1106,15 +910,9 @@ errr init_gcu(int argc, char **argv)
/*** Low level preparation ***/
-#ifdef USE_GETCH
-
- /* Paranoia -- Assume no waiting */
- nodelay(stdscr, FALSE);
-
-#endif
/* Prepare */
- cbreak();
+ raw();
noecho();
nonl();
@@ -1216,7 +1014,12 @@ errr init_gcu(int argc, char **argv)
return (0);
}
-
-#endif /* USE_GCU */
-
-
+int main(int argc, char *argv[])
+{
+ return main_real(
+ argc,
+ argv,
+ "gcu",
+ init_gcu,
+ " -- -b Requests big screen\n");
+}
diff --git a/src/main-gtk2.c b/src/main-gtk2.c
index 4830638a..124802c3 100644
--- a/src/main-gtk2.c
+++ b/src/main-gtk2.c
@@ -30,63 +30,12 @@
* and reorganised the file a bit.
*/
-#include "angband.h"
+#include "files.h"
+#include "main.h"
+#include "util.h"
+#include "variable.h"
-/*
- * Activate variant-specific features
- *
- * Angband 2.9.3 and close variants don't require any.
- *
- * Angband 2.9.4 alpha and later removed the short-lived
- * can_save flag, so please #define can_save TRUE, or remove
- * all the references to it. They also changed long-lived
- * 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 and ANG281_RESET_VISUALS.
- *
- * [O] needs ANG293_COMPAT and ZANG_SAVE_GAME.
- *
- * ZAngband has its own enhanced main-gtk.c as mentioned above, and
- * you *should* use it :-)
- *
- */
-#define TOME
-
-#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 */
-
-/*
- * 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 */
-# 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 */
-#endif /* OANGBAND */
-
-
-#ifdef USE_GTK2
-
/* Force ANSI standard */
/* #define __STRICT_ANSI__ */
@@ -99,19 +48,7 @@
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
-
-/* /me pffts Solaris */
-#ifndef NAME_MAX
-#define NAME_MAX _POSIX_NAME_MAX
-#endif
-
-
-/*
- * Include some helpful X11 code.
- */
-#ifndef ANG293_COMPAT
-# include "maid-x11.h"
-#endif /* !ANG293_COMPAT */
+#include <assert.h>
/*
@@ -134,22 +71,6 @@
* back to the term_data structure.
*/
-#ifdef USE_GRAPHICS
-
-/*
- * Since GdkRGB doesn't provide us some useful functions...
- */
-typedef struct GdkRGBImage GdkRGBImage;
-
-struct GdkRGBImage
-{
- gint width;
- gint height;
- gint ref_count;
- guchar *image;
-};
-
-#endif /* USE_GRAPHICS */
/*
@@ -176,18 +97,8 @@ struct term_data
int rows;
int cols;
-#ifdef USE_GRAPHICS
-
- int tile_wid;
- int tile_hgt;
- GdkRGBImage *tiles;
- guint32 bg_pixel;
- GdkRGBImage *trans_buf;
-
-#endif /* USE_GRAPHICS */
-
- cptr name;
+ char *name;
};
@@ -210,36 +121,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"
*/
@@ -277,8 +158,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.
*/
@@ -309,69 +188,11 @@ 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
*/
#define can_save TRUE
-#endif /* ANG293_COMPAT */
-
-
-#ifdef ANG291_COMPAT
-
-/*
- * The standard game uses this to implement lighting effects
- * for 16x16 tiles in cave.c...
- *
- * Because of the way it is implemented in X11 ports,
- * we can set this to TRUE even if we are using the 8x8 tileset.
- */
-static bool_ use_transparency = TRUE;
-
-#endif /* ANG291_COMPAT */
-
-
-
-
-/**** Low level routines - memory allocation ****/
-
-/*
- * 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);
-
- /* Success */
- return (NULL);
-}
-
-
-/*
- * Hook to "allocate" memory
- */
-static vptr hook_ralloc(huge size)
-{
- /* Make a new pointer */
- return (g_malloc(size));
-}
@@ -425,1868 +246,6 @@ static void term_data_set_fg(term_data *td, byte attr)
}
-#ifdef USE_GRAPHICS
-
-/*
- * Graphics mode selector - current setting and requested value
- */
-#define GRAF_MODE_NONE 0
-#define GRAF_MODE_OLD 1
-#define GRAF_MODE_NEW 2
-
-static int graf_mode = GRAF_MODE_NONE;
-static int graf_mode_request = GRAF_MODE_NONE;
-
-/*
- * Use smooth rescaling?
- */
-static bool_ smooth_rescaling = TRUE;
-static bool_ smooth_rescaling_request = TRUE;
-
-/*
- * Dithering
- */
-static GdkRgbDither dith_mode = GDK_RGB_DITHER_NORMAL;
-
-/*
- * Need to reload and resize tiles when fonts are changed.
- */
-static bool_ resize_request = FALSE;
-
-/*
- * Numbers of columns and rows in current tileset
- * calculated and set by the tile loading code in graf_init()
- * and used by Term_pict_gtk()
- */
-static int tile_rows;
-static int tile_cols;
-
-
-/*
- * Directory name(s)
- */
-static cptr ANGBAND_DIR_XTRA_GRAF;
-
-
-/*
- * Be nice to old graphics hardwares -- using GdkRGB.
- *
- * We don't have colour allocation failure any longer this way,
- * even with 8bpp X servers. Gimp *does* work with 8bpp, why not Angband?
- *
- * Initialisation (before any widgets are created)
- * gdk_rgb_init();
- * gtk_widget_set_default_colormap (gdk_rgb_get_cmap());
- * gtk_widget_set_default_visual (gdk_rgb_get_visual());
- *
- * Setting fg/bg colours
- * void gdk_rgb_gc_set_foreground(GdkGC *gc, guint32 rgb);
- * void gdk_rgb_gc_set_background(GdkGC *gc, guint32 rgb);
- * where rgb is 0xRRGGBB.
- *
- * Drawing rgb images
- * void gdk_draw_rgb_image(
- * GdkDrawable *drawable,
- * GdkGC *gc,
- * gint x, gint y,
- * gint width, gint height,
- * GdkRgbDither dith,
- * guchar *rgb_buf,
- * gint rowstride);
- *
- * dith:
- * GDK_RGB_DITHER_NORMAL : dither if 8bpp or below
- * GDK_RGB_DITHER_MAX : dither if 16bpp or below.
- *
- * for 0 <= i < width and 0 <= j < height,
- * the pixel (x + i, y + j) is colored with
- * red value rgb_buf[j * rowstride + i * 3],
- * green value rgb_buf[j * rowstride + i * 3 + 1], and
- * blue value rgb_buf[j * rowstride + i * 3 + 2].
- */
-
-/*
- * gdk_image compatibility functions - should be part of gdk, IMHO.
- */
-
-/*
- * Create GdkRGBImage of width * height and return pointer
- * to it. Returns NULL on failure
- */
-static GdkRGBImage *gdk_rgb_image_new(
- gint width,
- gint height)
-{
- GdkRGBImage *result;
-
- /* Allocate a struct */
- result = g_new(GdkRGBImage, 1);
-
- /* Oops */
- if (result == NULL) return (NULL);
-
- /* Allocate buffer */
- result->image = g_new0(guchar, width * height * 3);
-
- /* Oops */
- if (result->image == NULL)
- {
- g_free(result);
- return (NULL);
- }
-
- /* Initialise size fields */
- result->width = width;
- result->height = height;
-
- /* Initialise reference count */
- result->ref_count = 1;
-
- /* Success */
- return (result);
-}
-
-/*
- * Free a GdkRGBImage
- */
-static void gdk_rgb_image_destroy(
- GdkRGBImage *im)
-{
- /* Paranoia */
- if (im == NULL) return;
-
- /* Free the RGB buffer */
- g_free(im->image);
-
- /* Free the structure */
- g_free(im);
-}
-
-
-#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
- */
-static void gdk_rgb_image_put_pixel(
- GdkRGBImage *im,
- gint x,
- gint y,
- guint32 pixel)
-{
- guchar *rgbp;
-
- /* Paranoia */
- g_return_if_fail(im != NULL);
-
- /* Paranoia */
- if ((x < 0) || (x >= im->width)) return;
-
- /* Paranoia */
- if ((y < 0) || (y >= im->height)) return;
-
- /* Access RGB data */
- rgbp = &im->image[(y * im->width * 3) + (x * 3)];
-
- /* Red */
- *rgbp++ = (pixel >> 16) & 0xFF;
- /* Green */
- *rgbp++ = (pixel >> 8) & 0xFF;
- /* Blue */
- *rgbp = pixel & 0xFF;
-}
-
-
-/*
- * Returns RGB pixel (0xRRGGBB) at (x, y) in GdkRGBImage
- */
-static guint32 gdk_rgb_image_get_pixel(
- GdkRGBImage *im,
- gint x,
- gint y)
-{
- guchar *rgbp;
-
- /* Paranoia */
- if (im == NULL) return (0);
-
- /* Paranoia - returns black */
- if ((x < 0) || (x >= im->width)) return (0);
-
- /* Paranoia */
- if ((y < 0) || (y >= im->height)) return (0);
-
- /* Access RGB data */
- rgbp = &im->image[(y * im->width * 3) + (x * 3)];
-
- /* Return result */
- return ((rgbp[0] << 16) | (rgbp[1] << 8) | (rgbp[2]));
-}
-
-
-/*
- * Since gdk_draw_rgb_image is a bit harder to use than it's
- * GdkImage counterpart, I wrote a grue function that takes
- * exactly the same parameters as gdk_draw_image, with
- * the GdkImage parameter replaced with GdkRGBImage.
- */
-static void gdk_draw_rgb_image_2(
- GdkDrawable *drawable,
- GdkGC *gc,
- GdkRGBImage *image,
- gint xsrc,
- gint ysrc,
- gint xdest,
- gint ydest,
- gint width,
- gint height)
-{
- /* Paranoia */
- g_return_if_fail(drawable != NULL);
- g_return_if_fail(image != NULL);
-
- /* Paranoia */
- if (xsrc < 0 || (xsrc + width - 1) >= image->width) return;
- if (ysrc < 0 || (ysrc + height - 1) >= image->height) return;
-
- /* Draw the image at (xdest, ydest), with dithering if bpp <= 8/16 */
- gdk_draw_rgb_image(
- drawable,
- gc,
- xdest,
- ydest,
- width,
- height,
- dith_mode,
- &image->image[(ysrc * image->width * 3) + (xsrc * 3)],
- image->width * 3);
-}
-
-
-/*
- * Code for smooth icon rescaling from Uwe Siems, Jan 2000
- *
- * XXX XXX Duplication of maid-x11.c, again. It doesn't do any colour
- * allocation, either.
- */
-
-/*
- * to save ourselves some labour, define a maximum expected icon width here:
- */
-#define MAX_ICON_WIDTH 32
-
-
-/*
- * Each pixel is kept in this structure during smooth rescaling
- * calculations, to make things a bit easier
- */
-typedef struct rgb_type rgb_type;
-
-struct rgb_type
-{
- guint32 red;
- guint32 green;
- guint32 blue;
-};
-
-/*
- * Because there are many occurences of this, and because
- * it's logical to do so...
- */
-#define pixel_to_rgb(pix, rgb_buf) \
-(rgb_buf)->red = ((pix) >> 16) & 0xFF; \
-(rgb_buf)->green = ((pix) >> 8) & 0xFF; \
-(rgb_buf)->blue = (pix) & 0xFF
-
-
-/*
- * get_scaled_row reads a scan from the given GdkRGBImage, scales it smoothly
- * and returns the red, green and blue values in arrays.
- * The values in this arrays must be divided by a certain value that is
- * calculated in scale_icon.
- * x, y is the position, iw is the input width and ow the output width
- * scan must be sufficiently sized
- */
-static void get_scaled_row(
- GdkRGBImage *im,
- int x,
- int y,
- int iw,
- int ow,
- rgb_type *scan)
-{
- int xi, si, sifrac, ci, cifrac, add_whole, add_frac;
- guint32 pix;
- rgb_type prev;
- rgb_type next;
- bool_ get_next_pix;
-
- /* Unscaled */
- if (iw == ow)
- {
- for (xi = 0; xi < ow; xi++)
- {
- pix = gdk_rgb_image_get_pixel(im, x + xi, y);
- pixel_to_rgb(pix, &scan[xi]);
- }
- }
-
- /* Scaling by subsampling (grow) */
- else if (iw < ow)
- {
- iw--;
- ow--;
-
- /* read first pixel: */
- pix = gdk_rgb_image_get_pixel(im, x, y);
- pixel_to_rgb(pix, &next);
- prev = next;
-
- /* si and sifrac give the subsampling position: */
- si = x;
- sifrac = 0;
-
- /* get_next_pix tells us, that we need the next pixel */
- get_next_pix = TRUE;
-
- for (xi = 0; xi <= ow; xi++)
- {
- if (get_next_pix)
- {
- prev = next;
- if (xi < ow)
- {
- /* only get next pixel if in same icon */
- pix = gdk_rgb_image_get_pixel(im, si + 1, y);
- pixel_to_rgb(pix, &next);
- }
- }
-
- /* calculate subsampled color values: */
- /* division by ow occurs in scale_icon */
- scan[xi].red = prev.red * (ow - sifrac) + next.red * sifrac;
- scan[xi].green = prev.green * (ow - sifrac) + next.green * sifrac;
- scan[xi].blue = prev.blue * (ow - sifrac) + next.blue * sifrac;
-
- /* advance sampling position: */
- sifrac += iw;
- if (sifrac >= ow)
- {
- si++;
- sifrac -= ow;
- get_next_pix = TRUE;
- }
- else
- {
- get_next_pix = FALSE;
- }
-
- }
- }
-
- /* Scaling by averaging (shrink) */
- else
- {
- /* width of an output pixel in input pixels: */
- add_whole = iw / ow;
- add_frac = iw % ow;
-
- /* start position of the first output pixel: */
- si = x;
- sifrac = 0;
-
- /* get first input pixel: */
- pix = gdk_rgb_image_get_pixel(im, x, y);
- pixel_to_rgb(pix, &next);
-
- for (xi = 0; xi < ow; xi++)
- {
- /* find endpoint of the current output pixel: */
- ci = si + add_whole;
- cifrac = sifrac + add_frac;
- if (cifrac >= ow)
- {
- ci++;
- cifrac -= ow;
- }
-
- /* take fraction of current input pixel (starting segment): */
- scan[xi].red = next.red * (ow - sifrac);
- scan[xi].green = next.green * (ow - sifrac);
- scan[xi].blue = next.blue * (ow - sifrac);
- si++;
-
- /* add values for whole pixels: */
- while (si < ci)
- {
- rgb_type tmp_rgb;
-
- pix = gdk_rgb_image_get_pixel(im, si, y);
- pixel_to_rgb(pix, &tmp_rgb);
- scan[xi].red += tmp_rgb.red * ow;
- scan[xi].green += tmp_rgb.green * ow;
- scan[xi].blue += tmp_rgb.blue * ow;
- si++;
- }
-
- /* add fraction of current input pixel (ending segment): */
- if (xi < ow - 1)
- {
- /* only get next pixel if still in icon: */
- pix = gdk_rgb_image_get_pixel(im, si, y);
- pixel_to_rgb(pix, &next);
- }
-
- sifrac = cifrac;
- if (sifrac > 0)
- {
- scan[xi].red += next.red * sifrac;
- scan[xi].green += next.green * sifrac;
- scan[xi].blue += next.blue * sifrac;
- }
- }
- }
-}
-
-
-/*
- * put_rgb_scan takes arrays for red, green and blue and writes pixel values
- * according to this values in the GdkRGBImage-structure. w is the number of
- * pixels to write and div is the value by which all red/green/blue values
- * are divided first.
- */
-static void put_rgb_scan(
- GdkRGBImage *im,
- int x,
- int y,
- int w,
- int div,
- rgb_type *scan)
-{
- int xi;
- guint32 pix;
- guint32 adj = div / 2;
-
- for (xi = 0; xi < w; xi++)
- {
- byte r, g, b;
-
- /* un-factor the RGB values */
- r = (scan[xi].red + adj) / div;
- g = (scan[xi].green + adj) / div;
- b = (scan[xi].blue + adj) / div;
-
- /* Make a (virtual) 24-bit pixel */
- pix = (r << 16) | (g << 8) | (b);
-
- /* Draw it into image */
- gdk_rgb_image_put_pixel(im, x + xi, y, pix);
- }
-}
-
-
-/*
- * scale_icon transfers an area from GdkRGBImage im_in, locate (x1,y1) to
- * im_out, locate (x2, y2). Source size is (ix, iy) and destination size
- * is (ox, oy).
- *
- * It does this by getting icon scan line from get_scaled_scan and handling
- * them the same way as pixels are handled in get_scaled_scan.
- * This even allows icons to be scaled differently in horizontal and
- * vertical directions (eg. shrink horizontal, grow vertical).
- */
-static void scale_icon(
- GdkRGBImage *im_in,
- GdkRGBImage *im_out,
- int x1,
- int y1,
- int x2,
- int y2,
- int ix,
- int iy,
- int ox,
- int oy)
-{
- int div;
- int xi, yi, si, sifrac, ci, cifrac, add_whole, add_frac;
-
- /* buffers for pixel rows: */
- rgb_type prev[MAX_ICON_WIDTH];
- rgb_type next[MAX_ICON_WIDTH];
- rgb_type temp[MAX_ICON_WIDTH];
-
- bool_ get_next_row;
-
- /* get divider value for the horizontal scaling: */
- if (ix == ox)
- div = 1;
- else if (ix < ox)
- div = ox - 1;
- else
- div = ix;
-
- /* no scaling needed vertically: */
- if (iy == oy)
- {
- for (yi = 0; yi < oy; yi++)
- {
- get_scaled_row(im_in, x1, y1 + yi, ix, ox, temp);
- put_rgb_scan(im_out, x2, y2 + yi, ox, div, temp);
- }
- }
-
- /* scaling by subsampling (grow): */
- else if (iy < oy)
- {
- iy--;
- oy--;
- div *= oy;
-
- /* get first row: */
- get_scaled_row(im_in, x1, y1, ix, ox, next);
-
- /* si and sifrac give the subsampling position: */
- si = y1;
- sifrac = 0;
-
- /* get_next_row tells us, that we need the next row */
- get_next_row = TRUE;
- for (yi = 0; yi <= oy; yi++)
- {
- if (get_next_row)
- {
- for (xi = 0; xi < ox; xi++)
- {
- prev[xi] = next[xi];
- }
- if (yi < oy)
- {
- /* only get next row if in same icon */
- get_scaled_row(im_in, x1, si + 1, ix, ox, next);
- }
- }
-
- /* calculate subsampled color values: */
- /* division by oy occurs in put_rgb_scan */
- for (xi = 0; xi < ox; xi++)
- {
- temp[xi].red = (prev[xi].red * (oy - sifrac) +
- next[xi].red * sifrac);
- temp[xi].green = (prev[xi].green * (oy - sifrac) +
- next[xi].green * sifrac);
- temp[xi].blue = (prev[xi].blue * (oy - sifrac) +
- next[xi].blue * sifrac);
- }
-
- /* write row to output image: */
- put_rgb_scan(im_out, x2, y2 + yi, ox, div, temp);
-
- /* advance sampling position: */
- sifrac += iy;
- if (sifrac >= oy)
- {
- si++;
- sifrac -= oy;
- get_next_row = TRUE;
- }
- else
- {
- get_next_row = FALSE;
- }
-
- }
- }
-
- /* scaling by averaging (shrink) */
- else
- {
- div *= iy;
-
- /* height of a output row in input rows: */
- add_whole = iy / oy;
- add_frac = iy % oy;
-
- /* start position of the first output row: */
- si = y1;
- sifrac = 0;
-
- /* get first input row: */
- get_scaled_row(im_in, x1, y1, ix, ox, next);
- for (yi = 0; yi < oy; yi++)
- {
- /* find endpoint of the current output row: */
- ci = si + add_whole;
- cifrac = sifrac + add_frac;
- if (cifrac >= oy)
- {
- ci++;
- cifrac -= oy;
- }
-
- /* take fraction of current input row (starting segment): */
- for (xi = 0; xi < ox; xi++)
- {
- temp[xi].red = next[xi].red * (oy - sifrac);
- temp[xi].green = next[xi].green * (oy - sifrac);
- temp[xi].blue = next[xi].blue * (oy - sifrac);
- }
- si++;
-
- /* add values for whole pixels: */
- while (si < ci)
- {
- get_scaled_row(im_in, x1, si, ix, ox, next);
- for (xi = 0; xi < ox; xi++)
- {
- temp[xi].red += next[xi].red * oy;
- temp[xi].green += next[xi].green * oy;
- temp[xi].blue += next[xi].blue * oy;
- }
- si++;
- }
-
- /* add fraction of current input row (ending segment): */
- if (yi < oy - 1)
- {
- /* only get next row if still in icon: */
- get_scaled_row(im_in, x1, si, ix, ox, next);
- }
- sifrac = cifrac;
- for (xi = 0; xi < ox; xi++)
- {
- temp[xi].red += next[xi].red * sifrac;
- temp[xi].green += next[xi].green * sifrac;
- temp[xi].blue += next[xi].blue * sifrac;
- }
-
- /* write row to output image: */
- put_rgb_scan(im_out, x2, y2 + yi, ox, div, temp);
- }
- }
-}
-
-
-/*
- * Rescale icons using sort of anti-aliasing technique.
- */
-static GdkRGBImage *resize_tiles_smooth(
- GdkRGBImage *im,
- int ix,
- int iy,
- int ox,
- int oy)
-{
- int width1, height1, width2, height2;
- int x1, x2, y1, y2;
-
- GdkRGBImage *tmp;
-
- /* Original size */
- width1 = im->width;
- height1 = im->height;
-
- /* Rescaled size */
- width2 = ox * width1 / ix;
- height2 = oy * height1 / iy;
-
- /* Allocate GdkRGBImage for resized tiles */
- tmp = gdk_rgb_image_new(width2, height2);
-
- /* Oops */
- if (tmp == NULL) return (NULL);
-
- /* Scale each icon */
- for (y1 = 0, y2 = 0; (y1 < height1) && (y2 < height2); y1 += iy, y2 += oy)
- {
- for (x1 = 0, x2 = 0; (x1 < width1) && (x2 < width2); x1 += ix, x2 += ox)
- {
- scale_icon(im, tmp, x1, y1, x2, y2,
- ix, iy, ox, oy);
- }
- }
-
- return tmp;
-}
-
-
-/*
- * Steven Fuerst's tile resizing code
- * Taken from Z because I think the algorithm is cool.
- */
-
-/* 24-bit version - GdkRGB uses 24 bit RGB data internally */
-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 * 3];
- byte *dst = &new_image->image[y * new_image->width * 3];
-
- /* Copy to the image */
- for (i = 0; i < wid; i++)
- {
- *dst++ = src[3 * xoffsets[i]];
- *dst++ = src[3 * xoffsets[i] + 1];
- *dst++ = src[3 * xoffsets[i] + 2];
- }
-}
-
-
-#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
- */
-static GdkRGBImage *resize_tiles_fast(
- GdkRGBImage *old_image,
- int ix,
- int iy,
- int ox,
- int oy)
-{
- GdkRGBImage *new_image;
-
- int old_wid, old_hgt;
-
- int new_wid, new_hgt;
-
- int add, remainder, rem_tot, offset;
-
- int *xoffsets;
-
- int i;
-
-
- /* Get the size of the old image */
- old_wid = old_image->width;
- old_hgt = old_image->height;
-
- /* Calculate the size of the new image */
- new_wid = (old_wid / ix) * ox;
- new_hgt = (old_hgt / iy) * oy;
-
- /* Allocate a GdkRGBImage to store resized tiles */
- new_image = gdk_rgb_image_new(new_wid, new_hgt);
-
- /* Paranoia */
- if (new_image == NULL) return (NULL);
-
- /* now begins the cool part of SF's code */
-
- /*
- * Calculate an offsets table, so the transformation
- * is faster. This is much like the Bresenham algorithm
- */
-
- /* Set up x offset table */
- C_MAKE(xoffsets, new_wid, int);
-
- /* Initialize line parameters */
- add = old_wid / new_wid;
- remainder = old_wid % new_wid;
-
- /* Start at left */
- offset = 0;
-
- /* Half-tile offset so 'line' is centered correctly */
- rem_tot = new_wid / 2;
-
- for (i = 0; i < new_wid; i++)
- {
- /* Store into the table */
- xoffsets[i] = offset;
-
- /* Move to next entry */
- offset += add;
-
- /* Take care of fractional part */
- rem_tot += remainder;
- if (rem_tot >= new_wid)
- {
- rem_tot -= new_wid;
- offset++;
- }
- }
-
- /* Scan each row */
-
- /* Initialize line parameters */
- add = old_hgt / new_hgt;
- remainder = old_hgt % new_hgt;
-
- /* Start at left */
- offset = 0;
-
- /* Half-tile offset so 'line' is centered correctly */
- rem_tot = new_hgt / 2;
-
- for (i = 0; i < new_hgt; i++)
- {
- /* Copy pixels to new image */
- copy_pixels(new_wid, i, offset, xoffsets, old_image, new_image);
-
- /* Move to next entry */
- offset += add;
-
- /* Take care of fractional part */
- rem_tot += remainder;
- if (rem_tot >= new_hgt)
- {
- rem_tot -= new_hgt;
- offset++;
- }
- }
-
- /* Free offset table */
- C_FREE(xoffsets, new_wid, int);
-
- return (new_image);
-}
-
-
-/*
- * Resize an image of ix * iy pixels and return a newly allocated
- * image of ox * oy pixels.
- */
-static GdkRGBImage *resize_tiles(
- GdkRGBImage *im,
- int ix,
- int iy,
- int ox,
- int oy)
-{
- GdkRGBImage *result;
-
- /*
- * I hope we can always use this with GdkRGB, which uses a 5x5x5
- * colour cube (125 colours) by default, and resort to dithering
- * when it can't find good match there or expand the cube, so it
- * works with 8bpp X servers.
- */
- if (smooth_rescaling_request && (ix != ox || iy != oy))
- {
- result = resize_tiles_smooth(im, ix, iy, ox, oy);
- }
-
- /*
- * Unless smoothing is requested by user, we use the fast
- * resizing code.
- */
- else
- {
- result = resize_tiles_fast(im, ix, iy, ox, oy);
- }
-
- /* Return rescaled tiles, or NULL */
- return (result);
-}
-
-
-/*
- * Tile loaders - XPM and BMP
- */
-
-/*
- * A helper function for the XPM loader
- *
- * Read next string delimited by double quotes from
- * the input stream. Return TRUE on success, FALSE
- * if it finds EOF or buffer overflow.
- *
- * I never mean this to be generic, so its EOF and buffer
- * overflow behaviour is terribly stupid -- there are no
- * provisions for recovery.
- *
- * CAVEAT: treatment of backslash is not compatible with the standard
- * C usage XXX XXX XXX XXX
- */
-static bool_ read_str(char *buf, u32b len, FILE *f)
-{
- int c;
-
- /* Paranoia - Buffer too small */
- if (len <= 0) return (FALSE);
-
- /* Find " */
- while ((c = getc(f)) != '"')
- {
- /* Premature EOF */
- if (c == EOF) return (FALSE);
- }
-
- while (1)
- {
- /* Read next char */
- c = getc(f);
-
- /* Premature EOF */
- if (c == EOF) return (FALSE);
-
- /* Terminating " */
- if (c == '"') break;
-
- /* Escape */
- if (c == '\\')
- {
- /* Use next char */
- c = getc(f);
-
- /* Premature EOF */
- if (c == EOF) return (FALSE);
- }
-
- /* Store character in the buffer */
- *buf++ = c;
-
- /* Decrement count */
- len--;
-
- /* Buffer full - we have to place a NULL at the end */
- if (len <= 0) return (FALSE);
- }
-
- /* Make a C string if there's room left */
- if (len > 0) *buf = '\0';
-
- /* Success */
- return (TRUE);
-}
-
-
-/*
- * Remember pixel symbol to RGB colour mappings
- */
-
-/*
- * I've forgot the formula, but I remember prime number yields
- * good results
- */
-#define HASH_SIZE 19
-
-typedef struct pal_type pal_type;
-
-struct pal_type
-{
- u32b str;
- u32b rgb;
- pal_type *next;
-};
-
-
-/*
- * A simple, slow and stupid XPM loader
- */
-static GdkRGBImage *load_xpm(cptr filename)
-{
- FILE *f;
- GdkRGBImage *img = NULL;
- int width, height, colours, chars;
- int i, j, k;
- bool_ ret;
- pal_type *pal = NULL;
- pal_type *head[HASH_SIZE];
- u32b buflen = 0;
- char *lin = NULL;
- char buf[1024];
-
- /* Build path to the XPM file */
- path_build(buf, 1024, ANGBAND_DIR_XTRA_GRAF, filename);
-
- /* Open it */
- f = my_fopen(buf, "r");
-
- /* Oops */
- if (f == NULL) return (NULL);
-
- /* Read header */
- ret = read_str(buf, 1024, f);
-
- /* Oops */
- if (!ret)
- {
- /* Notify error */
- plog("Cannot find XPM header");
-
- /* Failure */
- goto oops;
- }
-
- /* Parse header */
- if (4 != sscanf(buf, "%d %d %d %d", &width, &height, &colours, &chars))
- {
- /* Notify error */
- plog("Bad XPM header");
-
- /* Failure */
- goto oops;
- }
-
- /*
- * Paranoia - the code can handle upto four letters per pixel,
- * but such large number of colours certainly requires a smarter
- * symbol-to-colour mapping algorithm...
- */
- if ((width <= 0) || (height <= 0) || (colours <= 0) || (chars <= 0) ||
- (chars > 2))
- {
- /* Notify error */
- plog("Invalid width/height/depth");
-
- /* Failure */
- goto oops;
- }
-
- /* Allocate palette */
- C_MAKE(pal, colours, pal_type);
-
- /* Initialise hash table */
- for (i = 0; i < HASH_SIZE; i++) head[i] = NULL;
-
- /* Parse palette */
- for (i = 0; i < colours; i++)
- {
- u32b tmp;
- int h_idx;
-
- /* Read next string */
- ret = read_str(buf, 1024, f);
-
- /* Check I/O result */
- if (!ret)
- {
- /* Notify error */
- plog("EOF in palette");
-
- /* Failure */
- goto oops;
- }
-
- /* Clear symbol code */
- tmp = 0;
-
- /* Encode pixel symbol */
- for (j = 0; j < chars; j++)
- {
- tmp = (tmp << 8) | (buf[j] & 0xFF);
- }
-
- /* Remember it */
- pal[i].str = tmp;
-
- /* Skip spaces */
- while ((buf[j] == ' ') || (buf[j] == '\t')) j++;
-
- /* Verify 'c' */
- if (buf[j] != 'c')
- {
- /* Notify error */
- plog("No 'c' in palette definition");
-
- /* Failure */
- goto oops;
- }
-
- /* Advance cursor */
- j++;
-
- /* Skip spaces */
- while ((buf[j] == ' ') || (buf[j] == '\t')) j++;
-
- /* Hack - Assume 'None' */
- if (buf[j] == 'N')
- {
- /* Angband always uses black background */
- pal[i].rgb = 0x000000;
- }
-
- /* Read colour */
- else if ((1 != sscanf(&buf[j], "#%06lX", &tmp)) &&
- (1 != sscanf(&buf[j], "#%06lx", &tmp)))
- {
- /* Notify error */
- plog("Badly formatted colour");
-
- /* Failure */
- goto oops;
- }
-
- /* Remember it */
- pal[i].rgb = tmp;
-
- /* Store it in hash table as well */
- h_idx = pal[i].str % HASH_SIZE;
-
- /* Link the entry */
- pal[i].next = head[h_idx];
- head[h_idx] = &pal[i];
- }
-
- /* Allocate image */
- img = gdk_rgb_image_new(width, height);
-
- /* Oops */
- if (img == NULL)
- {
- /* Notify error */
- plog("Cannot allocate image");
-
- /* Failure */
- goto oops;
- }
-
- /* Calculate buffer length */
- buflen = width * chars + 1;
-
- /* Allocate line buffer */
- C_MAKE(lin, buflen, char);
-
- /* For each row */
- for (i = 0; i < height; i++)
- {
- /* Read a row of image data */
- ret = read_str(lin, buflen, f);
-
- /* Oops */
- if (!ret)
- {
- /* Notify error */
- plog("EOF in middle of image data");
-
- /* Failure */
- goto oops;
- }
-
- /* For each column */
- for (j = 0; j < width; j++)
- {
- u32b tmp;
- pal_type *h_ptr;
-
- /* Clear encoded pixel */
- tmp = 0;
-
- /* Encode pixel symbol */
- for (k = 0; k < chars; k++)
- {
- tmp = (tmp << 8) | (lin[j * chars + k] & 0xFF);
- }
-
- /* Find colour */
- for (h_ptr = head[tmp % HASH_SIZE];
- h_ptr != NULL;
- h_ptr = h_ptr->next)
- {
- /* Found a match */
- if (h_ptr->str == tmp) break;
- }
-
- /* No match found */
- if (h_ptr == NULL)
- {
- /* Notify error */
- plog("Invalid pixel symbol");
-
- /* Failure */
- goto oops;
- }
-
- /* Draw it */
- gdk_rgb_image_put_pixel(
- img,
- j,
- i,
- h_ptr->rgb);
- }
- }
-
- /* Close file */
- my_fclose(f);
-
- /* Free line buffer */
- C_FREE(lin, buflen, char);
-
- /* Free palette */
- C_FREE(pal, colours, pal_type);
-
- /* Return result */
- return (img);
-
-oops:
-
- /* Close file */
- my_fclose(f);
-
- /* Free image */
- if (img) gdk_rgb_image_destroy(img);
-
- /* Free line buffer */
- if (lin) C_FREE(lin, buflen, char);
-
- /* Free palette */
- if (pal) C_FREE(pal, colours, pal_type);
-
- /* Failure */
- return (NULL);
-}
-
-
-/*
- * A BMP loader, yet another duplication of maid-x11.c functions.
- *
- * Another duplication, again because of different image format and
- * avoidance of colour allocation.
- *
- * XXX XXX XXX XXX Should avoid using a propriatary and closed format.
- * Since it's much bigger than gif that was used before, why don't
- * we switch to XPM? NetHack does. Well, NH has always been much
- * closer to the GNU/Un*x camp and it's GPL'ed quite early...
- *
- * The names and naming convention are worse than the worst I've ever
- * seen, so I deliberately changed them to fit well with the rest of
- * the code. Or are they what xx calls them? If it's the case, there's
- * no reason to follow *their* words.
- */
-
-/*
- * BMP file header
- */
-typedef struct bmp_file_type bmp_file_type;
-
-struct bmp_file_type
-{
- u16b type;
- u32b size;
- u16b reserved1;
- u16b reserved2;
- u32b offset;
-};
-
-
-/*
- * BMP file information fields
- */
-typedef struct bmp_info_type bmp_info_type;
-
-struct bmp_info_type
-{
- u32b size;
- u32b width;
- u32b height;
- u16b planes;
- u16b bit_count;
- u32b compression;
- u32b size_image;
- u32b x_pels_per_meter;
- u32b y_pels_per_meter;
- u32b colors_used;
- u32b color_importand;
-};
-
-/*
- * "RGBQUAD" type.
- */
-typedef struct rgb_quad_type rgb_quad_type;
-
-struct rgb_quad_type
-{
- unsigned char b, g, r;
- unsigned char filler;
-};
-
-
-/*** Helper functions for system independent file loading. ***/
-
-static byte get_byte(FILE *fff)
-{
- /* Get a character, and return it */
- return (getc(fff) & 0xFF);
-}
-
-static void rd_byte(FILE *fff, byte *ip)
-{
- *ip = get_byte(fff);
-}
-
-static void rd_u16b(FILE *fff, u16b *ip)
-{
- (*ip) = get_byte(fff);
- (*ip) |= ((u16b)(get_byte(fff)) << 8);
-}
-
-static void rd_u32b(FILE *fff, u32b *ip)
-{
- (*ip) = get_byte(fff);
- (*ip) |= ((u32b)(get_byte(fff)) << 8);
- (*ip) |= ((u32b)(get_byte(fff)) << 16);
- (*ip) |= ((u32b)(get_byte(fff)) << 24);
-}
-
-
-/*
- * Read a BMP file (a certain trademark nuked)
- *
- * This function replaces the old ReadRaw and RemapColors functions.
- *
- * Assumes that the bitmap has a size such that no padding is needed in
- * various places. Currently only handles bitmaps with 3 to 256 colors.
- */
-GdkRGBImage *load_bmp(cptr filename)
-{
- FILE *f;
-
- char path[1024];
-
- bmp_file_type file_hdr;
- bmp_info_type info_hdr;
-
- GdkRGBImage *result = NULL;
-
- int ncol;
-
- int i;
-
- u32b x, y;
-
- guint32 colour_pixels[256];
-
-
- /* Build the path to the bmp file */
- path_build(path, 1024, ANGBAND_DIR_XTRA_GRAF, filename);
-
- /* Open the BMP file */
- f = fopen(path, "r");
-
- /* No such file */
- if (f == NULL)
- {
- return (NULL);
- }
-
- /* Read the "bmp_file_type" */
- rd_u16b(f, &file_hdr.type);
- rd_u32b(f, &file_hdr.size);
- rd_u16b(f, &file_hdr.reserved1);
- rd_u16b(f, &file_hdr.reserved2);
- rd_u32b(f, &file_hdr.offset);
-
- /* Read the "bmp_info_type" */
- rd_u32b(f, &info_hdr.size);
- rd_u32b(f, &info_hdr.width);
- rd_u32b(f, &info_hdr.height);
- rd_u16b(f, &info_hdr.planes);
- rd_u16b(f, &info_hdr.bit_count);
- rd_u32b(f, &info_hdr.compression);
- rd_u32b(f, &info_hdr.size_image);
- rd_u32b(f, &info_hdr.x_pels_per_meter);
- rd_u32b(f, &info_hdr.y_pels_per_meter);
- rd_u32b(f, &info_hdr.colors_used);
- rd_u32b(f, &info_hdr.color_importand);
-
- /* Verify the header */
- if (feof(f) ||
- (file_hdr.type != 19778) ||
- (info_hdr.size != 40))
- {
- plog(format("Incorrect BMP file format %s", filename));
- fclose(f);
- return (NULL);
- }
-
- /*
- * The two headers above occupy 54 bytes total
- * The "offset" field says where the data starts
- * The "colors_used" field does not seem to be reliable
- */
-
- /* Compute number of colors recorded */
- ncol = (file_hdr.offset - 54) / 4;
-
- for (i = 0; i < ncol; i++)
- {
- rgb_quad_type clr;
-
- /* Read an "rgb_quad_type" */
- rd_byte(f, &clr.b);
- rd_byte(f, &clr.g);
- rd_byte(f, &clr.r);
- rd_byte(f, &clr.filler);
-
- /* Remember the pixel */
- colour_pixels[i] = (clr.r << 16) | (clr.g << 8) | (clr.b);
- }
-
- /* Allocate GdkRGBImage large enough to store the image */
- result = gdk_rgb_image_new(info_hdr.width, info_hdr.height);
-
- /* Failure */
- if (result == NULL)
- {
- fclose(f);
- return (NULL);
- }
-
- for (y = 0; y < info_hdr.height; y++)
- {
- u32b y2 = info_hdr.height - y - 1;
-
- for (x = 0; x < info_hdr.width; x++)
- {
- int ch = getc(f);
-
- /* Verify not at end of file XXX XXX */
- if (feof(f))
- {
- plog(format("Unexpected end of file in %s", filename));
- gdk_rgb_image_destroy(result);
- fclose(f);
- return (NULL);
- }
-
- if (info_hdr.bit_count == 24)
- {
- int c3, c2 = getc(f);
-
- /* Verify not at end of file XXX XXX */
- if (feof(f))
- {
- plog(format("Unexpected end of file in %s", filename));
- gdk_rgb_image_destroy(result);
- fclose(f);
- return (NULL);
- }
-
- c3 = getc(f);
-
- /* Verify not at end of file XXX XXX */
- if (feof(f))
- {
- plog(format("Unexpected end of file in %s", filename));
- gdk_rgb_image_destroy(result);
- fclose(f);
- return (NULL);
- }
-
- /* Draw the pixel */
- gdk_rgb_image_put_pixel(
- result,
- x,
- y2,
- (ch << 16) | (c2 << 8) | (c3));
- }
- else if (info_hdr.bit_count == 8)
- {
- gdk_rgb_image_put_pixel(result, x, y2, colour_pixels[ch]);
- }
- else if (info_hdr.bit_count == 4)
- {
- gdk_rgb_image_put_pixel(result, x, y2, colour_pixels[ch / 16]);
- x++;
- gdk_rgb_image_put_pixel(result, x, y2, colour_pixels[ch % 16]);
- }
- else
- {
- /* Technically 1 bit is legal too */
- plog(format("Illegal bit count %d in %s",
- info_hdr.bit_count, filename));
- gdk_rgb_image_destroy(result);
- fclose(f);
- return (NULL);
- }
- }
- }
-
- fclose(f);
-
- return result;
-}
-
-
-/*
- * Try to load an XPM file, or a BMP file if it fails
- *
- * Choice of file format may better be made yet another option XXX
- */
-static GdkRGBImage *load_tiles(cptr basename)
-{
- char buf[32];
- GdkRGBImage *img;
-
- /* build xpm file name */
- strnfmt(buf, 32, "%s.xpm", basename);
-
- /* Try to load it */
- img = load_xpm(buf);
-
- /* OK */
- if (img) return (img);
-
- /* Try again for a bmp file */
- strnfmt(buf, 32, "%s.bmp", basename);
-
- /* Try loading it */
- img = load_bmp(buf);
-
- /* Return result, success or failure */
- return (img);
-}
-
-
-/*
- * Free all tiles and graphics buffers associated with windows
- *
- * This is conspirator of graf_init() below, sharing its inefficiency
- */
-static void graf_nuke()
-{
- int i;
-
- term_data *td;
-
-
- /* Nuke all terms */
- for (i = 0; i < MAX_TERM_DATA; i++)
- {
- /* Access term_data structure */
- td = &data[i];
-
- /* Disable graphics */
- td->t.higher_pict = FALSE;
-
- /* Free previously allocated tiles */
- if (td->tiles) gdk_rgb_image_destroy(td->tiles);
-
- /* Forget pointer */
- td->tiles = NULL;
-
- /* Free previously allocated transparency buffer */
- if (td->trans_buf) gdk_rgb_image_destroy(td->trans_buf);
-
- /* Forget stale pointer */
- td->trans_buf = NULL;
- }
-}
-
-
-/*
- * Load tiles, scale them to current font size, and store a pointer
- * to them in a term_data structure for each term.
- *
- * XXX XXX XXX This is a terribly stupid quick hack.
- *
- * XXX XXX XXX Windows using the same font should share resized tiles
- */
-static bool_ graf_init(
- cptr filename,
- int tile_wid,
- int tile_hgt)
-{
- term_data *td;
-
- bool_ result;
-
- GdkRGBImage *raw_tiles, *scaled_tiles;
-
- GdkRGBImage *buffer;
-
- int i;
-
-
- /* Paranoia */
- if (filename == NULL) return (FALSE);
-
- /* Load tiles */
- raw_tiles = load_tiles(filename);
-
- /* Oops */
- if (raw_tiles == NULL)
- {
- /* Clean up */
- graf_nuke();
-
- /* Failure */
- return (FALSE);
- }
-
- /* Calculate and remember numbers of rows and columns */
- tile_rows = raw_tiles->height / tile_hgt;
- tile_cols = raw_tiles->width / tile_wid;
-
- /* Be optimistic */
- result = TRUE;
-
-
- /*
- * (Re-)init each term
- * XXX It might help speeding this up to avoid doing so if a window
- * doesn't need graphics (e.g. inventory/equipment and message recall).
- */
- for (i = 0; i < MAX_TERM_DATA; i++)
- {
- /* Access term_data */
- td = &data[i];
-
- /* Shouldn't waste anything for unused terms */
- if (!td->shown) continue;
-
- /* Enable graphics */
- td->t.higher_pict = TRUE;
-
- /* See if we need rescaled tiles XXX */
- if ((td->tiles == NULL) ||
- (td->tiles->width != td->tile_wid * tile_cols) ||
- (td->tiles->height != td->tile_hgt * tile_rows))
- {
- /* Free old tiles if present */
- if (td->tiles) gdk_rgb_image_destroy(td->tiles);
-
- /* Forget pointer */
- td->tiles = NULL;
-
- /* Scale the tiles to current font bounding rect */
- scaled_tiles = resize_tiles(
- raw_tiles,
- tile_wid, tile_hgt,
- td->tile_wid, td->tile_hgt);
-
- /* Oops */
- if (scaled_tiles == NULL)
- {
- /* Failure */
- result = FALSE;
-
- break;
- }
-
- /* Store it */
- td->tiles = scaled_tiles;
- }
-
- /* See if we have to (re)allocate a new buffer XXX */
- if ((td->trans_buf == NULL) ||
- (td->trans_buf->width != td->tile_wid) ||
- (td->trans_buf->height != td->tile_hgt))
- {
- /* Free old buffer if present */
- if (td->trans_buf) gdk_rgb_image_destroy(td->trans_buf);
-
- /* Forget pointer */
- td->trans_buf = NULL;
-
- /* Allocate a new buffer */
- buffer = gdk_rgb_image_new(td->tile_wid, td->tile_hgt);
-
- /* Oops */
- if (buffer == NULL)
- {
- /* Failure */
- result = FALSE;
-
- break;
- }
-
- /* Store it */
- td->trans_buf = buffer;
- }
-
- /*
- * Giga-Hack - assume top left corner of 0x86/0x80 should be
- * in the background colour XXX XXX XXX XXX
- */
- td->bg_pixel = gdk_rgb_image_get_pixel(
- raw_tiles,
- 0,
- tile_hgt * 6);
-
- }
-
-
- /* Alas, we need to free wasted images */
- if (result == FALSE) graf_nuke();
-
- /* We don't need the raw image any longer */
- gdk_rgb_image_destroy(raw_tiles);
-
- /* Report success or failure */
- return (result);
-}
-
-
-/*
- * React to various changes in graphics mode settings
- *
- * It is *not* a requirement for tiles to have same pixel width and height.
- * The program can work with any conbinations of graf_wid and graf_hgt
- * (oops, they must be representable by u16b), as long as they are lesser
- * or equal to 32 if you use smooth rescaling.
- */
-static void init_graphics(void)
-{
- cptr tile_name;
-
- u16b graf_wid = 0, graf_hgt = 0;
-
-
- /* No graphics requests are made - Can't this be simpler? XXX XXX */
- if ((graf_mode_request == graf_mode) &&
- (smooth_rescaling_request == smooth_rescaling) &&
- !resize_request) return;
-
- /* Prevent further unsolicited reaction */
- resize_request = FALSE;
-
-
- /* Dispose unusable old tiles - awkward... XXX XXX */
- if ((graf_mode_request == GRAF_MODE_NONE) ||
- (graf_mode_request != graf_mode) ||
- (smooth_rescaling_request != smooth_rescaling)) graf_nuke();
-
-
- /* Setup parameters according to request */
- switch (graf_mode_request)
- {
- /* ASCII - no graphics whatsoever */
- default:
- case GRAF_MODE_NONE:
- {
- tile_name = NULL;
- use_graphics = arg_graphics = FALSE;
-
- break;
- }
-
- /*
- * 8x8 tiles originally collected for the Amiga port
- * from several contributers by Lars Haugseth, converted
- * to 256 colours and expanded by the Z devteam
- *
- * Use the "old" tile assignments
- *
- * Dawnmist is working on it for ToME
- */
- case GRAF_MODE_OLD:
- {
- tile_name = "8x8";
- graf_wid = graf_hgt = 8;
- ANGBAND_GRAF = "old";
- use_graphics = arg_graphics = TRUE;
-
- break;
- }
-
- /*
- * Adam Bolt's 16x16 tiles
- * "new" tile assignments
- * It is updated for ToME by Andreas Koch
- */
- case GRAF_MODE_NEW:
- {
- tile_name = "16x16";
- graf_wid = graf_hgt = 16;
- ANGBAND_GRAF = "new";
- use_graphics = arg_graphics = TRUE;
-
- break;
- }
- }
-
-
- /* load tiles and set them up if tiles are requested */
- if ((graf_mode_request != GRAF_MODE_NONE) &&
- !graf_init(tile_name, graf_wid, graf_hgt))
- {
- /* Oops */
- plog("Cannot initialize graphics");
-
- /* reject requests */
- graf_mode_request = GRAF_MODE_NONE;
- smooth_rescaling_request = smooth_rescaling;
-
- /* reset graphics flags */
- use_graphics = arg_graphics = FALSE;
- }
-
- /* Update current graphics mode */
- graf_mode = graf_mode_request;
- smooth_rescaling = smooth_rescaling_request;
-
- /* Reset visuals */
-#ifndef ANG281_RESET_VISUALS
- reset_visuals(TRUE);
-#else
- reset_visuals();
-#endif /* !ANG281_RESET_VISUALS */
-}
-
-#endif /* USE_GRAPHICS */
@@ -2303,7 +262,7 @@ static void Term_nuke_gtk(term *t)
/* Free name */
- if (td->name) string_free(td->name);
+ if (td->name) free(td->name);
/* Forget it */
td->name = NULL;
@@ -2320,21 +279,6 @@ static void Term_nuke_gtk(term *t)
/* Forget it too */
td->backing_store = NULL;
-#ifdef USE_GRAPHICS
-
- /* Free tiles */
- if (td->tiles) gdk_rgb_image_destroy(td->tiles);
-
- /* Forget pointer */
- td->tiles = NULL;
-
- /* Free transparency buffer */
- if (td->trans_buf) gdk_rgb_image_destroy(td->trans_buf);
-
- /* Amnesia */
- td->trans_buf = NULL;
-
-#endif /* USE_GRAPHICS */
}
@@ -2458,20 +402,6 @@ static errr Term_curs_gtk(int x, int y)
/* Set foreground colour */
term_data_set_fg(td, TERM_YELLOW);
-#ifdef USE_DOUBLE_TILES
-
- /* Mogami's bigtile patch */
-
- /* Adjust it if wide tiles are requested */
- if (use_bigtile &&
- (x + 1 < Term->wid) &&
- (Term->old->a[y][x + 1] == 255))
- {
- cells = 2;
- }
-
-#endif /* USE_DOUBLE_TILES */
-
/* Draw the software cursor */
gdk_draw_rectangle(
TERM_DATA_DRAWABLE(td),
@@ -2490,299 +420,6 @@ static errr Term_curs_gtk(int x, int y)
}
-#ifdef USE_GRAPHICS
-
-/*
- * XXX XXX Low level graphics helper
- * Draw a tile at (s_x, s_y) over one at (t_x, t_y) and store the
- * result in td->trans_buf
- *
- * XXX XXX Even if CPU's are faster than necessary these days,
- * this should be made inline. Or better, there should be an API
- * to take advantage of graphics hardware. They almost always have
- * assortment of builtin bitblt's...
- */
-static void overlay_tiles_2(
- term_data *td,
- int s_x, int s_y,
- int t_x, int t_y)
-{
- guint32 pix;
- int x, y;
-
-
- /* Process each row */
- for (y = 0; y < td->tile_hgt; y++)
- {
- /* Process each column */
- for (x = 0; x < td->tile_wid; x++)
- {
- /* Get an overlay pixel */
- pix = gdk_rgb_image_get_pixel(td->tiles, s_x + x, s_y + y);
-
- /* If it's in background color, use terrain instead */
- if (pix == td->bg_pixel)
- pix = gdk_rgb_image_get_pixel(td->tiles, t_x + x, t_y + y);
-
- /* Store the result in trans_buf */
- gdk_rgb_image_put_pixel(td->trans_buf, x, y, pix);
- }
- }
-}
-
-
-/*
- * XXX XXX Low level graphics helper
- * Draw a tile at (e_x, e_y) over one at (s_x, s_y) over another one
- * at (t_x, t_y) and store the result in td->trans_buf
- *
- * XXX XXX The same comment applies as that for the above...
- */
-static void overlay_tiles_3(
- term_data *td,
- int e_x, int e_y,
- int s_x, int s_y,
- int t_x, int t_y)
-{
- guint32 pix;
- int x, y;
-
-
- /* Process each row */
- for (y = 0; y < td->tile_hgt; y++)
- {
- /* Process each column */
- for (x = 0; x < td->tile_wid; x++)
- {
- /* Get an overlay pixel */
- pix = gdk_rgb_image_get_pixel(td->tiles, e_x + x, e_y + y);
-
- /*
- * If it's background colour, try to use one from
- * the second layer
- */
- if (pix == td->bg_pixel)
- pix = gdk_rgb_image_get_pixel(td->tiles, s_x + x, s_y + y);
-
- /*
- * If it's background colour again, fall back to
- * the terrain layer
- */
- if (pix == td->bg_pixel)
- pix = gdk_rgb_image_get_pixel(td->tiles, t_x + x, t_y + y);
-
- /* Store the pixel in trans_buf */
- gdk_rgb_image_put_pixel(td->trans_buf, x, y, pix);
- }
- }
-}
-
-
-
-/*
- * Low level graphics (Assumes valid input)
- *
- * Draw "n" tiles/characters starting at (x,y)
- */
-static errr Term_pict_gtk(
- int x, int y, int n,
- const byte *ap, const char *cp,
- const byte *tap, const char *tcp,
- const byte *eap, const char *ecp)
-{
- term_data *td = (term_data*)(Term->data);
-
- int i;
-
- int d_x, d_y;
-
-# ifdef USE_DOUBLE_TILES
-
- /* Hack - remember real number of columns affected XXX XXX XXX */
- int cols;
-
-# endif /* USE_DOUBLE_TILES */
-
-
- /* Don't draw to hidden windows */
- if (!td->shown) return (0);
-
- /* Paranoia */
- g_assert(td->drawing_area->window != 0);
-
- /* Top left corner of the destination rect */
- d_x = x * td->font_wid;
- d_y = y * td->font_hgt;
-
-
-# ifdef USE_DOUBLE_TILES
-
- /* Reset column counter */
- cols = 0;
-
-# endif /* USE_DOUBLE_TILES */
-
- /* Scan the input */
- for (i = 0; i < n; i++)
- {
- byte a;
- char c;
- int s_x, s_y;
-
- byte ta;
- char tc;
- int t_x, t_y;
-
- byte ea;
- char ec;
- int e_x = 0, e_y = 0;
- bool_ has_overlay;
-
-
- /* Grid attr/char */
- a = *ap++;
- c = *cp++;
-
- /* Terrain attr/char */
- ta = *tap++;
- tc = *tcp++;
-
- /* Overlay attr/char */
- ea = *eap++;
- ec = *ecp++;
- has_overlay = (ea && ec);
-
- /* Row and Col */
- s_y = (((byte)a & 0x7F) % tile_rows) * td->tile_hgt;
- s_x = (((byte)c & 0x7F) % tile_cols) * td->tile_wid;
-
- /* Terrain Row and Col */
- t_y = (((byte)ta & 0x7F) % tile_rows) * td->tile_hgt;
- t_x = (((byte)tc & 0x7F) % tile_cols) * td->tile_wid;
-
- /* Overlay Row and Col */
- if (has_overlay)
- {
- e_y = (((byte)ea & 0x7F) % tile_rows) * td->tile_hgt;
- e_x = (((byte)ec & 0x7F) % tile_cols) * td->tile_wid;
- }
-
-
-# ifdef USE_DOUBLE_TILES
-
- /* Mogami's bigtile patch */
-
- /* Hack -- a filler for wide tile */
- if (use_bigtile && (a == 255))
- {
- /* Advance */
- d_x += td->font_wid;
-
- /* Ignore */
- continue;
- }
-
-# endif /* USE_DOUBLE_TILES */
-
- /* Optimise the common case: terrain == obj/mons */
- if (!use_transparency ||
- ((s_x == t_x) && (s_y == t_y)))
- {
-
- /* The simplest possible case - no overlay */
- if (!has_overlay)
- {
- /* Draw the tile */
- gdk_draw_rgb_image_2(
- TERM_DATA_DRAWABLE(td), td->gc, td->tiles,
- s_x, s_y,
- d_x, d_y,
- td->tile_wid, td->tile_hgt);
- }
-
- /* We have to draw overlay... */
- else
- {
- /* Overlay */
- overlay_tiles_2(td, e_x, e_y, s_x, s_y);
-
- /* And draw the result */
- gdk_draw_rgb_image_2(
- TERM_DATA_DRAWABLE(td), td->gc, td->trans_buf,
- 0, 0,
- d_x, d_y,
- td->tile_wid, td->tile_hgt);
-
- /* Hack -- Prevent potential display problem */
- gdk_flush();
- }
-
- }
-
- /*
- * Since there's no masking bitblt in X,
- * we have to do that manually...
- */
- else
- {
-
- /* No overlay */
- if (!has_overlay)
- {
- /* Build terrain + masked overlay image */
- overlay_tiles_2(td, s_x, s_y, t_x, t_y);
- }
-
- /* With overlay */
- else
- {
- /* Ego over mon/PC over terrain */
- overlay_tiles_3(td, e_x, e_y, s_x, s_y,
- t_x, t_y);
- }
-
- /* Draw it */
- gdk_draw_rgb_image_2(
- TERM_DATA_DRAWABLE(td), td->gc, td->trans_buf,
- 0, 0,
- d_x, d_y,
- td->tile_wid, td->tile_hgt);
-
- /* Hack -- Prevent potential display problem */
- gdk_flush();
- }
-
- /*
- * Advance x-coordinate - wide font fillers are taken care of
- * before entering the tile drawing code.
- */
- d_x += td->font_wid;
-
-# ifdef USE_DOUBLE_TILES
-
- /* Add up *real* number of columns updated XXX XXX XXX */
- cols += use_bigtile ? 2 : 1;
-
-# endif /* USE_DOUBLE_TILES */
- }
-
-# ifndef USE_DOUBLE_TILES
-
- /* Copy image from backing store if present */
- TERM_DATA_REFRESH(td, x, y, n, 1);
-
-# else
-
- /* Copy image from backing store if present */
- TERM_DATA_REFRESH(td, x, y, cols, 1);
-
-# endif /* USE_DOUBLE_TILES */
-
- /* Success */
- return (0);
-}
-
-#endif /* USE_GRAPHICS */
/*
@@ -2872,58 +509,6 @@ static errr Term_xtra_gtk(int n, int v)
case TERM_XTRA_CLEAR:
return (Term_clear_gtk());
- /* Delay for some milliseconds */
- case TERM_XTRA_DELAY:
- {
- /* sleep for v milliseconds */
- usleep(v * 1000);
-
- /* Done */
- return (0);
- }
-
- /* Get Delay of some milliseconds */
- case TERM_XTRA_GET_DELAY:
- {
- int ret;
- struct timeval tv;
-
- ret = gettimeofday(&tv, NULL);
- Term_xtra_long = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
-
- return ret;
- }
-
- /* Subdirectory scan */
- case TERM_XTRA_SCANSUBDIR:
- {
- DIR *directory;
- struct dirent *entry;
-
- scansubdir_max = 0;
-
- directory = opendir(scansubdir_dir);
- if (!directory) return (1);
-
- while ((entry = readdir(directory)) != NULL)
- {
- char file[PATH_MAX + NAME_MAX + 2];
- struct stat filedata;
-
- file[PATH_MAX + NAME_MAX] = 0;
- strncpy(file, scansubdir_dir, PATH_MAX);
- strncat(file, "/", 2);
- strncat(file, entry->d_name, NAME_MAX);
- if ((stat(file, &filedata) == 0) && S_ISDIR(filedata.st_mode))
- {
- string_free(scansubdir_result[scansubdir_max]);
- scansubdir_result[scansubdir_max] =
- string_make(entry->d_name);
- ++scansubdir_max;
- }
- }
- }
-
/* Rename main window */
case TERM_XTRA_RENAME_MAIN_WIN: gtk_window_set_title(GTK_WINDOW(data[0].window), angband_term_name[0]); return (0);
@@ -2933,12 +518,6 @@ static errr Term_xtra_gtk(int n, int v)
/* (re-)init colours */
init_colours();
-#ifdef USE_GRAPHICS
-
- /* Initialise graphics */
- init_graphics();
-
-#endif /* USE_GRAPHICS */
/* Success */
return (0);
@@ -3095,13 +674,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 */
}
@@ -3208,41 +781,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
@@ -3269,20 +807,6 @@ static void load_font(term_data *td, cptr fontname)
td->font_wid = gdk_char_width(td->font, '@');
td->font_hgt = td->font->ascent + td->font->descent;
-#ifndef USE_DOUBLE_TILES
-
- /* Use the current font size for tiles as well */
- td->tile_wid = td->font_wid;
- td->tile_hgt = td->font_hgt;
-
-#else /* !USE_DOUBLE_TILES */
-
- /* Calculate the size of tiles */
- if (use_bigtile && (td == &data[0])) td->tile_wid = td->font_wid * 2;
- else td->tile_wid = td->font_wid;
- td->tile_hgt = td->font_hgt;
-
-#endif /* !USE_DOUBLE_TILES */
}
@@ -3349,216 +873,6 @@ static void change_backing_store_event_handler(
}
-#ifdef USE_GRAPHICS
-
-/*
- * Set graf_mode_request according to user selection,
- * and let Term_xtra react to the change.
- */
-static void change_graf_mode_event_handler(
- gpointer user_data,
- guint user_action,
- GtkWidget *was_clicked)
-{
- /* Set request according to user selection */
- graf_mode_request = (int)user_action;
-
- /*
- * Hack - force redraw
- * This induces a call to Term_xtra(TERM_XTRA_REACT, 0) as well
- */
- Term_key_push(KTRL('R'));
-}
-
-
-/*
- * Set dither_mode according to user selection
- */
-static void change_dith_mode_event_handler(
- gpointer user_data,
- guint user_action,
- GtkWidget *was_clicked)
-{
- /* Set request according to user selection */
- dith_mode = (int)user_action;
-
- /*
- * Hack - force redraw
- */
- Term_key_push(KTRL('R'));
-}
-
-
-/*
- * Toggles the graphics tile scaling mode (Fast/Smooth)
- */
-static void change_smooth_mode_event_handler(
- gpointer user_data,
- guint user_action,
- GtkWidget *was_clicked)
-{
- /* (Try to) toggle the smooth rescaling mode */
- smooth_rescaling_request = !smooth_rescaling;
-
- /*
- * Hack - force redraw
- * This induces a call to Term_xtra(TERM_XTRA_REACT, 0) as well
- */
- Term_key_push(KTRL('R'));
-}
-
-
-# ifdef USE_DOUBLE_TILES
-
-static void change_wide_tile_mode_event_handler(
- gpointer user_data,
- guint user_action,
- GtkWidget *was_clicked)
-{
- term *old = Term;
- term_data *td = &data[0];
-
- /* 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)
- {
- td->tile_wid = td->font_wid * 2;
- }
-
- /* Use the width of current font */
- else
- {
- td->tile_wid = td->font_wid;
- }
-
- /* Need to resize the tiles */
- resize_request = TRUE;
-
- /* Activate the main window */
- Term_activate(&td->t);
-
- /* Resize the term */
- Term_resize(td->cols, td->rows);
-
- /* Activate the old term */
- Term_activate(old);
-
- /* Hack - force redraw XXX ??? XXX */
- Term_key_push(KTRL('R'));
-}
-
-# endif /* USE_DOUBLE_TILES */
-
-
-/*
- * Toggles the boolean value of use_transparency
- */
-static void change_trans_mode_event_handler(
- gpointer user_data,
- guint user_aciton,
- GtkWidget *was_clicked)
-{
- /* Toggle the transparency mode */
- use_transparency = !use_transparency;
-
- /* Hack - force redraw */
- Term_key_push(KTRL('R'));
-}
-
-#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 */
/*
@@ -3586,7 +900,6 @@ static gboolean keypress_event_handler(
GdkEventKey *event,
gpointer user_data)
{
-#if 1
int i, mc, ms, mo, mx;
char msg[128];
@@ -3703,123 +1016,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
}
@@ -4061,7 +1257,8 @@ static errr term_data_init(term_data *td, int i)
term_init(t, td->cols, td->rows, 1024);
/* Store the name of the term */
- td->name = string_make(angband_term_name[i]);
+ assert(angband_term_name[i] != NULL);
+ td->name = strdup(angband_term_name[i]);
/* Instance names should start with a lowercase letter XXX */
for (p = (char *)td->name; *p; p++) *p = tolower(*p);
@@ -4069,17 +1266,10 @@ static errr term_data_init(term_data *td, int i)
/* Use a "soft" cursor */
t->soft_cursor = TRUE;
- /* Erase with "white space" */
- t->attr_blank = TERM_WHITE;
- t->char_blank = ' ';
-
+ /* Hooks */
t->xtra_hook = Term_xtra_gtk;
t->text_hook = Term_text_gtk;
- t->wipe_hook = Term_wipe_gtk;
t->curs_hook = Term_curs_gtk;
-#ifdef USE_GRAPHICS
- t->pict_hook = Term_pict_gtk;
-#endif /* USE_GRAPHICS */
t->nuke_hook = Term_nuke_gtk;
/* Save the data */
@@ -4112,14 +1302,6 @@ static GtkItemFactoryEntry main_menu_items[] =
{ "/File", NULL,
NULL, 0, "<Branch>", NULL
},
-#ifndef SAVEFILE_SCREEN
- { "/File/New", "<mod1>N",
- new_event_handler, 0, NULL, NULL },
- { "/File/Open", "<mod1>O",
- open_event_handler, 0, NULL, NULL },
- { "/File/sep1", NULL,
- NULL, 0, "<Separator>", NULL },
-#endif /* !SAVEFILE_SCREEN */
{ "/File/Save", "<mod1>S",
save_event_handler, 0, NULL, NULL },
{ "/File/Quit", "<mod1>Q",
@@ -4171,37 +1353,6 @@ static GtkItemFactoryEntry main_menu_items[] =
{ NULL, NULL,
change_font_event_handler, 7, NULL, NULL },
-#ifdef USE_GRAPHICS
-
- /* "Graphics" submenu */
- { "/Options/Graphics", NULL,
- NULL, 0, "<Branch>", NULL },
- { "/Options/Graphics/None", NULL,
- change_graf_mode_event_handler, GRAF_MODE_NONE, "<CheckItem>", NULL },
- { "/Options/Graphics/Old", NULL,
- change_graf_mode_event_handler, GRAF_MODE_OLD, "<CheckItem>", NULL },
- { "/Options/Graphics/New", NULL,
- change_graf_mode_event_handler, GRAF_MODE_NEW, "<CheckItem>", NULL },
-# ifdef USE_DOUBLE_TILES
- { "/Options/Graphics/sep3", NULL,
- NULL, 0, "<Separator>", NULL },
- { "/Options/Graphics/Wide tiles", NULL,
- change_wide_tile_mode_event_handler, 0, "<CheckItem>", NULL },
-# endif /* USE_DOUBLE_TILES */
- { "/Options/Graphics/sep1", NULL,
- NULL, 0, "<Separator>", NULL },
- { "/Options/Graphics/Dither if <= 8bpp", NULL,
- change_dith_mode_event_handler, GDK_RGB_DITHER_NORMAL, "<CheckItem>", NULL },
- { "/Options/Graphics/Dither if <= 16bpp", NULL,
- change_dith_mode_event_handler, GDK_RGB_DITHER_MAX, "<CheckItem>", NULL },
- { "/Options/Graphics/sep2", NULL,
- NULL, 0, "<Separator>", NULL },
- { "/Options/Graphics/Smoothing", NULL,
- change_smooth_mode_event_handler, 0, "<CheckItem>", NULL },
- { "/Options/Graphics/Transparency", NULL,
- change_trans_mode_event_handler, 0, "<CheckItem>", NULL },
-
-#endif /* USE_GRAPHICS */
/* "Misc" submenu */
{ "/Options/Misc", NULL,
@@ -4257,13 +1408,13 @@ static void setup_menu_paths(void)
strnfmt(buf, 64, "/Terms/%s", angband_term_name[i]);
/* XXX XXX Store it in the menu definition */
- term_entry[i].path = (gchar*)string_make(buf);
+ term_entry[i].path = (gchar*) strdup(buf);
/* XXX XXX Build the real path name to the entry */
strnfmt(buf, 64, "/Options/Font/%s", angband_term_name[i]);
/* XXX XXX Store it in the menu definition */
- font_entry[i].path = (gchar*)string_make(buf);
+ font_entry[i].path = (gchar*) strdup(buf);
}
}
@@ -4309,10 +1460,10 @@ static void free_menu_paths(void)
for (i = 0; i < MAX_TERM_DATA; i++)
{
/* XXX XXX Free Term menu path */
- if (term_entry[i].path) string_free((cptr)term_entry[i].path);
+ if (term_entry[i].path) free(term_entry[i].path);
/* XXX XXX Free Font menu path */
- if (font_entry[i].path) string_free((cptr)font_entry[i].path);
+ if (font_entry[i].path) free(font_entry[i].path);
}
}
@@ -4399,18 +1550,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)
{
@@ -4424,10 +1565,6 @@ static void file_menu_update_handler(
}
/* Enable / disable menu items according to those conditions */
-#ifndef SAVEFILE_SCREEN
- enable_menu_item("<Angband>/File/New", game_start_ok);
- enable_menu_item("<Angband>/File/Open", game_start_ok);
-#endif /* !SAVEFILE_SCREEN */
enable_menu_item("<Angband>/File/Save", save_ok);
enable_menu_item("<Angband>/File/Quit", quit_ok);
}
@@ -4491,51 +1628,6 @@ static void misc_menu_update_handler(
}
-#ifdef USE_GRAPHICS
-
-/*
- * Update the "Graphics" submenu
- */
-static void graf_menu_update_handler(
- GtkWidget *widget,
- gpointer user_data)
-{
- /* Update menu items */
- check_menu_item(
- "<Angband>/Options/Graphics/None",
- (graf_mode == GRAF_MODE_NONE));
- check_menu_item(
- "<Angband>/Options/Graphics/Old",
- (graf_mode == GRAF_MODE_OLD));
- check_menu_item(
- "<Angband>/Options/Graphics/New",
- (graf_mode == GRAF_MODE_NEW));
-
-#ifdef USE_DOUBLE_TILES
-
- check_menu_item(
- "<Angband>/Options/Graphics/Wide tiles",
- use_bigtile);
-
-#endif /* USE_DOUBLE_TILES */
-
- check_menu_item(
- "<Angband>/Options/Graphics/Dither if <= 8bpp",
- (dith_mode == GDK_RGB_DITHER_NORMAL));
- check_menu_item(
- "<Angband>/Options/Graphics/Dither if <= 16bpp",
- (dith_mode == GDK_RGB_DITHER_MAX));
-
- check_menu_item(
- "<Angband>/Options/Graphics/Smoothing",
- smooth_rescaling);
-
- check_menu_item(
- "<Angband>/Options/Graphics/Transparency",
- use_transparency);
-}
-
-#endif /* USE_GRAPHICS */
/*
@@ -4644,23 +1736,6 @@ static void add_menu_update_callbacks()
GTK_SIGNAL_FUNC(misc_menu_update_handler),
NULL);
-#ifdef USE_GRAPHICS
-
- /* Access Graphics menu */
- widget = get_widget_from_path("<Angband>/Options/Graphics");
-
- /* Paranoia */
- g_assert(widget != NULL);
- g_assert(GTK_IS_MENU(widget));
-
- /* Assign callback */
- gtk_signal_connect(
- GTK_OBJECT(widget),
- "show",
- GTK_SIGNAL_FUNC(graf_menu_update_handler),
- NULL);
-
-#endif /* USE_GRAPHICS */
}
@@ -4808,42 +1883,16 @@ static void hook_quit(cptr str)
/* Free menu paths dynamically allocated */
free_menu_paths();
-# ifdef USE_GRAPHICS
-
- /* Free pathname string */
- if (ANGBAND_DIR_XTRA_GRAF) string_free(ANGBAND_DIR_XTRA_GRAF);
-
-# endif /* USE_GRAPHICS */
/* Terminate the program */
gtk_exit(0);
}
-#ifdef ANGBAND300
-
-/*
- * Help message for this port
- */
-const char help_gtk[] =
- "GTK for X11, subopts -n<windows>\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
*/
-errr init_gtk2(int argc, char **argv)
+int init_gtk2(int argc, char **argv)
{
int i;
@@ -4852,10 +1901,7 @@ errr init_gtk2(int argc, char **argv)
gtk_init(&argc, &argv);
/* Activate hooks - Use gtk/glib interface throughout */
- ralloc_aux = hook_ralloc;
- rnfree_aux = hook_rnfree;
quit_aux = hook_quit;
- core_aux = hook_quit;
/* Parse args */
for (i = 1; i < argc; i++)
@@ -4876,71 +1922,11 @@ errr init_gtk2(int argc, char **argv)
continue;
}
-#ifdef USE_GRAPHICS
-
- /* Requests "old" graphics */
- if (streq(argv[i], "-o"))
- {
- graf_mode_request = GRAF_MODE_OLD;
- continue;
- }
-
- /* Requests "new" graphics */
- if (streq(argv[i], "-g"))
- {
- graf_mode_request = GRAF_MODE_NEW;
- continue;
- }
-
-# ifdef USE_DOUBLE_TILES
-
- /* Requests wide tile mode */
- 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;
- }
-
-# endif /* USE_DOUBLE_TILES */
-
-
- /* Enable transparency effect */
- if (streq(argv[i], "-t"))
- {
- use_transparency = TRUE;
- continue;
- }
-
- /* Disable smooth rescaling of tiles */
- if (streq(argv[i], "-s"))
- {
- smooth_rescaling_request = FALSE;
- continue;
- }
-
-#endif /* USE_GRAPHICS */
/* None of the above */
- plog_fmt("Ignoring option: %s", argv[i]);
+ fprintf(stderr, "Ignoring option: %s", argv[i]);
}
-#ifdef USE_GRAPHICS
-
- {
- char path[1024];
-
- /* Build the "graf" path */
- path_build(path, 1024, ANGBAND_DIR_XTRA, "graf");
-
- /* Allocate the path */
- ANGBAND_DIR_XTRA_GRAF = string_make(path);
- }
-
-#endif /* USE_GRAPHICS */
/* Initialise colours */
gdk_rgb_init();
@@ -4973,54 +1959,27 @@ 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();
-
-#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();
-
- /* 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);
}
-#endif /* USE_GTK2 */
+/**
+ * Main
+ */
+int main(int argc, char *argv[])
+{
+ return main_real(
+ argc,
+ argv,
+ "gtk2",
+ init_gtk2,
+ // Usage:
+ " -- -n# Number of terms to use\n"
+ " -- -b Turn off software backing store\n");
+}
diff --git a/src/main-sdl.c b/src/main-sdl.c
index 1b53cfc7..e9aec927 100644
--- a/src/main-sdl.c
+++ b/src/main-sdl.c
@@ -23,25 +23,34 @@
// in this Software without prior written authorization from the author(s).
*/
-#ifdef USE_SDL
+#include "loadsave.h"
+#include "main.h"
+#include "util.h"
+#include "variable.h"
-#include "angband.h"
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_ttf.h>
+#include <assert.h>
#include <math.h>
/*************************************************
GLOBAL SDL-ToME PROPERTIES
*************************************************/
+
+/* Default window properties - used if none are available
+from other places*/
+#define DEF_SCREEN_WIDTH 800
+#define DEF_SCREEN_HEIGHT 600
+#define DEF_SCREEN_BPP 16
/*Main window properties that may be loaded at runtime from
a preference file or environmental variables. However,
default values (defined above) can be used. */
-static int arg_width = 0;
-static int arg_height = 0;
-static int arg_bpp = 16;
+static int arg_width = DEF_SCREEN_WIDTH;
+static int arg_height = DEF_SCREEN_HEIGHT;
+static int arg_bpp = DEF_SCREEN_BPP;
/**************/
@@ -58,21 +67,6 @@ static char arg_font_name[64] = DEF_FONT_FILE;
/**************/
-/* Graphics setting - signifies what graphics to use. Valid ints
-are available with given defines */
-
-/* No graphics - use only colored text */
-#define NO_GRAPHICS 0
-/* "Old" graphics - use 8x8.bmp to extract graphics tiles */
-#define GRAPHICS_8x8 8
-/* "New" graphics - use 16x16.bmp as tiles and apply mask.bmp for transparency*/
-#define GRAPHICS_16x16 16
-
-static int arg_graphics_type = NO_GRAPHICS;
-
-
-/**************/
-
/* The number of term_data structures to set aside mem for */
#define MAX_CONSOLE_COUNT 8
@@ -89,10 +83,6 @@ border */
/**************/
-/* some miscellaneous settings which have not been dealt
-with yet */
-static bool_ arg_double_width = FALSE;
-
/* flag signifying whether the game is in full screen */
static bool_ arg_full_screen = FALSE;
@@ -109,7 +99,7 @@ static bool_ window_properties_set = FALSE;
static SDL_Surface *screen;
/* the video settings for the system */
-static SDL_VideoInfo *videoInfo;
+static const SDL_VideoInfo *videoInfo;
/* a flag to suspend updating of the screen;
this is in place so that when a large area is being
@@ -502,9 +492,7 @@ void handleEvent(SDL_Event *event)
/* handle quit requests */
DB("Emergency Blit");
redrawAllTerminals();
- save_player();
- save_dungeon();
- sdl_quit("Quitting!\n");
+ /*sdl_quit("Quitting!\n");*/
break;
}
default:
@@ -577,23 +565,6 @@ static errr Term_xtra_sdl(int n, int v)
return (0);
}
- case TERM_XTRA_FROSH:
- {
- /*
- * Flush a row of output XXX XXX XXX
- *
- * This action should make sure that row "v" of the "output"
- * to the window will actually appear on the window.
- *
- * This action is optional, assuming that "Term_text_xxx()"
- * (and similar functions) draw directly to the screen, or
- * that the "TERM_XTRA_FRESH" entry below takes care of any
- * necessary flushing issues.
- */
-
- return (1);
- }
-
case TERM_XTRA_FRESH:
{
/*
@@ -603,9 +574,7 @@ static errr Term_xtra_sdl(int n, int v)
* window will actually appear on the window.
*
* This action is optional, assuming that "Term_text_xxx()"
- * (and similar functions) draw directly to the screen, or
- * that the "TERM_XTRA_FROSH" entry above takes care of any
- * necessary flushing issues.
+ * (and similar functions) draw directly to the screen.
*/
/* If terminal display has been held for any reason,
@@ -634,21 +603,6 @@ static errr Term_xtra_sdl(int n, int v)
return (1);
}
- case TERM_XTRA_SOUND:
- {
- /*
- * Make a sound XXX XXX XXX
- *
- * This action should produce sound number "v", where the
- * "name" of that sound is "sound_names[v]". This method
- * is still under construction.
- *
- * This action is optional, and not very important.
- */
-
- return (1);
- }
-
case TERM_XTRA_BORED:
{
/* Perform event checking without blocking */
@@ -714,40 +668,6 @@ static errr Term_xtra_sdl(int n, int v)
return (1);
}
- case TERM_XTRA_DELAY:
- {
- /*
- * Delay for some milliseconds XXX XXX XXX
- *
- * This action is useful for proper "timing" of certain
- * visual effects, such as breath attacks.
- *
- * This action is optional, but may be required by this file,
- * especially if special "macro sequences" must be supported.
- */
-
- /* I think that this command is system independent... */
- /*sleep(v/1000);*/
- /* main-x11 uses usleep(1000*v); */
- /* main-win uses Sleep(v); */
- return (1);
- }
-
- case TERM_XTRA_GET_DELAY:
- {
- /*
- * Get Delay of some milliseconds XXX XXX XXX
- * place the result in Term_xtra_long
- *
- * This action is useful for proper "timing" of certain
- * visual effects, such as recording cmovies.
- *
- * This action is optional, but cmovies wont perform
- * good without it
- */
-
- return (1);
- }
}
/* Unknown or Unhandled action */
@@ -1049,33 +969,6 @@ static errr Term_curs_sdl(int x, int y)
return (0);
}
-/* routine for wiping terminal locations - simply draws
-a black rectangle over the offending spots! */
-static errr Term_wipe_sdl(int x, int y, int n)
-{
- static SDL_Rect base;
- term_data *td = (term_data*)(Term->data);
-
- /* calculate boundaries of the area to clear */
- base.x = td->surf->clip_rect.x + x*t_width;
- base.y = td->surf->clip_rect.y + y*t_height;
- base.w = n*t_width;
- base.h = t_height;
-
- SDL_LOCK(td->surf);
-
- /* blank the screen area */
- SDL_FillRect(td->surf, &base, td->black);
-
- SDL_UNLOCK(td->surf);
-
- /* And... UPDATE the rectangle we just wrote to! */
- drawTermStuff(td,&base);
-
- /* Success */
- return (0);
-}
-
/* Perform a full clear of active terminal; redraw the borders.*/
void eraseTerminal(void)
{
@@ -1140,9 +1033,6 @@ void eraseTerminal(void)
* which is not black, then this function must be able to draw
* the resulting "blank" correctly.
*
- * Note that this function must correctly handle "black" text if
- * the "always_text" flag is set, if this flag is not set, all the
- * "black" text will be handled by the "Term_wipe_xxx()" hook.
*/
static errr Term_text_sdl(int x, int y, int n, byte a, const char *cp)
{
@@ -1186,7 +1076,8 @@ static errr Term_text_sdl(int x, int y, int n, byte a, const char *cp)
SDL_BlitSurface(worksurf,NULL,td->surf,&base);
} else {
/* copy the desired character onto working surface */
- SDL_BlitSurface(text[*cp],NULL,worksurf,NULL);
+ assert(*cp >= 0); // Make sure cast is valid
+ SDL_BlitSurface(text[(size_t)(*cp)],NULL,worksurf,NULL);
/* color our crayon surface with the desired color */
SDL_FillRect(crayon,NULL,color_data[a&0x0f]);
/* apply the color to the character on the working surface */
@@ -1376,7 +1267,6 @@ void moveTerminal(int x, int y)
void bringToTop(int current)
{
term_data *td;
- term_data *tc;
int n = 0;
int i;
@@ -1551,8 +1441,7 @@ void manipulationMode(void)
int mouse_x, mouse_y;
int value = 0, delta_x = 0, delta_y = 0;
int current_term;
- SDL_Surface backup;
-
+
/* Begin by redrawing the main terminal with its
purple border to signify that it is being edited*/
@@ -1844,19 +1733,9 @@ static errr term_data_init(term_data *td, int i)
/* Use a "soft" cursor */
t->soft_cursor = TRUE;
- /* Picture routine flags */
- t->always_pict = FALSE;
- t->higher_pict = FALSE;
- t->always_text = FALSE;
-
- /* Erase with "white space" */
- t->attr_blank = TERM_WHITE;
- t->char_blank = ' ';
-
/* Hooks */
t->xtra_hook = Term_xtra_sdl;
t->curs_hook = Term_curs_sdl;
- t->wipe_hook = Term_wipe_sdl;
t->text_hook = Term_text_sdl;
/* Save the data */
@@ -1944,9 +1823,9 @@ void dumpWindowSettings(void)
/* The main-sdl initialization routine!
This routine processes arguments, opens the SDL
window, loads fonts, etc. */
-errr init_sdl(int argc, char **argv)
+int init_sdl(int argc, char **argv)
{
- int i, surface_type;
+ int i;
char filename[PATH_MAX + 1];
const char file_sep = '.';
/* Flags to pass to SDL_SetVideoMode */
@@ -2049,25 +1928,6 @@ errr init_sdl(int argc, char **argv)
return -1;
}
}
- /* see if new graphics are requested...*/
- else if (0 == strcmp(argv[i], "-g"))
- {
- printf("New graphics (16x16) enabled!\n");
- arg_graphics_type = GRAPHICS_16x16;
- }
- /* see if old graphics are requested...*/
- else if (0 == strcmp(argv[i], "-o"))
- {
- printf("Old graphics (8x8) enabled!\n");
- arg_graphics_type = GRAPHICS_8x8;
- }
-
- /* see if double width tiles are requested */
- else if (0 == strcmp(argv[i], "-b"))
- {
- /* do nothing for now */
- /* arg_double_width = TRUE; */
- }
/* switch into full-screen at startup */
else if (0 == strcmp(argv[i], "-fs"))
{
@@ -2133,26 +1993,6 @@ errr init_sdl(int argc, char **argv)
else
videoFlags = SDL_SWSURFACE;
- /* Now ready the fonts! */
-
- DB("initializing SDL_ttf");
- if(TTF_Init()==-1) {
- printf("TTF_Init: %s\n", TTF_GetError());
- sdl_quit("Bah");
- }
-
- DB("loading font...");
-
- /* load and render the font */
- loadAndRenderFont(arg_font_name,arg_font_size);
-
- /* Make the window a nice default size if none is specified */
- if (arg_width < 1 || arg_height < 1)
- {
- arg_width = 80 * t_width;
- arg_height = 24 * t_height;
- }
-
/* now set the video mode that has been configured */
screen = SDL_SetVideoMode( arg_width, arg_height, arg_bpp, videoFlags );
@@ -2171,13 +2011,19 @@ errr init_sdl(int argc, char **argv)
DB("SDL Window Created!");
- /* Graphics! ----
- If graphics are selected, then load graphical tiles! */
- if (arg_graphics_type != NO_GRAPHICS)
- {
- /* load graphics tiles */
+ /* Now ready the fonts! */
+
+ DB("initializing SDL_ttf");
+ if(TTF_Init()==-1) {
+ printf("TTF_Init: %s\n", TTF_GetError());
+ sdl_quit("Bah");
}
-
+
+ DB("loading font...");
+
+ /* load and render the font */
+ loadAndRenderFont(arg_font_name,arg_font_size);
+
/* Initialize the working surface and crayon surface used for rendering
text in different colors. */
@@ -2250,4 +2096,18 @@ errr init_sdl(int argc, char **argv)
return 0;
}
-#endif
+int main(int argc, char *argv[])
+{
+ return main_real(
+ argc,
+ argv,
+ "sdl",
+ init_sdl,
+ " -- -n # Number of virtual consoles to use\n"
+ " -- -w # Request screen width in pixels\n"
+ " -- -h # Request screen height in pixels\n"
+ " -- -bpp # Request screen color depth in bits\n"
+ " -- -fs Start with full-screen display\n"
+ " -- -s # Request font size\n"
+ " -- -f <font> Request true-type font by name\n");
+}
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 <slang.h>
-
-
-/*
- * 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-win.c b/src/main-win.c
index 92a2a775..54336a37 100644
--- a/src/main-win.c
+++ b/src/main-win.c
@@ -36,14 +36,8 @@
*
* Compiling this file, and using the resulting executable, requires
* several extra files not distributed with the standard Angband code.
- * If "USE_GRAPHICS" is defined, then "readdib.h" and "readdib.c" must
- * be placed into "src/", and the "8X8.BMP" bitmap file must be placed
- * into "lib/xtra/graf". In any case, some "*.fon" files (including
- * "8X13.FON" if nothing else) must be placed into "lib/xtra/font/".
- * If "USE_SOUND" is defined, then some special library (for example,
- * "winmm.lib") may need to be linked in, and desired "*.WAV" sound
- * files must be placed into "lib/xtra/sound/". All of these extra
- * files can be found in the "ext-win" archive.
+ * In any case, some "*.fon" files (including "8X13.FON" if nothing
+ * else) must be placed into "lib/xtra/font/".
*
*
* The "Term_xtra_win_clear()" function should probably do a low-level
@@ -74,10 +68,11 @@
#include "angband.h"
-
-
-#ifdef WINDOWS
-
+#include "dungeon.h"
+#include "files.h"
+#include "init2.h"
+#include "util.h"
+#include "variable.h"
/*
* Extract the "WIN32" flag from the compiler
@@ -101,11 +96,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
@@ -171,17 +162,9 @@
#define IDM_WINDOW_D_HGT_6 276
#define IDM_WINDOW_D_HGT_7 277
-#define IDM_OPTIONS_OLD_GRAPHICS 400
-#define IDM_OPTIONS_NEW_GRAPHICS 401
-#define IDM_OPTIONS_ASCII_GRAPHICS 403
-#define IDM_OPTIONS_SOUND 402
-#define IDM_OPTIONS_BIGTILE 409
#define IDM_OPTIONS_UNUSED 410
#define IDM_OPTIONS_SAVER 411
-#define IDM_HELP_GENERAL 901
-#define IDM_HELP_SPOILERS 902
-
/*
* This may need to be removed for some compilers XXX XXX XXX
@@ -254,9 +237,6 @@
/*
* Include the support for loading bitmaps
*/
-#ifdef USE_GRAPHICS
-# include "readdib.h"
-#endif
/*
* Hack -- Fake declarations from "dos.h" XXX XXX XXX
@@ -447,39 +427,8 @@ static HWND hwndSaver;
#endif /* USE_SAVER */
-#ifdef USE_GRAPHICS
-
-/*
- * Flag set once "graphics" has been initialized
- */
-static bool_ can_use_graphics = FALSE;
-
-/*
- * The global bitmap
- */
-static DIBINIT infGraph;
-
-/*
- * The global bitmap mask
- */
-static DIBINIT infMask;
-
-#endif /* USE_GRAPHICS */
-
-
-#ifdef USE_SOUND
-
-/*
- * Flag set once "sound" has been initialized
- */
-static bool_ can_use_sound = FALSE;
-/*
- * An array of sound file names
- */
-static cptr sound_file[SOUND_MAX];
-#endif /* USE_SOUND */
/*
@@ -502,7 +451,6 @@ static cptr AngList = "AngList";
*/
static cptr ANGBAND_DIR_XTRA_FONT;
static cptr ANGBAND_DIR_XTRA_GRAF;
-static cptr ANGBAND_DIR_XTRA_SOUND;
static cptr ANGBAND_DIR_XTRA_HELP;
@@ -548,7 +496,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 +521,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
@@ -980,18 +845,6 @@ static void save_prefs(void)
char buf[128];
- /* Save the "arg_graphics" flag */
- sprintf(buf, "%d", arg_graphics);
- WritePrivateProfileString("Angband", "Graphics", buf, ini_file);
-
- /* Save the "arg_bigtile" flag */
- strcpy(buf, arg_bigtile ? "1" : "0");
- WritePrivateProfileString("Angband", "Bigtile", buf, ini_file);
-
- /* Save the "arg_sound" flag */
- strcpy(buf, arg_sound ? "1" : "0");
- WritePrivateProfileString("Angband", "Sound", buf, ini_file);
-
/* Save window prefs */
for (i = 0; i < MAX_TERM_DATA; ++i)
{
@@ -1023,7 +876,7 @@ static void load_prefs_aux(term_data *td, cptr sec_name)
td->bizarre = (GetPrivateProfileInt(sec_name, "Bizarre", td->bizarre, ini_file) != 0);
/* Analyze font, save desired font name */
- td->font_want = string_make(analyze_font(tmp, &wid, &hgt));
+ td->font_want = strdup(analyze_font(tmp, &wid, &hgt));
/* Tile size */
td->tile_wid = GetPrivateProfileInt(sec_name, "TileWid", wid, ini_file);
@@ -1048,16 +901,6 @@ static void load_prefs(void)
char buf[1024];
- /* Extract the "arg_graphics" flag */
- arg_graphics = GetPrivateProfileInt("Angband", "Graphics", 0, ini_file);
-
- /* Extract the "arg_bigtile" flag */
- arg_bigtile = GetPrivateProfileInt("Angband", "Bigtile", FALSE, ini_file);
- use_bigtile = arg_bigtile;
-
- /* Extract the "arg_sound" flag */
- arg_sound = (GetPrivateProfileInt("Angband", "Sound", 0, ini_file) != 0);
-
/* Load window prefs */
for (i = 0; i < MAX_TERM_DATA; ++i)
{
@@ -1108,37 +951,16 @@ static int new_palette(void)
lppe = NULL;
nEntries = 0;
-#ifdef USE_GRAPHICS
-
- /* Check the bitmap palette */
- hBmPal = infGraph.hPalette;
-
- /* Use the bitmap */
- if (hBmPal)
- {
- lppeSize = 256 * sizeof(PALETTEENTRY);
- lppe = (LPPALETTEENTRY)ralloc(lppeSize);
- nEntries = GetPaletteEntries(hBmPal, 0, 255, lppe);
- if ((nEntries == 0) || (nEntries > 220))
- {
- /* Warn the user */
- plog_fmt("Unusable bitmap palette (%d entries)", nEntries);
-
- /* Cleanup */
- rnfree(lppe, lppeSize);
-
- /* Fail */
- return (FALSE);
- }
- }
-
-#endif
/* Size of palette */
pLogPalSize = sizeof(LOGPALETTE) + (nEntries + 16) * sizeof(PALETTEENTRY);
/* Allocate palette */
- pLogPal = (LPLOGPALETTE)ralloc(pLogPalSize);
+ pLogPal = (LPLOGPALETTE) calloc(1, pLogPalSize);
+ if (pLogPal == NULL)
+ {
+ abort();
+ }
/* Version */
pLogPal->palVersion = 0x300;
@@ -1170,14 +992,19 @@ static int new_palette(void)
}
/* Free something */
- if (lppe) rnfree(lppe, lppeSize);
+ if (lppe)
+ {
+ free(lppe);
+ lppe = NULL;
+ }
/* Create a new palette, or fail */
hNewPal = CreatePalette(pLogPal);
if (!hNewPal) quit("Cannot create palette!");
/* Free the palette */
- rnfree(pLogPal, pLogPalSize);
+ free(pLogPal);
+ pLogPal = NULL;
/* Main window */
td = &data[0];
@@ -1210,120 +1037,6 @@ static int new_palette(void)
}
-/*
- * Initialize graphics
- */
-static bool_ init_graphics()
-{
- /* Initialize once */
- /*if (can_use_graphics != arg_graphics) */
- {
- char buf[1024];
- int wid, hgt;
- cptr name;
-
- /* Unused */
- PALETTEENTRY entry =
- {
- 0, 0, 0, 0
- };
- (void)entry;
-
- if (arg_graphics == 2)
- {
- wid = 16;
- hgt = 16;
-
- name = "16X16.BMP";
-
- ANGBAND_GRAF = "new";
- }
- else
- {
- wid = 8;
- hgt = 8;
-
- name = "8X8.BMP";
- ANGBAND_GRAF = "old";
- }
-
- /* Access the bitmap file */
- path_build(buf, 1024, ANGBAND_DIR_XTRA_GRAF, name);
-
- /* Load the bitmap or quit */
- if (!ReadDIB(data[0].w, buf, &infGraph))
- {
- plog_fmt("Cannot read bitmap file '%s'", name);
- return (FALSE);
- }
-
- /* Save the new sizes */
- infGraph.CellWidth = wid;
- infGraph.CellHeight = hgt;
-
-
- path_build(buf, 1024, ANGBAND_DIR_XTRA_GRAF, "mask.bmp");
- /* Load the bitmap or quit */
- if (!ReadDIB(data[0].w, buf, &infMask))
- {
- plog_fmt("Cannot read bitmap file '%s'", name);
- return (FALSE);
- }
-
- /* Activate a palette */
- if (!new_palette())
- {
- /* Free bitmap XXX XXX XXX */
-
- /* Oops */
- plog("Cannot activate palette!");
- return (FALSE);
- }
-
- /* Graphics available */
- can_use_graphics = arg_graphics;
- }
-
- /* Result */
- return (can_use_graphics);
-}
-
-
-/*
- * Initialize sound
- */
-static bool_ init_sound()
-{
- /* Initialize once */
- if (!can_use_sound)
- {
- int i;
-
- char wav[128];
- char buf[1024];
-
- /* Prepare the sounds */
- for (i = 1; i < SOUND_MAX; i++)
- {
- /* Extract name of sound file */
- sprintf(wav, "%s.wav", angband_sound_name[i]);
-
- /* Access the sound */
- path_build(buf, 1024, ANGBAND_DIR_XTRA_SOUND, wav);
-
- /* Save the sound filename, if it exists */
- if (check_file(buf)) sound_file[i] = string_make(buf);
- }
-
- /* Sound available */
- can_use_sound = TRUE;
- }
-
- /* Result */
- return (can_use_sound);
-}
-
-
/*
* Resize a window
@@ -1388,9 +1101,7 @@ static errr term_force_font(term_data *td, cptr path)
if (!used) RemoveFontResource(td->font_file);
/* Free the old name */
- string_free(td->font_file);
-
- /* Forget it */
+ free(td->font_file);
td->font_file = NULL;
}
@@ -1415,7 +1126,7 @@ static errr term_force_font(term_data *td, cptr path)
if (!AddFontResource(buf)) return (1);
/* Save new font name */
- td->font_file = string_make(base);
+ td->font_file = strdup(base);
/* Remove the "suffix" */
base[strlen(base) - 4] = '\0';
@@ -1531,38 +1242,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
- */
-static errr Term_user_win(int n)
-{
- /* Success */
- return (0);
-}
-
-
/*
* React to global changes
*/
@@ -1618,51 +1297,8 @@ static errr Term_xtra_win_react(void)
}
-#ifdef USE_SOUND
-
- /* Handle "arg_sound" */
- if (use_sound != arg_sound)
- {
- /* Initialize (if needed) */
- if (arg_sound && !init_sound())
- {
- /* Warning */
- plog("Cannot initialize sound!");
-
- /* Cannot enable */
- arg_sound = FALSE;
- }
-
- /* Change setting */
- use_sound = arg_sound;
- }
-
-#endif
-
-
-#ifdef USE_GRAPHICS
-
- /* Handle "arg_graphics" */
- if (use_graphics != arg_graphics)
- {
- /* Initialize (if needed) */
- if (arg_graphics && !init_graphics())
- {
- /* Warning */
- plog("Cannot initialize graphics!");
-
- /* Cannot enable */
- arg_graphics = FALSE;
- }
- /* Change setting */
- use_graphics = arg_graphics;
- /* Reset visuals */
- reset_visuals();
- }
-
-#endif /* USE_GRAPHICS */
/* Clean up windows */
@@ -1789,41 +1425,6 @@ static errr Term_xtra_win_noise(void)
/*
- * Hack -- make a sound
- */
-static errr Term_xtra_win_sound(int v)
-{
- /* Sound disabled */
- if (!use_sound) return (1);
-
- /* Illegal sound */
- if ((v < 0) || (v >= SOUND_MAX)) return (1);
-
- /* Unknown sound */
- if (!sound_file[v]) return (1);
-
-#ifdef USE_SOUND
-
-#ifdef WIN32
-
- /* Play the sound, catch errors */
- return (PlaySound(sound_file[v], 0, SND_FILENAME | SND_ASYNC));
-
-#else /* WIN32 */
-
-/* Play the sound, catch errors */
- return (sndPlaySound(sound_file[v], SND_ASYNC));
-
-#endif /* WIN32 */
-
-#endif /* USE_SOUND */
-
- /* Oops */
- return (1);
-}
-
-
-/*
* Delay for "x" milliseconds
*/
static int Term_xtra_win_delay(int v)
@@ -1881,12 +1482,6 @@ static errr Term_xtra_win(int n, int v)
return (Term_xtra_win_noise());
}
- /* Make a special sound */
- case TERM_XTRA_SOUND:
- {
- return (Term_xtra_win_sound(v));
- }
-
/* Process random events */
case TERM_XTRA_BORED:
{
@@ -1923,40 +1518,6 @@ static errr Term_xtra_win(int n, int v)
return (Term_xtra_win_delay(v));
}
- /* Get the current time in milliseconds */
- case TERM_XTRA_GET_DELAY:
- {
- DWORD t;
-
- t = GetTickCount();
- Term_xtra_long = t;
- return 0;
- }
-
- /*
- * Scans for subdirectories in a directory "scansubdir_dir"
- * and place teh result in "scansubdir_result/scansubdir_max"
- */
- case TERM_XTRA_SCANSUBDIR:
- {
- BOOL ok;
- HANDLE h;
- WIN32_FIND_DATA fd;
- for (h = FindFirstFile(format("%s\\*", scansubdir_dir), &fd), ok = 1;
- h != INVALID_HANDLE_VALUE && ok;
- ok = FindNextFile(h, &fd))
- {
- if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && (strcmp(fd.cFileName, ".")) && (strcmp(fd.cFileName, "..")))
- {
- string_free(scansubdir_result[scansubdir_max]);
- scansubdir_result[scansubdir_max] = string_make(fd.cFileName);
- scansubdir_max++;
- }
- }
-
- return 0;
- }
-
/* Rename main window */
case TERM_XTRA_RENAME_MAIN_WIN:
SetWindowText(get_main_hwnd(), angband_term_name[0]); return (0);
@@ -1986,9 +1547,6 @@ static errr Term_curs_win(int x, int y)
rc.top = y * td->tile_hgt + td->size_oh1;
rc.bottom = rc.top + td->tile_hgt;
- if (use_bigtile && x + 1 < Term->wid && Term->old->a[y][x + 1] == 255)
- rc.right += td->tile_wid;
-
/* Cursor is done as a yellow "box" */
hdc = GetDC(data[0].w);
FrameRect(hdc, &rc, hbrYellow);
@@ -2000,34 +1558,6 @@ static errr Term_curs_win(int x, int y)
/*
- * Low level graphics (Assumes valid input).
- *
- * Erase a "block" of "n" characters starting at (x,y).
- */
-static errr Term_wipe_win(int x, int y, int n)
-{
- term_data *td = (term_data*)(Term->data);
-
- HDC hdc;
- RECT rc;
-
- /* Rectangle to erase in client coords */
- rc.left = x * td->tile_wid + td->size_ow1;
- rc.right = rc.left + n * td->tile_wid;
- rc.top = y * td->tile_hgt + td->size_oh1;
- rc.bottom = rc.top + td->tile_hgt;
-
- hdc = GetDC(td->w);
- SetBkColor(hdc, RGB(0, 0, 0));
- SelectObject(hdc, td->font_id);
- ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
- ReleaseDC(td->w, hdc);
-
- /* Success */
- return 0;
-}
-
-/*
* Low level graphics. Assumes valid input.
*
* Draw several ("n") chars, with an attr, at a given location.
@@ -2119,197 +1649,6 @@ static errr Term_text_win(int x, int y, int n, byte a, const char *s)
}
-/*
- * Low level graphics. Assumes valid input.
- *
- * Draw an array of "special" attr/char pairs at the given location.
- *
- * We use the "Term_pict_win()" function for "graphic" data, which are
- * encoded by setting the "high-bits" of both the "attr" and the "char"
- * data. We use the "attr" to represent the "row" of the main bitmap,
- * and the "char" to represent the "col" of the main bitmap. The use
- * of this function is induced by the "higher_pict" flag.
- *
- * If "graphics" is not available, we simply "wipe" the given grids.
- */
-static errr Term_pict_win(int x, int y, int n, const byte *ap, const char *cp, const byte *tap, const char *tcp, const byte *eap, const char *ecp)
-{
- term_data *td = (term_data*)(Term->data);
-
-#ifdef USE_GRAPHICS
-
- int i;
- int x1, y1, w1, h1;
- int x2, y2, w2, h2, tw2;
-
- int x3, y3;
-
- HDC hdcMask = NULL;
-
- int x4, y4;
-
- HDC hdc;
- HDC hdcSrc;
- HBITMAP hbmSrcOld;
-
- /* Paranoia */
- if (!use_graphics)
- {
- /* Erase the grids */
- return (Term_wipe_win(x, y, n));
- }
-
- /* Size of bitmap cell */
- w1 = infGraph.CellWidth;
- h1 = infGraph.CellHeight;
-
- /* Size of window cell */
- w2 = td->tile_wid;
- h2 = td->tile_hgt;
- tw2 = w2;
-
- /* big tile mode */
- if (use_bigtile) tw2 *= 2;
-
- /* Location of window cell */
- x2 = x * w2 + td->size_ow1;
- y2 = y * h2 + td->size_oh1;
-
- /* Info */
- hdc = GetDC(td->w);
-
- /* More info */
- hdcSrc = CreateCompatibleDC(hdc);
- hbmSrcOld = SelectObject(hdcSrc, infGraph.hBitmap);
-
- if (arg_graphics == 2)
- {
- hdcMask = CreateCompatibleDC(hdc);
- SelectObject(hdcMask, infMask.hBitmap);
- }
-
- /* Draw attr/char pairs */
- for (i = 0; i < n; i++, x2 += w2)
- {
- byte a = ap[i];
- char c = cp[i];
-
- /* Extract picture */
- int row = (a & 0x7F);
- int col = (c & 0x7F);
-
- /* Location of bitmap cell */
- x1 = col * w1;
- y1 = row * h1;
-
- if (arg_graphics == 2)
- {
- x3 = (tcp[i] & 0x7F) * w1;
- y3 = (tap[i] & 0x7F) * h1;
-
- /* Perfect size */
- if ((w1 == tw2) && (h1 == h2))
- {
- /* Copy the terrain picture from the bitmap to the window */
- BitBlt(hdc, x2, y2, tw2, h2, hdcSrc, x3, y3, SRCCOPY);
-
- /* Mask out the tile */
- BitBlt(hdc, x2, y2, tw2, h2, hdcMask, x1, y1, SRCAND);
-
- /* Draw the tile */
- BitBlt(hdc, x2, y2, tw2, h2, hdcSrc, x1, y1, SRCPAINT);
-
- if (ecp[i] != 0 && eap[i] != 0)
- {
- x4 = (ecp[i] & 0x7F) * w1;
- y4 = (eap[i] & 0x7F) * h1;
-
- /* Mask out the tile */
- BitBlt(hdc, x2, y2, tw2, h2, hdcMask, x4, y4, SRCAND);
-
- /* Draw the tile */
- BitBlt(hdc, x2, y2, tw2, h2, hdcSrc, x4, y4, SRCPAINT);
- }
- }
-
- /* Need to stretch */
- else
- {
- /* Set the correct mode for stretching the tiles */
- SetStretchBltMode(hdc, COLORONCOLOR);
-
- /* Copy the terrain picture from the bitmap to the window */
- StretchBlt(hdc, x2, y2, tw2, h2, hdcSrc, x3, y3, w1, h1, SRCCOPY);
-
- /* Only draw if terrain and overlay are different */
- if ((x1 != x3) || (y1 != y3))
- {
- /* Mask out the tile */
- StretchBlt(hdc, x2, y2, tw2, h2, hdcMask, x1, y1, w1, h1, SRCAND);
-
- /* Draw the tile */
- StretchBlt(hdc, x2, y2, tw2, h2, hdcSrc, x1, y1, w1, h1, SRCPAINT);
- }
-
- if (ecp[i] != 0 && eap[i] != 0)
- {
- x4 = (ecp[i] & 0x7F) * w1;
- y4 = (eap[i] & 0x7F) * h1;
-
- /* Mask out the tile */
- StretchBlt(hdc, x2, y2, tw2, h2, hdcMask, x4, y4, w1, h1, SRCAND);
-
- /* Draw the tile */
- StretchBlt(hdc, x2, y2, tw2, h2, hdcSrc, x4, y4, w1, h1, SRCPAINT);
- }
- }
- }
- else
- {
- /* Perfect size */
- if ((w1 == tw2) && (h1 == h2))
- {
- /* Copy the picture from the bitmap to the window */
- BitBlt(hdc, x2, y2, tw2, h2, hdcSrc, x1, y1, SRCCOPY);
- }
-
- /* Need to stretch */
- else
- {
- /* Set the correct mode for stretching the tiles */
- SetStretchBltMode(hdc, COLORONCOLOR);
-
- /* Copy the picture from the bitmap to the window */
- StretchBlt(hdc, x2, y2, tw2, h2, hdcSrc, x1, y1, w1, h1, SRCCOPY);
- }
- }
- }
-
- /* Release */
- SelectObject(hdcSrc, hbmSrcOld);
- DeleteDC(hdcSrc);
-
- if (arg_graphics == 2)
- {
- /* Release */
- SelectObject(hdcMask, hbmSrcOld);
- DeleteDC(hdcMask);
- }
-
- /* Release */
- ReleaseDC(td->w, hdc);
-
-#else /* USE_GRAPHICS */
-
- /* Just erase this grid */
- return (Term_wipe_win(x, y, n));
-
-#endif /* USE_GRAPHICS */
-
- /* Success */
- return 0;
-}
-
/*** Other routines ***/
@@ -2327,26 +1666,10 @@ static void term_data_link(term_data *td)
/* Use a "software" cursor */
t->soft_cursor = TRUE;
- /* Use "Term_pict" for "graphic" data */
- t->higher_pict = TRUE;
-
- /* Erase with "white space" */
- 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;
t->curs_hook = Term_curs_win;
- t->wipe_hook = Term_wipe_win;
t->text_hook = Term_text_win;
- t->pict_hook = Term_pict_win;
/* Remember where we came from */
t->data = (vptr)(td);
@@ -2373,7 +1696,7 @@ static void init_windows(void)
/* Main window */
td = &data[0];
- WIPE(td, term_data);
+ memset(td, 0, sizeof(term_data));
td->s = angband_term_name[0];
td->keys = 1024;
td->rows = 24;
@@ -2390,7 +1713,7 @@ static void init_windows(void)
for (i = 1; i < MAX_TERM_DATA; i++)
{
td = &data[i];
- WIPE(td, term_data);
+ memset(td, 0, sizeof(term_data));
td->s = angband_term_name[i];
td->keys = 16;
td->rows = 24;
@@ -2548,13 +1871,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);
@@ -2578,14 +1896,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)
{
@@ -2593,8 +1903,6 @@ static void setup_menus(void)
MF_BYCOMMAND | MF_ENABLED);
}
-#endif
-
/* Menu "File", Item "Exit" */
EnableMenuItem(hm, IDM_FILE_EXIT,
MF_BYCOMMAND | MF_ENABLED);
@@ -2700,52 +2008,18 @@ static void setup_menus(void)
}
/* Menu "Options", disable all */
- EnableMenuItem(hm, IDM_OPTIONS_OLD_GRAPHICS,
- MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
- EnableMenuItem(hm, IDM_OPTIONS_NEW_GRAPHICS,
- MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
- EnableMenuItem(hm, IDM_OPTIONS_ASCII_GRAPHICS,
- MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
- EnableMenuItem(hm, IDM_OPTIONS_BIGTILE,
- MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
- EnableMenuItem(hm, IDM_OPTIONS_SOUND,
- MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
EnableMenuItem(hm, IDM_OPTIONS_UNUSED,
MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
EnableMenuItem(hm, IDM_OPTIONS_SAVER,
MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
/* Menu "Options", update all */
- CheckMenuItem(hm, IDM_OPTIONS_OLD_GRAPHICS,
- (arg_graphics == 1 ? MF_CHECKED : MF_UNCHECKED));
- CheckMenuItem(hm, IDM_OPTIONS_NEW_GRAPHICS,
- (arg_graphics == 2 ? MF_CHECKED : MF_UNCHECKED));
- CheckMenuItem(hm, IDM_OPTIONS_ASCII_GRAPHICS,
- (arg_graphics == 0 ? MF_CHECKED : MF_UNCHECKED));
- CheckMenuItem(hm, IDM_OPTIONS_BIGTILE,
- (arg_bigtile ? MF_CHECKED : MF_UNCHECKED));
- CheckMenuItem(hm, IDM_OPTIONS_SOUND,
- (arg_sound ? MF_CHECKED : MF_UNCHECKED));
CheckMenuItem(hm, IDM_OPTIONS_UNUSED,
(0 ? MF_CHECKED : MF_UNCHECKED));
CheckMenuItem(hm, IDM_OPTIONS_SAVER,
(hwndSaver ? MF_CHECKED : MF_UNCHECKED));
-#ifdef USE_GRAPHICS
- /* Menu "Options", Item "Graphics" */
- EnableMenuItem(hm, IDM_OPTIONS_OLD_GRAPHICS, MF_ENABLED);
- /* Menu "Options", Item "Graphics" */
- EnableMenuItem(hm, IDM_OPTIONS_NEW_GRAPHICS, MF_ENABLED);
- /* Menu "Options", Item "Graphics" */
- EnableMenuItem(hm, IDM_OPTIONS_ASCII_GRAPHICS, MF_ENABLED);
- /* Menu "Options", Item "Graphics" */
- EnableMenuItem(hm, IDM_OPTIONS_BIGTILE, MF_ENABLED);
-#endif
-#ifdef USE_SOUND
- /* Menu "Options", Item "Sound" */
- EnableMenuItem(hm, IDM_OPTIONS_SOUND, MF_ENABLED);
-#endif
#ifdef USE_SAVER
/* Menu "Options", Item "ScreenSaver" */
@@ -2789,7 +2063,7 @@ static void check_for_save_file(LPSTR cmd_line)
game_in_progress = TRUE;
/* Play game */
- play_game(FALSE);
+ play_game();
}
@@ -2822,7 +2096,7 @@ static void process_menus(WORD wCmd)
{
game_in_progress = TRUE;
Term_flush();
- play_game(TRUE);
+ play_game();
quit(NULL);
}
break;
@@ -2861,7 +2135,7 @@ ofn.lStructSize = sizeof(OPENFILENAME);
validate_file(savefile);
game_in_progress = TRUE;
Term_flush();
- play_game(FALSE);
+ play_game();
quit(NULL);
}
}
@@ -2915,102 +2189,15 @@ 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:
{
- 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_APEX, "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;
}
-#endif
-
case IDM_WINDOW_VIS_0:
{
plog("You are not allowed to do that!");
@@ -3194,114 +2381,6 @@ ofn.lStructSize = sizeof(OPENFILENAME);
break;
}
- case IDM_OPTIONS_OLD_GRAPHICS:
- {
- /* Paranoia */
- if (!inkey_flag)
- {
- plog("You may not do that right now.");
- break;
- }
-
- /* Set "arg_graphics" */
- arg_graphics = 1;
-
- /* React to changes */
- Term_xtra_win_react();
-
- /* Hack -- Force redraw */
- Term_key_push(KTRL('R'));
-
- break;
- }
-
- case IDM_OPTIONS_NEW_GRAPHICS:
- {
- /* Paranoia */
- if (!inkey_flag)
- {
- plog("You may not do that right now.");
- break;
- }
-
- /* Set "arg_graphics" */
- arg_graphics = 2;
-
- /* React to changes */
- Term_xtra_win_react();
-
- /* Hack -- Force redraw */
- Term_key_push(KTRL('R'));
-
- break;
- }
- case IDM_OPTIONS_ASCII_GRAPHICS:
- {
- /* Paranoia */
- if (!inkey_flag)
- {
- plog("You may not do that right now.");
- break;
- }
-
- /* Set "ASCII Graphics" */
- arg_graphics = 0;
- /* React to Changes */
- Term_xtra_win_react();
-
- /* Hack -- Force redraw */
- Term_key_push(KTRL('R'));
-
- break;
- }
-
- case IDM_OPTIONS_BIGTILE:
- {
- term_data *td = &data[0];
-
- /* Paranoia */
- if (!inkey_flag)
- {
- plog("You may not do that right now.");
- break;
- }
-
- /* Toggle "arg_sound" */
- arg_bigtile = !arg_bigtile;
-
- /* Activate */
- Term_activate(&td->t);
-
- /* Resize the term */
- Term_resize(td->cols, td->rows);
-
- /* Redraw later */
- InvalidateRect(td->w, NULL, TRUE);
-
- break;
- }
-
- case IDM_OPTIONS_SOUND:
- {
- /* Paranoia */
- if (!inkey_flag)
- {
- plog("You may not do that right now.");
- break;
- }
-
- /* Toggle "arg_sound" */
- arg_sound = !arg_sound;
-
- /* React to changes */
- Term_xtra_win_react();
-
- /* Hack -- Force redraw */
- Term_key_push(KTRL('R'));
-
- break;
- }
-
case IDM_OPTIONS_UNUSED:
{
/* Unused for now XXX XXX XXX */
@@ -3343,55 +2422,12 @@ ofn.lStructSize = sizeof(OPENFILENAME);
#endif
- case IDM_HELP_GENERAL:
- {
- char buf[1024];
- char tmp[1024];
- path_build(tmp, 1024, ANGBAND_DIR_XTRA_HELP, "angband.hlp");
- if (check_file(tmp))
- {
- sprintf(buf, "winhelp.exe %s", tmp);
- WinExec(buf, SW_NORMAL);
- }
- else
- {
- plog_fmt("Cannot find help file: %s", tmp);
- plog("Use the online help files instead.");
- }
- break;
- }
-
- case IDM_HELP_SPOILERS:
- {
- char buf[1024];
- char tmp[1024];
- path_build(tmp, 1024, ANGBAND_DIR_XTRA_HELP, "spoilers.hlp");
- if (check_file(tmp))
- {
- sprintf(buf, "winhelp.exe %s", tmp);
- WinExec(buf, SW_NORMAL);
- }
- else
- {
- plog_fmt("Cannot find help file: %s", tmp);
- plog("Use the online help files instead.");
- }
- break;
- }
- }
}
-#ifdef __MWERKS__
-LRESULT FAR PASCAL AngbandWndProc(HWND hWnd, UINT uMsg,
- WPARAM wParam, LPARAM lParam);
-LRESULT FAR PASCAL AngbandWndProc(HWND hWnd, UINT uMsg,
- WPARAM wParam, LPARAM lParam)
-#else /* __MWERKS__ */
LRESULT FAR PASCAL AngbandWndProc(HWND hWnd, UINT uMsg,
WPARAM wParam, LPARAM lParam)
-#endif /* __MWERKS__ */
{
PAINTSTRUCT ps;
HDC hdc;
@@ -3671,15 +2707,8 @@ LRESULT FAR PASCAL AngbandWndProc(HWND hWnd, UINT uMsg,
}
-#ifdef __MWERKS__
-LRESULT FAR PASCAL AngbandListProc(HWND hWnd, UINT uMsg,
- WPARAM wParam, LPARAM lParam);
LRESULT FAR PASCAL AngbandListProc(HWND hWnd, UINT uMsg,
WPARAM wParam, LPARAM lParam)
-#else /* __MWERKS__ */
-LRESULT FAR PASCAL AngbandListProc(HWND hWnd, UINT uMsg,
- WPARAM wParam, LPARAM lParam)
-#endif /* __MWERKS__ */
{
term_data *td;
MINMAXINFO FAR *lpmmi;
@@ -3883,15 +2912,8 @@ LRESULT FAR PASCAL AngbandListProc(HWND hWnd, UINT uMsg,
#define MOUSE_SENS 40
-#ifdef __MWERKS__
-LRESULT FAR PASCAL AngbandSaverProc(HWND hWnd, UINT uMsg,
- WPARAM wParam, LPARAM lParam);
-LRESULT FAR PASCAL AngbandSaverProc(HWND hWnd, UINT uMsg,
- WPARAM wParam, LPARAM lParam)
-#else /* __MWERKS__ */
LRESULT FAR PASCAL AngbandSaverProc(HWND hWnd, UINT uMsg,
WPARAM wParam, LPARAM lParam)
-#endif /* __MWERKS__ */
{
static int iMouse = 0;
static WORD xMouse = 0;
@@ -3915,15 +2937,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:
@@ -4059,7 +3072,11 @@ static void hook_quit(cptr str)
for (i = MAX_TERM_DATA - 1; i >= 0; --i)
{
term_force_font(&data[i], NULL);
- if (data[i].font_want) string_free(data[i].font_want);
+ if (data[i].font_want)
+ {
+ free(data[i].font_want);
+ data[i].font_want = NULL;
+ }
if (data[i].w) DestroyWindow(data[i].w);
data[i].w = 0;
}
@@ -4098,7 +3115,7 @@ static void init_stuff(void)
strcpy(path + strlen(path) - 4, ".INI");
/* Save the the name of the ini-file */
- ini_file = string_make(path);
+ ini_file = strdup(path);
/* Validate the ini-file */
validate_file(ini_file);
@@ -4131,12 +3148,11 @@ static void init_stuff(void)
path_build(path, 1024, ANGBAND_DIR_XTRA, "font");
/* Allocate the path */
- ANGBAND_DIR_XTRA_FONT = string_make(path);
+ ANGBAND_DIR_XTRA_FONT = strdup(path);
/*** 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);
@@ -4157,45 +3173,15 @@ static void init_stuff(void)
validate_file(path);
-#ifdef USE_GRAPHICS
-
- /* Build the "graf" path */
- path_build(path, 1024, ANGBAND_DIR_XTRA, "graf");
- /* Allocate the path */
- ANGBAND_DIR_XTRA_GRAF = string_make(path);
- /* Validate the "graf" directory */
- validate_dir(ANGBAND_DIR_XTRA_GRAF);
-
- /* Build the filename */
- path_build(path, 1024, ANGBAND_DIR_XTRA_GRAF, "8X8.BMP");
-
- /* Hack -- Validate the basic graf */
- validate_file(path);
-
-#endif
-
-
-#ifdef USE_SOUND
-
- /* Build the "sound" path */
- path_build(path, 1024, ANGBAND_DIR_XTRA, "sound");
-
- /* Allocate the path */
- ANGBAND_DIR_XTRA_SOUND = string_make(path);
-
- /* Validate the "sound" directory */
- validate_dir(ANGBAND_DIR_XTRA_SOUND);
-
-#endif
/* Build the "help" path */
path_build(path, 1024, ANGBAND_DIR_XTRA, "help");
/* Allocate the path */
- ANGBAND_DIR_XTRA_HELP = string_make(path);
+ ANGBAND_DIR_XTRA_HELP = strdup(path);
/* Validate the "help" directory */
/* validate_dir(ANGBAND_DIR_XTRA_HELP); */
@@ -4252,7 +3238,6 @@ int FAR PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrevInst,
/* Temporary hooks */
plog_aux = hack_plog;
quit_aux = hack_quit;
- core_aux = hack_quit;
/* Prepare the filepaths */
init_stuff();
@@ -4338,7 +3323,7 @@ int FAR PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrevInst,
check_for_save_file(lpCmdLine);
game_in_progress = TRUE;
- play_game(FALSE);
+ play_game();
/* Prompt the user */
Term_fresh();
@@ -4361,8 +3346,3 @@ int FAR PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrevInst,
/* Paranoia */
return (0);
}
-
-
-#endif /* WINDOWS */
-
-
diff --git a/src/main-x11.c b/src/main-x11.c
index e32e2617..19d2ac94 100644
--- a/src/main-x11.c
+++ b/src/main-x11.c
@@ -92,9 +92,10 @@
*
*/
-#include "angband.h"
-
-#ifdef USE_X11
+#include "loadsave.h"
+#include "main.h"
+#include "util.h"
+#include "variable.h"
#ifndef __MAKEDEPEND__
#include <X11/Xlib.h>
@@ -112,20 +113,86 @@
#include <sys/time.h>
-/* /me pffts Solaris */
-#ifndef NAME_MAX
-#define NAME_MAX _POSIX_NAME_MAX
-#endif
/*
- * Include some helpful X11 code.
+ * This file is designed to be "included" by "main-x11.c" or "main-xaw.c",
+ * which will have already "included" several relevant header files.
+ */
+
+#ifndef IsModifierKey
+
+/*
+ * Keysym macros, used on Keysyms to test for classes of symbols
+ * These were stolen from one of the X11 header files
+ *
+ * Also appears in "main-x11.c".
+ */
+
+#define IsKeypadKey(keysym) \
+(((unsigned)(keysym) >= XK_KP_Space) && ((unsigned)(keysym) <= XK_KP_Equal))
+
+#define IsCursorKey(keysym) \
+(((unsigned)(keysym) >= XK_Home) && ((unsigned)(keysym) < XK_Select))
+
+#define IsPFKey(keysym) \
+(((unsigned)(keysym) >= XK_KP_F1) && ((unsigned)(keysym) <= XK_KP_F4))
+
+#define IsFunctionKey(keysym) \
+(((unsigned)(keysym) >= XK_F1) && ((unsigned)(keysym) <= XK_F35))
+
+#define IsMiscFunctionKey(keysym) \
+(((unsigned)(keysym) >= XK_Select) && ((unsigned)(keysym) < XK_KP_Space))
+
+#define IsModifierKey(keysym) \
+(((unsigned)(keysym) >= XK_Shift_L) && ((unsigned)(keysym) <= XK_Hyper_R))
+
+#endif /* IsModifierKey */
+
+
+/*
+ * Checks if the keysym is a special key or a normal key
+ * Assume that XK_MISCELLANY keysyms are special
+ *
+ * Also appears in "main-x11.c".
*/
-#include "maid-x11.c"
+#define IsSpecialKey(keysym) \
+((unsigned)(keysym) >= 0xFF00)
+
/*
- * Hack -- avoid some compiler warnings
+ * Hack -- Convert an RGB value to an X11 Pixel, or die.
+ *
+ * Original code by Desvignes Sebastien (desvigne@solar12.eerie.fr).
+ *
+ * BMP format support by Denis Eropkin (denis@dream.homepage.ru).
+ *
+ * Major fixes and cleanup by Ben Harrison (benh@phial.com).
*/
-#define IGNORE_UNUSED_FUNCTIONS
+static unsigned long create_pixel(Display *dpy, byte red, byte green, byte blue)
+{
+ Colormap cmap = DefaultColormapOfScreen(DefaultScreenOfDisplay(dpy));
+
+ char cname[8];
+
+ XColor xcolour;
+
+ /* Build the color */
+
+ xcolour.red = red * 255 + red;
+ xcolour.green = green * 255 + green;
+ xcolour.blue = blue * 255 + blue;
+ xcolour.flags = DoRed | DoGreen | DoBlue;
+
+ /* Attempt to Allocate the Parsed color */
+ if (!(XAllocColor(dpy, cmap, &xcolour)))
+ {
+ quit_fmt("Couldn't allocate bitmap color '%s'\n", cname);
+ }
+
+ return (xcolour.pixel);
+}
+
+
/*
@@ -406,15 +473,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) \
@@ -494,7 +555,7 @@ int Term_queue_space(void)
*
* NB: The keys added here will be interpreted by any macros or keymaps.
*/
-errr type_string(char *str, uint len)
+static errr type_string(char *str, uint len)
{
char *s;
@@ -615,36 +676,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 +721,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 +761,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.
*
@@ -807,7 +779,7 @@ static errr Infowin_init_data(Window dad, int x, int y, int w, int h,
Window xid;
/* Wipe it clean */
- (void)WIPE(Infowin, infowin);
+ memset(Infowin, 0, sizeof(struct infowin));
/*** Error Check XXX ***/
@@ -880,23 +852,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 +865,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 +878,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 +891,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 +953,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', '<name>' and '#<code>'
- */
-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
*
@@ -1214,7 +1014,7 @@ static errr Infoclr_init_data(Pixell fg, Pixell bg, int op, int stip)
/*** Initialize ***/
/* Wipe the iclr clean */
- (void)WIPE(iclr, infoclr);
+ memset(iclr, 0, sizeof(struct infoclr));
/* Assign the GC */
iclr->gc = gc;
@@ -1262,36 +1062,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'
*/
@@ -1311,44 +1081,13 @@ static errr Infofnt_prepare(XFontStruct *info)
ifnt->asc = info->ascent;
ifnt->hgt = info->ascent + info->descent;
ifnt->wid = cs->width;
- if (use_bigtile)
- ifnt->twid = 2 * ifnt->wid;
- else
- 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
+ ifnt->twid = ifnt->wid;
/* Success */
return (0);
}
-#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
*
@@ -1375,7 +1114,7 @@ static errr Infofnt_init_data(cptr name)
/*** Init the font ***/
/* Wipe the thing */
- (void)WIPE(Infofnt, infofnt);
+ memset(Infofnt, 0, sizeof(struct infofnt));
/* Attempt to prepare it */
if (Infofnt_prepare(info))
@@ -1388,7 +1127,7 @@ static errr Infofnt_init_data(cptr name)
}
/* Save a copy of the font name */
- Infofnt->name = string_make(name);
+ Infofnt->name = strdup(name);
/* Mark it as nukable */
Infofnt->nuke = 1;
@@ -1543,14 +1282,6 @@ struct term_data
infowin *win;
-#ifdef USE_GRAPHICS
-
- XImage *tiles;
-
- /* Tempory storage for overlaying tiles. */
- XImage *TmpImage;
-
-#endif
};
@@ -2009,8 +1740,6 @@ error:
XSendEvent(DPY, rq->requestor, FALSE, NoEventMask, &event);
}
-extern errr type_string(char *str, uint len);
-
/*
* Add the contents of the PRIMARY buffer to the input queue.
*
@@ -2433,56 +2162,6 @@ static errr Term_xtra_x11(int n, int v)
/* Clear the screen, and redraw any selection later. */
case TERM_XTRA_CLEAR: Infowin_wipe(); s_ptr->drawn = FALSE; return (0);
- /* Delay for some milliseconds */
- case TERM_XTRA_DELAY:
- usleep(1000 * v);
- return (0);
-
- /* Get Delay of some milliseconds */
- case TERM_XTRA_GET_DELAY:
- {
- int ret;
- struct timeval tv;
-
- ret = gettimeofday(&tv, NULL);
- Term_xtra_long = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
-
- return ret;
- }
-
- /* Subdirectory scan */
- case TERM_XTRA_SCANSUBDIR:
- {
- DIR *directory;
- struct dirent *entry;
-
- scansubdir_max = 0;
-
- directory = opendir(scansubdir_dir);
- if (!directory)
- return 1;
-
- while ((entry = readdir(directory)))
- {
- char file[PATH_MAX + NAME_MAX + 2];
- struct stat filedata;
-
- file[PATH_MAX + NAME_MAX] = 0;
- strncpy(file, scansubdir_dir, PATH_MAX);
- strncat(file, "/", 2);
- strncat(file, entry->d_name, NAME_MAX);
- if (!stat(file, &filedata) && S_ISDIR((filedata.st_mode)))
- {
- string_free(scansubdir_result[scansubdir_max]);
- scansubdir_result[scansubdir_max] = string_make(entry->d_name);
- ++scansubdir_max;
- }
- }
-
- closedir(directory);
- return 0;
- }
-
/* React to changes */
case TERM_XTRA_REACT: return (Term_xtra_x11_react());
@@ -2505,30 +2184,8 @@ static errr Term_curs_x11(int x, int y)
/* Draw the cursor */
Infoclr_set(xor);
- if (use_bigtile && x + 1 < Term->wid && Term->old->a[y][x + 1] == 255)
- Infofnt_text_non(x, y, " ", 2);
- else
- /* Hilite the cursor character */
- Infofnt_text_non(x, y, " ", 1);
-
- /* Redraw the selection if any, as it may have been obscured. (later) */
- s_ptr->drawn = FALSE;
-
- /* Success */
- return (0);
-}
-
-
-/*
- * Erase some characters.
- */
-static errr Term_wipe_x11(int x, int y, int n)
-{
- /* Erase (use black) */
- Infoclr_set(clr[TERM_DARK]);
-
- /* Mega-Hack -- Erase some space */
- Infofnt_text_non(x, y, "", n);
+ /* Hilite the cursor character */
+ Infofnt_text_non(x, y, " ", 1);
/* Redraw the selection if any, as it may have been obscured. (later) */
s_ptr->drawn = FALSE;
@@ -2554,170 +2211,6 @@ static errr Term_text_x11(int x, int y, int n, byte a, cptr s)
}
-#ifdef USE_GRAPHICS
-
-/*
- * Draw some graphical characters.
- */
-static errr Term_pict_x11(int x, int y, int n, const byte *ap, const char *cp,
- const byte *tap, const char *tcp, const byte *eap, const char *ecp)
-{
- int i, x1, y1;
-
- byte a;
- char c;
-
- byte ta;
- char tc;
- int x2, y2;
-
- byte ea;
- char ec;
- int x3, y3;
- bool_ has_overlay;
-
- int k, l;
-
- unsigned long pixel, blank;
-
- term_data *td = (term_data*)(Term->data);
-
- y *= Infofnt->hgt;
- x *= Infofnt->wid;
-
- /* Add in affect of window boundaries */
- y += Infowin->oy;
- x += Infowin->ox;
-
- for (i = 0; i < n; ++i, x += td->fnt->wid)
- {
- a = *ap++;
- c = *cp++;
-
- /* For extra speed - cache these values */
- x1 = (c & 0x7F) * td->fnt->twid;
- y1 = (a & 0x7F) * td->fnt->hgt;
-
- ta = *tap++;
- tc = *tcp++;
-
- /* For extra speed - cache these values */
- x2 = (tc & 0x7F) * td->fnt->twid;
- y2 = (ta & 0x7F) * td->fnt->hgt;
-
- ea = *eap++;
- ec = *ecp++;
- has_overlay = (ea && ec);
-
- /* For extra speed - cache these values too */
- x3 = (ec & 0x7F) * td->fnt->twid;
- y3 = (ea & 0x7F) * td->fnt->hgt;
-
- /* Optimise the common case */
- if ((x1 == x2) && (y1 == y2))
- {
- /* Draw object / terrain */
- if (!has_overlay)
- {
- XPutImage(Metadpy->dpy, td->win->win,
- clr[0]->gc,
- td->tiles,
- x1, y1,
- x, y,
- td->fnt->twid, td->fnt->hgt);
- }
-
- /* There's a terrain overlay */
- else
- {
- /* Mega Hack^2 - assume the top left corner is "black" */
- blank = XGetPixel(td->tiles, 0, td->fnt->hgt * 6);
- for (k = 0; k < td->fnt->twid; k++)
- {
- for (l = 0; l < td->fnt->hgt; l++)
- {
- /* If mask set in overlay... */
- if ((pixel = XGetPixel(td->tiles, x3 + k, y3 + l)) == blank)
- {
- /* Output from the terrain */
- pixel = XGetPixel(td->tiles, x1 + k, y1 + l);
- }
-
- /* Store into the temp storage. */
- XPutPixel(td->TmpImage, k, l, pixel);
- }
- }
-
- /* Draw to screen */
- XPutImage(Metadpy->dpy, td->win->win,
- clr[0]->gc,
- td->TmpImage,
- 0, 0, x, y,
- td->fnt->twid, td->fnt->hgt);
- }
-
- }
- else
- {
-
- /* Mega Hack^2 - assume the top left corner is "black" */
- blank = XGetPixel(td->tiles, 0, td->fnt->hgt * 6);
-
- for (k = 0; k < td->fnt->twid; k++)
- {
- for (l = 0; l < td->fnt->hgt; l++)
- {
- /* Overlay */
- if (has_overlay)
- {
- pixel = XGetPixel(td->tiles, x3 + k, y3 + l);
- }
-
- /* Hack -- No overlay */
- else
- {
- pixel = blank;
- }
-
- /* If it's blank... */
- if (pixel == blank)
- {
- /* Look at mon/obj */
- pixel = XGetPixel(td->tiles, x1 + k, y1 + l);
- }
-
- /* If it's blank too, use terrain */
- if (pixel == blank)
- {
- pixel = XGetPixel(td->tiles, x2 + k, y2 + l);
- }
-
- /* Store into the temp storage. */
- XPutPixel(td->TmpImage, k, l, pixel);
- }
- }
-
-
-
- /* Draw to screen */
- XPutImage(Metadpy->dpy, td->win->win,
- clr[0]->gc,
- td->TmpImage,
- 0, 0, x, y,
- td->fnt->twid, td->fnt->hgt);
- }
-
- x += td->fnt->wid;
- }
-
- /* Redraw the selection if any, as it may have been obscured. (later) */
- s_ptr->drawn = FALSE;
-
- /* Success */
- return (0);
-}
-
-#endif /* USE_GRAPHICS */
@@ -2856,7 +2349,11 @@ static errr term_data_init(term_data *td, int i)
/* Prepare the standard font */
- MAKE(td->fnt, infofnt);
+ td->fnt = calloc(1, sizeof(struct infofnt));
+ if (td->fnt == NULL)
+ {
+ abort();
+ }
Infofnt_set(td->fnt);
Infofnt_init_data(font);
@@ -2868,7 +2365,11 @@ static errr term_data_init(term_data *td, int i)
hgt = rows * td->fnt->hgt + (oy + oy);
/* Create a top-window */
- MAKE(td->win, infowin);
+ td->win = calloc(1, sizeof(struct infowin));
+ if (td->win == NULL)
+ {
+ abort();
+ }
Infowin_set(td->win);
Infowin_init_top(x, y, wid, hgt, 0,
Metadpy->fg, Metadpy->bg);
@@ -2953,14 +2454,9 @@ static errr term_data_init(term_data *td, int i)
/* Use a "soft" cursor */
t->soft_cursor = TRUE;
- /* Erase with "white space" */
- t->attr_blank = TERM_WHITE;
- t->char_blank = ' ';
-
/* Hooks */
t->xtra_hook = Term_xtra_x11;
t->curs_hook = Term_curs_x11;
- t->wipe_hook = Term_wipe_x11;
t->text_hook = Term_text_x11;
/* Save the data */
@@ -2985,17 +2481,6 @@ errr init_x11(int argc, char *argv[])
int num_term = 1;
-#ifdef USE_GRAPHICS
-
- char filename[1024];
-
- int pict_wid = 0;
- int pict_hgt = 0;
- bool_ force_old_graphics = FALSE;
-
- char *TmpData;
-
-#endif /* USE_GRAPHICS */
/* Parse args */
@@ -3007,27 +2492,6 @@ errr init_x11(int argc, char *argv[])
continue;
}
-#ifdef USE_GRAPHICS
-
- if (prefix(argv[i], "-s"))
- {
- smoothRescaling = FALSE;
- continue;
- }
-
- if (prefix(argv[i], "-o"))
- {
- force_old_graphics = TRUE;
- continue;
- }
-
- if (prefix(argv[i], "-b"))
- {
- arg_bigtile = use_bigtile = TRUE;
- continue;
- }
-
-#endif /* USE_GRAPHICS */
if (prefix(argv[i], "-n"))
{
@@ -3037,7 +2501,7 @@ errr init_x11(int argc, char *argv[])
continue;
}
- plog_fmt("Ignoring option: %s", argv[i]);
+ fprintf(stderr, "Ignoring option: %s", argv[i]);
}
@@ -3046,7 +2510,11 @@ errr init_x11(int argc, char *argv[])
/* Prepare cursor color */
- MAKE(xor, infoclr);
+ xor = calloc(1, sizeof(struct infoclr));
+ if (xor == NULL)
+ {
+ abort();
+ }
Infoclr_set(xor);
Infoclr_init_ppn(Metadpy->fg, Metadpy->bg, "xor", 0);
@@ -3056,8 +2524,11 @@ errr init_x11(int argc, char *argv[])
{
Pixell pixel;
- MAKE(clr[i], infoclr);
-
+ clr[i] = calloc(1, sizeof(struct infoclr));
+ if (clr[i] == NULL)
+ {
+ abort();
+ }
Infoclr_set(clr[i]);
/* Acquire Angband colors */
@@ -3104,107 +2575,19 @@ errr init_x11(int argc, char *argv[])
Term_activate(&data[0].t);
-#ifdef USE_GRAPHICS
-
- /* Try graphics */
- if (arg_graphics)
- {
- /* Try the "16x16.bmp" file */
- path_build(filename, 1024, ANGBAND_DIR_XTRA, "graf/16x16.bmp");
-
- /* Use the "16x16.bmp" file if it exists */
- if (!force_old_graphics &&
- (0 == fd_close(fd_open(filename, O_RDONLY))))
- {
- /* Use graphics */
- use_graphics = TRUE;
-
- pict_wid = pict_hgt = 16;
-
- ANGBAND_GRAF = "new";
- }
- else
- {
- /* Try the "8x8.bmp" file */
- path_build(filename, 1024, ANGBAND_DIR_XTRA, "graf/8x8.bmp");
-
- /* Use the "8x8.bmp" file if it exists */
- if (0 == fd_close(fd_open(filename, O_RDONLY)))
- {
- /* Use graphics */
- use_graphics = TRUE;
-
- pict_wid = pict_hgt = 8;
-
- ANGBAND_GRAF = "old";
- }
- }
- }
-
- /* Load graphics */
- if (use_graphics)
- {
- Display *dpy = Metadpy->dpy;
-
- XImage *tiles_raw;
-
- /* Load the graphical tiles */
- tiles_raw = ReadBMP(dpy, filename);
-
- /* Initialize the windows */
- for (i = 0; i < num_term; i++)
- {
- term_data *td = &data[i];
-
- term *t = &td->t;
-
- /* Graphics hook */
- t->pict_hook = Term_pict_x11;
-
- /* Use graphics sometimes */
- t->higher_pict = TRUE;
-
- /* Resize tiles */
- td->tiles =
- ResizeImage(dpy, tiles_raw,
- pict_wid, pict_hgt,
- td->fnt->twid, td->fnt->hgt);
- }
-
- /* Initialize the transparency masks */
- for (i = 0; i < num_term; i++)
- {
- term_data *td = &data[i];
- int ii, jj;
- int depth = DefaultDepth(dpy, DefaultScreen(dpy));
- Visual *visual = DefaultVisual(dpy, DefaultScreen(dpy));
- int total;
-
-
- /* Determine total bytes needed for image */
- ii = 1;
- jj = (depth - 1) >> 2;
- while (jj >>= 1) ii <<= 1;
- total = td->fnt->twid * td->fnt->hgt * ii;
-
-
- TmpData = (char *)malloc(total);
-
- td->TmpImage = XCreateImage(dpy, visual, depth,
- ZPixmap, 0, TmpData,
- td->fnt->twid, td->fnt->hgt, 8, 0);
-
- }
-
- /* Free tiles_raw? XXX XXX */
- }
-
-#endif /* USE_GRAPHICS */
/* Success */
return (0);
}
-#endif /* USE_X11 */
-
+int main(int argc, char *argv[])
+{
+ return main_real(
+ argc,
+ argv,
+ "x11",
+ init_x11,
+ " -- -n# Number of terms to use\n"
+ " -- -d<name> Display to use\n");
+}
diff --git a/src/main-xaw.c b/src/main-xaw.c
deleted file mode 100644
index 8795e00d..00000000
--- a/src/main-xaw.c
+++ /dev/null
@@ -1,1888 +0,0 @@
-/* File: main-xaw.c */
-
-/*
- * Copyright (c) 1997 Ben Harrison, Torbjorn Lindgren, and others
- *
- * 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.
- */
-
-
-/*
- * This file helps Angband work with UNIX/X11 computers.
- *
- * To use this file, compile with "USE_XAW" defined, and link against all
- * the various "X11" libraries which may be needed.
- *
- * See also "main-x11.c".
- *
- * The Angband widget is not as self-contained as it really should be.
- * Originally everything was output to a Pixmap which was later copied
- * to the screen when necessary. The idea was abandoned since Pixmaps
- * create big performance problems for some really old X terminals (such
- * as 3/50's running Xkernel).
- *
- * Initial framework (and some code) by Ben Harrison (benh@phial.com).
- *
- * Most of this file is by Torbjorn Lindgren (tl@cd.chalmers.se).
- *
- * Major modifications by Ben Harrison (benh@phial.com).
- */
-
-
-#include "angband.h"
-
-
-#ifdef USE_XAW
-
-
-#ifndef __MAKEDEPEND__
-#include <X11/Xlib.h>
-#include <X11/StringDefs.h>
-#include <X11/Xutil.h>
-#include <X11/Intrinsic.h>
-#include <X11/Shell.h>
-#include <X11/keysym.h>
-#include <X11/keysymdef.h>
-#include <X11/IntrinsicP.h>
-#include <X11/CoreP.h>
-#include <X11/ShellP.h>
-#include <X11/StringDefs.h>
-#include <X11/Xaw/SimpleP.h>
-#include <X11/Xaw/Simple.h>
-#include <X11/Xaw/XawInit.h>
-#endif /* __MAKEDEPEND__ */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <dirent.h>
-
-/* /me pffts Solaris */
-#ifndef NAME_MAX
-#define NAME_MAX _POSIX_NAME_MAX
-#endif
-
-
-/*
- * Include some helpful X11 code.
- */
-#include "maid-x11.c"
-
-
-
-/**** Resources ****/
-
-
-/*
-
-Name Class RepType Default Value
----- ----- ------- -------------
-background Background Pixel XtDefaultBackground
-border BorderColor Pixel XtDefaultForeground
-borderWidth BorderWidth Dimension 1
-cursor Cursor Cursor None
-cursorName Cursor String NULL
-destroyCallback Callback Pointer NULL
-height Height Dimension 0
-insensitiveBorder Insensitive Pixmap Gray
-mappedWhenManaged MappedWhenManaged Boolean True
-pointerColor Foreground Pixel XtDefaultForeground
-pointerColorBackground Background Pixel XtDefaultBackground
-sensitive Sensitive Boolean True
-width Width Dimension 0
-x Position Position 0
-y Position Position 0
-
-
-The colors can be changed using the standard Angband user pref files,
-which can also be used to provide black text on a white background,
-by setting color zero to "#FFFFFF" and color one to "#000000", since
-the other colors are unused.
-
-*/
-
-
-/*
- * New resource names
- */
-#define XtNstartRows "startRows"
-#define XtNstartColumns "startColumns"
-#define XtNminRows "minRows"
-#define XtNminColumns "minColumns"
-#define XtNmaxRows "maxRows"
-#define XtNmaxColumns "maxColumns"
-#define XtNinternalBorder "internalBorder"
-#define XtNredrawCallback "redrawCallback"
-
-/*
- * Total normal colors
- */
-#define NUM_COLORS 256
-
-/*
- * Special "XOR" color
- */
-#define COLOR_XOR 256
-
-
-
-/**** The Widget Code ****/
-
-
-/*
- * Forward declarations
- */
-typedef struct AngbandPart AngbandPart;
-typedef struct AngbandRec *AngbandWidget;
-typedef struct AngbandRec AngbandRec;
-typedef struct AngbandClassRec *AngbandWidgetClass;
-typedef struct AngbandClassPart AngbandClassPart;
-typedef struct AngbandClassRec AngbandClassRec;
-
-typedef struct term_data term_data;
-
-
-/*
- * A structure for each "term"
- */
-struct term_data
-{
- term t;
-
- AngbandWidget widget;
-};
-
-
-/*
- * Maximum number of windows
- */
-#define MAX_TERM_DATA 8
-
-
-/*
- * An array of term_data's
- */
-static term_data data[MAX_TERM_DATA];
-
-
-/*
- * Current number of windows open
- */
-static int num_term = MAX_TERM_DATA;
-
-
-/*
- * New fields for the Angband widget record
- */
-struct AngbandPart
-{
- /* Settable resources */
- int start_rows;
- int start_columns;
- int min_rows;
- int min_columns;
- int max_rows;
- int max_columns;
- int internal_border;
- String font;
-
- XtCallbackList redraw_callbacks;
-
-#ifdef USE_GRAPHICS
-
- /* Tiles */
- XImage *tiles;
-
- /* Tempory storage for overlaying tiles. */
- XImage *TmpImage;
-
-#endif /* USE_GRAPHICS */
-
- /* Private state */
- XFontStruct *fnt;
- Dimension fontheight;
- Dimension fontwidth;
- Dimension fontascent;
-
- /* Color info for GC's */
- byte color[NUM_COLORS][4];
-
- /* GC's (including "xor") */
- GC gc[NUM_COLORS + 1];
-};
-
-
-/*
- * Full instance record declaration
- */
-struct AngbandRec
-{
- CorePart core;
- SimplePart simple;
- AngbandPart angband;
-};
-
-
-/*
- * New fields for the Angband widget class record
- */
-struct AngbandClassPart
-{
- int dummy;
-};
-
-
-/*
- * Full class record declaration
- */
-struct AngbandClassRec
-{
- CoreClassPart core_class;
- SimpleClassPart simple_class;
- AngbandClassPart angband_class;
-};
-
-
-
-/*
- * Hack -- see below
- */
-#define offset(field) XtOffsetOf(AngbandRec, angband.field)
-
-
-/*
- * Fallback resources for Angband widget
- */
-static XtResource resources[] =
-{
- { XtNstartRows, XtCValue, XtRInt, sizeof(int),
- offset(start_rows), XtRImmediate, (XtPointer) 24 },
- { XtNstartColumns, XtCValue, XtRInt, sizeof(int),
- offset(start_columns), XtRImmediate, (XtPointer) 80 },
- { XtNminRows, XtCValue, XtRInt, sizeof(int),
- offset(min_rows), XtRImmediate, (XtPointer) 1 },
- { XtNminColumns, XtCValue, XtRInt, sizeof(int),
- offset(min_columns), XtRImmediate, (XtPointer) 1 },
- { XtNmaxRows, XtCValue, XtRInt, sizeof(int),
- offset(max_rows), XtRImmediate, (XtPointer) 255 },
- { XtNmaxColumns, XtCValue, XtRInt, sizeof(int),
- offset(max_columns), XtRImmediate, (XtPointer) 255 },
- { XtNinternalBorder, XtCValue, XtRInt, sizeof(int),
- offset(internal_border), XtRImmediate, (XtPointer) 2 },
- { XtNfont, XtCFont, XtRString, sizeof(char *),
- offset(font), XtRString, DEFAULT_X11_FONT },
- { XtNredrawCallback, XtCCallback, XtRCallback, sizeof(XtPointer),
- offset(redraw_callbacks), XtRCallback, (XtPointer)NULL }
-};
-
-
-/*
- * Hack -- see above
- */
-#undef offset
-
-
-/*
- * Forward declarations for Widget functions
- */
-static void Initialize(AngbandWidget request, AngbandWidget wnew);
-static void Redisplay(AngbandWidget w, XEvent *event, Region region);
-static Boolean SetValues(AngbandWidget current, AngbandWidget request,
- AngbandWidget wnew, ArgList args, Cardinal *num_args);
-static void Destroy(AngbandWidget widget);
-static void Resize_term(AngbandWidget wnew);
-
-/*
- * Forward declaration for internal functions
- */
-static void calculateSizeHints(AngbandWidget wnew);
-static XFontStruct *getFont(AngbandWidget widget,
- String font, Boolean fallback);
-
-
-/*
- * Hack -- see below
- */
-#define superclass (&simpleClassRec)
-
-
-/*
- * Class record constanst
- */
-AngbandClassRec angbandClassRec =
-{
- {
- /* Core class fields initialization */
- /* superclass */ (WidgetClass) superclass,
- /* class_name */ "Angband",
- /* widget_size */ sizeof(AngbandRec),
- /* class_initialize */ NULL,
- /* class_part_initialize*/ NULL,
- /* class_inited */ FALSE,
- /* initialize */ (XtInitProc) Initialize,
- /* initialize_hook */ NULL,
- /* realize */ XtInheritRealize,
- /* actions */ NULL,
- /* num_actions */ 0,
- /* resources */ resources,
- /* num_resources */ XtNumber(resources),
- /* xrm_class */ NULLQUARK,
- /* compress_motion */ TRUE,
- /* compress_exposure */ XtExposeCompressMultiple,
- /* compress_enterleave */ TRUE,
- /* visible_interest */ FALSE,
- /* destroy */ (XtWidgetProc) Destroy,
- /* resize */ (XtWidgetProc) Resize_term,
- /* expose */ (XtExposeProc) Redisplay,
- /* set_values */ (XtSetValuesFunc) SetValues,
- /* set_values_hook */ NULL,
- /* set_values_almost */ XtInheritSetValuesAlmost,
- /* get_values_hook */ NULL,
- /* accept_focus */ NULL,
- /* version */ XtVersion,
- /* callback_private */ NULL,
- /* tm_table */ NULL,
- /* query_geometry */ NULL,
- /* display_accelerator */ XtInheritDisplayAccelerator,
- /* extension */ NULL
- },
- /* Simple class fields initialization */
- {
- /* change_sensitive */ XtInheritChangeSensitive
-#ifndef OLDXAW
- , NULL
-#endif
- },
- /* Angband class fields initialization */
- {
- /* nothing */ 0
- }
-};
-
-/*
- * Hack -- see above
- */
-#undef superclass
-
-
-/*
- * Class record pointer
- */
-WidgetClass angbandWidgetClass = (WidgetClass) &angbandClassRec;
-
-
-/*
- * Public procedures
- */
-
-/*
- * Simple routine to save the state of the game when the display connection
- * is broken. Remember, you cannot do anything in this function that will
- * generate X protocol requests.
- */
-static int x_io_error_handler(Display *d)
-{
- /* We have nothing to save */
- if (!character_generated) return 0;
-
- save_dungeon();
- save_player();
-
- return 0;
-}
-
-
-/*
- * Clear an area
- */
-static void AngbandClearArea(AngbandWidget widget,
- int x, int y, int w, int h, int a)
-{
- /* Figure out which area to clear */
- y = y * widget->angband.fontheight + widget->angband.internal_border;
- x = x * widget->angband.fontwidth + widget->angband.internal_border;
-
- /* Clear the area */
- XFillRectangle(XtDisplay(widget), XtWindow(widget),
- widget->angband.gc[a],
- x, y,
- widget->angband.fontwidth * w,
- widget->angband.fontheight * h);
-}
-
-
-
-/*
- * Output some text
- */
-static void AngbandOutputText(AngbandWidget widget, int x, int y,
- String txt, int len, int a)
-{
- /* Do nothing if the string is null */
- if (!txt || !*txt) return;
-
- /* Check the length, and fix it if it's below zero */
- if (len < 0) len = strlen(txt);
-
- /* Figure out where to place the text */
- y = (y * widget->angband.fontheight + widget->angband.fontascent +
- widget->angband.internal_border);
- x = (x * widget->angband.fontwidth + widget->angband.internal_border);
-
- /* Place the string */
- XDrawImageString(XtDisplay(widget), XtWindow(widget),
- widget->angband.gc[a], x, y, txt, len);
-}
-
-
-#ifdef USE_GRAPHICS
-
-/*
- * Draw some graphical characters.
- */
-static void AngbandOutputPict(AngbandWidget widget, int x, int y, int n,
- const byte *ap, const char *cp, const byte *tap, const char *tcp,
- const byte *eap, const char *ecp)
-{
- int i, x1, y1;
-
- byte a;
- char c;
-
- byte ta;
- char tc;
-
- int x2, y2;
-
- byte ea;
- char ec;
-
- int x3, y3;
- bool_ has_overlay;
-
- int k, l;
- unsigned long pixel, blank;
-
- /* Figure out where to place the text */
- y = (y * widget->angband.fontheight + widget->angband.internal_border);
- x = (x * widget->angband.fontwidth + widget->angband.internal_border);
-
- for (i = 0; i < n; ++i)
- {
- a = *ap++;
- c = *cp++;
-
- /* For extra speed - cache these values */
- x1 = (c & 0x7F) * widget->angband.fontwidth;
- y1 = (a & 0x7F) * widget->angband.fontheight;
-
- ta = *tap++;
- tc = *tcp++;
-
- /* For extra speed - cache these values */
- x2 = (tc & 0x7F) * widget->angband.fontwidth;
- y2 = (ta & 0x7F) * widget->angband.fontheight;
-
- ea = *eap++;
- ec = *ecp++;
- has_overlay = (ea && ec);
-
- /* For extra speed -- cache these values */
- x3 = (ec & 0x7F) * widget->angband.fontwidth;
- y3 = (ea & 0x7F) * widget->angband.fontheight;
-
- /* Optimise the common case */
- if ((x1 == x2) && (y1 == y2))
- {
-
- /* No overlay */
- if (!has_overlay)
- {
- /* Draw object / terrain */
- XPutImage(XtDisplay(widget), XtWindow(widget),
- widget->angband.gc[0],
- widget->angband.tiles,
- x1, y1,
- x, y,
- widget->angband.fontwidth,
- widget->angband.fontheight);
- }
-
- /* Terrain overlay */
- else
- {
- /* Mega Hack^2 - assume the top left corner is "black" */
- blank = XGetPixel(widget->angband.tiles,
- 0, widget->angband.fontheight * 6);
-
- for (k = 0; k < widget->angband.fontwidth; k++)
- {
- for (l = 0; l < widget->angband.fontheight; l++)
- {
- /* If mask set... */
- if ((pixel = XGetPixel(widget->angband.tiles,
- x3 + k, y3 + l)) == blank)
- {
- /* Output from the terrain */
- pixel = XGetPixel(widget->angband.tiles,
- x1 + k, y1 + l);
- }
-
- /* Store into the temp storage */
- XPutPixel(widget->angband.TmpImage,
- k, l, pixel);
- }
- }
-
- /* Draw terrain + overlay */
- XPutImage(XtDisplay(widget), XtWindow(widget),
- widget->angband.gc[0],
- widget->angband.TmpImage,
- 0, 0,
- x, y,
- widget->angband.fontwidth,
- widget->angband.fontheight);
- }
-
- }
- else
- {
- /* Mega Hack^2 - assume the top left corner is "black" */
- blank = XGetPixel(widget->angband.tiles,
- 0, widget->angband.fontheight * 6);
-
- for (k = 0; k < widget->angband.fontwidth; k++)
- {
- for (l = 0; l < widget->angband.fontheight; l++)
- {
- /* Get overlay pixel */
- if (has_overlay)
- {
- pixel = XGetPixel(widget->angband.tiles,
- x3 + k, y3 + l);
- }
-
- /* Hack -- no overlay */
- else
- {
- pixel = blank;
- }
-
- /* If it's blank */
- if (pixel == blank)
- {
- /* Use obj/mon */
- pixel = XGetPixel(widget->angband.tiles,
- x1 + k, y1 + l);
- }
-
- /* Use terrain if it's blank too */
- if (pixel == blank)
- {
- pixel = XGetPixel(widget->angband.tiles,
- x2 + k, y2 + l);
- }
-
- /* Store into the temp storage. */
- XPutPixel(widget->angband.TmpImage,
- k, l, pixel);
- }
- }
-
- /* Draw to screen */
-
- /* Draw object / terrain */
- XPutImage(XtDisplay(widget), XtWindow(widget),
- widget->angband.gc[0],
- widget->angband.TmpImage,
- 0, 0,
- x, y,
- widget->angband.fontwidth,
- widget->angband.fontheight);
- }
-
- x += widget->angband.fontwidth;
- }
-}
-
-#endif /* USE_GRAPHICS */
-
-/*
- * Private procedures
- */
-
-
-/*
- * Procedure Initialize() is called during the widget creation
- * process. Initialize() load fonts and calculates window geometry.
- * The request parameter is filled in by parents to this widget. The
- * wnew parameter is the request parameter plus data filled in by this
- * widget. All changes should be done to the wnew parameter.
- */
-static void Initialize(AngbandWidget request, AngbandWidget wnew)
-{
- Display *dpy = XtDisplay(wnew);
-
- int depth = DefaultDepthOfScreen(XtScreen((Widget) wnew));
-
- XGCValues gcv;
- TopLevelShellWidget parent =
- (TopLevelShellWidget)XtParent((Widget) wnew);
- int i;
-
- /* Default background pixel */
- unsigned long bg = create_pixel(dpy,
- angband_color_table[0][1],
- angband_color_table[0][2],
- angband_color_table[0][3]);
-
- /* Default foreground pixel */
- unsigned long fg = create_pixel(dpy,
- angband_color_table[1][1],
- angband_color_table[1][2],
- angband_color_table[1][3]);
-
- /* Fix the background color */
- wnew->core.background_pixel = bg;
-
- /* Get some information about the font */
- wnew->angband.fnt = getFont(wnew, wnew->angband.font, TRUE);
- wnew->angband.fontheight = wnew->angband.fnt->ascent +
- wnew->angband.fnt->descent;
- wnew->angband.fontwidth = wnew->angband.fnt->max_bounds.width;
- wnew->angband.fontascent = wnew->angband.fnt->ascent;
-
- /* Create and initialize the graphics contexts */ /* GXset? */
- gcv.font = wnew->angband.fnt->fid;
- gcv.graphics_exposures = FALSE;
- gcv.background = bg;
-
- for (i = 0; i < NUM_COLORS; i++)
- {
- unsigned long pixel;
-
- /* Acquire Angband colors */
- wnew->angband.color[i][0] = angband_color_table[i][0];
- wnew->angband.color[i][1] = angband_color_table[i][1];
- wnew->angband.color[i][2] = angband_color_table[i][2];
- wnew->angband.color[i][3] = angband_color_table[i][3];
-
- if (depth > 1)
- {
- /* Create pixel */
- pixel = create_pixel(dpy,
- wnew->angband.color[i][1],
- wnew->angband.color[i][2],
- wnew->angband.color[i][3]);
- }
- else
- {
- /* Use background or foreground */
- pixel = ((i == 0) ? bg : fg);
- }
-
- gcv.foreground = pixel;
-
- /* Copy */
- gcv.function = 3;
-
- wnew->angband.gc[i] = XtGetGC((Widget)wnew,
- (GCFont | GCForeground | GCFunction |
- GCBackground | GCGraphicsExposures),
- &gcv);
- }
-
- /* Create a special GC for highlighting */
- gcv.foreground = (BlackPixelOfScreen(XtScreen((Widget)wnew)) ^
- WhitePixelOfScreen(XtScreen((Widget)wnew)));
- gcv.background = 0;
-
- gcv.function = GXxor;
- wnew->angband.gc[COLOR_XOR] = XtGetGC((Widget)wnew,
- (GCFunction | GCForeground | GCBackground |
- GCGraphicsExposures),
- &gcv);
-
- /* Calculate window geometry */
- wnew->core.height = (wnew->angband.start_rows * wnew->angband.fontheight +
- 2 * wnew->angband.internal_border);
- wnew->core.width = (wnew->angband.start_columns * wnew->angband.fontwidth +
- 2 * wnew->angband.internal_border);
-
- /* We need to be able to resize the Widget if the user wants to */
- /* change font on the fly! */
- parent->shell.allow_shell_resize = TRUE;
-
- /* Calculates all the size hints */
- calculateSizeHints(wnew);
-}
-
-
-/*
- * Procedure Destroy() is called during the destruction of the widget.
- * Destroy() releases and frees GCs, frees the pixmaps and frees the
- * fonts.
- */
-static void Destroy(AngbandWidget widget)
-{
- int n;
-
- /* Free all GC's */
- for (n = 0; n < NUM_COLORS + 1; n++)
- {
- XtReleaseGC((Widget)widget, widget->angband.gc[n]);
- }
-
- /* Free the font */
- XFreeFont(XtDisplay((Widget)widget), widget->angband.fnt);
-}
-
-
-static void Resize_term(AngbandWidget wnew)
-{
- int cols, rows, wid, hgt;
-
- int ox = wnew->angband.internal_border;
- int oy = wnew->angband.internal_border;
-
- int i;
- term_data *old_td;
- term_data *td = &data[0];
-
-
- /*
- * Mega-Hack -- avoid calling this before the terms package is
- * initialised
- */
- if (!Term) return;
-
- old_td = (term_data*)(Term->data);
-
- /* Hack - Find the term to activate */
- for (i = 0; i < num_term; i++)
- {
- td = &data[i];
-
- /* Paranoia: none of the widgets matched */
- if (!td) return;
-
- /* Have we found it? */
- if (td->widget == wnew) break;
- }
-
- /* Paranoia -- No matches */
- if (i == num_term) return;
-
- /* Activate the proper Term */
- Term_activate(&td->t);
-
- /* Determine "proper" number of rows/cols */
- cols = ((wnew->core.width - (ox + ox)) / wnew->angband.fontwidth);
- rows = ((wnew->core.height - (oy + oy)) / wnew->angband.fontheight);
-
- /* Hack -- minimal size */
- if (cols < 1) cols = 1;
- if (rows < 1) rows = 1;
-
- if (i == 0)
- {
- /* Hack the main window must be at least 80x24 */
- if (cols < 80) cols = 80;
- if (rows < 24) rows = 24;
- }
-
- /* Desired size of window */
- wid = cols * wnew->angband.fontwidth + (ox + ox);
- hgt = rows * wnew->angband.fontheight + (oy + oy);
-
- /* Resize the Term (if needed) */
- (void) Term_resize(cols, rows);
-
- /* Activate the old term */
- Term_activate(&old_td->t);
-}
-
-/*
- * Procedure Redisplay() is called as the result of an Expose event.
- * Use the redraw callback to do a full redraw
- */
-static void Redisplay(AngbandWidget wnew, XEvent *xev, Region region)
-{
- int x1, x2, y1, y2;
-
- int i;
-
- term_data *old_td = (term_data*)(Term->data);
- term_data *td = &data[0];
-
- /* Hack - Find the term to activate */
- for (i = 0; i < num_term; i++)
- {
- td = &data[i];
-
- /* Have we found it? */
- if (td->widget == wnew) break;
-
- /* Paranoia: none of the widgets matched */
- if (!td) return;
- }
-
- /* Activate the proper Term */
- Term_activate(&td->t);
-
- /* Find the bounds of the exposed region */
-
- /*
- * This probably could be obtained from the Region parameter -
- * but I don't know anything about XAW.
- */
- x1 = (xev->xexpose.x - wnew->angband.internal_border)
- / wnew->angband.fontwidth;
- x2 = (xev->xexpose.x + xev->xexpose.width -
- wnew->angband.internal_border) / wnew->angband.fontwidth;
-
- y1 = (xev->xexpose.y - wnew->angband.internal_border)
- / wnew->angband.fontheight;
- y2 = (xev->xexpose.y + xev->xexpose.height -
- wnew->angband.internal_border) / wnew->angband.fontheight;
-
- Term_redraw_section(x1, y1, x2, y2);
-
- /* Activate the old term */
- Term_activate(&old_td->t);
-
-
-#if 0
- if (XtHasCallbacks((Widget)widget, XtNredrawCallback) == XtCallbackHasSome)
- {
- XtCallCallbacks((Widget)widget, XtNredrawCallback, NULL);
- }
-#endif /* 0 */
-}
-
-
-/*
- * Font and internal_border can be changed on the fly.
- *
- * The entire widget is redrawn if any of those parameters change (all
- * can potentially have effects that spans the whole widget).
- *
- * Color changes are handled elsewhere.
- *
- * This function is very underspecified, in terms of how these changes can
- * occur, and what is true about the various AngbandWidget's passed in. It
- * is very likely that this code no longer works.
- */
-static Boolean SetValues(AngbandWidget current, AngbandWidget request,
- AngbandWidget wnew, ArgList args,
- Cardinal *num_args)
-{
- Display *dpy = XtDisplay(wnew);
-
- Boolean font_changed = FALSE;
- Boolean border_changed = FALSE;
- int height, width;
- int i;
-
-
- /* Handle font change */
- if (wnew->angband.font != current->angband.font)
- {
- /* Check if the font exists */
- wnew->angband.fnt = getFont(wnew, wnew->angband.font, FALSE);
-
- /* The font didn't exist */
- if (wnew->angband.fnt == NULL)
- {
- wnew->angband.fnt = current->angband.fnt;
- wnew->angband.font = current->angband.font;
- XtWarning("Couldn't find the requested font!");
- }
- else
- {
- font_changed = TRUE;
-
- /* Free the old font */
- XFreeFont(XtDisplay((Widget)wnew), current->angband.fnt);
- /* Update font information */
- wnew->angband.fontheight = wnew->angband.fnt->ascent +
- wnew->angband.fnt->descent;
- wnew->angband.fontwidth = wnew->angband.fnt->max_bounds.width;
- wnew->angband.fontascent = wnew->angband.fnt->ascent;
- }
- }
-
- /* Handle font change */
- if (font_changed)
- {
- /* Update all GC's */
- for (i = 0; i < NUM_COLORS; i++)
- {
- /* Steal the old GC */
- wnew->angband.gc[i] = current->angband.gc[i];
- current->angband.gc[i] = NULL;
-
- /* Be sure the correct font is ready */
- XSetFont(dpy, wnew->angband.gc[i], wnew->angband.fnt->fid);
- }
-
- /* Steal the old GC */
- wnew->angband.gc[NUM_COLORS] = current->angband.gc[NUM_COLORS];
- current->angband.gc[NUM_COLORS] = NULL;
- }
-
-
- /* Check if internal border width has changed, used later */
- if (current->angband.internal_border != wnew->angband.internal_border)
- {
- border_changed = TRUE;
- }
-
-
- /* If the font or the internal border has changed, all geometry */
- /* has to be recalculated */
- if (font_changed || border_changed)
- {
- /* Change window size */
- height = ((current->core.height - 2 * current->angband.internal_border) /
- current->angband.fontheight * wnew->angband.fontheight +
- 2 * current->angband.internal_border);
- width = ((current->core.width - 2 * current->angband.internal_border) /
- current->angband.fontwidth * wnew->angband.fontwidth +
- 2 * wnew->angband.internal_border);
-
- /* Get the new width */
- if (XtMakeResizeRequest((Widget)wnew, width, height, NULL, NULL) ==
- XtGeometryNo)
- {
- /* Not allowed */
- XtWarning("Size change denied!");
- }
- else
- {
- /* Recalculate size hints */
- calculateSizeHints(wnew);
- }
- }
-
- /* Tell it to redraw the widget if anything has changed */
- return (font_changed || border_changed);
-}
-
-
-/*
- * Calculate size hints
- */
-static void calculateSizeHints(AngbandWidget wnew)
-{
- TopLevelShellWidget parent =
- (TopLevelShellWidget)XtParent((Widget) wnew);
-
- /* Calculate minimum size */
- parent->wm.size_hints.min_height =
- (wnew->angband.min_rows * wnew->angband.fontheight +
- 2 * wnew->angband.internal_border);
-
- /* Calculate minimum size */
- parent->wm.size_hints.min_width =
- (wnew->angband.min_columns * wnew->angband.fontwidth +
- 2 * wnew->angband.internal_border);
-
- /* Calculate minimum size */
- parent->wm.size_hints.flags |= PMinSize;
-
- /* Calculate maximum size */
- parent->wm.size_hints.max_height =
- (wnew->angband.max_rows * wnew->angband.fontheight +
- 2 * wnew->angband.internal_border);
-
- /* Calculate maximum size */
- parent->wm.size_hints.max_width =
- (wnew->angband.max_columns * wnew->angband.fontwidth +
- 2 * wnew->angband.internal_border);
-
- /* Calculate maximum size */
- parent->wm.size_hints.flags |= PMaxSize;
-
- /* Calculate increment size */
- parent->wm.size_hints.height_inc = wnew->angband.fontheight;
- parent->wm.size_hints.width_inc = wnew->angband.fontwidth;
- parent->wm.size_hints.flags |= PResizeInc;
-
- /* Calculate base size */
- parent->wm.base_height = 2 * wnew->angband.internal_border;
- parent->wm.base_width = 2 * wnew->angband.internal_border;
- parent->wm.size_hints.flags |= PBaseSize;
-}
-
-
-/*
- * Load a font
- */
-static XFontStruct *getFont(AngbandWidget widget,
- String font, Boolean fallback)
-{
- Display *dpy = XtDisplay((Widget) widget);
- char buf[256];
- XFontStruct *fnt = NULL;
-
- if (!(fnt = XLoadQueryFont(dpy, font)) && fallback)
- {
- sprintf(buf, "Can't find the font \"%s\", trying fixed\n", font);
- XtWarning(buf);
- if (!(fnt = XLoadQueryFont(dpy, "fixed")))
- {
- XtError("Can't fint the font \"fixed\"!, bailing out\n");
- }
- }
-
- return fnt;
-}
-
-
-
-/*** The Angband code ****/
-
-
-
-
-
-/*
- * Number of fallback resources per window
- */
-#define TERM_FALLBACKS 6
-
-
-
-/*
- * The names of the term_data's
- */
-char *termNames[MAX_TERM_DATA] =
-{
- "angband",
- "mirror",
- "recall",
- "choice",
- "term-4",
- "term-5",
- "term-6",
- "term-7"
-};
-
-
-/*
- * The special Arg's
- */
-Arg specialArgs[TERM_FALLBACKS] =
-{
- { XtNstartRows, 24},
- { XtNstartColumns, 80},
- { XtNminRows, 24},
- { XtNminColumns, 80},
- { XtNmaxRows, 255},
- { XtNmaxColumns, 255}
-};
-
-
-/*
- * The default Arg's
- */
-Arg defaultArgs[TERM_FALLBACKS] =
-{
- { XtNstartRows, 24},
- { XtNstartColumns, 80},
- { XtNminRows, 1},
- { XtNminColumns, 1},
- { XtNmaxRows, 255},
- { XtNmaxColumns, 255}
-};
-
-
-/*
- * The application context
- */
-XtAppContext appcon;
-
-
-/*
- * User changable information about widgets
- */
-static String fallback[] =
-{
- "Angband.angband.iconName: ToME",
- "Angband.angband.title: ToME",
- "Angband.term-1.iconName: Mirror",
- "Angband.term-1.title: Mirror",
- "Angband.term-2.iconName: Recall",
- "Angband.term-2.title: Recall",
- "Angband.term-3.iconName: Choice",
- "Angband.term-3.title: Choice",
- "Angband.term-4.iconName: Term 4",
- "Angband.term-4.title: Term 4",
- "Angband.term-5.iconName: Term 5",
- "Angband.term-5.title: Term 5",
- "Angband.term-6.iconName: Term 6",
- "Angband.term-6.title: Term 6",
- "Angband.term-7.iconName: Term 7",
- "Angband.term-7.title: Term 7",
- NULL
-};
-
-
-
-/*
- * Do a redraw
- */
-static void react_redraw(Widget widget,
- XtPointer client_data, XtPointer call_data)
-{
- term_data *old_td = (term_data*)(Term->data);
- term_data *td = (term_data*)client_data;
-
- /* Activate the proper Term */
- Term_activate(&td->t);
-
- /* Request a redraw */
- Term_redraw();
-
- /* Activate the old Term */
- Term_activate(&old_td->t);
-}
-
-
-
-/*
- * Process a keypress event
- *
- * Also appears in "main-x11.c".
- */
-static void react_keypress(XKeyEvent *xev)
-{
- int i, n, mc, ms, mo, mx;
-
- uint ks1;
-
- XKeyEvent *ev = (XKeyEvent*)(xev);
-
- KeySym ks;
-
- char buf[128];
- char msg[128];
-
-
- /* Check for "normal" keypresses */
- n = XLookupString(ev, buf, 125, &ks, NULL);
-
- /* Terminate */
- buf[n] = '\0';
-
-
- /* Hack -- Ignore "modifier keys" */
- if (IsModifierKey(ks)) return;
-
-
- /* Hack -- convert into an unsigned int */
- ks1 = (uint)(ks);
-
- /* Extract four "modifier flags" */
- mc = (ev->state & ControlMask) ? TRUE : FALSE;
- ms = (ev->state & ShiftMask) ? TRUE : FALSE;
- mo = (ev->state & Mod1Mask) ? TRUE : FALSE;
- mx = (ev->state & Mod2Mask) ? TRUE : FALSE;
-
-
- /* Normal keys with no modifiers */
- if (n && !mo && !mx && !IsSpecialKey(ks))
- {
- /* Enqueue the normal key(s) */
- for (i = 0; buf[i]; i++) Term_keypress(buf[i]);
-
- /* All done */
- return;
- }
-
-
- /* Handle a few standard keys (bypass modifiers) XXX XXX XXX */
- switch (ks1)
- {
- case XK_Escape:
- {
- Term_keypress(ESCAPE);
- return;
- }
-
- case XK_Return:
- {
- Term_keypress('\r');
- return;
- }
-
- case XK_Tab:
- {
- Term_keypress('\t');
- return;
- }
-
- case XK_Delete:
- case XK_BackSpace:
- {
- Term_keypress('\010');
- return;
- }
- }
-
-
- /* Hack -- Use the KeySym */
- if (ks)
- {
- sprintf(msg, "%c%s%s%s%s_%lX%c", 31,
- mc ? "N" : "", ms ? "S" : "",
- mo ? "O" : "", mx ? "M" : "",
- (unsigned long)(ks), 13);
- }
-
- /* Hack -- Use the Keycode */
- else
- {
- sprintf(msg, "%c%s%s%s%sK_%X%c", 31,
- mc ? "N" : "", ms ? "S" : "",
- mo ? "O" : "", mx ? "M" : "",
- ev->keycode, 13);
- }
-
- /* Enqueue the "macro trigger" string */
- for (i = 0; msg[i]; i++) Term_keypress(msg[i]);
-
-
- /* Hack -- auto-define macros as needed */
- if (n && (macro_find_exact(msg) < 0))
- {
- /* Create a macro */
- macro_add(msg, buf);
- }
-}
-
-
-/*
- * Handle an event
- */
-static void handle_event(Widget widget, XtPointer client_data, XEvent *event,
- Boolean *continue_to_dispatch)
-{
- term_data *old_td = (term_data*)(Term->data);
- term_data *td = (term_data *)client_data;
-
- /* Continue to process the event by default */
- *continue_to_dispatch = TRUE;
-
- /* Activate the Term */
- Term_activate(&td->t);
-
- switch (event->type)
- {
- case KeyPress:
- {
- /* Hack -- use old term */
- Term_activate(&old_td->t);
-
- /* Handle the keypress */
- react_keypress(&(event->xkey));
-
- /* We took care of the event */
- *continue_to_dispatch = FALSE;
-
- break;
- }
-
- /* Oops */
- default:
- {
- break;
- }
- }
-
- /* Activate the old term */
- Term_activate(&old_td->t);
-
- return;
-}
-
-
-/*
- * Process an event (or just check for one)
- */
-errr CheckEvent(bool_ wait)
-{
- XEvent event;
-
- /* No events ready, and told to just check */
- if (!wait && !XtAppPending(appcon)) return 1;
-
- /* Process */
- while (1)
- {
- XtAppNextEvent(appcon, &event);
- XtDispatchEvent(&event);
- if (!XtAppPending(appcon)) break;
- }
-
- return (0);
-}
-
-
-/*
- * Monstrous hack.
- */
-static void Term_xtra_xaw_react_aux(term_data *td)
-{
- AngbandWidget wnew = td->widget;
-
- Display *dpy = XtDisplay((Widget) wnew);
-
- int depth = DefaultDepthOfScreen(XtScreen((Widget) wnew));
-
- int i;
-
- /* See if any colors need to be changed */
- for (i = 0; i < NUM_COLORS; i++)
- {
- if (depth > 1)
- {
- if ((wnew->angband.color[i][0] != angband_color_table[i][0]) ||
- (wnew->angband.color[i][1] != angband_color_table[i][1]) ||
- (wnew->angband.color[i][2] != angband_color_table[i][2]) ||
- (wnew->angband.color[i][3] != angband_color_table[i][3]))
- {
- unsigned long pixel;
-
- /* Save new values */
- wnew->angband.color[i][0] = angband_color_table[i][0];
- wnew->angband.color[i][1] = angband_color_table[i][1];
- wnew->angband.color[i][2] = angband_color_table[i][2];
- wnew->angband.color[i][3] = angband_color_table[i][3];
-
- /* Create pixel */
- pixel = create_pixel(dpy,
- wnew->angband.color[i][1],
- wnew->angband.color[i][2],
- wnew->angband.color[i][3]);
-
-
- /* Change */
- XSetForeground(dpy, wnew->angband.gc[i], pixel);
- }
- }
- }
-}
-
-
-/*
- * Monstrous hack.
- */
-static errr Term_xtra_xaw_react(void)
-{
- int i;
-
- /* Initialize the windows */
- for (i = 0; i < num_term; i++)
- {
- term_data *td = &data[i];
-
- if (!td) break;
-
- Term_xtra_xaw_react_aux(td);
- }
-
- return (0);
-}
-
-
-/*
- * Handle a "special request"
- */
-static errr Term_xtra_xaw(int n, int v)
-{
- term_data *td = (term_data*)(Term->data);
-
- Widget widget = (Widget)(td->widget);
-
- Display *dpy = XtDisplay(widget);
-
- /* Handle a subset of the legal requests */
- switch (n)
- {
- /* Make a noise */
- case TERM_XTRA_NOISE:
- XBell(dpy, 100);
- return (0);
-
- /* Flush the output */
- case TERM_XTRA_FRESH:
- XFlush(dpy);
- /* Allow flushed events to be showed */
- CheckEvent(FALSE);
- return (0);
-
- /* Process random events */
- case TERM_XTRA_BORED:
- return (CheckEvent(0));
-
- /* Process events */
- case TERM_XTRA_EVENT:
- return (CheckEvent(v));
-
- /* Flush events */
- case TERM_XTRA_FLUSH:
- while (!CheckEvent(FALSE));
- return (0);
-
- /* Clear the window */
- case TERM_XTRA_CLEAR:
- XClearWindow(dpy, XtWindow(widget));
- return (0);
-
- /* Delay */
- case TERM_XTRA_DELAY:
- usleep(1000 * v);
- return (0);
-
- /* Get Delay of some milliseconds */
- case TERM_XTRA_GET_DELAY:
- {
- int ret;
- struct timeval tv;
-
- ret = gettimeofday(&tv, NULL);
- Term_xtra_long = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
-
- return ret;
- }
-
- /* Subdirectory scan */
- case TERM_XTRA_SCANSUBDIR:
- {
- DIR *directory;
- struct dirent *entry;
-
- scansubdir_max = 0;
-
- directory = opendir(scansubdir_dir);
- if (!directory)
- return 1;
-
- while (entry = readdir(directory))
- {
- char file[PATH_MAX + NAME_MAX + 2];
- struct stat filedata;
-
- file[PATH_MAX + NAME_MAX] = 0;
- strncpy(file, scansubdir_dir, PATH_MAX);
- strncat(file, "/", 2);
- strncat(file, entry->d_name, NAME_MAX);
- if (!stat(file, &filedata) && S_ISDIR((filedata.st_mode)))
- {
- string_free(scansubdir_result[scansubdir_max]);
- scansubdir_result[scansubdir_max] = string_make(entry->d_name);
- ++scansubdir_max;
- }
- }
- }
-
- case TERM_XTRA_REACT:
- return (Term_xtra_xaw_react());
- }
-
- /* Unknown */
- return (1);
-}
-
-
-
-/*
- * Erase a number of characters
- */
-static errr Term_wipe_xaw(int x, int y, int n)
-{
- term_data *td = (term_data*)(Term->data);
-
- /* Erase using color 0 */
- AngbandClearArea(td->widget, x, y, n, 1, 0);
-
- /* Success */
- return (0);
-}
-
-
-
-/*
- * Draw the cursor, by hiliting with XOR
- *
- * Should perhaps use rectangle outline, ala "main-mac.c". XXX XXX XXX
- */
-static errr Term_curs_xaw(int x, int y)
-{
- term_data *td = (term_data*)(Term->data);
-
- /* Hilite the cursor character */
- AngbandClearArea(td->widget, x, y, 1, 1, COLOR_XOR);
-
- /* Success */
- return (0);
-}
-
-
-/*
- * Draw a number of characters
- */
-static errr Term_text_xaw(int x, int y, int n, byte a, cptr s)
-{
- term_data *td = (term_data*)(Term->data);
-
- /* Draw the text */
- AngbandOutputText(td->widget, x, y, (String)s, n, a);
-
- /* Success */
- return (0);
-}
-
-
-#ifdef USE_GRAPHICS
-
-/*
- * Draw some graphical characters.
- */
-static errr Term_pict_xaw(int x, int y, int n, const byte *ap, const char *cp,
- const byte *tap, const char *tcp, const byte *eap, const char *ecp)
-{
- term_data *td = (term_data*)(Term->data);
-
- /* Draw the pictures */
- AngbandOutputPict(td->widget, x, y, n, ap, cp, tap, tcp, eap, ecp);
-
- /* Success */
- return (0);
-}
-
-#endif /* USE_GRAPHICS */
-
-
-/*
- * Raise a term
- */
-static void term_raise(term_data *td)
-{
- Widget widget = (Widget)(td->widget);
-
- XRaiseWindow(XtDisplay(XtParent(widget)), XtWindow(XtParent(widget)));
-}
-
-
-/*
- * Initialize a term_data
- */
-static errr term_data_init(term_data *td, Widget topLevel,
- int key_buf, String name,
- ArgList widget_arg, Cardinal widget_arg_no, int i)
-{
- Widget parent;
- term *t = &td->t;
-
- int cols = 80;
- int rows = 24;
-
- char buf[80];
- cptr str;
-
- int val;
-
- /* Create the shell widget */
- parent = XtCreatePopupShell(name, topLevelShellWidgetClass, topLevel,
- NULL, 0);
-
- /* Window specific cols */
- sprintf(buf, "ANGBAND_X11_COLS_%d", i);
- str = getenv(buf);
- val = (str != NULL) ? atoi(str) : -1;
- if (val > 0) cols = val;
-
- /* Window specific rows */
- sprintf(buf, "ANGBAND_X11_ROWS_%d", i);
- str = getenv(buf);
- val = (str != NULL) ? atoi(str) : -1;
- if (val > 0) rows = val;
-
- /* Hack the main window must be at least 80x24 */
- if (i == 0)
- {
- if (cols < 80) cols = 80;
- if (rows < 24) rows = 24;
- }
-
- /* Reset the initial size */
- widget_arg[0].value = rows;
- widget_arg[1].value = cols;
-
- /* Create the interior widget */
- td->widget = (AngbandWidget)
- XtCreateManagedWidget(name, angbandWidgetClass,
- parent, widget_arg, widget_arg_no);
-
- /* Initialize the term (full size) */
- term_init(t, cols, rows, key_buf);
-
- /* Use a "soft" cursor */
- t->soft_cursor = TRUE;
-
- /* Erase with "white space" */
- t->attr_blank = TERM_WHITE;
- t->char_blank = ' ';
-
- /* Hooks */
- t->xtra_hook = Term_xtra_xaw;
- t->curs_hook = Term_curs_xaw;
- t->wipe_hook = Term_wipe_xaw;
- t->text_hook = Term_text_xaw;
-
- /* Save the data */
- t->data = td;
-
- /* Register the keypress event handler */
- XtAddEventHandler((Widget)td->widget, KeyPressMask,
- False, (XtEventHandler) handle_event, td);
-
- /* Redraw callback */
- XtAddCallback((Widget)td->widget, XtNredrawCallback,
- react_redraw, td);
-
- /* Realize the widget */
- XtRealizeWidget(parent);
-
- /* Make it visible */
- XtPopup(parent, XtGrabNone);
-
- /* Activate (important) */
- Term_activate(t);
-
- Resize_term(td->widget);
-
- return 0;
-}
-
-
-/*
- * Initialization function for an X Athena Widget module to Angband
- *
- * We should accept "-d<dpy>" requests in the "argv" array. XXX XXX XXX
- */
-errr init_xaw(int argc, char *argv[])
-{
- int i;
- Widget topLevel;
- Display *dpy;
-
- cptr dpy_name = "";
-
-
-#ifdef USE_GRAPHICS
-
- char filename[1024];
-
- int pict_wid = 0;
- int pict_hgt = 0;
- bool_ force_old_graphics = FALSE;
-
- char *TmpData;
-
-#endif /* USE_GRAPHICS */
-
- /* Parse args */
- for (i = 1; i < argc; i++)
- {
- if (prefix(argv[i], "-d"))
- {
- dpy_name = &argv[i][2];
- continue;
- }
-
-#ifdef USE_GRAPHICS
-
- if (prefix(argv[i], "-s"))
- {
- smoothRescaling = FALSE;
- continue;
- }
-
- if (prefix(argv[i], "-o"))
- {
- force_old_graphics = TRUE;
- continue;
- }
-
-#endif /* USE_GRAPHICS */
-
- if (prefix(argv[i], "-n"))
- {
- num_term = atoi(&argv[i][2]);
- if (num_term > MAX_TERM_DATA) num_term = MAX_TERM_DATA;
- else if (num_term < 1) num_term = 1;
- continue;
- }
-
- plog_fmt("Ignoring option: %s", argv[i]);
- }
-
-
- /* Attempt to open the local display */
- dpy = XOpenDisplay(dpy_name);
-
- /* Failure -- assume no X11 available */
- if (!dpy) return ( -1);
-
- /* Close the local display */
- XCloseDisplay(dpy);
-
-
-#ifdef USE_XAW_LANG
-
- /* Support locale processing */
- XtSetLanguageProc(NULL, NULL, NULL);
-
-#endif /* USE_XAW_LANG */
-
-
- /* Initialize the toolkit */
- topLevel = XtAppInitialize(&appcon, "Angband", NULL, 0, &argc, argv,
- fallback, NULL, 0);
-
- XSetIOErrorHandler(x_io_error_handler);
-
- /* Initialize the windows */
- for (i = 0; i < num_term; i++)
- {
- term_data *td = &data[i];
-
- term_data_init(td, topLevel, 1024, termNames[i],
- (i == 0) ? specialArgs : defaultArgs,
- TERM_FALLBACKS, i);
-
- angband_term[i] = Term;
- }
-
- /* Activate the "Angband" window screen */
- Term_activate(&data[0].t);
-
- /* Raise the "Angband" window */
- term_raise(&data[0]);
-
-
-#ifdef USE_GRAPHICS
-
- /* Try graphics */
- if (arg_graphics)
- {
- /* Try the "16x16.bmp" file */
- path_build(filename, 1024, ANGBAND_DIR_XTRA, "graf/16x16.bmp");
-
- /* Use the "16x16.bmp" file if it exists */
- if (!force_old_graphics &&
- (0 == fd_close(fd_open(filename, O_RDONLY))))
- {
- /* Use graphics */
- use_graphics = TRUE;
-
- pict_wid = pict_hgt = 16;
-
- ANGBAND_GRAF = "new";
- }
- else
- {
- /* Try the "8x8.bmp" file */
- path_build(filename, 1024, ANGBAND_DIR_XTRA, "graf/8x8.bmp");
-
- /* Use the "8x8.bmp" file if it exists */
- if (0 == fd_close(fd_open(filename, O_RDONLY)))
- {
- /* Use graphics */
- use_graphics = TRUE;
-
- pict_wid = pict_hgt = 8;
-
- ANGBAND_GRAF = "old";
- }
- }
- }
-
- /* Load graphics */
- if (use_graphics)
- {
- /* Hack -- Get the Display */
- term_data *td = &data[0];
- Widget widget = (Widget)(td->widget);
- Display *dpy = XtDisplay(widget);
-
- XImage *tiles_raw;
-
- /* Load the graphical tiles */
- tiles_raw = ReadBMP(dpy, filename);
-
- /* Initialize the windows */
- for (i = 0; i < num_term; i++)
- {
- term_data *td = &data[i];
-
- term *t = &td->t;
-
- t->pict_hook = Term_pict_xaw;
-
- t->higher_pict = TRUE;
-
- /* Resize tiles */
- td->widget->angband.tiles =
- ResizeImage(dpy, tiles_raw,
- pict_wid, pict_hgt,
- td->widget->angband.fontwidth,
- td->widget->angband.fontheight);
- }
-
- /* Initialize the transparency temp storage*/
- for (i = 0; i < num_term; i++)
- {
- term_data *td = &data[i];
- int ii, jj;
- int depth = DefaultDepth(dpy, DefaultScreen(dpy));
- Visual *visual = DefaultVisual(dpy, DefaultScreen(dpy));
- int total;
-
-
- /* Determine total bytes needed for image */
- ii = 1;
- jj = (depth - 1) >> 2;
- while (jj >>= 1) ii <<= 1;
- total = td->widget->angband.fontwidth *
- td->widget->angband.fontheight * ii;
-
-
- TmpData = (char *)malloc(total);
-
- td->widget->angband.TmpImage = XCreateImage(dpy,
- visual, depth,
- ZPixmap, 0, TmpData,
- td->widget->angband.fontwidth,
- td->widget->angband.fontheight, 8, 0);
-
- }
-
-
- /* Free tiles_raw? XXX XXX */
- }
-
-#endif /* USE_GRAPHICS */
-
- /* Success */
- return (0);
-}
-
-#endif /* USE_XAW */
-
diff --git a/src/main-xxx.c b/src/main-xxx.c
deleted file mode 100644
index c80f01f0..00000000
--- a/src/main-xxx.c
+++ /dev/null
@@ -1,785 +0,0 @@
-/* File: main-xxx.c */
-
-/* Purpose: Sample visual module for Angband 2.8.1 */
-
-/*
- * This file written by "Ben Harrison (benh@phial.com)".
- *
- * This file is intended to show one way to build a "visual module"
- * for Angband to allow it to work with a new system. It does not
- * actually work, but if the code near "XXX XXX XXX" comments were
- * replaced with functional code, then it probably would.
- *
- * See "z-term.c" for info on the concept of the "generic terminal",
- * and for more comments about what this file must supply.
- *
- * There are two basic ways to port Angband to a new system. The
- * first involves modifying the "main-gcu.c" and/or "main-x11.c"
- * files to support some version of "curses" and/or "X11" on your
- * machine, and to compile with the "USE_GCU" and/or "USE_X11"
- * compilation flags defined. The second involves creating a
- * new "main-xxx.c" file, based on this sample file (or on any
- * existing "main-xxx.c" file), and comes in two flavors, based
- * on whether it contains a "main()" function (as in "main-mac.c"
- * and "main-win.c") or not (as in "main-gcu.c" or "main-x11.c").
- *
- * If the "main-xxx.c" file includes its own "main()" function,
- * then you should NOT link in the "main.c" file, and your "main()"
- * function must process any command line arguments, initialize the
- * "visual system", and call "play_game()" with appropriate arguments.
- *
- * If the "main-xxx.c" file does not include its own "main()"
- * function, then you must add some code to "main.c" which, if
- * the appropriate "USE_XXX" compilation flag is defined, will
- * attempt to call the "init_xxx()" function in the "main-xxx.c"
- * file, which should initialize the "visual system" and return
- * zero if it was successful. The "main()" function in "main.c"
- * will take care of processing command line arguments and then
- * calling "play_game()" with appropriate arguments.
- *
- * Note that the "util.c" file often contains functions which must
- * be modified in small ways for various platforms, even if you are
- * able to use the existing "main-gcu.c" and/or "main-x11.c" files,
- * in particular, the "file handling" functions may not work on all
- * systems.
- *
- * When you complete a port to a new system, you should email any
- * newly created files, and any changes made to existing files,
- * including "h-config.h", "config.h", and any of the "Makefile"
- * files, to "benh@phial.com" for inclusion in the next version.
- *
- * Try to stick to a "three letter" naming scheme for "main-xxx.c"
- * and "Makefile.xxx" and such for consistency and simplicity.
- */
-
-
-#include "angband.h"
-
-
-#ifdef USE_XXX
-
-
-/*
- * Extra data to associate with each "window"
- *
- * Each "window" is represented by a "term_data" structure, which
- * contains a "term" structure, which contains a pointer (t->data)
- * back to the term_data structure.
- */
-
-typedef struct term_data term_data;
-
-struct term_data
-{
- term t;
-
- /* Other fields if needed XXX XXX XXX */
-};
-
-
-
-/*
- * Number of "term_data" structures to support XXX XXX XXX
- *
- * You MUST support at least one "term_data" structure, and the
- * game will currently use up to eight "term_data" structures if
- * they are available.
- *
- * If only one "term_data" structure is supported, then a lot of
- * the things that would normally go into a "term_data" structure
- * could be made into global variables instead.
- */
-#define MAX_TERM_DATA 1
-
-
-/*
- * An array of "term_data" structures, one for each "sub-window"
- */
-static term_data data[MAX_TERM_DATA];
-
-
-#if 0 /* Fix the syntax below XXX XXX XXX */
-
-/*
- * The "color" array for the visual module XXX XXX XXX
- *
- * This table should be used in whetever way is necessary to
- * convert the Angband Color Indexes into the proper "color data"
- * for the visual system. On the Macintosh, these are arrays of
- * three shorts, on the IBM, these are combinations of the eight
- * basic color codes with optional "bright" bits, on X11, these
- * are actual "pixel" codes extracted from another table which
- * contains textual color names.
- *
- * The Angband Color Set (0 to 15):
- * Black, White, Slate, Orange, Red, Blue, Green, Umber
- * D-Gray, L-Gray, Violet, Yellow, L-Red, L-Blue, L-Green, L-Umber
- *
- * Colors 8 to 15 are basically "enhanced" versions of Colors 0 to 7.
- *
- * As decribed in one of the header files, in a perfect world, the
- * colors below should fit a nice clean "quartered" specification
- * in RGB codes, but this must often be Gamma Corrected. The 1/4
- * parts of each Red,Green,Blue are shown in the comments below,
- * again, these values are *before* gamma correction.
- */
-static local_color_data_type color_data[16] =
-{
- /* XXX XXX XXX 0,0,0 */, /* TERM_DARK */
- /* XXX XXX XXX 4,4,4 */, /* TERM_WHITE */
- /* XXX XXX XXX 2,2,2 */, /* TERM_SLATE */
- /* XXX XXX XXX 4,2,0 */, /* TERM_ORANGE */
- /* XXX XXX XXX 3,0,0 */, /* TERM_RED */
- /* XXX XXX XXX 0,2,1 */, /* TERM_GREEN */
- /* XXX XXX XXX 0,0,4 */, /* TERM_BLUE */
- /* XXX XXX XXX 2,1,0 */, /* TERM_UMBER */
- /* XXX XXX XXX 1,1,1 */, /* TERM_L_DARK */
- /* XXX XXX XXX 3,3,3 */, /* TERM_L_WHITE */
- /* XXX XXX XXX 4,0,4 */, /* TERM_VIOLET */
- /* XXX XXX XXX 4,4,0 */, /* TERM_YELLOW */
- /* XXX XXX XXX 4,0,0 */, /* TERM_L_RED */
- /* XXX XXX XXX 0,4,0 */, /* TERM_L_GREEN */
- /* XXX XXX XXX 0,4,4 */, /* TERM_L_BLUE */
- /* XXX XXX XXX 3,2,1 */ /* TERM_L_UMBER */
-};
-
-#endif
-
-
-
-/*** Function hooks needed by "Term" ***/
-
-
-/*
- * Init a new "term"
- *
- * This function should do whatever is necessary to prepare a new "term"
- * for use by the "term.c" package. This may include clearing the window,
- * preparing the cursor, setting the font/colors, etc. Usually, this
- * function does nothing, and the "init_xxx()" function does it all.
- */
-static void Term_init_xxx(term *t)
-{
- term_data *td = (term_data*)(t->data);
-
- /* XXX XXX XXX */
-}
-
-
-
-/*
- * Nuke an old "term"
- *
- * This function is called when an old "term" is no longer needed. It should
- * do whatever is needed to clean up before the program exits, such as wiping
- * the screen, restoring the cursor, fixing the font, etc. Often this function
- * does nothing and lets the operating system clean up when the program quits.
- */
-static void Term_nuke_xxx(term *t)
-{
- term_data *td = (term_data*)(t->data);
-
- /* XXX XXX XXX */
-}
-
-
-
-/*
- * Do a "user action" on the current "term"
- *
- * This function allows the visual module to do implementation defined
- * things when the user activates the "system defined command" command.
- *
- * This function is normally not used.
- *
- * In general, this function should return zero if the action is successfully
- * handled, and non-zero if the action is unknown or incorrectly handled.
- */
-static errr Term_user_xxx(int n)
-{
- term_data *td = (term_data*)(Term->data);
-
- /* XXX XXX XXX */
-
- /* Unknown */
- return (1);
-}
-
-
-/*
- * Do a "special thing" to the current "term"
- *
- * This function must react to a large number of possible arguments, each
- * corresponding to a different "action request" by the "z-term.c" package,
- * or by the application itself.
- *
- * The "action type" is specified by the first argument, which must be a
- * constant of the form "TERM_XTRA_*" as given in "term.h", and the second
- * argument specifies the "information" for that argument, if any, and will
- * vary according to the first argument.
- *
- * In general, this function should return zero if the action is successfully
- * handled, and non-zero if the action is unknown or incorrectly handled.
- */
-static errr Term_xtra_xxx(int n, int v)
-{
- term_data *td = (term_data*)(Term->data);
-
- /* Analyze */
- switch (n)
- {
- case TERM_XTRA_EVENT:
- {
- /*
- * Process some pending events XXX XXX XXX
- *
- * Wait for at least one event if "v" is non-zero
- * otherwise, if no events are ready, return at once.
- * When "keypress" events are encountered, the "ascii"
- * value corresponding to the key should be sent to the
- * "Term_keypress()" function. Certain "bizarre" keys,
- * such as function keys or arrow keys, may send special
- * sequences of characters, such as control-underscore,
- * plus letters corresponding to modifier keys, plus an
- * underscore, plus carriage return, which can be used by
- * the main program for "macro" triggers. This action
- * should handle as many events as is efficiently possible
- * but is only required to handle a single event, and then
- * only if one is ready or "v" is true.
- *
- * This action is required.
- */
-
- return (0);
- }
-
- case TERM_XTRA_FLUSH:
- {
- /*
- * Flush all pending events XXX XXX XXX
- *
- * This action should handle all events waiting on the
- * queue, optionally discarding all "keypress" events,
- * since they will be discarded anyway in "z-term.c".
- *
- * This action is required, but may not be "essential".
- */
-
- return (0);
- }
-
- case TERM_XTRA_CLEAR:
- {
- /*
- * Clear the entire window XXX XXX XXX
- *
- * This action should clear the entire window, and redraw
- * any "borders" or other "graphic" aspects of the window.
- *
- * This action is required.
- */
-
- return (0);
- }
-
- case TERM_XTRA_SHAPE:
- {
- /*
- * Set the cursor visibility XXX XXX XXX
- *
- * This action should change the visibility of the cursor,
- * if possible, to the requested value (0=off, 1=on)
- *
- * This action is optional, but can improve both the
- * efficiency (and attractiveness) of the program.
- */
-
- return (0);
- }
-
- case TERM_XTRA_FROSH:
- {
- /*
- * Flush a row of output XXX XXX XXX
- *
- * This action should make sure that row "v" of the "output"
- * to the window will actually appear on the window.
- *
- * This action is optional, assuming that "Term_text_xxx()"
- * (and similar functions) draw directly to the screen, or
- * that the "TERM_XTRA_FRESH" entry below takes care of any
- * necessary flushing issues.
- */
-
- return (0);
- }
-
- case TERM_XTRA_FRESH:
- {
- /*
- * Flush output XXX XXX XXX
- *
- * This action should make sure that all "output" to the
- * window will actually appear on the window.
- *
- * This action is optional, assuming that "Term_text_xxx()"
- * (and similar functions) draw directly to the screen, or
- * that the "TERM_XTRA_FROSH" entry above takes care of any
- * necessary flushing issues.
- */
-
- return (0);
- }
-
- case TERM_XTRA_NOISE:
- {
- /*
- * Make a noise XXX XXX XXX
- *
- * This action should produce a "beep" noise.
- *
- * This action is optional, but convenient.
- */
-
- return (0);
- }
-
- case TERM_XTRA_SOUND:
- {
- /*
- * Make a sound XXX XXX XXX
- *
- * This action should produce sound number "v", where the
- * "name" of that sound is "sound_names[v]". This method
- * is still under construction.
- *
- * This action is optional, and not very important.
- */
-
- return (0);
- }
-
- case TERM_XTRA_BORED:
- {
- /*
- * Handle random events when bored XXX XXX XXX
- *
- * This action is optional, and normally not important
- */
-
- return (0);
- }
-
- case TERM_XTRA_REACT:
- {
- /*
- * React to global changes XXX XXX XXX
- *
- * For example, this action can be used to react to
- * changes in the global "color_table[256][4]" array.
- *
- * This action is optional, but can be very useful for
- * handling "color changes" and the "arg_sound" and/or
- * "arg_graphics" options.
- */
-
- return (0);
- }
-
- case TERM_XTRA_ALIVE:
- {
- /*
- * Change the "hard" level XXX XXX XXX
- *
- * This action is used if the program changes "aliveness"
- * by being either "suspended" (v=0) or "resumed" (v=1)
- * This action is optional, unless the computer uses the
- * same "physical screen" for multiple programs, in which
- * case this action should clean up to let other programs
- * use the screen, or resume from such a cleaned up state.
- *
- * This action is currently only used by "main-gcu.c",
- * on UNIX machines, to allow proper "suspending".
- */
-
- return (0);
- }
-
- case TERM_XTRA_LEVEL:
- {
- /*
- * Change the "soft" level XXX XXX XXX
- *
- * This action is used when the term window changes "activation"
- * either by becoming "inactive" (v=0) or "active" (v=1)
- *
- * This action can be used to do things like activate the proper
- * font / drawing mode for the newly active term window. This
- * action should NOT change which window has the "focus", which
- * window is "raised", or anything like that.
- *
- * This action is optional if all the other things which depend
- * on what term is active handle activation themself, or if only
- * one "term_data" structure is supported by this file.
- */
-
- return (0);
- }
-
- case TERM_XTRA_DELAY:
- {
- /*
- * Delay for some milliseconds XXX XXX XXX
- *
- * This action is useful for proper "timing" of certain
- * visual effects, such as breath attacks.
- *
- * This action is optional, but may be required by this file,
- * especially if special "macro sequences" must be supported.
- */
-
- return (0);
- }
-
- case TERM_XTRA_GET_DELAY:
- {
- /*
- * Get Delay of some milliseconds XXX XXX XXX
- * place the result in Term_xtra_long
- *
- * This action is useful for proper "timing" of certain
- * visual effects, such as recording cmovies.
- *
- * This action is optional, but cmovies wont perform
- * good without it
- */
-
- return (0);
- }
- }
-
- /* Unknown or Unhandled action */
- return (1);
-}
-
-
-/*
- * Display the cursor
- *
- * This routine should display the cursor at the given location
- * (x,y) in some manner. On some machines this involves actually
- * moving the physical cursor, on others it involves drawing a fake
- * cursor in some form of graphics mode. Note the "soft_cursor"
- * flag which tells "z-term.c" to treat the "cursor" as a "visual"
- * thing and not as a "hardware" cursor.
- *
- * You may assume "valid" input if the window is properly sized.
- *
- * You may use the "Term_grab(x, y, &a, &c)" function, if needed,
- * to determine what attr/char should be "under" the new cursor,
- * for "inverting" purposes or whatever.
- */
-static errr Term_curs_xxx(int x, int y)
-{
- term_data *td = (term_data*)(Term->data);
-
- /* XXX XXX XXX */
-
- /* Success */
- return (0);
-}
-
-
-/*
- * Erase some characters
- *
- * This function should erase "n" characters starting at (x,y).
- *
- * You may assume "valid" input if the window is properly sized.
- */
-static errr Term_wipe_xxx(int x, int y, int n)
-{
- term_data *td = (term_data*)(Term->data);
-
- /* XXX XXX XXX */
-
- /* Success */
- return (0);
-}
-
-
-/*
- * Draw some text on the screen
- *
- * This function should actually display an array of characters
- * starting at the given location, using the given "attribute",
- * and using the given string of characters, which contains
- * exactly "n" characters and which is NOT null-terminated.
- *
- * You may assume "valid" input if the window is properly sized.
- *
- * You must be sure that the string, when written, erases anything
- * (including any visual cursor) that used to be where the text is
- * drawn. On many machines this happens automatically, on others,
- * you must first call "Term_wipe_xxx()" to clear the area.
- *
- * In color environments, you should activate the color contained
- * in "color_data[a & 0x0F]", if needed, before drawing anything.
- *
- * You may ignore the "attribute" if you are only supporting a
- * monochrome environment, since this routine is normally never
- * called to display "black" (invisible) text, including the
- * default "spaces", and all other colors should be drawn in
- * the "normal" color in a monochrome environment.
- *
- * Note that if you have changed the "attr_blank" to something
- * which is not black, then this function must be able to draw
- * the resulting "blank" correctly.
- *
- * Note that this function must correctly handle "black" text if
- * the "always_text" flag is set, if this flag is not set, all the
- * "black" text will be handled by the "Term_wipe_xxx()" hook.
- */
-static errr Term_text_xxx(int x, int y, int n, byte a, const char *cp)
-{
- term_data *td = (term_data*)(Term->data);
-
- /* XXX XXX XXX */
-
- /* Success */
- return (0);
-}
-
-
-/*
- * Draw some attr/char pairs on the screen
- *
- * This routine should display the given "n" attr/char pairs at
- * the given location (x,y). This function is only used if one
- * of the flags "always_pict" or "higher_pict" is defined.
- *
- * You must be sure that the attr/char pairs, when displayed, will
- * erase anything (including any visual cursor) that used to be at
- * the given location. On many machines this is automatic, but on
- * others, you must first call "Term_wipe_xxx(x, y, 1)".
- *
- * With the "higher_pict" flag, this function can be used to allow
- * the display of "pseudo-graphic" pictures, for example, by using
- * the attr/char pair as an encoded index into a pixmap of special
- * "pictures".
- *
- * With the "always_pict" flag, this function can be used to force
- * every attr/char pair to be drawn by this function, which can be
- * very useful if this file can optimize its own display calls.
- *
- * This function is often associated with the "arg_graphics" flag.
- *
- * This function is only used if one of the "higher_pict" and/or
- * "always_pict" flags are set.
- */
-static errr Term_pict_xxx(int x, int y, int n, const byte *ap, const char *cp)
-{
- term_data *td = (term_data*)(Term->data);
-
- /* XXX XXX XXX */
-
- /* Success */
- return (0);
-}
-
-
-
-/*** Internal Functions ***/
-
-
-/*
- * Instantiate a "term_data" structure
- *
- * This is one way to prepare the "term_data" structures and to
- * "link" the various informational pieces together.
- *
- * This function assumes that every window should be 80x24 in size
- * (the standard size) and should be able to queue 256 characters.
- * Technically, only the "main screen window" needs to queue any
- * characters, but this method is simple. One way to allow some
- * variation is to add fields to the "term_data" structure listing
- * parameters for that window, initialize them in the "init_xxx()"
- * function, and then use them in the code below.
- *
- * Note that "activation" calls the "Term_init_xxx()" hook for
- * the "term" structure, if needed.
- */
-static void term_data_link(int i)
-{
- term_data *td = &data[i];
-
- /* Initialize the term */
- term_init(td->t, 80, 24, 256);
-
- /* Choose "soft" or "hard" cursor XXX XXX XXX */
- /* A "soft" cursor must be explicitly "drawn" by the program */
- /* while a "hard" cursor has some "physical" existance and is */
- /* moved whenever text is drawn on the screen. See "term.c". */
- /* td->t->soft_cursor = TRUE; */
-
- /* Avoid the "corner" of the window XXX XXX XXX */
- /* td->t->icky_corner = TRUE; */
-
- /* Use "Term_pict()" for all attr/char pairs XXX XXX XXX */
- /* See the "Term_pict_xxx()" function above. */
- /* td->t->always_pict = TRUE; */
-
- /* Use "Term_pict()" for some attr/char pairs XXX XXX XXX */
- /* See the "Term_pict_xxx()" function above. */
- /* td->t->higher_pict = TRUE; */
-
- /* Use "Term_text()" even for "black" text XXX XXX XXX */
- /* See the "Term_text_xxx()" function above. */
- /* td->t->always_text = TRUE; */
-
- /* Ignore the "TERM_XTRA_BORED" action XXX XXX XXX */
- /* This may make things slightly more efficient. */
- /* td->t->never_bored = TRUE; */
-
- /* Ignore the "TERM_XTRA_FROSH" action XXX XXX XXX */
- /* This may make things slightly more efficient. */
- /* td->t->never_frosh = TRUE; */
-
- /* Erase with "white space" XXX XXX XXX */
- /* td->t->attr_blank = TERM_WHITE; */
- /* td->t->char_blank = ' '; */
-
- /* Prepare the init/nuke hooks */
- td->t->init_hook = Term_init_xxx;
- td->t->nuke_hook = Term_nuke_xxx;
-
- /* Prepare the template hooks */
- td->t->user_hook = Term_user_xxx;
- td->t->xtra_hook = Term_xtra_xxx;
- td->t->curs_hook = Term_curs_xxx;
- td->t->wipe_hook = Term_wipe_xxx;
- td->t->text_hook = Term_text_xxx;
- td->t->pict_hook = Term_pict_xxx;
-
- /* Remember where we came from */
- td->t->data = (vptr)(td);
-
- /* Activate it */
- Term_activate(td->t);
-
- /* Global pointer */
- ang_term[i] = td->t;
-}
-
-
-
-/*
- * Initialization function
- */
-errr init_xxx(void)
-{
- /* Initialize globals XXX XXX XXX */
-
- /* Initialize "term_data" structures XXX XXX XXX */
-
- /* Create windows (backwards!) */
- for (i = TERM_DATA_MAX - 1; i >= 0; i--)
- {
- /* Link */
- term_data_link(i);
- }
-
- /* Success */
- return (0);
-}
-
-
-#ifdef INTERNAL_MAIN
-
-
-/*
- * Some special machines need their own "main()" function, which they
- * can provide here, making sure NOT to compile the "main.c" file.
- *
- * These systems usually have some form of "event loop", run forever
- * as the last step of "main()", which handles things like menus and
- * window movement, and calls "play_game(FALSE)" to load a game after
- * initializing "savefile" to a filename, or "play_game(TRUE)" to make
- * a new game. The event loop would also be triggered by "Term_xtra()"
- * (the TERM_XTRA_EVENT action), in which case the event loop would not
- * actually "loop", but would run once and return.
- */
-
-
-/*
- * An event handler XXX XXX XXX
- *
- * You may need an event handler, which can be used by both
- * by the "TERM_XTRA_BORED" and "TERM_XTRA_EVENT" entries in
- * the "Term_xtra_xxx()" function, and also to wait for the
- * user to perform whatever user-interface operation is needed
- * to request the start of a new game or the loading of an old
- * game, both of which should launch the "play_game()" function.
- */
-static bool_ CheckEvents(bool_ wait)
-{
- /* XXX XXX XXX */
-
- return (0);
-}
-
-
-/*
- * Init some stuff
- *
- * This function is used to keep the "path" variable off the stack.
- */
-static void init_stuff(void)
-{
- char path[1024];
-
- /* Prepare the path XXX XXX XXX */
- /* This must in some way prepare the "path" variable */
- /* so that it points at the "lib" directory. Every */
- /* machine handles this in a different way... */
- strcpy(path, "XXX XXX XXX");
-
- /* Prepare the filepaths */
- init_file_paths(path);
-}
-
-
-/*
- * Main function
- *
- * This function must do a lot of stuff.
- */
-int main(int argc, char *argv[])
-{
- /* Initialize the machine itself XXX XXX XXX */
-
- /* Process command line arguments XXX XXX XXX */
-
- /* Initialize the windows */
- if (init_xxx()) quit("Oops!");
-
- /* XXX XXX XXX */
- ANGBAND_SYS = "xxx";
-
- /* Initialize some stuff */
- init_stuff();
-
- /* Initialize */
- init_angband * /
-
- /* Allow auto-startup XXX XXX XXX */
-
- /* Event loop forever XXX XXX XXX */
- while (TRUE) CheckEvents(TRUE);
-}
-
-
-#endif /* INTERNAL_MAIN */
-
-
-#endif /* USE_XXX */
diff --git a/src/main.c b/src/main.c
deleted file mode 100644
index 48ab3f04..00000000
--- a/src/main.c
+++ /dev/null
@@ -1,691 +0,0 @@
-/* File: main.c */
-
-/*
- * Copyright (c) 1997 Ben Harrison, and others
- *
- * 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"
-
-
-
-/*
- * Some machines have a "main()" function in their "main-xxx.c" file,
- * all the others use this file for their "main()" function.
- */
-
-
-#if !defined(MACINTOSH) && !defined(WINDOWS)
-
-
-/*
- * A hook for "quit()".
- *
- * Close down, then fall back into "quit()".
- */
-static void quit_hook(cptr s)
-{
- int j;
-
- /* Scan windows */
- for (j = 8 - 1; j >= 0; j--)
- {
- /* Unused */
- if (!angband_term[j]) continue;
-
- /* Nuke it */
- term_nuke(angband_term[j]);
- }
-}
-
-
-
-/*
- * Check and create if needed the directory dirpath
- */
-bool_ private_check_user_directory(cptr dirpath)
-{
- /* Is this used anywhere else in *bands? */
- struct stat stat_buf;
-
- int ret;
-
- /* See if it already exists */
- ret = stat(dirpath, &stat_buf);
-
- /* It does */
- if (ret == 0)
- {
- /* Now we see if it's a directory */
- if ((stat_buf.st_mode & S_IFMT) == S_IFDIR) return (TRUE);
-
- /*
- * Something prevents us from create a directory with
- * the same pathname
- */
- return (FALSE);
- }
-
- /* No - this maybe the first time. Try to create a directory */
- else
- {
- /* Create the ~/.ToME directory */
- ret = mkdir(dirpath, 0700);
-
- /* An error occured */
- if (ret == -1) return (FALSE);
-
- /* Success */
- return (TRUE);
- }
-}
-
-/*
- * Check existence of ".ToME/" directory in the user's
- * home directory or try to create it if it doesn't exist.
- * Returns FALSE if all the attempts fail.
- */
-static bool_ check_create_user_dir(void)
-{
- char dirpath[1024];
- char versionpath[1024];
- char savepath[1024];
-
- /* Get an absolute path from the filename */
- path_parse(dirpath, 1024, PRIVATE_USER_PATH);
- strcpy(versionpath, dirpath);
- strcat(versionpath, USER_PATH_VERSION);
- strcpy(savepath, versionpath);
- strcat(savepath, "/save");
-
- return private_check_user_directory(dirpath) && private_check_user_directory(versionpath) && private_check_user_directory(savepath);
-}
-
-
-/*
- * Initialize and verify the file paths, and the score file.
- *
- * Use the ANGBAND_PATH environment var if possible, else use
- * DEFAULT_PATH, and in either case, branch off appropriately.
- *
- * First, we'll look for the ANGBAND_PATH environment variable,
- * and then look for the files in there. If that doesn't work,
- * we'll try the DEFAULT_PATH constant. So be sure that one of
- * these two things works...
- *
- * We must ensure that the path ends with "PATH_SEP" if needed,
- * since the "init_file_paths()" function will simply append the
- * relevant "sub-directory names" to the given path.
- */
-static void init_stuff(void)
-{
- char path[1024];
-
- cptr tail;
-
- /* Get the environment variable */
- tail = getenv("TOME_PATH");
-
- /* Use the angband_path, or a default */
- strcpy(path, tail ? tail : DEFAULT_PATH);
-
- /* Hack -- Add a path separator (only if needed) */
- if (!suffix(path, PATH_SEP)) strcat(path, PATH_SEP);
-
- /* Initialize */
- init_file_paths(path);
-}
-
-
-
-/*
- * Handle a "-d<what>=<path>" option
- *
- * The "<what>" can be any string starting with the same letter as the
- * name of a subdirectory of the "lib" folder (i.e. "i" or "info").
- *
- * The "<path>" can be any legal path for the given system, and should
- * not end in any special path separator (i.e. "/tmp" or "~/.ang-info").
- */
-static void change_path(cptr info)
-{
- cptr s;
-
- /* Find equal sign */
- s = strchr(info, '=');
-
- /* Verify equal sign */
- if (!s) quit_fmt("Try '-d<what>=<path>' not '-d%s'", 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);
- ANGBAND_DIR_FILE = string_make(s + 1);
- break;
- }
-
- case 'h':
- {
- string_free(ANGBAND_DIR_HELP);
- ANGBAND_DIR_HELP = string_make(s + 1);
- break;
- }
-
- case 'i':
- {
- string_free(ANGBAND_DIR_INFO);
- ANGBAND_DIR_INFO = string_make(s + 1);
- break;
- }
-
- case 'u':
- {
- string_free(ANGBAND_DIR_USER);
- ANGBAND_DIR_USER = string_make(s + 1);
- break;
- }
-
- case 'x':
- {
- string_free(ANGBAND_DIR_XTRA);
- ANGBAND_DIR_XTRA = string_make(s + 1);
- break;
- }
-
- case 'd':
- {
- string_free(ANGBAND_DIR_DATA);
- ANGBAND_DIR_DATA = string_make(s + 1);
- break;
- }
-
- case 'e':
- {
- string_free(ANGBAND_DIR_EDIT);
- ANGBAND_DIR_EDIT = string_make(s + 1);
- break;
- }
-
- case 's':
- {
- string_free(ANGBAND_DIR_SAVE);
- ANGBAND_DIR_SAVE = string_make(s + 1);
- break;
- }
-
- default:
- {
- quit_fmt("Bad semantics in '-d%s'", info);
- }
- }
-}
-
-
-/*
- * Simple "main" function for multiple platforms.
- *
- * Note the special "--" option which terminates the processing of
- * standard options. All non-standard options (if any) are passed
- * directly to the "init_xxx()" function.
- */
-int main(int argc, char *argv[])
-{
- int i;
-
- bool_ done = FALSE;
-
- bool_ new_game = FALSE;
-
- int show_score = 0;
-
- cptr mstr = NULL;
-
- bool_ args = TRUE;
-
-#ifdef CHECK_MEMORY_LEAKS
- GC_find_leak = 1;
-#endif /* CHECK_MEMORY_LEAKS */
-
-
- /* Save the "program name" XXX XXX XXX */
- argv0 = argv[0];
-
-
- /* Default permissions on files */
- (void)umask(022);
-
-
- /* Get the file paths */
- init_stuff();
-
-
- /* Get the user id (?) */
- player_uid = getuid();
-
- /* Acquire the "user name" as a default player name */
- user_name(player_name, player_uid);
-
-
- /*
- * On multiuser systems, users' private directories are
- * used to store pref files, chardumps etc.
- */
- {
- bool_ ret;
-
- /* Create a directory for the user's files */
- ret = check_create_user_dir();
-
- /* Oops */
- if (ret == FALSE) quit("Cannot create directory " PRIVATE_USER_PATH);
- }
-
-
-
-
- /* Process the command line arguments */
- for (i = 1; args && (i < argc); i++)
- {
- /* Require proper options */
- if (argv[i][0] != '-') goto usage;
-
- /* Analyze option */
- switch (argv[i][1])
- {
- case 'N':
- case 'n':
- {
- new_game = TRUE;
- break;
- }
-
- case 'F':
- case 'f':
- {
- arg_fiddle = TRUE;
- break;
- }
-
- case 'W':
- case 'w':
- {
- arg_wizard = TRUE;
- break;
- }
-
- case 'V':
- case 'v':
- {
- arg_sound = TRUE;
- break;
- }
-
- case 'G':
- case 'g':
- {
- arg_graphics = TRUE;
- break;
- }
-
- case 'R':
- case 'r':
- {
- arg_force_roguelike = TRUE;
- break;
- }
-
- case 'O':
- case 'o':
- {
- arg_force_original = TRUE;
- break;
- }
-
- case 'S':
- case 's':
- {
- show_score = atoi(&argv[i][2]);
- if (show_score <= 0) show_score = 10;
- break;
- }
-
- case 'u':
- case 'U':
- {
- if (!argv[i][2]) goto usage;
- strcpy(player_name, &argv[i][2]);
- strcpy(player_base, &argv[i][2]);
- no_begin_screen = TRUE;
- break;
- }
-
- case 'm':
- {
- if (!argv[i][2]) goto usage;
- mstr = &argv[i][2];
- break;
- }
-
- case 'M':
- {
- if (!argv[i][2]) goto usage;
- force_module = string_make(&argv[i][2]);
- break;
- }
-
- case 'h':
- {
- goto usage;
- break;
- }
-
- case 'H':
- {
- char *s;
- int j;
-
- init_lua();
- for (j = i + 1; j < argc; j++)
- {
- s = argv[j];
-
- while (*s != '.') s++;
- *s = '\0';
- s++;
- txt_to_html("head.aux", "foot.aux", argv[j], s, FALSE, FALSE);
- }
-
- return 0;
- }
-
- case 'd':
- case 'D':
- {
- change_path(&argv[i][2]);
- break;
- }
-
- case '-':
- {
- if (argv[i][2] == 'h' && !strcmp((argv[i] + 2), "help"))
- goto usage;
- else
- {
- argv[i] = argv[0];
- argc = argc - i;
- argv = argv + i;
- args = FALSE;
- break;
- }
- }
-
- default:
-usage:
- {
- int j;
-
- /* Dump usage information */
- for (j = 0; j < argc; j++) printf("%s ", argv[j]);
- printf("\n");
- 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");
- puts(" -o Request original keyset");
- puts(" -r Request rogue-like keyset");
- puts(" -H <list of files> Convert helpfile to html");
- puts(" -s<num> Show <num> high scores");
- puts(" -u<who> Use your <who> savefile");
- puts(" -M<which> Use the <which> module");
- puts(" -m<sys> Force 'main-<sys>.c' usage");
- puts(" -d<def> Define a 'lib' dir sub-path");
-
-#ifdef USE_GTK2
- puts(" -mgtk2 To use GTK2");
- puts(" -- Sub options");
- puts(" -- -n# Number of terms to use");
- puts(" -- -b Turn off software backing store");
-# ifdef USE_GRAPHICS
- puts(" -- -s Turn off smoothscaling graphics");
- puts(" -- -o Requests \"old\" graphics");
- puts(" -- -g Requests \"new\" graphics");
- puts(" -- -t Enable transparency effect");
-# endif /* USE_GRAPHICS */
-#endif /* USE_GTK2 */
-
-#ifdef USE_XAW
- puts(" -mxaw To use XAW");
- puts(" -- Sub options");
- puts(" -- -n# Number of terms to use");
- puts(" -- -d<name> Display to use");
-# ifdef USE_GRAPHICS
- puts(" -- -s Turn off smoothscaling graphics");
- puts(" -- -o Requests \"old\" graphics");
-# endif /* USE_GRAPHICS */
-#endif /* USE_XAW */
-
-#ifdef USE_X11
- puts(" -mx11 To use X11");
- puts(" -- Sub options");
- puts(" -- -n# Number of terms to use");
- puts(" -- -d<name> Display to use");
-# ifdef USE_GRAPHICS
- puts(" -- -s Turn off smoothscaling graphics");
- puts(" -- -o Requests \"old\" graphics");
- puts(" -- -b Requests double-width tiles");
-# endif /* USE_GRAPHICS */
-#endif /* USE_X11 */
-
-#ifdef USE_GCU
- puts(" -mgcu To use curses");
- puts(" -- Sub options");
- 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");
- puts(" -- -n # Number of virtual consoles to use");
- puts(" -- -g Request new graphics (16x16)");
- puts(" -- -o Request old graphics (8x8)");
- puts(" -- -b Requests double-width tiles");
- puts(" -- -w # Request screen width in pixels");
- puts(" -- -h # Request screen height in pixels");
- puts(" -- -bpp # Request screen color depth in bits");
- puts(" -- -fs Start with full-screen display");
- puts(" -- -s # Request font size");
- puts(" -- -f <font> Request true-type font by name");
-#endif /* USE_SDL */
-
- /* Actually abort the process */
- quit(NULL);
- }
- }
- }
-
- /* Hack -- Forget standard args */
- if (args)
- {
- argc = 1;
- argv[1] = NULL;
- }
-
-
- /* Process the player name */
- process_player_name(TRUE);
-
-
- /* Install "quit" hook */
- 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"))))
- {
- extern errr init_gtk2(int, char**);
- if (0 == init_gtk2(argc, argv))
- {
- ANGBAND_SYS = "gtk2";
- done = TRUE;
- }
- }
-#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"))))
- {
- extern errr init_xaw(int, char**);
- if (0 == init_xaw(argc, argv))
- {
- ANGBAND_SYS = "xaw";
- done = TRUE;
- }
- }
-#endif
-
-#ifdef USE_X11
- /* Attempt to use the "main-x11.c" support */
- if (!done && (!mstr || (streq(mstr, "x11"))))
- {
- extern errr init_x11(int, char**);
- if (0 == init_x11(argc, argv))
- {
- ANGBAND_SYS = "x11";
- done = TRUE;
- }
- }
-#endif
-
-#ifdef USE_GCU
- /* Attempt to use the "main-gcu.c" support */
- if (!done && (!mstr || (streq(mstr, "gcu"))))
- {
- extern errr init_gcu(int, char**);
- if (0 == init_gcu(argc, argv))
- {
- ANGBAND_SYS = "gcu";
- done = TRUE;
- }
- }
-#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_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"))))
- {
- extern errr init_sdl(int, char**);
- if (0 == init_sdl(argc, argv))
- {
- ANGBAND_SYS = "sdl";
- done = TRUE;
- }
- }
-#endif
-
- /* Make sure we have a display! */
- if (!done) quit("Unable to prepare any 'display module'!");
-
-
- /* Catch nasty signals */
- signals_init();
-
- /* Initialize */
- init_angband();
-
- /* Hack -- If requested, display scores and quit */
- if (show_score > 0) display_scores(0, show_score);
-
- /* Wait for response */
- pause_line(23);
-
- /* Play the game */
- play_game(new_game);
-
-#ifdef CHECK_MEMORY_LEAKS
- CHECK_LEAKS();
-#endif
-
- /* Quit */
- quit(NULL);
-
- /* Exit */
- return (0);
-}
-
-#endif
diff --git a/src/main.cc b/src/main.cc
new file mode 100644
index 00000000..c0ac3826
--- /dev/null
+++ b/src/main.cc
@@ -0,0 +1,270 @@
+/*
+ * Copyright (c) 1997 Ben Harrison, and others
+ *
+ * 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 "main.h"
+
+#include "birth.hpp"
+#include "dungeon.h"
+#include "files.hpp"
+#include "game.hpp"
+#include "init2.h"
+#include "modules.hpp"
+#include "util.h"
+#include "util.hpp"
+#include "variable.h"
+#include "variable.hpp"
+
+
+/*
+ * A hook for "quit()".
+ *
+ * Close down, then fall back into "quit()".
+ */
+static void quit_hook(cptr s)
+{
+ int j;
+
+ /* Scan windows */
+ for (j = 8 - 1; j >= 0; j--)
+ {
+ /* Unused */
+ if (!angband_term[j]) continue;
+
+ /* Nuke it */
+ term_nuke(angband_term[j]);
+ }
+}
+
+
+
+/*
+ * Check existence of ".ToME/" directory in the user's
+ * home directory or try to create it if it doesn't exist.
+ * Returns FALSE if all the attempts fail.
+ */
+static void init_save_dir()
+{
+ char dirpath[1024];
+ char versionpath[1024];
+ char savepath[1024];
+
+ /* Get an absolute path from the filename */
+ path_parse(dirpath, 1024, PRIVATE_USER_PATH);
+ strcpy(versionpath, dirpath);
+ strcat(versionpath, USER_PATH_VERSION);
+ strcpy(savepath, versionpath);
+ strcat(savepath, "/save");
+
+ if (!private_check_user_directory(dirpath))
+ {
+ quit_fmt("Cannot create directory '%s'", dirpath);
+ }
+
+ if (!private_check_user_directory(versionpath))
+ {
+ quit_fmt("Cannot create directory '%s'", versionpath);
+ }
+
+ if (!private_check_user_directory(savepath))
+ {
+ quit_fmt("Cannot create directory '%s'", savepath);
+ }
+}
+
+/*
+ * Initialize and verify the file paths, and the score file.
+ *
+ * Use the ANGBAND_PATH environment var if possible, else use
+ * DEFAULT_PATH, and in either case, branch off appropriately.
+ *
+ * First, we'll look for the ANGBAND_PATH environment variable,
+ * and then look for the files in there. If that doesn't work,
+ * we'll try the DEFAULT_PATH constant. So be sure that one of
+ * these two things works...
+ *
+ * We must ensure that the path ends with "PATH_SEP" if needed,
+ * since the "init_file_paths()" function will simply append the
+ * relevant "sub-directory names" to the given path.
+ */
+static void init_file_paths_with_env()
+{
+ char path[1024];
+
+ /* Get the environment variable */
+ cptr tail = getenv("TOME_PATH");
+
+ /* Use the angband_path, or a default */
+ strcpy(path, tail ? tail : DEFAULT_PATH);
+
+ /* Hack -- Add a path separator (only if needed) */
+ if (!suffix(path, PATH_SEP)) strcat(path, PATH_SEP);
+
+ /* Initialize */
+ init_file_paths(path);
+}
+
+
+/*
+ * Simple "main" function for multiple platforms.
+ *
+ * Note the special "--" option which terminates the processing of
+ * standard options. All non-standard options (if any) are passed
+ * directly to the platform initialization function.
+ */
+int main_real(int argc, char *argv[], char const *platform_sys, int (*init_platform)(int, char *[]), char const *platform_usage)
+{
+ int i;
+
+ bool_ args = TRUE;
+
+ // Initialize game structure
+ game = new Game();
+
+ /* Get the file paths */
+ init_file_paths_with_env();
+
+ /* Initialize the player name */
+ game->player_name = user_name();
+
+ /* Make sure save directory exists */
+ init_save_dir();
+
+
+ /* Process the command line arguments */
+ for (i = 1; args && (i < argc); i++)
+ {
+ /* Require proper options */
+ if (argv[i][0] != '-') goto usage;
+
+ /* Analyze option */
+ switch (argv[i][1])
+ {
+ case 'W':
+ case 'w':
+ {
+ arg_wizard = TRUE;
+ break;
+ }
+
+ case 'R':
+ case 'r':
+ {
+ arg_force_roguelike = TRUE;
+ break;
+ }
+
+ case 'O':
+ case 'o':
+ {
+ arg_force_original = TRUE;
+ break;
+ }
+
+ case 'u':
+ case 'U':
+ {
+ if (!argv[i][2]) goto usage;
+ game->player_name = &argv[i][2];
+ game->player_base = &argv[i][2];
+ no_begin_screen = TRUE;
+ break;
+ }
+
+ case 'M':
+ {
+ if (!argv[i][2]) goto usage;
+ force_module = &argv[i][2];
+ break;
+ }
+
+ case 'h':
+ {
+ goto usage;
+ }
+
+ case '-':
+ {
+ if (argv[i][2] == 'h' && !strcmp((argv[i] + 2), "help"))
+ {
+ goto usage;
+ }
+ else
+ {
+ argv[i] = argv[0];
+ argc = argc - i;
+ argv = argv + i;
+ args = FALSE;
+ break;
+ }
+ }
+
+ default:
+usage:
+ {
+ int j;
+
+ /* Dump usage information */
+ for (j = 0; j < argc; j++) printf("%s ", argv[j]);
+ printf("\n");
+ puts("Usage: tome [options] [-- subopts]");
+ puts(" -h This help");
+ puts(" -w Request wizard mode");
+ puts(" -o Request original keyset");
+ puts(" -r Request rogue-like keyset");
+ puts(" -u<who> Use your <who> savefile");
+ puts(" -M<which> Use the <which> module");
+
+ puts(" -- Sub options");
+ puts(platform_usage);
+
+ /* Actually abort the process */
+ quit(NULL);
+ }
+ }
+ }
+
+ /* Hack -- Forget standard args */
+ if (args)
+ {
+ argc = 1;
+ argv[1] = NULL;
+ }
+
+
+ /* Process the player name */
+ process_player_name(TRUE);
+
+
+ /* Install "quit" hook */
+ quit_aux = quit_hook;
+
+ /* Run the platform main initialization */
+ if (init_platform(argc, argv))
+ {
+ quit("Unable to prepare any 'display module'!");
+ }
+ else
+ {
+ ANGBAND_SYS = platform_sys;
+
+ /* Initialize */
+ init_angband();
+
+ /* Wait for response */
+ pause_line(23);
+
+ /* Play the game */
+ play_game();
+
+ /* Quit */
+ quit(NULL);
+
+ }
+ /* Exit */
+ return (0);
+}
diff --git a/src/main.h b/src/main.h
new file mode 100644
index 00000000..edc590b3
--- /dev/null
+++ b/src/main.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int main_real(int argc, char *argv[], char const *platform_sys, int (*init_platform)(int, char *[]), char const *platform_usage);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/src/martial_arts.hpp b/src/martial_arts.hpp
new file mode 100644
index 00000000..1f2f0cbe
--- /dev/null
+++ b/src/martial_arts.hpp
@@ -0,0 +1,18 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * Martial arts descriptors
+ */
+struct martial_arts
+{
+ cptr desc; /* A verbose attack description */
+ int min_level; /* Minimum level to use */
+ int chance; /* Chance of 'success' */
+ int dd; /* Damage dice */
+ int ds; /* Damage sides */
+ s16b effect; /* Special effects */
+ s16b power; /* Special effects power */
+};
+
diff --git a/src/melee1.c b/src/melee1.cc
index 4e5d3208..58ebfbaa 100644
--- a/src/melee1.c
+++ b/src/melee1.cc
@@ -1,7 +1,3 @@
-/* File: melee1.c */
-
-/* Purpose: Monster attacks */
-
/*
* Copyright (c) 1989 James E. Wilson, Robert A. Koeneke
*
@@ -10,9 +6,36 @@
* included in all such copies.
*/
-#include "angband.h"
-
-
+#include "melee1.hpp"
+
+#include "cave.hpp"
+#include "cmd5.hpp"
+#include "game.hpp"
+#include "gods.hpp"
+#include "mimic.hpp"
+#include "monster2.hpp"
+#include "monster3.hpp"
+#include "monster_race.hpp"
+#include "monster_race_flag.hpp"
+#include "monster_type.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "player_type.hpp"
+#include "skills.hpp"
+#include "spells1.hpp"
+#include "spells2.hpp"
+#include "stats.hpp"
+#include "store.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+#include "xtra1.hpp"
+#include "xtra2.hpp"
+#include "z-rand.hpp"
+
+#include <boost/algorithm/string/predicate.hpp>
+
+using boost::algorithm::iequals;
/*
* Critical blow. All hits that do 95% of total possible damage,
@@ -201,7 +224,9 @@ int get_attack_power(int effect)
*/
bool_ carried_make_attack_normal(int r_idx)
{
- monster_race *r_ptr = &r_info[r_idx];
+ auto const &r_info = game->edit_data.r_info;
+
+ auto r_ptr = &r_info[r_idx];
int ap_cnt;
@@ -209,12 +234,12 @@ bool_ carried_make_attack_normal(int r_idx)
int do_cut, do_stun;
char ddesc[80] = "your symbiote";
- cptr sym_name = symbiote_name(TRUE);
+ auto sym_name = symbiote_name(true);
- bool_ touched = FALSE, alive = TRUE;
+ bool_ alive = TRUE;
/* Not allowed to attack */
- if (r_ptr->flags1 & (RF1_NEVER_BLOW)) return (FALSE);
+ if (r_ptr->flags & RF_NEVER_BLOW) return (FALSE);
/* Total armor */
ac = p_ptr->ac + p_ptr->to_a;
@@ -225,9 +250,6 @@ bool_ carried_make_attack_normal(int r_idx)
/* 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;
@@ -250,9 +272,6 @@ bool_ carried_make_attack_normal(int r_idx)
/* Handle "leaving" */
if (p_ptr->leaving) break;
- /* Extract visibility (before blink) */
- visible = TRUE;
-
/* Extract the attack "power" */
power = get_attack_power(effect);
@@ -261,35 +280,16 @@ bool_ carried_make_attack_normal(int r_idx)
if (!effect || check_hit(power, rlev))
{
/* Always disturbing */
- disturb(1, 0);
+ disturb();
/* Hack -- Apply "protection from evil" */
if ((p_ptr->protevil > 0) &&
- (r_ptr->flags3 & (RF3_EVIL)) &&
+ (r_ptr->flags & RF_EVIL) &&
(p_ptr->lev >= rlev) &&
((rand_int(100) + p_ptr->lev) > 50))
{
- /* Remember the Evil-ness */
- r_ptr->r_flags3 |= (RF3_EVIL);
-
/* Message */
- msg_format("%s is repelled.", sym_name);
-
- /* Hack -- Next attack */
- continue;
- }
-
- /* Hack -- Apply "protection from good" */
- if ((p_ptr->protgood > 0) &&
- (r_ptr->flags3 & (RF3_GOOD)) &&
- (p_ptr->lev >= rlev) &&
- ((rand_int(100) + p_ptr->lev) > 50))
- {
- /* Remember the Good-ness */
- r_ptr->r_flags3 |= (RF3_GOOD);
-
- /* Message */
- msg_format("%s is repelled.", sym_name);
+ msg_format("%s is repelled.", sym_name.c_str());
/* Hack -- Next attack */
continue;
@@ -305,43 +305,33 @@ bool_ carried_make_attack_normal(int r_idx)
{
act = "hits you.";
do_cut = do_stun = 1;
- touched = TRUE;
- sound(SOUND_HIT);
break;
}
case RBM_TOUCH:
{
act = "touches you.";
- touched = TRUE;
- sound(SOUND_TOUCH);
break;
}
case RBM_PUNCH:
{
act = "punches you.";
- touched = TRUE;
do_stun = 1;
- sound(SOUND_HIT);
break;
}
case RBM_KICK:
{
act = "kicks you.";
- touched = TRUE;
do_stun = 1;
- sound(SOUND_HIT);
break;
}
case RBM_CLAW:
{
act = "claws you.";
- touched = TRUE;
do_cut = 1;
- sound(SOUND_CLAW);
break;
}
@@ -349,16 +339,12 @@ bool_ carried_make_attack_normal(int r_idx)
{
act = "bites you.";
do_cut = 1;
- touched = TRUE;
- sound(SOUND_BITE);
break;
}
case RBM_STING:
{
act = "stings you.";
- touched = TRUE;
- sound(SOUND_STING);
break;
}
@@ -372,8 +358,6 @@ bool_ carried_make_attack_normal(int r_idx)
{
act = "butts you.";
do_stun = 1;
- touched = TRUE;
- sound(SOUND_HIT);
break;
}
@@ -381,46 +365,36 @@ bool_ carried_make_attack_normal(int r_idx)
{
act = "crushes you.";
do_stun = 1;
- touched = TRUE;
- sound(SOUND_CRUSH);
break;
}
case RBM_ENGULF:
{
act = "engulfs you.";
- touched = TRUE;
- sound(SOUND_CRUSH);
break;
}
case RBM_CHARGE:
{
act = "charges you.";
- touched = TRUE;
- sound(SOUND_BUY); /* Note! This is "charges", not "charges at". */
break;
}
case RBM_CRAWL:
{
act = "crawls on you.";
- touched = TRUE;
- sound(SOUND_SLIME);
break;
}
case RBM_DROOL:
{
act = "drools on you.";
- sound(SOUND_SLIME);
break;
}
case RBM_SPIT:
{
act = "spits on you.";
- sound(SOUND_SLIME);
break;
}
@@ -439,14 +413,12 @@ bool_ carried_make_attack_normal(int r_idx)
case RBM_WAIL:
{
act = "wails at you.";
- sound(SOUND_WAIL);
break;
}
case RBM_SPORE:
{
act = "releases spores at you.";
- sound(SOUND_SLIME);
break;
}
@@ -459,21 +431,18 @@ bool_ carried_make_attack_normal(int r_idx)
case RBM_BEG:
{
act = "begs you for money.";
- sound(SOUND_MOAN);
break;
}
case RBM_INSULT:
{
act = desc_insult[rand_int(8)];
- sound(SOUND_MOAN);
break;
}
case RBM_MOAN:
{
act = desc_moan[rand_int(4)];
- sound(SOUND_MOAN);
break;
}
@@ -483,17 +452,13 @@ bool_ carried_make_attack_normal(int r_idx)
act = "sings 'We are a happy family.'";
else
act = "sings 'I love you, you love me.'";
- sound(SOUND_SHOW);
break;
}
}
/* Message */
- if (act) msg_format("%s %s", sym_name, act);
-
+ if (act) msg_format("%s %s", sym_name.c_str(), act);
- /* Hack -- assume all attacks are obvious */
- obvious = TRUE;
/* Roll out the damage */
damage = damroll(d_dice, d_side);
@@ -503,9 +468,6 @@ bool_ carried_make_attack_normal(int r_idx)
{
case 0:
{
- /* Hack -- Assume obvious */
- obvious = TRUE;
-
/* Hack -- No damage */
damage = 0;
@@ -514,9 +476,6 @@ bool_ carried_make_attack_normal(int r_idx)
case RBE_HURT:
{
- /* Obvious */
- obvious = TRUE;
-
/* Hack -- Player armor reduces total damage */
damage -= (damage * ((ac < 150) ? ac : 150) / 250);
@@ -529,9 +488,6 @@ bool_ carried_make_attack_normal(int r_idx)
case RBE_ABOMINATION:
{
- /* Obvious */
- obvious = TRUE;
-
/* Morph, but let mimicry skill have a chance to stop this */
if (magik(60 - get_skill(SKILL_MIMICRY)))
{
@@ -551,8 +507,6 @@ bool_ carried_make_attack_normal(int r_idx)
case RBE_SANITY:
{
- obvious = TRUE;
-
take_sanity_hit(damage, ddesc);
break;
}
@@ -566,10 +520,7 @@ bool_ carried_make_attack_normal(int r_idx)
/* Take "poison" effect */
if (!(p_ptr->resist_pois || p_ptr->oppose_pois))
{
- if (set_poisoned(p_ptr->poisoned + randint(rlev) + 5))
- {
- obvious = TRUE;
- }
+ set_poisoned(p_ptr->poisoned + randint(rlev) + 5);
}
break;
@@ -585,7 +536,7 @@ bool_ carried_make_attack_normal(int r_idx)
if (!p_ptr->resist_disen)
{
/* Apply disenchantment */
- if (apply_disenchant(0)) obvious = TRUE;
+ apply_disenchant(0);
}
break;
@@ -633,9 +584,6 @@ bool_ carried_make_attack_normal(int r_idx)
case RBE_ACID:
{
- /* Obvious */
- obvious = TRUE;
-
/* Message */
msg_print("You are covered in acid!");
@@ -648,9 +596,6 @@ bool_ carried_make_attack_normal(int r_idx)
case RBE_ELEC:
{
- /* Obvious */
- obvious = TRUE;
-
/* Message */
msg_print("You are struck by electricity!");
@@ -664,9 +609,6 @@ bool_ carried_make_attack_normal(int r_idx)
case RBE_FIRE:
{
- /* Obvious */
- obvious = TRUE;
-
/* Message */
msg_print("You are enveloped in flames!");
@@ -680,9 +622,6 @@ bool_ carried_make_attack_normal(int r_idx)
case RBE_COLD:
{
- /* Obvious */
- obvious = TRUE;
-
/* Message */
msg_print("You are covered with frost!");
@@ -703,10 +642,7 @@ bool_ carried_make_attack_normal(int r_idx)
/* Increase "blind" */
if (!p_ptr->resist_blind)
{
- if (set_blind(p_ptr->blind + 10 + randint(rlev)))
- {
- obvious = TRUE;
- }
+ set_blind(p_ptr->blind + 10 + randint(rlev));
}
@@ -722,10 +658,7 @@ bool_ carried_make_attack_normal(int r_idx)
/* Increase "confused" */
if (!p_ptr->resist_conf)
{
- if (set_confused(p_ptr->confused + 3 + randint(rlev)))
- {
- obvious = TRUE;
- }
+ set_confused(p_ptr->confused + 3 + randint(rlev));
}
@@ -742,19 +675,14 @@ bool_ carried_make_attack_normal(int r_idx)
if (p_ptr->resist_fear)
{
msg_print("You stand your ground!");
- obvious = TRUE;
}
else if (rand_int(100) < p_ptr->skill_sav)
{
msg_print("You stand your ground!");
- obvious = TRUE;
}
else
{
- if (set_afraid(p_ptr->afraid + 3 + randint(rlev)))
- {
- obvious = TRUE;
- }
+ set_afraid(p_ptr->afraid + 3 + randint(rlev));
}
@@ -774,19 +702,14 @@ bool_ carried_make_attack_normal(int r_idx)
if (p_ptr->free_act)
{
msg_print("You are unaffected!");
- obvious = TRUE;
}
else if (rand_int(100) < p_ptr->skill_sav)
{
msg_print("You resist the effects!");
- obvious = TRUE;
}
else
{
- if (set_paralyzed(p_ptr->paralyzed + 3 + randint(rlev)))
- {
- obvious = TRUE;
- }
+ set_paralyzed(3 + randint(rlev));
}
@@ -800,7 +723,7 @@ bool_ carried_make_attack_normal(int r_idx)
take_hit(damage, ddesc);
/* Damage (stat) */
- if (do_dec_stat(A_STR, STAT_DEC_NORMAL)) obvious = TRUE;
+ do_dec_stat(A_STR, STAT_DEC_NORMAL);
break;
}
@@ -812,7 +735,7 @@ bool_ carried_make_attack_normal(int r_idx)
take_hit(damage, ddesc);
/* Damage (stat) */
- if (do_dec_stat(A_INT, STAT_DEC_NORMAL)) obvious = TRUE;
+ do_dec_stat(A_INT, STAT_DEC_NORMAL);
break;
}
@@ -824,7 +747,7 @@ bool_ carried_make_attack_normal(int r_idx)
take_hit(damage, ddesc);
/* Damage (stat) */
- if (do_dec_stat(A_WIS, STAT_DEC_NORMAL)) obvious = TRUE;
+ do_dec_stat(A_WIS, STAT_DEC_NORMAL);
break;
}
@@ -836,7 +759,7 @@ bool_ carried_make_attack_normal(int r_idx)
take_hit(damage, ddesc);
/* Damage (stat) */
- if (do_dec_stat(A_DEX, STAT_DEC_NORMAL)) obvious = TRUE;
+ do_dec_stat(A_DEX, STAT_DEC_NORMAL);
break;
}
@@ -848,7 +771,7 @@ bool_ carried_make_attack_normal(int r_idx)
take_hit(damage, ddesc);
/* Damage (stat) */
- if (do_dec_stat(A_CON, STAT_DEC_NORMAL)) obvious = TRUE;
+ do_dec_stat(A_CON, STAT_DEC_NORMAL);
break;
}
@@ -860,7 +783,7 @@ bool_ carried_make_attack_normal(int r_idx)
take_hit(damage, ddesc);
/* Damage (stat) */
- if (do_dec_stat(A_CHR, STAT_DEC_NORMAL)) obvious = TRUE;
+ do_dec_stat(A_CHR, STAT_DEC_NORMAL);
break;
}
@@ -872,21 +795,18 @@ bool_ carried_make_attack_normal(int r_idx)
take_hit(damage, ddesc);
/* Damage (stats) */
- if (do_dec_stat(A_STR, STAT_DEC_NORMAL)) obvious = TRUE;
- if (do_dec_stat(A_DEX, STAT_DEC_NORMAL)) obvious = TRUE;
- if (do_dec_stat(A_CON, STAT_DEC_NORMAL)) obvious = TRUE;
- if (do_dec_stat(A_INT, STAT_DEC_NORMAL)) obvious = TRUE;
- if (do_dec_stat(A_WIS, STAT_DEC_NORMAL)) obvious = TRUE;
- if (do_dec_stat(A_CHR, STAT_DEC_NORMAL)) obvious = TRUE;
+ do_dec_stat(A_STR, STAT_DEC_NORMAL);
+ do_dec_stat(A_DEX, STAT_DEC_NORMAL);
+ do_dec_stat(A_CON, STAT_DEC_NORMAL);
+ do_dec_stat(A_INT, STAT_DEC_NORMAL);
+ do_dec_stat(A_WIS, STAT_DEC_NORMAL);
+ do_dec_stat(A_CHR, STAT_DEC_NORMAL);
break;
}
case RBE_SHATTER:
{
- /* Obvious */
- obvious = TRUE;
-
/* Hack -- Reduce damage based on the player armor class */
damage -= (damage * ((ac < 150) ? ac : 150) / 250);
@@ -907,9 +827,6 @@ bool_ carried_make_attack_normal(int r_idx)
case RBE_EXP_10:
{
- /* Obvious */
- obvious = TRUE;
-
/* Take damage */
carried_monster_hit = TRUE;
take_hit(damage, ddesc);
@@ -937,9 +854,6 @@ bool_ carried_make_attack_normal(int r_idx)
case RBE_EXP_20:
{
- /* Obvious */
- obvious = TRUE;
-
/* Take damage */
carried_monster_hit = TRUE;
take_hit(damage, ddesc);
@@ -967,9 +881,6 @@ bool_ carried_make_attack_normal(int r_idx)
case RBE_EXP_40:
{
- /* Obvious */
- obvious = TRUE;
-
/* Take damage */
carried_monster_hit = TRUE;
take_hit(damage, ddesc);
@@ -997,9 +908,6 @@ bool_ carried_make_attack_normal(int r_idx)
case RBE_EXP_80:
{
- /* Obvious */
- obvious = TRUE;
-
/* Take damage */
carried_monster_hit = TRUE;
take_hit(damage, ddesc);
@@ -1034,10 +942,7 @@ bool_ carried_make_attack_normal(int r_idx)
/* Take "poison" effect */
if (!(p_ptr->resist_pois || p_ptr->oppose_pois))
{
- if (set_poisoned(p_ptr->poisoned + randint(rlev) + 5))
- {
- obvious = TRUE;
- }
+ set_poisoned(p_ptr->poisoned + randint(rlev) + 5);
}
/* Damage CON (10% chance)*/
@@ -1045,16 +950,13 @@ bool_ carried_make_attack_normal(int r_idx)
{
/* 1% chance for perm. damage */
bool_ perm = (randint(10) == 1);
- if (dec_stat(A_CON, randint(10), perm)) obvious = TRUE;
+ dec_stat(A_CON, randint(10), perm);
}
break;
}
case RBE_PARASITE:
{
- /* Obvious */
- obvious = TRUE;
-
if (!p_ptr->parasite) set_parasite(damage, r_idx);
break;
@@ -1067,10 +969,7 @@ bool_ carried_make_attack_normal(int r_idx)
/* Increase "image" */
if (!p_ptr->resist_chaos)
{
- if (set_image(p_ptr->image + 3 + randint(rlev / 2)))
- {
- obvious = TRUE;
- }
+ set_image(p_ptr->image + 3 + randint(rlev / 2));
}
break;
@@ -1201,7 +1100,7 @@ bool_ carried_make_attack_normal(int r_idx)
}
/* Apply the cut */
- if (k) (void)set_cut(p_ptr->cut + k);
+ if (k) set_cut(p_ptr->cut + k);
}
/* Handle stun */
@@ -1242,21 +1141,7 @@ bool_ carried_make_attack_normal(int r_idx)
}
/* Apply the stun */
- if (k) (void)set_stun(p_ptr->stun + k);
- }
-
- if (touched)
- {
- if (p_ptr->sh_fire && alive)
- {
- r_ptr->r_flags3 |= RF3_IM_FIRE;
- }
-
- if (p_ptr->sh_elec && alive)
- {
- r_ptr->r_flags3 |= RF3_IM_ELEC;
- }
- touched = FALSE;
+ if (k) set_stun(p_ptr->stun + k);
}
}
@@ -1280,29 +1165,14 @@ bool_ carried_make_attack_normal(int r_idx)
case RBM_CHARGE:
/* Disturbing */
- disturb(1, 0);
+ disturb();
/* Message */
- msg_format("%s misses you.", sym_name);
+ msg_format("%s misses you.", sym_name.c_str());
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]++;
- }
- }
- }
}
/* Assume we attacked */
return (TRUE);
@@ -1314,7 +1184,7 @@ bool_ carried_make_attack_normal(int r_idx)
*/
void black_breath_attack(int chance)
{
- if (!p_ptr->protundead && randint(chance) == 1)
+ if (randint(chance) == 1)
{
msg_print("Your foe calls upon your soul!");
msg_print("You feel the Black Breath slowly draining you of life...");
@@ -1329,12 +1199,10 @@ bool_ make_attack_normal(int m_idx, byte divis)
{
monster_type *m_ptr = &m_list[m_idx];
- monster_race *r_ptr = race_inf(m_ptr);
-
int ap_cnt;
int i, j, k, tmp, ac, rlev;
- int do_cut, do_stun, do_vampire;
+ int do_cut, do_stun;
s32b gold;
@@ -1350,8 +1218,9 @@ bool_ make_attack_normal(int m_idx, byte divis)
bool_ touched = FALSE, fear = FALSE, alive = TRUE;
bool_ explode = FALSE;
- /* Not allowed to attack */
- if (r_ptr->flags1 & (RF1_NEVER_BLOW)) return (FALSE);
+ /* Not allowed to attack? */
+ auto r_ptr = m_ptr->race();
+ if (r_ptr->flags & RF_NEVER_BLOW) return (FALSE);
/* ...nor if friendly */
if (is_friend(m_ptr) >= 0)
@@ -1361,7 +1230,7 @@ bool_ make_attack_normal(int m_idx, byte divis)
}
/* Cannot attack the player if mortal and player fated to never die by the ... */
- if ((r_ptr->flags7 & RF7_MORTAL) && (p_ptr->no_mortal)) return (FALSE);
+ if ((r_ptr->flags & RF_MORTAL) && (p_ptr->no_mortal)) return (FALSE);
/* Total armor */
ac = p_ptr->ac + p_ptr->to_a;
@@ -1383,9 +1252,6 @@ bool_ make_attack_normal(int m_idx, byte divis)
/* 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;
@@ -1408,9 +1274,6 @@ bool_ make_attack_normal(int m_idx, byte divis)
/* Handle "leaving" */
if (p_ptr->leaving) break;
- /* Extract visibility (before blink) */
- if (m_ptr->ml) visible = TRUE;
-
/* Extract the attack "power" */
switch (effect)
{
@@ -1525,7 +1388,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();
if ((chance > 0) && magik(chance))
{
@@ -1536,18 +1399,15 @@ bool_ make_attack_normal(int m_idx, byte divis)
}
/* Eru can help you */
- PRAY_GOD(GOD_ERU)
+ if (praying_to(GOD_ERU))
{
s32b chance = p_ptr->grace;
if (chance > 50000) chance = 50000;
chance -= rlev * 300;
- if ((randint(100000) < chance) && (r_ptr->flags3 & (RF3_EVIL)))
+ if ((randint(100000) < chance) && (r_ptr->flags & RF_EVIL))
{
- /* Remember the Evil-ness */
- r_ptr->r_flags3 |= (RF3_EVIL);
-
/* Message */
msg_format("The hand of Eru Iluvatar stops %s blow.", m_name);
@@ -1558,35 +1418,10 @@ bool_ make_attack_normal(int m_idx, byte divis)
/* Hack -- Apply "protection from evil" */
if ((p_ptr->protevil > 0) &&
- (r_ptr->flags3 & (RF3_EVIL)) &&
+ (r_ptr->flags & RF_EVIL) &&
(p_ptr->lev >= rlev) &&
((rand_int(100) + p_ptr->lev) > 50))
{
- /* Remember the Evil-ness */
- if (m_ptr->ml)
- {
- r_ptr->r_flags3 |= (RF3_EVIL);
- }
-
- /* Message */
- msg_format("%^s is repelled.", m_name);
-
- /* Hack -- Next attack */
- continue;
- }
-
- /* Hack -- Apply "protection from good" */
- if ((p_ptr->protgood > 0) &&
- (r_ptr->flags3 & (RF3_GOOD)) &&
- (p_ptr->lev >= rlev) &&
- ((rand_int(100) + p_ptr->lev) > 50))
- {
- /* Remember the Good-ness */
- if (m_ptr->ml)
- {
- r_ptr->r_flags3 |= (RF3_GOOD);
- }
-
/* Message */
msg_format("%^s is repelled.", m_name);
@@ -1595,7 +1430,7 @@ bool_ make_attack_normal(int m_idx, byte divis)
}
/* Assume no cut or stun */
- do_cut = do_stun = do_vampire = 0;
+ do_cut = do_stun = 0;
/* Describe the attack method */
switch (method)
@@ -1605,7 +1440,6 @@ bool_ make_attack_normal(int m_idx, byte divis)
act = "hits you.";
do_cut = do_stun = 1;
touched = TRUE;
- sound(SOUND_HIT);
break;
}
@@ -1613,7 +1447,6 @@ bool_ make_attack_normal(int m_idx, byte divis)
{
act = "touches you.";
touched = TRUE;
- sound(SOUND_TOUCH);
break;
}
@@ -1622,7 +1455,6 @@ bool_ make_attack_normal(int m_idx, byte divis)
act = "punches you.";
touched = TRUE;
do_stun = 1;
- sound(SOUND_HIT);
break;
}
@@ -1631,7 +1463,6 @@ bool_ make_attack_normal(int m_idx, byte divis)
act = "kicks you.";
touched = TRUE;
do_stun = 1;
- sound(SOUND_HIT);
break;
}
@@ -1640,7 +1471,6 @@ bool_ make_attack_normal(int m_idx, byte divis)
act = "claws you.";
touched = TRUE;
do_cut = 1;
- sound(SOUND_CLAW);
break;
}
@@ -1648,10 +1478,7 @@ bool_ make_attack_normal(int m_idx, byte divis)
{
act = "bites you.";
do_cut = 1;
- if (magik(5) && (strstr(r_name + r_ptr->name, "Vampire") || strstr(r_name + r_ptr->name, "vampire")))
- do_vampire = TRUE;
touched = TRUE;
- sound(SOUND_BITE);
break;
}
@@ -1659,7 +1486,6 @@ bool_ make_attack_normal(int m_idx, byte divis)
{
act = "stings you.";
touched = TRUE;
- sound(SOUND_STING);
break;
}
@@ -1674,7 +1500,6 @@ bool_ make_attack_normal(int m_idx, byte divis)
act = "butts you.";
do_stun = 1;
touched = TRUE;
- sound(SOUND_HIT);
break;
}
@@ -1683,7 +1508,6 @@ bool_ make_attack_normal(int m_idx, byte divis)
act = "crushes you.";
do_stun = 1;
touched = TRUE;
- sound(SOUND_CRUSH);
break;
}
@@ -1691,7 +1515,6 @@ bool_ make_attack_normal(int m_idx, byte divis)
{
act = "engulfs you.";
touched = TRUE;
- sound(SOUND_CRUSH);
break;
}
@@ -1699,7 +1522,6 @@ bool_ make_attack_normal(int m_idx, byte divis)
{
act = "charges you.";
touched = TRUE;
- sound(SOUND_BUY); /* Note! This is "charges", not "charges at". */
break;
}
@@ -1707,21 +1529,18 @@ bool_ make_attack_normal(int m_idx, byte divis)
{
act = "crawls on you.";
touched = TRUE;
- sound(SOUND_SLIME);
break;
}
case RBM_DROOL:
{
act = "drools on you.";
- sound(SOUND_SLIME);
break;
}
case RBM_SPIT:
{
act = "spits on you.";
- sound(SOUND_SLIME);
break;
}
@@ -1741,14 +1560,12 @@ bool_ make_attack_normal(int m_idx, byte divis)
case RBM_WAIL:
{
act = "wails at you.";
- sound(SOUND_WAIL);
break;
}
case RBM_SPORE:
{
act = "releases spores at you.";
- sound(SOUND_SLIME);
break;
}
@@ -1761,24 +1578,21 @@ bool_ make_attack_normal(int m_idx, byte divis)
case RBM_BEG:
{
act = "begs you for money.";
- sound(SOUND_MOAN);
break;
}
case RBM_INSULT:
{
act = desc_insult[rand_int(8)];
- sound(SOUND_MOAN);
break;
}
case RBM_MOAN:
{
- if (strstr((r_name + r_ptr->name), "Mathilde, the Science Student"))
+ if (strstr(r_ptr->name, "Mathilde, the Science Student"))
act = desc_moan[rand_int(3) + 4];
else
act = desc_moan[rand_int(4)];
- sound(SOUND_MOAN);
break;
}
@@ -1788,7 +1602,6 @@ bool_ make_attack_normal(int m_idx, byte divis)
act = "sings 'We are a happy family.'";
else
act = "sings 'I love you, you love me.'";
- sound(SOUND_SHOW);
break;
}
}
@@ -1800,23 +1613,20 @@ bool_ make_attack_normal(int m_idx, byte divis)
* a successful blow. Uniques have a better chance. -LM-
* Nazgul have a 25% chance
*/
- if (r_ptr->flags7 & RF7_NAZGUL)
+ if (r_ptr->flags & RF_NAZGUL)
{
black_breath_attack(4);
}
- else if ((m_ptr->level >= 35) && (r_ptr->flags3 & (RF3_UNDEAD)) &&
- (r_ptr->flags1 & (RF1_UNIQUE)))
+ else if ((m_ptr->level >= 35) && (r_ptr->flags & RF_UNDEAD) &&
+ (r_ptr->flags & RF_UNIQUE))
{
black_breath_attack(300 - m_ptr->level);
}
- else if ((m_ptr->level >= 40) && (r_ptr->flags3 & (RF3_UNDEAD)))
+ else if ((m_ptr->level >= 40) && (r_ptr->flags & RF_UNDEAD))
{
black_breath_attack(450 - m_ptr->level);
}
- /* Hack -- assume all attacks are obvious */
- obvious = TRUE;
-
/* Roll out the damage */
damage = damroll(d_dice, d_side);
@@ -1828,9 +1638,6 @@ bool_ make_attack_normal(int m_idx, byte divis)
{
case 0:
{
- /* Hack -- Assume obvious */
- obvious = TRUE;
-
/* Hack -- No damage */
damage = 0;
@@ -1839,9 +1646,6 @@ bool_ make_attack_normal(int m_idx, byte divis)
case RBE_HURT:
{
- /* Obvious */
- obvious = TRUE;
-
/* Hack -- Player armor reduces total damage */
damage -= (damage * ((ac < 150) ? ac : 150) / 250);
@@ -1853,9 +1657,6 @@ bool_ make_attack_normal(int m_idx, byte divis)
case RBE_ABOMINATION:
{
- /* Obvious */
- obvious = TRUE;
-
/* Morph, but let mimicry skill have a chance to stop this */
if (magik(60 - get_skill(SKILL_MIMICRY)))
{
@@ -1875,8 +1676,6 @@ bool_ make_attack_normal(int m_idx, byte divis)
case RBE_SANITY:
{
- obvious = TRUE;
-
take_sanity_hit(damage, ddesc);
break;
}
@@ -1889,10 +1688,7 @@ bool_ make_attack_normal(int m_idx, byte divis)
/* Take "poison" effect */
if (!(p_ptr->resist_pois || p_ptr->oppose_pois))
{
- if (set_poisoned(p_ptr->poisoned + randint(rlev) + 5))
- {
- obvious = TRUE;
- }
+ set_poisoned(p_ptr->poisoned + randint(rlev) + 5);
}
/* Learn about the player */
@@ -1909,8 +1705,7 @@ bool_ make_attack_normal(int m_idx, byte divis)
/* Allow complete resist */
if (!p_ptr->resist_disen)
{
- /* Apply disenchantment */
- if (apply_disenchant(0)) obvious = TRUE;
+ apply_disenchant(0);
}
/* Learn about the player */
@@ -1946,16 +1741,13 @@ bool_ make_attack_normal(int m_idx, byte divis)
/* Message */
msg_print("Energy drains from your pack!");
- /* Obvious */
- obvious = TRUE;
-
/* Heal */
j = rlev;
m_ptr->hp += j * o_ptr->pval * o_ptr->number;
if (m_ptr->hp > m_ptr->maxhp) m_ptr->hp = m_ptr->maxhp;
/* Redraw (later) if needed */
- if (health_who == m_idx) p_ptr->redraw |= (PR_HEALTH);
+ if (health_who == m_idx) p_ptr->redraw |= (PR_FRAME);
/* Uncharge */
o_ptr->pval = 0;
@@ -1979,9 +1771,6 @@ bool_ make_attack_normal(int m_idx, byte divis)
/* Take some damage */
take_hit(damage, ddesc);
- /* Obvious */
- obvious = TRUE;
-
/* Saving throw (unless paralyzed) based on dex and level */
if (!p_ptr->paralyzed &&
(rand_int(100) < (adj_dex_safe[p_ptr->stat_ind[A_DEX]] +
@@ -2036,7 +1825,7 @@ bool_ make_attack_normal(int m_idx, byte divis)
}
/* Redraw gold */
- p_ptr->redraw |= (PR_GOLD);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
@@ -2064,9 +1853,6 @@ bool_ make_attack_normal(int m_idx, byte divis)
/* Occasional "blink" anyway */
blinked = TRUE;
- /* Obvious */
- obvious = TRUE;
-
/* Done */
break;
}
@@ -2084,7 +1870,7 @@ bool_ make_attack_normal(int m_idx, byte divis)
if (!o_ptr->k_idx) continue;
/* Skip artifacts */
- if (artifact_p(o_ptr) || o_ptr->art_name) continue;
+ if (artifact_p(o_ptr)) continue;
/* Get a description */
object_desc(o_name, o_ptr, FALSE, 3);
@@ -2094,8 +1880,7 @@ bool_ make_attack_normal(int m_idx, byte divis)
((o_ptr->number > 1) ? "One of y" : "Y"),
o_name, index_to_label(i));
- /* Option */
- if (testing_carry)
+ /* Copy into inventory of monster */
{
s16b o_idx;
@@ -2133,52 +1918,13 @@ bool_ make_attack_normal(int m_idx, byte divis)
j_ptr->held_m_idx = m_idx;
/* Build stack */
- j_ptr->next_o_idx = m_ptr->hold_o_idx;
-
- /* Build stack */
- m_ptr->hold_o_idx = o_idx;
- }
- }
- else
- {
- if (strstr((r_name + r_ptr->name), "black market")
- && randint(2) != 1)
- {
- s16b o_idx;
-
- /* Make an object */
- o_idx = o_pop();
-
- /* Success */
- if (o_idx)
- {
- object_type *j_ptr;
- if (cheat_xtra || cheat_peek)
- msg_print("Moving object to black market...");
-
- /* Get new object */
- j_ptr = &o_list[o_idx];
-
- /* Copy object */
- object_copy(j_ptr, o_ptr);
-
- /* Modify number */
- j_ptr->number = 1;
-
- /* Forget mark */
- j_ptr->marked = FALSE;
-
- move_to_black_market(j_ptr);
- }
+ m_ptr->hold_o_idxs.push_back(o_idx);
}
}
/* Steal the items */
inc_stack_size_ex(i, -1, OPTIMIZE, NO_DESCRIBE);
- /* Obvious */
- obvious = TRUE;
-
/* Blink away */
blinked = TRUE;
@@ -2220,9 +1966,6 @@ bool_ make_attack_normal(int m_idx, byte divis)
/* Steal the items */
inc_stack_size_ex(i, -1, OPTIMIZE, NO_DESCRIBE);
- /* Obvious */
- obvious = TRUE;
-
/* Done */
break;
}
@@ -2249,7 +1992,6 @@ bool_ make_attack_normal(int m_idx, byte divis)
if (!p_ptr->blind)
{
msg_print("Your light dims.");
- obvious = TRUE;
}
/* Window stuff */
@@ -2261,9 +2003,6 @@ bool_ make_attack_normal(int m_idx, byte divis)
case RBE_ACID:
{
- /* Obvious */
- obvious = TRUE;
-
/* Message */
msg_print("You are covered in acid!");
@@ -2278,9 +2017,6 @@ bool_ make_attack_normal(int m_idx, byte divis)
case RBE_ELEC:
{
- /* Obvious */
- obvious = TRUE;
-
/* Message */
msg_print("You are struck by electricity!");
@@ -2295,9 +2031,6 @@ bool_ make_attack_normal(int m_idx, byte divis)
case RBE_FIRE:
{
- /* Obvious */
- obvious = TRUE;
-
/* Message */
msg_print("You are enveloped in flames!");
@@ -2312,9 +2045,6 @@ bool_ make_attack_normal(int m_idx, byte divis)
case RBE_COLD:
{
- /* Obvious */
- obvious = TRUE;
-
/* Message */
msg_print("You are covered with frost!");
@@ -2335,10 +2065,7 @@ bool_ make_attack_normal(int m_idx, byte divis)
/* Increase "blind" */
if (!p_ptr->resist_blind)
{
- if (set_blind(p_ptr->blind + 10 + randint(rlev)))
- {
- obvious = TRUE;
- }
+ set_blind(p_ptr->blind + 10 + randint(rlev));
}
/* Learn about the player */
@@ -2355,10 +2082,7 @@ bool_ make_attack_normal(int m_idx, byte divis)
/* Increase "confused" */
if (!p_ptr->resist_conf)
{
- if (set_confused(p_ptr->confused + 3 + randint(rlev)))
- {
- obvious = TRUE;
- }
+ set_confused(p_ptr->confused + 3 + randint(rlev));
}
/* Learn about the player */
@@ -2376,19 +2100,14 @@ bool_ make_attack_normal(int m_idx, byte divis)
if (p_ptr->resist_fear)
{
msg_print("You stand your ground!");
- obvious = TRUE;
}
else if (rand_int(100) < p_ptr->skill_sav)
{
msg_print("You stand your ground!");
- obvious = TRUE;
}
else
{
- if (set_afraid(p_ptr->afraid + 3 + randint(rlev)))
- {
- obvious = TRUE;
- }
+ set_afraid(p_ptr->afraid + 3 + randint(rlev));
}
/* Learn about the player */
@@ -2409,19 +2128,14 @@ bool_ make_attack_normal(int m_idx, byte divis)
if (p_ptr->free_act)
{
msg_print("You are unaffected!");
- obvious = TRUE;
}
else if (rand_int(100) < p_ptr->skill_sav)
{
msg_print("You resist the effects!");
- obvious = TRUE;
}
else
{
- if (set_paralyzed(p_ptr->paralyzed + 3 + randint(rlev)))
- {
- obvious = TRUE;
- }
+ set_paralyzed(3 + randint(rlev));
}
/* Learn about the player */
@@ -2436,7 +2150,7 @@ bool_ make_attack_normal(int m_idx, byte divis)
take_hit(damage, ddesc);
/* Damage (stat) */
- if (do_dec_stat(A_STR, STAT_DEC_NORMAL)) obvious = TRUE;
+ do_dec_stat(A_STR, STAT_DEC_NORMAL);
break;
}
@@ -2447,7 +2161,7 @@ bool_ make_attack_normal(int m_idx, byte divis)
take_hit(damage, ddesc);
/* Damage (stat) */
- if (do_dec_stat(A_INT, STAT_DEC_NORMAL)) obvious = TRUE;
+ do_dec_stat(A_INT, STAT_DEC_NORMAL);
break;
}
@@ -2458,7 +2172,7 @@ bool_ make_attack_normal(int m_idx, byte divis)
take_hit(damage, ddesc);
/* Damage (stat) */
- if (do_dec_stat(A_WIS, STAT_DEC_NORMAL)) obvious = TRUE;
+ do_dec_stat(A_WIS, STAT_DEC_NORMAL);
break;
}
@@ -2469,7 +2183,7 @@ bool_ make_attack_normal(int m_idx, byte divis)
take_hit(damage, ddesc);
/* Damage (stat) */
- if (do_dec_stat(A_DEX, STAT_DEC_NORMAL)) obvious = TRUE;
+ do_dec_stat(A_DEX, STAT_DEC_NORMAL);
break;
}
@@ -2480,7 +2194,7 @@ bool_ make_attack_normal(int m_idx, byte divis)
take_hit(damage, ddesc);
/* Damage (stat) */
- if (do_dec_stat(A_CON, STAT_DEC_NORMAL)) obvious = TRUE;
+ do_dec_stat(A_CON, STAT_DEC_NORMAL);
break;
}
@@ -2491,7 +2205,7 @@ bool_ make_attack_normal(int m_idx, byte divis)
take_hit(damage, ddesc);
/* Damage (stat) */
- if (do_dec_stat(A_CHR, STAT_DEC_NORMAL)) obvious = TRUE;
+ do_dec_stat(A_CHR, STAT_DEC_NORMAL);
break;
}
@@ -2502,21 +2216,18 @@ bool_ make_attack_normal(int m_idx, byte divis)
take_hit(damage, ddesc);
/* Damage (stats) */
- if (do_dec_stat(A_STR, STAT_DEC_NORMAL)) obvious = TRUE;
- if (do_dec_stat(A_DEX, STAT_DEC_NORMAL)) obvious = TRUE;
- if (do_dec_stat(A_CON, STAT_DEC_NORMAL)) obvious = TRUE;
- if (do_dec_stat(A_INT, STAT_DEC_NORMAL)) obvious = TRUE;
- if (do_dec_stat(A_WIS, STAT_DEC_NORMAL)) obvious = TRUE;
- if (do_dec_stat(A_CHR, STAT_DEC_NORMAL)) obvious = TRUE;
+ do_dec_stat(A_STR, STAT_DEC_NORMAL);
+ do_dec_stat(A_DEX, STAT_DEC_NORMAL);
+ do_dec_stat(A_CON, STAT_DEC_NORMAL);
+ do_dec_stat(A_INT, STAT_DEC_NORMAL);
+ do_dec_stat(A_WIS, STAT_DEC_NORMAL);
+ do_dec_stat(A_CHR, STAT_DEC_NORMAL);
break;
}
case RBE_SHATTER:
{
- /* Obvious */
- obvious = TRUE;
-
/* Hack -- Reduce damage based on the player armor class */
damage -= (damage * ((ac < 150) ? ac : 150) / 250);
@@ -2536,9 +2247,6 @@ bool_ make_attack_normal(int m_idx, byte divis)
case RBE_EXP_10:
{
- /* Obvious */
- obvious = TRUE;
-
/* Take damage */
take_hit(damage, ddesc);
@@ -2565,9 +2273,6 @@ bool_ make_attack_normal(int m_idx, byte divis)
case RBE_EXP_20:
{
- /* Obvious */
- obvious = TRUE;
-
/* Take damage */
take_hit(damage, ddesc);
@@ -2594,9 +2299,6 @@ bool_ make_attack_normal(int m_idx, byte divis)
case RBE_EXP_40:
{
- /* Obvious */
- obvious = TRUE;
-
/* Take damage */
take_hit(damage, ddesc);
@@ -2623,9 +2325,6 @@ bool_ make_attack_normal(int m_idx, byte divis)
case RBE_EXP_80:
{
- /* Obvious */
- obvious = TRUE;
-
/* Take damage */
take_hit(damage, ddesc);
@@ -2658,10 +2357,7 @@ bool_ make_attack_normal(int m_idx, byte divis)
/* Take "poison" effect */
if (!(p_ptr->resist_pois || p_ptr->oppose_pois))
{
- if (set_poisoned(p_ptr->poisoned + randint(rlev) + 5))
- {
- obvious = TRUE;
- }
+ set_poisoned(p_ptr->poisoned + randint(rlev) + 5);
}
/* Damage CON (10% chance)*/
@@ -2669,7 +2365,7 @@ bool_ make_attack_normal(int m_idx, byte divis)
{
/* 1% chance for perm. damage */
bool_ perm = (randint(10) == 1);
- if (dec_stat(A_CON, randint(10), perm)) obvious = TRUE;
+ dec_stat(A_CON, randint(10), perm);
}
break;
@@ -2682,10 +2378,7 @@ bool_ make_attack_normal(int m_idx, byte divis)
/* Increase "image" */
if (!p_ptr->resist_chaos)
{
- if (set_image(p_ptr->image + 3 + randint(rlev / 2)))
- {
- obvious = TRUE;
- }
+ set_image(p_ptr->image + 3 + randint(rlev / 2));
}
/* Learn about the player */
@@ -2764,9 +2457,6 @@ bool_ make_attack_normal(int m_idx, byte divis)
}
case RBE_PARASITE:
{
- /* Obvious */
- obvious = TRUE;
-
if (!p_ptr->parasite) set_parasite(damage, m_ptr->r_idx);
break;
@@ -2828,7 +2518,7 @@ bool_ make_attack_normal(int m_idx, byte divis)
}
/* Apply the cut */
- if (k) (void)set_cut(p_ptr->cut + k);
+ if (k) set_cut(p_ptr->cut + k);
}
/* Handle stun */
@@ -2869,20 +2559,11 @@ bool_ make_attack_normal(int m_idx, byte divis)
}
/* Apply the stun */
- if (k) (void)set_stun(p_ptr->stun + k);
- }
-
- /* Do vampiric thingies */
- if (do_vampire)
- {
- /* Change to resist(but never total protection) */
-/* if (magik(3) || (magik(m_ptr->level - (p_ptr->lev / 2))))
- call_lua("gain_corruption", "(s)", "", "Vampire");*/
+ if (k) set_stun(p_ptr->stun + k);
}
if (explode)
{
- sound(SOUND_EXPLODE);
if (mon_take_hit(m_idx, m_ptr->hp + 1, &fear, NULL))
{
blinked = FALSE;
@@ -2894,7 +2575,7 @@ bool_ make_attack_normal(int m_idx, byte divis)
{
if (p_ptr->sh_fire && alive)
{
- if (!(r_ptr->flags3 & RF3_IM_FIRE))
+ if (!(r_ptr->flags & RF_IM_FIRE))
{
msg_format("%^s is suddenly very hot!", m_name);
if (mon_take_hit(m_idx, damroll(2, 6), &fear,
@@ -2904,16 +2585,11 @@ bool_ make_attack_normal(int m_idx, byte divis)
alive = FALSE;
}
}
- else
- {
- if (m_ptr->ml)
- r_ptr->r_flags3 |= RF3_IM_FIRE;
- }
}
if (p_ptr->sh_elec && alive)
{
- if (!(r_ptr->flags3 & RF3_IM_ELEC))
+ if (!(r_ptr->flags & RF_IM_ELEC))
{
msg_format("%^s gets zapped!", m_name);
if (mon_take_hit(m_idx, damroll(2, 6), &fear,
@@ -2923,12 +2599,8 @@ bool_ make_attack_normal(int m_idx, byte divis)
alive = FALSE;
}
}
- else
- {
- if (m_ptr->ml)
- r_ptr->r_flags3 |= RF3_IM_ELEC;
- }
}
+
if (p_ptr->shield && (p_ptr->shield_opt & SHIELD_COUNTER) && alive)
{
msg_format("%^s gets bashed by your mystic shield!", m_name);
@@ -2939,9 +2611,10 @@ bool_ make_attack_normal(int m_idx, byte divis)
alive = FALSE;
}
}
+
if (p_ptr->shield && (p_ptr->shield_opt & SHIELD_FIRE) && alive)
{
- if (!(r_ptr->flags3 & RF3_IM_FIRE))
+ if (!(r_ptr->flags & RF_IM_FIRE))
{
msg_format("%^s gets burned by your fiery shield!", m_name);
if (mon_take_hit(m_idx, damroll(p_ptr->shield_power_opt, p_ptr->shield_power_opt2), &fear,
@@ -2951,12 +2624,8 @@ bool_ make_attack_normal(int m_idx, byte divis)
alive = FALSE;
}
}
- else
- {
- if (m_ptr->ml)
- r_ptr->r_flags3 |= RF3_IM_FIRE;
- }
}
+
if (p_ptr->shield && (p_ptr->shield_opt & SHIELD_GREAT_FIRE) && alive)
{
msg_format("%^s gets burned by your fiery shield!", m_name);
@@ -2967,11 +2636,12 @@ bool_ make_attack_normal(int m_idx, byte divis)
alive = FALSE;
}
}
+
if (p_ptr->shield && (p_ptr->shield_opt & SHIELD_FEAR) && alive)
{
int tmp;
- if ((!(r_ptr->flags1 & RF1_UNIQUE)) && (damroll(p_ptr->shield_power_opt, p_ptr->shield_power_opt2) - m_ptr->level > 0))
+ if ((!(r_ptr->flags & RF_UNIQUE)) && (damroll(p_ptr->shield_power_opt, p_ptr->shield_power_opt2) - m_ptr->level > 0))
{
msg_format("%^s gets scared away!", m_name);
@@ -3011,7 +2681,7 @@ bool_ make_attack_normal(int m_idx, byte divis)
if (m_ptr->ml)
{
/* Disturbing */
- disturb(1, 0);
+ disturb();
/* Message */
msg_format("%^s misses you.", m_name);
@@ -3020,21 +2690,6 @@ bool_ make_attack_normal(int m_idx, byte divis)
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]++;
- }
- }
- }
}
@@ -3045,16 +2700,9 @@ bool_ make_attack_normal(int m_idx, byte divis)
teleport_away(m_idx, MAX_SIGHT * 2 + 5);
}
-
- /* Always notice cause of death */
- if (death && (r_ptr->r_deaths < MAX_SHORT))
- {
- r_ptr->r_deaths++;
- }
-
+ /* Fear */
if (m_ptr->ml && fear)
{
- sound (SOUND_FLEE);
msg_format("%^s flees in terror!", m_name);
}
diff --git a/src/melee1.hpp b/src/melee1.hpp
new file mode 100644
index 00000000..90ece431
--- /dev/null
+++ b/src/melee1.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "h-basic.h"
+
+int get_attack_power(int effect);
+bool_ carried_make_attack_normal(int r_idx);
+bool_ make_attack_normal(int m_idx, byte divis);
diff --git a/src/melee2.c b/src/melee2.cc
index 6ada6bd0..d769355a 100644
--- a/src/melee2.c
+++ b/src/melee2.cc
@@ -1,27 +1,62 @@
-/* File: melee2.c */
-
-/* Purpose: Monster spells and movement */
-
/*
-* 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.
-*/
+ * 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.
+ */
/*
* This file has several additions to it by Keldon Jones (keldon@umr.edu)
* to improve the general quality of the AI (version 0.1.1).
*/
-#include "angband.h"
+#include "melee2.hpp"
+
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "cmd1.hpp"
+#include "dungeon_flag.hpp"
+#include "feature_flag.hpp"
+#include "feature_type.hpp"
+#include "files.hpp"
+#include "game.hpp"
+#include "hook_mon_speak_in.hpp"
+#include "hook_monster_ai_in.hpp"
+#include "hook_monster_ai_out.hpp"
+#include "hooks.hpp"
+#include "melee1.hpp"
+#include "messages.hpp"
+#include "monster2.hpp"
+#include "monster3.hpp"
+#include "monster_race.hpp"
+#include "monster_race_flag.hpp"
+#include "monster_spell.hpp"
+#include "monster_spell_flag.hpp"
+#include "monster_type.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_flag.hpp"
+#include "options.hpp"
+#include "player_type.hpp"
+#include "skills.hpp"
+#include "spells1.hpp"
+#include "spells2.hpp"
+#include "stats.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+#include "xtra2.hpp"
+#include "z-rand.hpp"
+
+#include <cassert>
#define SPEAK_CHANCE 8
#define GRINDNOISE 20
#define FOLLOW_DISTANCE 6
+
/*
* Based on mon_take_hit... all monster attacks on
* other monsters should use
@@ -30,15 +65,34 @@ bool_ mon_take_hit_mon(int s_idx, int m_idx, int dam, bool_ *fear, cptr note)
{
monster_type *m_ptr = &m_list[m_idx], *s_ptr = &m_list[s_idx];
- monster_race *r_ptr = race_inf(m_ptr);
-
- s32b div, new_exp, new_exp_frac;
+ /* Output */
+ auto cmonster_msg = [m_ptr](std::string const &suffix) {
+ auto &messages = game->messages;
+ // Build monster name
+ char m_name[80];
+ monster_desc(m_name, m_ptr, 0);
+ capitalize(m_name);
+ // Add suffix
+ auto msg = std::string(m_name);
+ msg += suffix;
+ // Display
+ if (options->disturb_other)
+ {
+ cmsg_print(TERM_L_RED, msg);
+ }
+ else
+ {
+ messages.add(msg, TERM_L_RED);
+ p_ptr->window |= PW_MESSAGE;
+ }
+ };
/* Redraw (later) if needed */
- if (health_who == m_idx) p_ptr->redraw |= (PR_HEALTH);
+ if (health_who == m_idx) p_ptr->redraw |= (PR_FRAME);
- /* Some mosnters are immune to death */
- if (r_ptr->flags7 & RF7_NO_DEATH) return FALSE;
+ /* Some monsters are immune to death */
+ auto const r_ptr = m_ptr->race();
+ if (r_ptr->flags & RF_NO_DEATH) return FALSE;
/* Wake it up */
m_ptr->csleep = 0;
@@ -49,39 +103,24 @@ bool_ mon_take_hit_mon(int s_idx, int m_idx, int dam, bool_ *fear, cptr note)
/* It is dead now... or is it? */
if (m_ptr->hp < 0)
{
- if (((r_ptr->flags1 & RF1_UNIQUE) && (m_ptr->status <= MSTATUS_NEUTRAL_P)) ||
+ if (((r_ptr->flags & RF_UNIQUE) && (m_ptr->status <= MSTATUS_NEUTRAL_P)) ||
(m_ptr->mflag & MFLAG_QUEST))
{
m_ptr->hp = 1;
}
else
{
- char m_name[80];
s32b dive = s_ptr->level;
- if (!dive) dive = 1;
-
- /* Extract monster name */
- monster_desc(m_name, m_ptr, 0);
-
- /* Make a sound */
- if ((r_ptr->flags3 & RF3_DEMON) ||
- (r_ptr->flags3 & RF3_UNDEAD) ||
- (r_ptr->flags2 & RF2_STUPID) ||
- (r_ptr->flags3 & RF3_NONLIVING) ||
- (strchr("Evg", r_ptr->d_char)))
- {
- sound(SOUND_N_KILL);
- }
- else
+ if (!dive)
{
- sound(SOUND_KILL);
+ dive = 1;
}
/* Death by Missile/Spell attack */
if (note)
{
- cmonster_msg(TERM_L_RED, "%^s%s", m_name, note);
+ cmonster_msg(note);
}
/* Death by Physical attack -- living monster */
else if (!m_ptr->ml)
@@ -89,17 +128,17 @@ bool_ mon_take_hit_mon(int s_idx, int m_idx, int dam, bool_ *fear, cptr note)
/* Do nothing */
}
/* Death by Physical attack -- non-living monster */
- else if ((r_ptr->flags3 & (RF3_DEMON)) ||
- (r_ptr->flags3 & (RF3_UNDEAD)) ||
- (r_ptr->flags2 & (RF2_STUPID)) ||
- (r_ptr->flags3 & (RF3_NONLIVING)) ||
+ else if ((r_ptr->flags & RF_DEMON) ||
+ (r_ptr->flags & RF_UNDEAD) ||
+ (r_ptr->flags & RF_STUPID) ||
+ (r_ptr->flags & RF_NONLIVING) ||
(strchr("Evg", r_ptr->d_char)))
{
- cmonster_msg(TERM_L_RED, "%^s is destroyed.", m_name);
+ cmonster_msg(" is destroyed.");
}
else
{
- cmonster_msg(TERM_L_RED, "%^s is killed.", m_name);
+ cmonster_msg(" is killed.");
}
dive = r_ptr->mexp * m_ptr->level / dive;
@@ -112,13 +151,13 @@ bool_ mon_take_hit_mon(int s_idx, int m_idx, int dam, bool_ *fear, cptr note)
if (get_skill(SKILL_LORE) && (s_ptr->status >= MSTATUS_PET))
{
/* Maximum player level */
- div = p_ptr->max_plv;
+ s32b div = p_ptr->max_plv;
/* Give some experience for the kill */
- new_exp = ((long)r_ptr->mexp * m_ptr->level) / div;
+ s32b new_exp = ((long)r_ptr->mexp * m_ptr->level) / div;
/* Handle fractional experience */
- new_exp_frac = ((((long)r_ptr->mexp * m_ptr->level) % div)
+ s32b new_exp_frac = ((((long)r_ptr->mexp * m_ptr->level) % div)
* 0x10000L / div) + p_ptr->exp_frac;
/* Keep track of experience */
@@ -143,7 +182,7 @@ bool_ mon_take_hit_mon(int s_idx, int m_idx, int dam, bool_ *fear, cptr note)
}
/* When an Unique dies, it stays dead */
- if (r_ptr->flags1 & (RF1_UNIQUE))
+ if (r_ptr->flags & RF_UNIQUE)
{
r_ptr->max_num = 0;
}
@@ -163,7 +202,17 @@ 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)
+{
+ assert(m_ptr != NULL);
/* Mega-Hack -- Pain cancels fear */
if (m_ptr->monfear && (dam > 0))
@@ -189,7 +238,8 @@ bool_ mon_take_hit_mon(int s_idx, int m_idx, int dam, bool_ *fear, cptr note)
}
/* Sometimes a monster gets scared by damage */
- if (!m_ptr->monfear && !(r_ptr->flags3 & (RF3_NO_FEAR)))
+ auto const r_ptr = m_ptr->race();
+ if (!m_ptr->monfear && !(r_ptr->flags & RF_NO_FEAR))
{
int percentage;
@@ -197,9 +247,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)))
{
@@ -212,17 +262,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).
*
@@ -247,10 +289,7 @@ bool_ mon_take_hit_mon(int s_idx, int m_idx, int dam, bool_ *fear, cptr note)
*
* This has the added advantage that attacks and spells are related.
* The "smart_learn" option means that the monster "learns" the flags
-* that should be set, and "smart_cheat" means that he "knows" them.
-* So "smart_cheat" means that the "smart" field is always up to date,
-* while "smart_learn" means that the "smart" field is slowly learned.
-* Both of them have the same effect on the "choose spell" routine.
+* that should be set.
*/
@@ -258,10 +297,10 @@ bool_ mon_take_hit_mon(int s_idx, int m_idx, int dam, bool_ *fear, cptr note)
/*
* Internal probability routine
*/
-static bool_ int_outof(monster_race *r_ptr, int prob)
+static bool_ int_outof(std::shared_ptr<monster_race> r_ptr, int prob)
{
/* Non-Smart monsters are half as "smart" */
- if (!(r_ptr->flags2 & (RF2_SMART))) prob = prob / 2;
+ if (!(r_ptr->flags & RF_SMART)) prob = prob / 2;
/* Roll the dice */
return (rand_int(100) < prob);
@@ -272,77 +311,32 @@ static bool_ int_outof(monster_race *r_ptr, int prob)
/*
* Remove the "bad" spells from a spell list
*/
-static void remove_bad_spells(int m_idx, u32b *f4p, u32b *f5p, u32b *f6p)
+static void remove_bad_spells(int m_idx, monster_spell_flag_set *spells_p)
{
monster_type *m_ptr = &m_list[m_idx];
- monster_race *r_ptr = race_inf(m_ptr);
-
- u32b f4 = (*f4p);
- u32b f5 = (*f5p);
- u32b f6 = (*f6p);
-
u32b smart = 0L;
+ // Shorthand
+ auto spells(*spells_p);
- /* Too stupid to know anything */
- if (r_ptr->flags2 & (RF2_STUPID)) return;
-
-
- /* Must be cheating or learning */
- if (!smart_cheat && !smart_learn) return;
-
-
- /* Update acquired knowledge */
- if (smart_learn)
+ /* Too stupid to know anything? */
+ auto const r_ptr = m_ptr->race();
+ if (r_ptr->flags & RF_STUPID)
{
- /* Hack -- Occasionally forget player status */
- if (m_ptr->smart && (rand_int(100) < 1)) m_ptr->smart = 0L;
-
- /* Use the memorized flags */
- smart = m_ptr->smart;
+ return;
}
-
- /* Cheat if requested */
- if (smart_cheat)
+ /* Must be cheating or learning */
+ if (!options->smart_learn)
{
- /* Know basic info */
- if (p_ptr->resist_acid) smart |= (SM_RES_ACID);
- if (p_ptr->oppose_acid) smart |= (SM_OPP_ACID);
- if (p_ptr->immune_acid) smart |= (SM_IMM_ACID);
- if (p_ptr->resist_elec) smart |= (SM_RES_ELEC);
- if (p_ptr->oppose_elec) smart |= (SM_OPP_ELEC);
- if (p_ptr->immune_elec) smart |= (SM_IMM_ELEC);
- if (p_ptr->resist_fire) smart |= (SM_RES_FIRE);
- if (p_ptr->oppose_fire) smart |= (SM_OPP_FIRE);
- if (p_ptr->immune_fire) smart |= (SM_IMM_FIRE);
- if (p_ptr->resist_cold) smart |= (SM_RES_COLD);
- if (p_ptr->oppose_cold) smart |= (SM_OPP_COLD);
- if (p_ptr->immune_cold) smart |= (SM_IMM_COLD);
-
- /* Know poison info */
- if (p_ptr->resist_pois) smart |= (SM_RES_POIS);
- if (p_ptr->oppose_pois) smart |= (SM_OPP_POIS);
-
- /* Know special resistances */
- if (p_ptr->resist_neth) smart |= (SM_RES_NETH);
- if (p_ptr->resist_lite) smart |= (SM_RES_LITE);
- if (p_ptr->resist_dark) smart |= (SM_RES_DARK);
- if (p_ptr->resist_fear) smart |= (SM_RES_FEAR);
- if (p_ptr->resist_conf) smart |= (SM_RES_CONF);
- if (p_ptr->resist_chaos) smart |= (SM_RES_CHAOS);
- if (p_ptr->resist_disen) smart |= (SM_RES_DISEN);
- if (p_ptr->resist_blind) smart |= (SM_RES_BLIND);
- if (p_ptr->resist_nexus) smart |= (SM_RES_NEXUS);
- if (p_ptr->resist_sound) smart |= (SM_RES_SOUND);
- if (p_ptr->resist_shard) smart |= (SM_RES_SHARD);
- if (p_ptr->reflect) smart |= (SM_IMM_REFLECT);
-
- /* Know bizarre "resistances" */
- if (p_ptr->free_act) smart |= (SM_IMM_FREE);
- if (!p_ptr->msp) smart |= (SM_IMM_MANA);
+ return;
}
+ /* Hack -- Occasionally forget player status */
+ if (m_ptr->smart && magik(1)) m_ptr->smart = 0L;
+
+ /* Use the memorized flags */
+ smart = m_ptr->smart;
/* Nothing known */
if (!smart) return;
@@ -350,201 +344,199 @@ static void remove_bad_spells(int m_idx, u32b *f4p, u32b *f5p, u32b *f6p)
if (smart & (SM_IMM_ACID))
{
- if (int_outof(r_ptr, 100)) f4 &= ~(RF4_BR_ACID);
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_BA_ACID);
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_BO_ACID);
+ if (int_outof(r_ptr, 100)) spells &= ~SF_BR_ACID;
+ if (int_outof(r_ptr, 100)) spells &= ~SF_BA_ACID;
+ if (int_outof(r_ptr, 100)) spells &= ~SF_BO_ACID;
}
else if ((smart & (SM_OPP_ACID)) && (smart & (SM_RES_ACID)))
{
- if (int_outof(r_ptr, 80)) f4 &= ~(RF4_BR_ACID);
- if (int_outof(r_ptr, 80)) f5 &= ~(RF5_BA_ACID);
- if (int_outof(r_ptr, 80)) f5 &= ~(RF5_BO_ACID);
+ if (int_outof(r_ptr, 80)) spells &= ~SF_BR_ACID;
+ if (int_outof(r_ptr, 80)) spells &= ~SF_BA_ACID;
+ if (int_outof(r_ptr, 80)) spells &= ~SF_BO_ACID;
}
else if ((smart & (SM_OPP_ACID)) || (smart & (SM_RES_ACID)))
{
- if (int_outof(r_ptr, 30)) f4 &= ~(RF4_BR_ACID);
- if (int_outof(r_ptr, 30)) f5 &= ~(RF5_BA_ACID);
- if (int_outof(r_ptr, 30)) f5 &= ~(RF5_BO_ACID);
+ if (int_outof(r_ptr, 30)) spells &= ~SF_BR_ACID;
+ if (int_outof(r_ptr, 30)) spells &= ~SF_BA_ACID;
+ if (int_outof(r_ptr, 30)) spells &= ~SF_BO_ACID;
}
if (smart & (SM_IMM_ELEC))
{
- if (int_outof(r_ptr, 100)) f4 &= ~(RF4_BR_ELEC);
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_BA_ELEC);
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_BO_ELEC);
+ if (int_outof(r_ptr, 100)) spells &= ~SF_BR_ELEC;
+ if (int_outof(r_ptr, 100)) spells &= ~SF_BA_ELEC;
+ if (int_outof(r_ptr, 100)) spells &= ~SF_BO_ELEC;
}
else if ((smart & (SM_OPP_ELEC)) && (smart & (SM_RES_ELEC)))
{
- if (int_outof(r_ptr, 80)) f4 &= ~(RF4_BR_ELEC);
- if (int_outof(r_ptr, 80)) f5 &= ~(RF5_BA_ELEC);
- if (int_outof(r_ptr, 80)) f5 &= ~(RF5_BO_ELEC);
+ if (int_outof(r_ptr, 80)) spells &= ~SF_BR_ELEC;
+ if (int_outof(r_ptr, 80)) spells &= ~SF_BA_ELEC;
+ if (int_outof(r_ptr, 80)) spells &= ~SF_BO_ELEC;
}
else if ((smart & (SM_OPP_ELEC)) || (smart & (SM_RES_ELEC)))
{
- if (int_outof(r_ptr, 30)) f4 &= ~(RF4_BR_ELEC);
- if (int_outof(r_ptr, 30)) f5 &= ~(RF5_BA_ELEC);
- if (int_outof(r_ptr, 30)) f5 &= ~(RF5_BO_ELEC);
+ if (int_outof(r_ptr, 30)) spells &= ~SF_BR_ELEC;
+ if (int_outof(r_ptr, 30)) spells &= ~SF_BA_ELEC;
+ if (int_outof(r_ptr, 30)) spells &= ~SF_BO_ELEC;
}
if (smart & (SM_IMM_FIRE))
{
- if (int_outof(r_ptr, 100)) f4 &= ~(RF4_BR_FIRE);
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_BA_FIRE);
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_BO_FIRE);
+ if (int_outof(r_ptr, 100)) spells &= ~SF_BR_FIRE;
+ if (int_outof(r_ptr, 100)) spells &= ~SF_BA_FIRE;
+ if (int_outof(r_ptr, 100)) spells &= ~SF_BO_FIRE;
}
else if ((smart & (SM_OPP_FIRE)) && (smart & (SM_RES_FIRE)))
{
- if (int_outof(r_ptr, 80)) f4 &= ~(RF4_BR_FIRE);
- if (int_outof(r_ptr, 80)) f5 &= ~(RF5_BA_FIRE);
- if (int_outof(r_ptr, 80)) f5 &= ~(RF5_BO_FIRE);
+ if (int_outof(r_ptr, 80)) spells &= ~SF_BR_FIRE;
+ if (int_outof(r_ptr, 80)) spells &= ~SF_BA_FIRE;
+ if (int_outof(r_ptr, 80)) spells &= ~SF_BO_FIRE;
}
else if ((smart & (SM_OPP_FIRE)) || (smart & (SM_RES_FIRE)))
{
- if (int_outof(r_ptr, 30)) f4 &= ~(RF4_BR_FIRE);
- if (int_outof(r_ptr, 30)) f5 &= ~(RF5_BA_FIRE);
- if (int_outof(r_ptr, 30)) f5 &= ~(RF5_BO_FIRE);
+ if (int_outof(r_ptr, 30)) spells &= ~SF_BR_FIRE;
+ if (int_outof(r_ptr, 30)) spells &= ~SF_BA_FIRE;
+ if (int_outof(r_ptr, 30)) spells &= ~SF_BO_FIRE;
}
if (smart & (SM_IMM_COLD))
{
- if (int_outof(r_ptr, 100)) f4 &= ~(RF4_BR_COLD);
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_BA_COLD);
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_BO_COLD);
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_BO_ICEE);
+ if (int_outof(r_ptr, 100)) spells &= ~SF_BR_COLD;
+ if (int_outof(r_ptr, 100)) spells &= ~SF_BA_COLD;
+ if (int_outof(r_ptr, 100)) spells &= ~SF_BO_COLD;
+ if (int_outof(r_ptr, 100)) spells &= ~SF_BO_ICEE;
}
else if ((smart & (SM_OPP_COLD)) && (smart & (SM_RES_COLD)))
{
- if (int_outof(r_ptr, 80)) f4 &= ~(RF4_BR_COLD);
- if (int_outof(r_ptr, 80)) f5 &= ~(RF5_BA_COLD);
- if (int_outof(r_ptr, 80)) f5 &= ~(RF5_BO_COLD);
- if (int_outof(r_ptr, 80)) f5 &= ~(RF5_BO_ICEE);
+ if (int_outof(r_ptr, 80)) spells &= ~SF_BR_COLD;
+ if (int_outof(r_ptr, 80)) spells &= ~SF_BA_COLD;
+ if (int_outof(r_ptr, 80)) spells &= ~SF_BO_COLD;
+ if (int_outof(r_ptr, 80)) spells &= ~SF_BO_ICEE;
}
else if ((smart & (SM_OPP_COLD)) || (smart & (SM_RES_COLD)))
{
- if (int_outof(r_ptr, 30)) f4 &= ~(RF4_BR_COLD);
- if (int_outof(r_ptr, 30)) f5 &= ~(RF5_BA_COLD);
- if (int_outof(r_ptr, 30)) f5 &= ~(RF5_BO_COLD);
- if (int_outof(r_ptr, 30)) f5 &= ~(RF5_BO_ICEE);
+ if (int_outof(r_ptr, 30)) spells &= ~SF_BR_COLD;
+ if (int_outof(r_ptr, 30)) spells &= ~SF_BA_COLD;
+ if (int_outof(r_ptr, 30)) spells &= ~SF_BO_COLD;
+ if (int_outof(r_ptr, 30)) spells &= ~SF_BO_ICEE;
}
if ((smart & (SM_OPP_POIS)) && (smart & (SM_RES_POIS)))
{
- if (int_outof(r_ptr, 80)) f4 &= ~(RF4_BR_POIS);
- if (int_outof(r_ptr, 80)) f5 &= ~(RF5_BA_POIS);
- if (int_outof(r_ptr, 40)) f4 &= ~(RF4_BA_NUKE);
- if (int_outof(r_ptr, 40)) f4 &= ~(RF4_BR_NUKE);
+ if (int_outof(r_ptr, 80)) spells &= ~SF_BR_POIS;
+ if (int_outof(r_ptr, 80)) spells &= ~SF_BA_POIS;
+ if (int_outof(r_ptr, 40)) spells &= ~SF_BA_NUKE;
+ if (int_outof(r_ptr, 40)) spells &= ~SF_BR_NUKE;
}
else if ((smart & (SM_OPP_POIS)) || (smart & (SM_RES_POIS)))
{
- if (int_outof(r_ptr, 30)) f4 &= ~(RF4_BR_POIS);
- if (int_outof(r_ptr, 30)) f5 &= ~(RF5_BA_POIS);
+ if (int_outof(r_ptr, 30)) spells &= ~SF_BR_POIS;
+ if (int_outof(r_ptr, 30)) spells &= ~SF_BA_POIS;
}
if (smart & (SM_RES_NETH))
{
- if (int_outof(r_ptr, 50)) f4 &= ~(RF4_BR_NETH);
- if (int_outof(r_ptr, 50)) f5 &= ~(RF5_BA_NETH);
- if (int_outof(r_ptr, 50)) f5 &= ~(RF5_BO_NETH);
+ if (int_outof(r_ptr, 50)) spells &= ~SF_BR_NETH;
+ if (int_outof(r_ptr, 50)) spells &= ~SF_BA_NETH;
+ if (int_outof(r_ptr, 50)) spells &= ~SF_BO_NETH;
}
if (smart & (SM_RES_LITE))
{
- if (int_outof(r_ptr, 50)) f4 &= ~(RF4_BR_LITE);
+ if (int_outof(r_ptr, 50)) spells &= ~SF_BR_LITE;
}
if (smart & (SM_RES_DARK))
{
- if (int_outof(r_ptr, 50)) f4 &= ~(RF4_BR_DARK);
- if (int_outof(r_ptr, 50)) f5 &= ~(RF5_BA_DARK);
+ if (int_outof(r_ptr, 50)) spells &= ~SF_BR_DARK;
+ if (int_outof(r_ptr, 50)) spells &= ~SF_BA_DARK;
}
if (smart & (SM_RES_FEAR))
{
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_SCARE);
+ if (int_outof(r_ptr, 100)) spells &= ~SF_SCARE;
}
if (smart & (SM_RES_CONF))
{
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_CONF);
- if (int_outof(r_ptr, 50)) f4 &= ~(RF4_BR_CONF);
+ if (int_outof(r_ptr, 100)) spells &= ~SF_CONF;
+ if (int_outof(r_ptr, 50)) spells &= ~SF_BR_CONF;
}
if (smart & (SM_RES_CHAOS))
{
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_CONF);
- if (int_outof(r_ptr, 50)) f4 &= ~(RF4_BR_CONF);
- if (int_outof(r_ptr, 50)) f4 &= ~(RF4_BR_CHAO);
- if (int_outof(r_ptr, 50)) f4 &= ~(RF4_BA_CHAO);
+ if (int_outof(r_ptr, 100)) spells &= ~SF_CONF;
+ if (int_outof(r_ptr, 50)) spells &= ~SF_BR_CONF;
+ if (int_outof(r_ptr, 50)) spells &= ~SF_BR_CHAO;
+ if (int_outof(r_ptr, 50)) spells &= ~SF_BA_CHAO;
}
if (smart & (SM_RES_DISEN))
{
- if (int_outof(r_ptr, 100)) f4 &= ~(RF4_BR_DISE);
+ if (int_outof(r_ptr, 100)) spells &= ~SF_BR_DISE;
}
if (smart & (SM_RES_BLIND))
{
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_BLIND);
+ if (int_outof(r_ptr, 100)) spells &= ~SF_BLIND;
}
if (smart & (SM_RES_NEXUS))
{
- if (int_outof(r_ptr, 50)) f4 &= ~(RF4_BR_NEXU);
- if (int_outof(r_ptr, 50)) f6 &= ~(RF6_TELE_LEVEL);
+ if (int_outof(r_ptr, 50)) spells &= ~SF_BR_NEXU;
+ if (int_outof(r_ptr, 50)) spells &= ~SF_TELE_LEVEL;
}
if (smart & (SM_RES_SOUND))
{
- if (int_outof(r_ptr, 50)) f4 &= ~(RF4_BR_SOUN);
+ if (int_outof(r_ptr, 50)) spells &= ~SF_BR_SOUN;
}
if (smart & (SM_RES_SHARD))
{
- if (int_outof(r_ptr, 50)) f4 &= ~(RF4_BR_SHAR);
- if (int_outof(r_ptr, 20)) f4 &= ~(RF4_ROCKET);
+ if (int_outof(r_ptr, 50)) spells &= ~SF_BR_SHAR;
+ if (int_outof(r_ptr, 20)) spells &= ~SF_ROCKET;
}
if (smart & (SM_IMM_REFLECT))
{
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_BO_COLD);
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_BO_FIRE);
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_BO_ACID);
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_BO_ELEC);
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_BO_POIS);
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_BO_NETH);
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_BO_WATE);
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_BO_MANA);
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_BO_PLAS);
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_BO_ICEE);
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_MISSILE);
- if (int_outof(r_ptr, 100)) f4 &= ~(RF4_ARROW_1);
- if (int_outof(r_ptr, 100)) f4 &= ~(RF4_ARROW_2);
- if (int_outof(r_ptr, 100)) f4 &= ~(RF4_ARROW_3);
- if (int_outof(r_ptr, 100)) f4 &= ~(RF4_ARROW_4);
+ if (int_outof(r_ptr, 100)) spells &= ~SF_BO_COLD;
+ if (int_outof(r_ptr, 100)) spells &= ~SF_BO_FIRE;
+ if (int_outof(r_ptr, 100)) spells &= ~SF_BO_ACID;
+ if (int_outof(r_ptr, 100)) spells &= ~SF_BO_ELEC;
+ if (int_outof(r_ptr, 100)) spells &= ~SF_BO_POIS;
+ if (int_outof(r_ptr, 100)) spells &= ~SF_BO_NETH;
+ if (int_outof(r_ptr, 100)) spells &= ~SF_BO_WATE;
+ if (int_outof(r_ptr, 100)) spells &= ~SF_BO_MANA;
+ if (int_outof(r_ptr, 100)) spells &= ~SF_BO_PLAS;
+ if (int_outof(r_ptr, 100)) spells &= ~SF_BO_ICEE;
+ if (int_outof(r_ptr, 100)) spells &= ~SF_MISSILE;
+ if (int_outof(r_ptr, 100)) spells &= ~(SF_ARROW_1);
+ if (int_outof(r_ptr, 100)) spells &= ~(SF_ARROW_2);
+ if (int_outof(r_ptr, 100)) spells &= ~(SF_ARROW_3);
+ if (int_outof(r_ptr, 100)) spells &= ~(SF_ARROW_4);
}
if (smart & (SM_IMM_FREE))
{
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_HOLD);
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_SLOW);
+ if (int_outof(r_ptr, 100)) spells &= ~SF_HOLD;
+ if (int_outof(r_ptr, 100)) spells &= ~SF_SLOW;
}
if (smart & (SM_IMM_MANA))
{
- if (int_outof(r_ptr, 100)) f5 &= ~(RF5_DRAIN_MANA);
+ if (int_outof(r_ptr, 100)) spells &= ~SF_DRAIN_MANA;
}
/* XXX XXX XXX No spells left? */
/* if (!f4 && !f5 && !f6) ... */
- (*f4p) = f4;
- (*f5p) = f5;
- (*f6p) = f6;
+ *spells_p = spells;
}
@@ -635,122 +627,75 @@ static void bolt(int m_idx, int typ, int dam_hp)
int flg = PROJECT_STOP | PROJECT_KILL;
/* Target the player with a bolt attack */
- (void)project(m_idx, 0, p_ptr->py, p_ptr->px, dam_hp, typ, flg);
-}
-
-
-/*
- * Return TRUE if a spell is good for hurting the player (directly).
- */
-static bool_ spell_attack(byte spell)
-{
- /* All RF4 spells hurt (except for shriek, multiply, summon animal) */
- if (spell >= 96 + 3 && spell <= 96 + 31) return (TRUE);
-
- /* Various "ball" spells */
- if (spell >= 128 && spell <= 128 + 8) return (TRUE);
-
- /* "Cause wounds" and "bolt" spells */
- if (spell >= 128 + 12 && spell <= 128 + 26) return (TRUE);
-
- /* Hand of Doom */
- if (spell == 160 + 1) return (TRUE);
-
- /* Doesn't hurt */
- return (FALSE);
+ project(m_idx, 0, p_ptr->py, p_ptr->px, dam_hp, typ, flg);
}
/*
- * Return TRUE if a spell is good for escaping.
+ * Calculate the mask for "bolt" spells
*/
-static bool_ spell_escape(byte spell)
+static monster_spell_flag_set compute_bolt_mask()
{
- /* Blink or Teleport */
- if (spell == 160 + 4 || spell == 160 + 5) return (TRUE);
-
- /* Teleport the player away */
- if (spell == 160 + 7 || spell == 160 + 8) return (TRUE);
-
- /* Isn't good for escaping */
- return (FALSE);
-}
-
-/*
- * Return TRUE if a spell is good for annoying the player.
- */
-static bool_ spell_annoy(byte spell)
-{
- /* Shriek */
- if (spell == 96 + 0) return (TRUE);
-
- /* Brain smash, et al (added curses) */
- if (spell >= 128 + 9 && spell <= 128 + 14) return (TRUE);
-
- /* Scare, confuse, blind, slow, paralyze */
- if (spell >= 128 + 27 && spell <= 128 + 31) return (TRUE);
-
- /* Teleport to */
- if (spell == 160 + 6) return (TRUE);
-
- /* Darkness, make traps, cause amnesia */
- if (spell >= 160 + 9 && spell <= 160 + 11) return (TRUE);
-
- /* Doesn't annoy */
- return (FALSE);
-}
-
-/*
- * Return TRUE if a spell summons help.
- */
-static bool_ spell_summon(byte spell)
-{
- /* RF4_S_ANIMAL, RF6_S_ANIMALS */
- if (spell == 96 + 2 || spell == 160 + 3) return (TRUE);
- /* All other summon spells */
- if (spell >= 160 + 13 && spell <= 160 + 31) return (TRUE);
-
- /* Doesn't summon */
- return (FALSE);
+ monster_spell_flag_set flags;
+ for (auto const &monster_spell: monster_spells())
+ {
+ if (monster_spell->is_bolt)
+ {
+ flags |= monster_spell->flag_set;
+ }
+ }
+ return flags;
}
/*
- * Return TRUE if a spell is good in a tactical situation.
+ * Calculate mask for summoning spells
*/
-static bool_ spell_tactic(byte spell)
+static monster_spell_flag_set compute_summoning_mask()
{
- /* Blink */
- if (spell == 160 + 4) return (TRUE);
-
- /* Not good */
- return (FALSE);
+ monster_spell_flag_set flags;
+ for (auto const &monster_spell: monster_spells())
+ {
+ if (monster_spell->is_summon)
+ {
+ flags |= monster_spell->flag_set;
+ }
+ }
+ return flags;
}
/*
- * Return TRUE if a spell hastes.
+ * Calculate mask for spells requiring SMART flag
*/
-static bool_ spell_haste(byte spell)
+static monster_spell_flag_set compute_smart_mask()
{
- /* Haste self */
- if (spell == 160 + 0) return (TRUE);
-
- /* Not a haste spell */
- return (FALSE);
+ monster_spell_flag_set flags;
+ for (auto const &monster_spell: monster_spells())
+ {
+ if (monster_spell->is_smart)
+ {
+ flags |= monster_spell->flag_set;
+ }
+ }
+ return flags;
}
/*
- * Return TRUE if a spell is good for healing.
+ * Calculate mask for spells requiring SMART flag
*/
-static bool_ spell_heal(byte spell)
+static monster_spell_flag_set compute_innate_mask()
{
- /* Heal */
- if (spell == 160 + 2) return (TRUE);
-
- /* No healing */
- return (FALSE);
+ monster_spell_flag_set flags;
+ for (auto const &monster_spell: monster_spells())
+ {
+ if (monster_spell->is_innate)
+ {
+ flags |= monster_spell->flag_set;
+ }
+ }
+ return flags;
}
@@ -768,51 +713,71 @@ static bool_ spell_heal(byte spell)
*
* This function may well be an efficiency bottleneck.
*/
-static int choose_attack_spell(int m_idx, byte spells[], byte num)
+static monster_spell const *choose_attack_spell(int m_idx, std::vector<monster_spell const *> const &spells)
{
monster_type *m_ptr = &m_list[m_idx];
- monster_race *r_ptr = race_inf(m_ptr);
-
- byte escape[96], escape_num = 0;
- byte attack[96], attack_num = 0;
- byte summon[96], summon_num = 0;
- byte tactic[96], tactic_num = 0;
- byte annoy[96], annoy_num = 0;
- byte haste[96], haste_num = 0;
- byte heal[96], heal_num = 0;
-
- int i;
/* Stupid monsters choose randomly */
- if (r_ptr->flags2 & (RF2_STUPID))
+ auto const r_ptr = m_ptr->race();
+ if (r_ptr->flags & RF_STUPID)
{
/* Pick at random */
- return (spells[rand_int(num)]);
+ return spells[rand_int(spells.size())];
}
+ /* Spells by category */
+ std::vector<monster_spell const *> escape; escape.reserve(spells.size());
+ std::vector<monster_spell const *> attack; attack.reserve(spells.size());
+ std::vector<monster_spell const *> summon; summon.reserve(spells.size());
+ std::vector<monster_spell const *> tactic; tactic.reserve(spells.size());
+ std::vector<monster_spell const *> annoy ; annoy.reserve(spells.size());
+ std::vector<monster_spell const *> haste ; haste.reserve(spells.size());
+ std::vector<monster_spell const *> heal ; heal.reserve(spells.size());
+
/* Categorize spells */
- for (i = 0; i < num; i++)
+ for (std::size_t i = 0; i < spells.size(); i++)
{
/* Escape spell? */
- if (spell_escape(spells[i])) escape[escape_num++] = spells[i];
+ if (spells[i]->is_escape)
+ {
+ escape.push_back(spells[i]);
+ }
/* Attack spell? */
- if (spell_attack(spells[i])) attack[attack_num++] = spells[i];
+ if (spells[i]->is_damage)
+ {
+ attack.push_back(spells[i]);
+ }
/* Summon spell? */
- if (spell_summon(spells[i])) summon[summon_num++] = spells[i];
+ if (spells[i]->is_summon)
+ {
+ summon.push_back(spells[i]);
+ }
/* Tactical spell? */
- if (spell_tactic(spells[i])) tactic[tactic_num++] = spells[i];
+ if (spells[i]->is_tactic)
+ {
+ tactic.push_back(spells[i]);
+ }
/* Annoyance spell? */
- if (spell_annoy(spells[i])) annoy[annoy_num++] = spells[i];
+ if (spells[i]->is_annoy)
+ {
+ annoy.push_back(spells[i]);
+ }
/* Haste spell? */
- if (spell_haste(spells[i])) haste[haste_num++] = spells[i];
+ if (spells[i]->is_haste)
+ {
+ haste.push_back(spells[i]);
+ }
/* Heal spell? */
- if (spell_heal(spells[i])) heal[heal_num++] = spells[i];
+ if (spells[i]->is_heal)
+ {
+ heal.push_back(spells[i]);
+ }
}
/*** Try to pick an appropriate spell type ***/
@@ -820,68 +785,59 @@ static int choose_attack_spell(int m_idx, byte spells[], byte num)
/* Hurt badly or afraid, attempt to flee */
if ((m_ptr->hp < m_ptr->maxhp / 3) || m_ptr->monfear)
{
- /* Choose escape spell if possible */
- if (escape_num) return (escape[rand_int(escape_num)]);
+ if (!escape.empty()) return escape[rand_int(escape.size())];
}
/* Still hurt badly, couldn't flee, attempt to heal */
if (m_ptr->hp < m_ptr->maxhp / 3)
{
- /* Choose heal spell if possible */
- if (heal_num) return (heal[rand_int(heal_num)]);
+ if (!heal.empty()) return heal[rand_int(heal.size())];
}
/* Player is close and we have attack spells, blink away */
- if ((distance(p_ptr->py, p_ptr->px, m_ptr->fy, m_ptr->fx) < 4) && attack_num && (rand_int(100) < 75))
+ if ((distance(p_ptr->py, p_ptr->px, m_ptr->fy, m_ptr->fx) < 4) && !attack.empty() && (rand_int(100) < 75))
{
- /* Choose tactical spell */
- if (tactic_num) return (tactic[rand_int(tactic_num)]);
+ if (!tactic.empty()) return tactic[rand_int(tactic.size())];
}
/* We're hurt (not badly), try to heal */
if ((m_ptr->hp < m_ptr->maxhp * 3 / 4) && (rand_int(100) < 75))
{
- /* Choose heal spell if possible */
- if (heal_num) return (heal[rand_int(heal_num)]);
+ if (!heal.empty()) return heal[rand_int(heal.size())];
}
/* Summon if possible (sometimes) */
- if (summon_num && (rand_int(100) < 50))
+ if (!summon.empty() && (rand_int(100) < 50))
{
- /* Choose summon spell */
- return (summon[rand_int(summon_num)]);
+ return summon[rand_int(summon.size())];
}
/* Attack spell (most of the time) */
- if (attack_num && (rand_int(100) < 85))
+ if (!attack.empty() && (rand_int(100) < 85))
{
- /* Choose attack spell */
- return (attack[rand_int(attack_num)]);
+ return attack[rand_int(attack.size())];
}
/* Try another tactical spell (sometimes) */
- if (tactic_num && (rand_int(100) < 50))
+ if (!tactic.empty() && (rand_int(100) < 50))
{
- /* Choose tactic spell */
- return (tactic[rand_int(tactic_num)]);
+ return tactic[rand_int(tactic.size())];
}
/* Haste self if we aren't already somewhat hasted (rarely) */
- if (haste_num && (rand_int(100) < (20 + m_ptr->speed - m_ptr->mspeed)))
+ if (!haste.empty() && (rand_int(100) < (20 + m_ptr->speed - m_ptr->mspeed)))
{
- /* Choose haste spell */
- return (haste[rand_int(haste_num)]);
+ return haste[rand_int(haste.size())];
}
/* Annoy player (most of the time) */
- if (annoy_num && (rand_int(100) < 85))
+ if (!annoy.empty() && (rand_int(100) < 85))
{
- /* Choose annoyance spell */
- return (annoy[rand_int(annoy_num)]);
+ return annoy[rand_int(annoy.size())];
}
/* Choose no spell */
- return (0);
+ return nullptr;
}
@@ -895,13 +851,13 @@ static void breath(int m_idx, int typ, int dam_hp, int rad)
int flg = PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL;
monster_type *m_ptr = &m_list[m_idx];
- monster_race *r_ptr = race_inf(m_ptr);
+ auto const r_ptr = m_ptr->race();
/* Determine the radius of the blast */
- if (rad < 1) rad = (r_ptr->flags2 & (RF2_POWERFUL)) ? 3 : 2;
+ if (rad < 1) rad = (r_ptr->flags & RF_POWERFUL) ? 3 : 2;
/* Target the player with a ball attack */
- (void)project(m_idx, rad, p_ptr->py, p_ptr->px, dam_hp, typ, flg);
+ project(m_idx, rad, p_ptr->py, p_ptr->px, dam_hp, typ, flg);
}
@@ -915,12 +871,12 @@ static void monst_breath_monst(int m_idx, int y, int x, int typ, int dam_hp, int
int flg = PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL;
monster_type *m_ptr = &m_list[m_idx];
- monster_race *r_ptr = race_inf(m_ptr);
+ auto const r_ptr = m_ptr->race();
/* Determine the radius of the blast */
- if (rad < 1) rad = (r_ptr->flags2 & (RF2_POWERFUL)) ? 3 : 2;
+ if (rad < 1) rad = (r_ptr->flags & RF_POWERFUL) ? 3 : 2;
- (void)project(m_idx, rad, y, x, dam_hp, typ, flg);
+ project(m_idx, rad, y, x, dam_hp, typ, flg);
}
@@ -933,11 +889,11 @@ static void monst_bolt_monst(int m_idx, int y, int x, int typ, int dam_hp)
{
int flg = PROJECT_STOP | PROJECT_KILL;
- (void)project(m_idx, 0, y, x, dam_hp, typ, flg);
+ project(m_idx, 0, y, x, dam_hp, typ, flg);
}
-void monster_msg(cptr fmt, ...)
+static void monster_msg(cptr fmt, ...)
{
va_list vp;
@@ -947,46 +903,49 @@ void monster_msg(cptr fmt, ...)
va_start(vp, fmt);
/* Format the args, save the length */
- (void)vstrnfmt(buf, 1024, fmt, vp);
+ vstrnfmt(buf, 1024, fmt, vp);
/* End the Varargs Stuff */
va_end(vp);
+ /* Print */
+ monster_msg_simple(buf);
+}
+
+void monster_msg_simple(cptr s)
+{
+ auto &messages = game->messages;
+
/* Display */
- if (disturb_other)
- msg_print(buf);
+ if (options->disturb_other)
+ {
+ msg_print(s);
+ }
else
{
- message_add(MESSAGE_MSG, buf, TERM_WHITE);
+ messages.add(s, TERM_WHITE);
p_ptr->window |= PW_MESSAGE;
}
}
-void cmonster_msg(char a, cptr fmt, ...)
+/**
+ * Extract list of spell indexes from a flag set.
+ */
+static std::vector<monster_spell const *> extract_spells(monster_spell_flag_set const &spell_flag_set)
{
- va_list vp;
-
- char buf[1024];
-
- /* Begin the Varargs Stuff */
- va_start(vp, fmt);
-
- /* Format the args, save the length */
- (void)vstrnfmt(buf, 1024, fmt, vp);
-
- /* End the Varargs Stuff */
- va_end(vp);
+ auto result = std::vector<monster_spell const *>();
+ result.reserve(spell_flag_set.nbits);
- /* Display */
- if (disturb_other)
- cmsg_print(a, buf);
- else
+ for (auto const &monster_spell: monster_spells())
{
- message_add(MESSAGE_MSG, buf, a);
- p_ptr->window |= PW_MESSAGE;
+ if (bool(spell_flag_set & monster_spell->flag_set))
+ {
+ result.push_back(monster_spell);
+ }
}
-}
+ return result;
+}
/*
* Monster tries to 'cast a spell' (or breath, etc)
@@ -995,19 +954,13 @@ void cmonster_msg(char a, cptr fmt, ...)
int monst_spell_monst_spell = -1;
static bool_ monst_spell_monst(int m_idx)
{
+ static const monster_spell_flag_set SF_INT_MASK = compute_smart_mask();
+
int y = 0, x = 0;
- int i = 1, k, t_idx;
- int chance, thrown_spell, count = 0;
- byte spell[96], num = 0;
char m_name[80], t_name[80];
char m_poss[80];
char ddesc[80];
- int rlev; /* monster level */
monster_type *m_ptr = &m_list[m_idx]; /* Attacker */
- monster_race *r_ptr = race_inf(m_ptr);
- monster_type *t_ptr; /* Putative target */
- monster_race *tr_ptr;
- u32b f4, f5, f6; /* racial spell flags */
bool_ direct = TRUE;
bool_ wake_up = FALSE;
@@ -1030,29 +983,25 @@ static bool_ monst_spell_monst(int m_idx)
if (m_ptr->confused) return (FALSE);
/* Hack -- Extract the spell probability */
- chance = (r_ptr->freq_inate + r_ptr->freq_spell) / 2;
+ const auto r_ptr = m_ptr->race();
+ const int chance = (r_ptr->freq_inate + r_ptr->freq_spell) / 2;
/* Not allowed to cast spells */
if ((!chance) && (monst_spell_monst_spell == -1)) return (FALSE);
if ((rand_int(100) >= chance) && (monst_spell_monst_spell == -1)) return (FALSE);
- /* Target location */
- if (m_ptr->target > -1)
+ /* Make sure monster actually has a target */
+ if (m_ptr->target <= 0)
{
- if (m_ptr->target > 0)
- {
- i = m_ptr->target;
- }
- else return FALSE;
+ return FALSE;
}
- else return FALSE;
-
{
- t_idx = i;
- t_ptr = &m_list[t_idx];
- tr_ptr = race_inf(t_ptr);
+ int t_idx = m_ptr->target;
+
+ monster_type *t_ptr = &m_list[t_idx];
+ auto const tr_ptr = t_ptr->race();
/* Hack -- no fighting >100 squares from player */
if (t_ptr->cdis > MAX_RANGE) return FALSE;
@@ -1065,47 +1014,28 @@ static bool_ monst_spell_monst(int m_idx)
x = t_ptr->fx;
/* Extract the monster level */
- rlev = ((m_ptr->level >= 1) ? m_ptr->level : 1);
+ const int rlev = ((m_ptr->level >= 1) ? m_ptr->level : 1);
- /* Extract the racial spell flags */
- f4 = r_ptr->flags4;
- f5 = r_ptr->flags5;
- f6 = r_ptr->flags6;
+ /* Which spells are allowed? */
+ monster_spell_flag_set allowed_spells = r_ptr->spells;
/* Hack -- allow "desperate" spells */
- if ((r_ptr->flags2 & (RF2_SMART)) &&
+ if ((r_ptr->flags & RF_SMART) &&
(m_ptr->hp < m_ptr->maxhp / 10) &&
(rand_int(100) < 50))
{
/* Require intelligent spells */
- f4 &= (RF4_INT_MASK);
- f5 &= (RF5_INT_MASK);
- f6 &= (RF6_INT_MASK);
-
- /* No spells left */
- if ((!f4 && !f5 && !f6) && (monst_spell_monst_spell == -1)) return (FALSE);
- }
-
- /* Extract the "inate" spells */
- for (k = 0; k < 32; k++)
- {
- if (f4 & (1L << k)) spell[num++] = k + 32 * 3;
- }
+ allowed_spells &= SF_INT_MASK;
- /* Extract the "normal" spells */
- for (k = 0; k < 32; k++)
- {
- if (f5 & (1L << k)) spell[num++] = k + 32 * 4;
+ /* No spells left? */
+ if ((!allowed_spells) && (monst_spell_monst_spell == -1)) return (FALSE);
}
- /* Extract the "bizarre" spells */
- for (k = 0; k < 32; k++)
- {
- if (f6 & (1L << k)) spell[num++] = k + 32 * 5;
- }
+ /* Extract spells */
+ auto spell = extract_spells(allowed_spells);
- /* No spells left */
- if (!num) return (FALSE);
+ /* No spells left? */
+ if (spell.empty()) return (FALSE);
/* Stop if player is dead or gone */
if (!alive || death) return (FALSE);
@@ -1126,12 +1056,12 @@ static bool_ monst_spell_monst(int m_idx)
monster_desc(ddesc, m_ptr, 0x88);
/* Choose a spell to cast */
- thrown_spell = spell[rand_int(num)];
+ auto thrown_spell = spell[rand_int(spell.size())];
/* Force a spell ? */
if (monst_spell_monst_spell > -1)
{
- thrown_spell = monst_spell_monst_spell;
+ thrown_spell = spell[monst_spell_monst_spell];
monst_spell_monst_spell = -1;
}
@@ -1140,46 +1070,115 @@ static bool_ monst_spell_monst(int m_idx)
see_either = (see_m || see_t);
see_both = (see_m && see_t);
- switch (thrown_spell)
+ /* Do a breath */
+ auto do_breath = [&](char const *element, int gf, s32b max, int divisor) -> void {
+ // Interrupt
+ disturb_on_other();
+ // Message
+ if (!see_either)
+ {
+ monster_msg("You hear breathing noise.");
+ }
+ else if (blind)
+ {
+ monster_msg("%^s breathes.", m_name);
+ }
+ else
+ {
+ monster_msg("%^s breathes %s at %s.", m_name, element, t_name);
+ }
+ // Breathe
+ monst_breath_monst(m_idx, y, x, gf, std::min(max, m_ptr->hp / divisor), 0);
+ };
+
+ /* Messages for summoning */
+ struct summon_messages {
+ char const *singular;
+ char const *plural;
+ };
+
+ /* Default message for summoning when player is blinded */
+ auto blind_msg_default = summon_messages {
+ "You hear something appear nearby.",
+ "You hear many things appear nearby."
+ };
+
+ /* Do a summoning spell */
+ auto do_summon = [&](char const *action, int n, int friendly_type, int hostile_type, summon_messages const &blind_msg) -> void {
+ // Interrupt
+ disturb_on_other();
+
+ // Message
+ if (blind || !see_m)
+ {
+ monster_msg("%^s mumbles.", m_name);
+ }
+ else
+ {
+ monster_msg("%^s magically %s", m_name, action);
+ }
+
+ // Do the actual summoning
+ int count = 0;
+ for (int k = 0; k < n; k++)
+ {
+ if (friendly)
+ {
+ count += summon_specific_friendly(m_ptr->fy, m_ptr->fx, rlev, friendly_type, TRUE);
+ }
+ else if (!friendly)
+ {
+ count += summon_specific(m_ptr->fy, m_ptr->fx, rlev, hostile_type);
+ }
+ }
+ // Message for blinded characters
+ if (blind)
+ {
+ if (count == 1)
+ {
+ monster_msg(blind_msg.singular);
+ }
+ else if (count > 1)
+ {
+ monster_msg(blind_msg.plural);
+ }
+ }
+ };
+
+ /* There's no summoning friendly uniques or Nazgul */
+ auto spell_idx = thrown_spell->spell_idx;
+
+ if (friendly)
+ {
+ if ((thrown_spell->spell_idx == SF_S_UNIQUE_IDX) &&
+ (thrown_spell->spell_idx == SF_S_WRAITH_IDX))
+ {
+ // Summon high undead instead
+ spell_idx = SF_S_HI_UNDEAD_IDX;
+ }
+ }
+
+ /* Spell effect */
+ switch (spell_idx)
{
- /* RF4_SHRIEK */
- case 96 + 0:
+ case SF_SHRIEK_IDX:
{
if (!direct) break;
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
if (!see_m) monster_msg("You hear a shriek.");
else monster_msg("%^s shrieks at %s.", m_name, t_name);
wake_up = TRUE;
break;
}
- /* RF4_MULTIPLY */
- case 96 + 1:
- {
- break;
- }
-
- /* RF4_S_ANIMAL */
- case 96 + 2:
+ case SF_MULTIPLY_IDX:
{
- if (disturb_other) disturb(1, 0);
- 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++)
- {
- if (friendly)
- count += summon_specific_friendly(y, x, rlev, SUMMON_ANIMAL, TRUE);
- else
- count += summon_specific(y, x, rlev, SUMMON_ANIMAL);
- }
- if (blind && count) monster_msg("You hear something appear nearby.");
break;
}
- /* RF4_ROCKET */
- case 96 + 3:
+ case SF_ROCKET_IDX:
{
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
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);
@@ -1188,371 +1187,204 @@ static bool_ monst_spell_monst(int m_idx)
break;
}
- /* RF4_ARROW_1 */
- case 96 + 4:
+ case SF_ARROW_1_IDX:
{
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
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);
- sound(SOUND_SHOOT);
monst_bolt_monst(m_idx, y, x, GF_ARROW, damroll(1, 6));
break;
}
- /* RF4_ARROW_2 */
- case 96 + 5:
+ case SF_ARROW_2_IDX:
{
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
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);
- sound(SOUND_SHOOT);
monst_bolt_monst(m_idx, y, x, GF_ARROW, damroll(3, 6));
break;
}
- /* RF4_ARROW_3 */
- case 96 + 6:
+ case SF_ARROW_3_IDX:
{
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
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 a missile at %s.", m_name, t_name);
- sound(SOUND_SHOOT);
monst_bolt_monst(m_idx, y, x, GF_ARROW, damroll(5, 6));
break;
}
- /* RF4_ARROW_4 */
- case 96 + 7:
+ case SF_ARROW_4_IDX:
{
if (!see_either) monster_msg("You hear a strange noise.");
- else if (disturb_other) disturb(1, 0);
+ else disturb_on_other();
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);
monst_bolt_monst(m_idx, y, x, GF_ARROW, damroll(7, 6));
break;
}
- /* RF4_BR_ACID */
- case 96 + 8:
+ case SF_BR_ACID_IDX:
{
- if (disturb_other) disturb(1, 0);
- 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);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_ACID,
- ((m_ptr->hp / 3) > 1600 ? 1600 : (m_ptr->hp / 3)), 0);
+ do_breath("acid", GF_ACID, 1600, 3);
break;
}
- /* RF4_BR_ELEC */
- case 96 + 9:
+ case SF_BR_ELEC_IDX:
{
- if (disturb_other) disturb(1, 0);
- 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);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_ELEC,
- ((m_ptr->hp / 3) > 1600 ? 1600 : (m_ptr->hp / 3)), 0);
+ do_breath("lightning", GF_ELEC, 1600, 3);
break;
}
- /* RF4_BR_FIRE */
- case 96 + 10:
+ case SF_BR_FIRE_IDX:
{
- if (disturb_other) disturb(1, 0);
- 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);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_FIRE,
- ((m_ptr->hp / 3) > 1600 ? 1600 : (m_ptr->hp / 3)), 0);
+ do_breath("fire", GF_FIRE, 1600, 3);
break;
}
- /* RF4_BR_COLD */
- case 96 + 11:
+ case SF_BR_COLD_IDX:
{
- if (disturb_other) disturb(1, 0);
- 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);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_COLD,
- ((m_ptr->hp / 3) > 1600 ? 1600 : (m_ptr->hp / 3)), 0);
+ do_breath("frost", GF_COLD, 1600, 3);
break;
}
- /* RF4_BR_POIS */
- case 96 + 12:
+ case SF_BR_POIS_IDX:
{
- if (disturb_other) disturb(1, 0);
- 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);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_POIS,
- ((m_ptr->hp / 3) > 800 ? 800 : (m_ptr->hp / 3)), 0);
+ do_breath("gas", GF_POIS, 800, 3);
break;
}
- /* RF4_BR_NETH */
- case 96 + 13:
+ case SF_BR_NETH_IDX:
{
- if (disturb_other) disturb(1, 0);
- 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);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_NETHER,
- ((m_ptr->hp / 6) > 550 ? 550 : (m_ptr->hp / 6)), 0);
+ do_breath("nether", GF_NETHER, 550, 6);
break;
}
- /* RF4_BR_LITE */
- case 96 + 14:
+ case SF_BR_LITE_IDX:
{
- if (disturb_other) disturb(1, 0);
- 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);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_LITE,
- ((m_ptr->hp / 6) > 400 ? 400 : (m_ptr->hp / 6)), 0);
+ do_breath("light", GF_LITE, 400, 6);
break;
}
- /* RF4_BR_DARK */
- case 96 + 15:
+ case SF_BR_DARK_IDX:
{
- if (disturb_other) disturb(1, 0);
- 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);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_DARK,
- ((m_ptr->hp / 6) > 400 ? 400 : (m_ptr->hp / 6)), 0);
+ do_breath("darkness", GF_DARK, 400, 6);
break;
}
- /* RF4_BR_CONF */
- case 96 + 16:
+ case SF_BR_CONF_IDX:
{
- if (disturb_other) disturb(1, 0);
- 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);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_CONFUSION,
- ((m_ptr->hp / 6) > 400 ? 400 : (m_ptr->hp / 6)), 0);
+ do_breath("confusion", GF_CONFUSION, 400, 6);
break;
}
- /* RF4_BR_SOUN */
- case 96 + 17:
+ case SF_BR_SOUN_IDX:
{
- if (disturb_other) disturb(1, 0);
- 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);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_SOUND,
- ((m_ptr->hp / 6) > 400 ? 400 : (m_ptr->hp / 6)), 0);
+ do_breath("sound", GF_SOUND, 400, 6);
break;
}
- /* RF4_BR_CHAO */
- case 96 + 18:
+ case SF_BR_CHAO_IDX:
{
- if (disturb_other) disturb(1, 0);
- 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);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_CHAOS,
- ((m_ptr->hp / 6) > 600 ? 600 : (m_ptr->hp / 6)), 0);
+ do_breath("chaos", GF_CHAOS, 600, 6);
break;
}
- /* RF4_BR_DISE */
- case 96 + 19:
+ case SF_BR_DISE_IDX:
{
- if (disturb_other) disturb(1, 0);
- 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);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_DISENCHANT,
- ((m_ptr->hp / 6) > 500 ? 500 : (m_ptr->hp / 6)), 0);
+ do_breath("disenchantment", GF_DISENCHANT, 500, 6);
break;
}
- /* RF4_BR_NEXU */
- case 96 + 20:
+ case SF_BR_NEXU_IDX:
{
- if (disturb_other) disturb(1, 0);
- 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);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_NEXUS,
- ((m_ptr->hp / 3) > 250 ? 250 : (m_ptr->hp / 3)), 0);
+ do_breath("nexus", GF_NEXUS, 250, 3);
break;
}
- /* RF4_BR_TIME */
- case 96 + 21:
+ case SF_BR_TIME_IDX:
{
- if (disturb_other) disturb(1, 0);
- 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);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_TIME,
- ((m_ptr->hp / 3) > 150 ? 150 : (m_ptr->hp / 3)), 0);
+ do_breath("time", GF_TIME, 150, 3);
break;
}
- /* RF4_BR_INER */
- case 96 + 22:
+ case SF_BR_INER_IDX:
{
- if (disturb_other) disturb(1, 0);
- 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);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_INERTIA,
- ((m_ptr->hp / 6) > 200 ? 200 : (m_ptr->hp / 6)), 0);
+ do_breath("inertia", GF_INERTIA, 200, 6);
break;
}
- /* RF4_BR_GRAV */
- case 96 + 23:
+ case SF_BR_GRAV_IDX:
{
- if (disturb_other) disturb(1, 0);
- 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);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_GRAVITY,
- ((m_ptr->hp / 3) > 200 ? 200 : (m_ptr->hp / 3)), 0);
+ do_breath("gravity", GF_GRAVITY, 200, 3);
break;
}
- /* RF4_BR_SHAR */
- case 96 + 24:
+ case SF_BR_SHAR_IDX:
{
- if (disturb_other) disturb(1, 0);
- 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);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_SHARDS,
- ((m_ptr->hp / 6) > 400 ? 400 : (m_ptr->hp / 6)), 0);
+ do_breath("shards", GF_SHARDS, 400, 6);
break;
}
- /* RF4_BR_PLAS */
- case 96 + 25:
+ case SF_BR_PLAS_IDX:
{
- if (disturb_other) disturb(1, 0);
- 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);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_PLASMA,
- ((m_ptr->hp / 6) > 150 ? 150 : (m_ptr->hp / 6)), 0);
+ do_breath("plasma", GF_PLASMA, 150, 6);
break;
}
- /* RF4_BR_WALL */
- case 96 + 26:
+ case SF_BR_WALL_IDX:
{
- if (disturb_other) disturb(1, 0);
- 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);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_FORCE,
- ((m_ptr->hp / 6) > 200 ? 200 : (m_ptr->hp / 6)), 0);
+ do_breath("force", GF_FORCE, 200, 6);
break;
}
- /* RF4_BR_MANA */
- case 96 + 27:
+ case SF_BR_MANA_IDX:
{
- if (disturb_other) disturb(1, 0);
- 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);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_MANA,
- ((m_ptr->hp / 3) > 250 ? 250 : (m_ptr->hp / 3)), 0);
+ do_breath("magical energy", GF_MANA, 250, 3);
break;
}
- /* RF4_BA_NUKE */
- case 96 + 28:
+ case SF_BA_NUKE_IDX:
{
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
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);
- sound(SOUND_BREATH);
monst_breath_monst(m_idx, y, x, GF_NUKE,
(rlev + damroll(10, 6)), 2);
break;
}
- /* RF4_BR_NUKE */
- case 96 + 29:
+ case SF_BR_NUKE_IDX:
{
- if (disturb_other) disturb(1, 0);
- 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);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_NUKE,
- ((m_ptr->hp / 3) > 800 ? 800 : (m_ptr->hp / 3)), 0);
+ do_breath("toxic waste", GF_NUKE, 800, 3);
break;
}
- /* RF4_BA_CHAO */
- case 96 + 30:
+ case SF_BA_CHAO_IDX:
{
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
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);
- sound(SOUND_BREATH);
monst_breath_monst(m_idx, y, x, GF_CHAOS,
(rlev * 2) + damroll(10, 10), 4);
break;
}
- /* RF4_BR_DISI -> Breathe Disintegration */
- case 96 + 31:
+ case SF_BR_DISI_IDX:
{
- if (disturb_other) disturb(1, 0);
- 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);
- sound(SOUND_BREATH);
- monst_breath_monst(m_idx, y, x, GF_DISINTEGRATE,
- ((m_ptr->hp / 3) > 300 ? 300 : (m_ptr->hp / 3)), 0);
+ do_breath("disintegration", GF_DISINTEGRATE, 300, 3);
break;
}
- /* RF5_BA_ACID */
- case 128 + 0:
+ case SF_BA_ACID_IDX:
{
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
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);
@@ -1560,10 +1392,9 @@ static bool_ monst_spell_monst(int m_idx)
break;
}
- /* RF5_BA_ELEC */
- case 128 + 1:
+ case SF_BA_ELEC_IDX:
{
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
if (!see_either) monster_msg ("You hear someone mumble.");
else
if (blind) monster_msg("%^s mumbles.", m_name);
@@ -1572,10 +1403,9 @@ static bool_ monst_spell_monst(int m_idx)
break;
}
- /* RF5_BA_FIRE */
- case 128 + 2:
+ case SF_BA_FIRE_IDX:
{
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
if (!see_either) monster_msg ("You hear someone mumble.");
else
if (blind) monster_msg("%^s mumbles.", m_name);
@@ -1584,10 +1414,9 @@ static bool_ monst_spell_monst(int m_idx)
break;
}
- /* RF5_BA_COLD */
- case 128 + 3:
+ case SF_BA_COLD_IDX:
{
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
if (!see_either) monster_msg ("You hear someone mumble.");
else
if (blind) monster_msg("%^s mumbles.", m_name);
@@ -1596,10 +1425,9 @@ static bool_ monst_spell_monst(int m_idx)
break;
}
- /* RF5_BA_POIS */
- case 128 + 4:
+ case SF_BA_POIS_IDX:
{
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
if (!see_either) monster_msg ("You hear someone mumble.");
else
if (blind) monster_msg("%^s mumbles.", m_name);
@@ -1608,10 +1436,9 @@ static bool_ monst_spell_monst(int m_idx)
break;
}
- /* RF5_BA_NETH */
- case 128 + 5:
+ case SF_BA_NETH_IDX:
{
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
if (!see_either) monster_msg ("You hear someone mumble.");
else
if (blind) monster_msg("%^s mumbles.", m_name);
@@ -1620,10 +1447,9 @@ static bool_ monst_spell_monst(int m_idx)
break;
}
- /* RF5_BA_WATE */
- case 128 + 6:
+ case SF_BA_WATE_IDX:
{
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
if (!see_either) monster_msg ("You hear someone mumble.");
else
if (blind) monster_msg("%^s mumbles.", m_name);
@@ -1633,10 +1459,9 @@ static bool_ monst_spell_monst(int m_idx)
break;
}
- /* RF5_BA_MANA */
- case 128 + 7:
+ case SF_BA_MANA_IDX:
{
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
if (!see_either) monster_msg ("You hear someone mumble powerfully.");
else
if (blind) monster_msg("%^s mumbles powerfully.", m_name);
@@ -1645,10 +1470,9 @@ static bool_ monst_spell_monst(int m_idx)
break;
}
- /* RF5_BA_DARK */
- case 128 + 8:
+ case SF_BA_DARK_IDX:
{
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
if (!see_either) monster_msg ("You hear someone mumble powerfully.");
else
if (blind) monster_msg("%^s mumbles powerfully.", m_name);
@@ -1657,8 +1481,7 @@ static bool_ monst_spell_monst(int m_idx)
break;
}
- /* RF5_DRAIN_MANA */
- case 128 + 9:
+ case SF_DRAIN_MANA_IDX:
{
/* Attack power */
int r1 = (randint(rlev) / 2) + 1;
@@ -1672,7 +1495,7 @@ static bool_ monst_spell_monst(int m_idx)
/* Heal the monster */
if (m_ptr->hp < m_ptr->maxhp)
{
- if (!(tr_ptr->flags4 || tr_ptr->flags5 || tr_ptr->flags6))
+ if (!tr_ptr->spells)
{
if (see_both)
monster_msg("%^s is unaffected!", t_name);
@@ -1684,7 +1507,7 @@ static bool_ monst_spell_monst(int m_idx)
if (m_ptr->hp > m_ptr->maxhp) m_ptr->hp = m_ptr->maxhp;
/* Redraw (later) if needed */
- if (health_who == m_idx) p_ptr->redraw |= (PR_HEALTH);
+ if (health_who == m_idx) p_ptr->redraw |= (PR_FRAME);
/* Special message */
if (seen)
@@ -1698,12 +1521,11 @@ static bool_ monst_spell_monst(int m_idx)
break;
}
- /* RF5_MIND_BLAST */
- case 128 + 10:
+ case SF_MIND_BLAST_IDX:
{
if (!direct) break;
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
if (!seen)
{
@@ -1715,16 +1537,10 @@ static bool_ monst_spell_monst(int m_idx)
}
/* Attempt a saving throw */
- if ((tr_ptr->flags1 & (RF1_UNIQUE)) ||
- (tr_ptr->flags3 & (RF3_NO_CONF)) ||
+ if ((tr_ptr->flags & RF_UNIQUE) ||
+ (tr_ptr->flags & RF_NO_CONF) ||
(t_ptr->level > randint((rlev - 10) < 1 ? 1 : (rlev - 10)) + 10))
{
- /* Memorize a flag */
- if (tr_ptr->flags3 & (RF3_NO_CONF))
- {
- if (seen) tr_ptr->r_flags3 |= (RF3_NO_CONF);
- }
-
/* No obvious effect */
if (see_t)
{
@@ -1744,11 +1560,10 @@ static bool_ monst_spell_monst(int m_idx)
break;
}
- /* RF5_BRAIN_SMASH */
- case 128 + 11:
+ case SF_BRAIN_SMASH_IDX:
{
if (!direct) break;
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
if (!seen)
{
/* */
@@ -1759,15 +1574,10 @@ static bool_ monst_spell_monst(int m_idx)
}
/* Attempt a saving throw */
- if ((tr_ptr->flags1 & (RF1_UNIQUE)) ||
- (tr_ptr->flags3 & (RF3_NO_CONF)) ||
+ if ((tr_ptr->flags & RF_UNIQUE) ||
+ (tr_ptr->flags & RF_NO_CONF) ||
(t_ptr->level > randint((rlev - 10) < 1 ? 1 : (rlev - 10)) + 10))
{
- /* Memorize a flag */
- if (tr_ptr->flags3 & (RF3_NO_CONF))
- {
- if (seen) tr_ptr->r_flags3 |= (RF3_NO_CONF);
- }
/* No obvious effect */
if (see_t)
{
@@ -1790,11 +1600,10 @@ static bool_ monst_spell_monst(int m_idx)
break;
}
- /* RF5_CAUSE_1 */
- case 128 + 12:
+ case SF_CAUSE_1_IDX:
{
if (!direct) break;
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
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)
@@ -1811,11 +1620,10 @@ static bool_ monst_spell_monst(int m_idx)
break;
}
- /* RF5_CAUSE_2 */
- case 128 + 13:
+ case SF_CAUSE_2_IDX:
{
if (!direct) break;
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
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)
@@ -1831,11 +1639,10 @@ static bool_ monst_spell_monst(int m_idx)
break;
}
- /* RF5_CAUSE_3 */
- case 128 + 14:
+ case SF_CAUSE_3_IDX:
{
if (!direct) break;
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
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)
@@ -1851,11 +1658,10 @@ static bool_ monst_spell_monst(int m_idx)
break;
}
- /* RF5_CAUSE_4 */
- case 128 + 15:
+ case SF_CAUSE_4_IDX:
{
if (!direct) break;
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
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)
@@ -1871,10 +1677,9 @@ static bool_ monst_spell_monst(int m_idx)
break;
}
- /* RF5_BO_ACID */
- case 128 + 16:
+ case SF_BO_ACID_IDX:
{
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
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,
@@ -1882,10 +1687,9 @@ static bool_ monst_spell_monst(int m_idx)
break;
}
- /* RF5_BO_ELEC */
- case 128 + 17:
+ case SF_BO_ELEC_IDX:
{
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
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,
@@ -1893,10 +1697,9 @@ static bool_ monst_spell_monst(int m_idx)
break;
}
- /* RF5_BO_FIRE */
- case 128 + 18:
+ case SF_BO_FIRE_IDX:
{
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
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,
@@ -1904,10 +1707,9 @@ static bool_ monst_spell_monst(int m_idx)
break;
}
- /* RF5_BO_COLD */
- case 128 + 19:
+ case SF_BO_COLD_IDX:
{
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
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,
@@ -1915,17 +1717,15 @@ static bool_ monst_spell_monst(int m_idx)
break;
}
- /* RF5_BO_POIS */
- case 128 + 20:
+ case SF_BO_POIS_IDX:
{
/* XXX XXX XXX */
break;
}
- /* RF5_BO_NETH */
- case 128 + 21:
+ case SF_BO_NETH_IDX:
{
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
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,
@@ -1933,10 +1733,9 @@ static bool_ monst_spell_monst(int m_idx)
break;
}
- /* RF5_BO_WATE */
- case 128 + 22:
+ case SF_BO_WATE_IDX:
{
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
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,
@@ -1944,10 +1743,9 @@ static bool_ monst_spell_monst(int m_idx)
break;
}
- /* RF5_BO_MANA */
- case 128 + 23:
+ case SF_BO_MANA_IDX:
{
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
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,
@@ -1955,10 +1753,9 @@ static bool_ monst_spell_monst(int m_idx)
break;
}
- /* RF5_BO_PLAS */
- case 128 + 24:
+ case SF_BO_PLAS_IDX:
{
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
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,
@@ -1966,10 +1763,9 @@ static bool_ monst_spell_monst(int m_idx)
break;
}
- /* RF5_BO_ICEE */
- case 128 + 25:
+ case SF_BO_ICEE_IDX:
{
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
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,
@@ -1977,10 +1773,9 @@ static bool_ monst_spell_monst(int m_idx)
break;
}
- /* RF5_MISSILE */
- case 128 + 26:
+ case SF_MISSILE_IDX:
{
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
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,
@@ -1988,14 +1783,13 @@ static bool_ monst_spell_monst(int m_idx)
break;
}
- /* RF5_SCARE */
- case 128 + 27:
+ case SF_SCARE_IDX:
{
if (!direct) break;
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
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)
+ if (tr_ptr->flags & RF_NO_FEAR)
{
if (see_t) monster_msg("%^s refuses to be frightened.", t_name);
}
@@ -2012,15 +1806,14 @@ static bool_ monst_spell_monst(int m_idx)
break;
}
- /* RF5_BLIND */
- case 128 + 28:
+ case SF_BLIND_IDX:
{
if (!direct) break;
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
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"));
- if (tr_ptr->flags3 & RF3_NO_CONF) /* Simulate blindness with confusion */
+ if (tr_ptr->flags & RF_NO_CONF) /* Simulate blindness with confusion */
{
if (see_t) monster_msg("%^s is unaffected.", t_name);
}
@@ -2038,14 +1831,13 @@ static bool_ monst_spell_monst(int m_idx)
}
- /* RF5_CONF */
- case 128 + 29:
+ case SF_CONF_IDX:
{
if (!direct) break;
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
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)
+ if (tr_ptr->flags & RF_NO_CONF)
{
if (see_t) monster_msg("%^s disbelieves the feeble spell.", t_name);
}
@@ -2062,14 +1854,13 @@ static bool_ monst_spell_monst(int m_idx)
break;
}
- /* RF5_SLOW */
- case 128 + 30:
+ case SF_SLOW_IDX:
{
if (!direct) break;
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
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)
+ if (tr_ptr->flags & RF_UNIQUE)
{
if (see_t) monster_msg("%^s is unaffected.", t_name);
}
@@ -2086,14 +1877,13 @@ static bool_ monst_spell_monst(int m_idx)
break;
}
- /* RF5_HOLD */
- case 128 + 31:
+ case SF_HOLD_IDX:
{
if (!direct) break;
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
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))
+ if ((tr_ptr->flags & RF_UNIQUE) ||
+ (tr_ptr->flags & RF_NO_STUN))
{
if (see_t) monster_msg("%^s is unaffected.", t_name);
}
@@ -2110,11 +1900,9 @@ static bool_ monst_spell_monst(int m_idx)
break;
}
-
- /* RF6_HASTE */
- case 160 + 0:
+ case SF_HASTE_IDX:
{
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
if (blind || !see_m)
{
monster_msg("%^s mumbles.", m_name);
@@ -2141,16 +1929,15 @@ static bool_ monst_spell_monst(int m_idx)
break;
}
- /* RF6_HAND_DOOM */
- case 160 + 1:
+ case SF_HAND_DOOM_IDX:
{
if (!direct) break;
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
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
monster_msg ("You hear someone invoke the Hand of Doom!");
- if (tr_ptr->flags1 & RF1_UNIQUE)
+ if (tr_ptr->flags & RF_UNIQUE)
{
if (!blind && see_t) monster_msg("^%s is unaffected!", t_name);
}
@@ -2173,10 +1960,9 @@ static bool_ monst_spell_monst(int m_idx)
break;
}
- /* RF6_HEAL */
- case 160 + 2:
+ case SF_HEAL_IDX:
{
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
/* Message */
if (blind || !see_m)
@@ -2223,7 +2009,7 @@ static bool_ monst_spell_monst(int m_idx)
}
/* Redraw (later) if needed */
- if (health_who == m_idx) p_ptr->redraw |= (PR_HEALTH);
+ if (health_who == m_idx) p_ptr->redraw |= (PR_FRAME);
/* Cancel fear */
if (m_ptr->monfear)
@@ -2238,72 +2024,59 @@ static bool_ monst_spell_monst(int m_idx)
break;
}
- /* RF6_S_ANIMALS */
- case 160 + 3:
+ case SF_BLINK_IDX:
{
- if (disturb_other) disturb(1, 0);
- 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++)
- {
- if (friendly)
- count += summon_specific_friendly(y, x, rlev, SUMMON_ANIMAL, TRUE);
- else
- count += summon_specific(y, x, rlev, SUMMON_ANIMAL);
- }
- if (blind && count) monster_msg("You hear many things appear nearby.");
- break;
- }
-
- /* RF6_BLINK */
- case 160 + 4:
- {
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
if (see_m) monster_msg("%^s blinks away.", m_name);
teleport_away(m_idx, 10);
break;
}
- /* RF6_TPORT */
- case 160 + 5:
+ case SF_TPORT_IDX:
{
- if (dungeon_flags2 & DF2_NO_TELEPORT) break; /* No teleport on special levels */
+ if (dungeon_flags & DF_NO_TELEPORT)
+ {
+ break; /* No teleport on special levels */
+ }
else
{
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
if (see_m) monster_msg("%^s teleports away.", m_name);
teleport_away(m_idx, MAX_SIGHT * 2 + 5);
break;
}
}
- /* RF6_TELE_TO */
- case 160 + 6:
+ case SF_TELE_TO_IDX:
{
/* Not implemented */
break;
}
- /* RF6_TELE_AWAY */
- case 160 + 7:
+ case SF_TELE_AWAY_IDX:
{
- if (dungeon_flags2 & DF2_NO_TELEPORT) break;
+ if (dungeon_flags & DF_NO_TELEPORT)
+ {
+ break;
+ }
- if (!direct) break;
+ if (!direct)
+ {
+ break;
+ }
else
{
bool_ resists_tele = FALSE;
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
monster_msg("%^s teleports %s away.", m_name, t_name);
- if (tr_ptr->flags3 & (RF3_RES_TELE))
+ if (tr_ptr->flags & RF_RES_TELE)
{
- if (tr_ptr->flags1 & (RF1_UNIQUE))
+ if (tr_ptr->flags & RF_UNIQUE)
{
if (see_t)
{
- tr_ptr->r_flags3 |= RF3_RES_TELE;
monster_msg("%^s is unaffected!", t_name);
}
resists_tele = TRUE;
@@ -2312,7 +2085,6 @@ static bool_ monst_spell_monst(int m_idx)
{
if (see_t)
{
- tr_ptr->r_flags3 |= RF3_RES_TELE;
monster_msg("%^s resists!", t_name);
}
resists_tele = TRUE;
@@ -2328,388 +2100,212 @@ static bool_ monst_spell_monst(int m_idx)
break;
}
- /* RF6_TELE_LEVEL */
- case 160 + 8:
+ case SF_TELE_LEVEL_IDX:
{
/* Not implemented */
break;
}
- /* RF6_DARKNESS */
- case 160 + 9:
+ case SF_DARKNESS_IDX:
{
if (!direct) break;
- if (disturb_other) disturb(1, 0);
+ disturb_on_other();
if (blind) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s gestures in shadow.", m_name);
if (seen)
monster_msg("%^s is surrounded by darkness.", t_name);
- (void)project(m_idx, 3, y, x, 0, GF_DARK_WEAK, PROJECT_GRID | PROJECT_KILL);
+ project(m_idx, 3, y, x, 0, GF_DARK_WEAK, PROJECT_GRID | PROJECT_KILL);
/* Lite up the room */
unlite_room(y, x);
break;
}
- /* RF6_TRAPS */
- case 160 + 10:
+ case SF_FORGET_IDX:
{
/* Not implemented */
break;
}
- /* RF6_FORGET */
- case 160 + 11:
- {
- /* Not implemented */
+ case SF_S_ANIMAL_IDX:
+ {
+ do_summon("summons an animal!", 1, SUMMON_ANIMAL, SUMMON_ANIMAL, blind_msg_default);
break;
- }
+ }
+
+ case SF_S_ANIMALS_IDX:
+ {
+ do_summon("summons some animals!", 4, SUMMON_ANIMAL, SUMMON_ANIMAL, blind_msg_default);
+ break;
+ }
- /* RF6_ANIM_DEAD */
- case 160 + 12:
+ case SF_S_BUG_IDX:
{
+ do_summon("codes some software bugs.", 6, SUMMON_BUG, SUMMON_BUG, blind_msg_default);
break;
}
- /* RF6_S_BUG */
- case 160 + 13:
+ case SF_S_RNG_IDX:
{
- if (disturb_other) disturb(1, 0);
- 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++)
- {
- if (friendly)
- count += summon_specific_friendly(y, x, rlev, SUMMON_BUG, TRUE);
- else
- count += summon_specific(y, x, rlev, SUMMON_BUG);
- }
- if (blind && count) monster_msg("You hear many things appear nearby.");
+ do_summon("codes some RNGs.", 6, SUMMON_RNG, SUMMON_RNG, blind_msg_default);
break;
}
- /* RF6_S_RNG */
- case 160 + 14:
+ case SF_S_THUNDERLORD_IDX:
{
- if (disturb_other) disturb(1, 0);
- 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++)
- {
- if (friendly)
- count += summon_specific_friendly(y, x, rlev, SUMMON_RNG, TRUE);
- else
- count += summon_specific(y, x, rlev, SUMMON_RNG);
- }
- if (blind && count) monster_msg("You hear many things appear nearby.");
+ do_summon("summons a Thunderlord!", 1, SUMMON_THUNDERLORD, SUMMON_THUNDERLORD, blind_msg_default);
break;
}
-
- /* RF6_S_THUNDERLORD */
- case 160 + 15:
+ case SF_S_KIN_IDX:
{
- if (disturb_other) disturb(1, 0);
- 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++)
- {
- if (friendly)
- count += summon_specific_friendly(y, x, rlev, SUMMON_THUNDERLORD, TRUE);
- else
- count += summon_specific(y, x, rlev, SUMMON_THUNDERLORD);
- }
- if (blind && count) monster_msg("You hear something appear nearby.");
+ // Describe the summons
+ char action[256];
+ sprintf(action,
+ "summons %s %s.",
+ m_poss,
+ (r_ptr->flags & RF_UNIQUE ? "minions" : "kin"));
+ // Force the right type of "kin"
+ summon_kin_type = r_ptr->d_char;
+ // Summon
+ do_summon(action, 6, SUMMON_KIN, SUMMON_KIN, blind_msg_default);
break;
}
- /* RF6_SUMMON_KIN */
- case 160 + 16:
+ case SF_S_HI_DEMON_IDX:
{
- if (disturb_other) disturb(1, 0);
- if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s magically summons %s %s.",
- m_name, m_poss,
- ((r_ptr->flags1) & RF1_UNIQUE ?
- "minions" : "kin"));
- summon_kin_type = r_ptr->d_char; /* Big hack */
- for (k = 0; k < 6; k++)
- {
- if (friendly)
- count += summon_specific_friendly(y, x, rlev, SUMMON_KIN, TRUE);
- else
- count += summon_specific(y, x, rlev, SUMMON_KIN);
- }
- if (blind && count) monster_msg("You hear many things appear nearby.");
-
-
+ do_summon("summons greater demons!", 8, SUMMON_HI_DEMON, SUMMON_HI_DEMON, blind_msg_default);
break;
- }
+ }
- /* RF6_S_HI_DEMON */
- case 160 + 17:
+ case SF_S_MONSTER_IDX:
{
- if (disturb_other) disturb(1, 0);
- 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.");
- if (friendly)
- summon_specific_friendly(y, x, rlev, SUMMON_HI_DEMON, TRUE);
- else
- summon_cyber();
+ do_summon("summons help!", 1, SUMMON_NO_UNIQUES, 0, blind_msg_default);
break;
}
- /* RF6_S_MONSTER */
- case 160 + 18:
+ case SF_S_MONSTERS_IDX:
{
- if (disturb_other) disturb(1, 0);
- 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++)
- {
- if (friendly)
- count += summon_specific_friendly(y, x, rlev, SUMMON_NO_UNIQUES, TRUE);
- else
- count += summon_specific(y, x, rlev, 0);
- }
- if (blind && count) monster_msg("You hear something appear nearby.");
+ do_summon("summons monsters!", 8, SUMMON_NO_UNIQUES, 0, blind_msg_default);
break;
}
- /* RF6_S_MONSTERS */
- case 160 + 19:
+ case SF_S_ANT_IDX:
{
- if (disturb_other) disturb(1, 0);
- 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++)
- {
- if (friendly)
- count += summon_specific_friendly(y, x, rlev, SUMMON_NO_UNIQUES, TRUE);
- else
- count += summon_specific(y, x, rlev, 0);
- }
- if (blind && count) monster_msg("You hear many things appear nearby.");
+ do_summon("summons ants.", 6, SUMMON_ANT, SUMMON_ANT, blind_msg_default);
break;
}
- /* RF6_S_ANT */
- case 160 + 20:
+ case SF_S_SPIDER_IDX:
{
- if (disturb_other) disturb(1, 0);
- 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++)
- {
- if (friendly)
- count += summon_specific_friendly(y, x, rlev, SUMMON_ANT, TRUE);
- else
- count += summon_specific(y, x, rlev, SUMMON_ANT);
- }
- if (blind && count) monster_msg("You hear many things appear nearby.");
+ do_summon("summons spiders.", 6, SUMMON_SPIDER, SUMMON_SPIDER, blind_msg_default);
break;
}
- /* RF6_S_SPIDER */
- case 160 + 21:
+ case SF_S_HOUND_IDX:
{
- if (disturb_other) disturb(1, 0);
- 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++)
- {
- if (friendly)
- count += summon_specific_friendly(y, x, rlev, SUMMON_SPIDER, TRUE);
- else
- count += summon_specific(y, x, rlev, SUMMON_SPIDER);
- }
- if (blind && count) monster_msg("You hear many things appear nearby.");
+ do_summon("summons hounds.", 6, SUMMON_HOUND, SUMMON_HOUND, blind_msg_default);
break;
}
- /* RF6_S_HOUND */
- case 160 + 22:
+ case SF_S_HYDRA_IDX:
{
- if (disturb_other) disturb(1, 0);
- 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++)
- {
- if (friendly)
- count += summon_specific_friendly(y, x, rlev, SUMMON_HOUND, TRUE);
- else
- count += summon_specific(y, x, rlev, SUMMON_HOUND);
- }
- if (blind && count) monster_msg("You hear many things appear nearby.");
+ do_summon("summons hydras.", 6, SUMMON_HYDRA, SUMMON_HYDRA, blind_msg_default);
break;
}
- /* RF6_S_HYDRA */
- case 160 + 23:
+ case SF_S_ANGEL_IDX:
{
- if (disturb_other) disturb(1, 0);
- 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++)
- {
- if (friendly)
- count += summon_specific_friendly(y, x, rlev, SUMMON_HYDRA, TRUE);
- else
- count += summon_specific(y, x, rlev, SUMMON_HYDRA);
- }
- if (blind && count) monster_msg("You hear many things appear nearby.");
+ do_summon("summons an angel!", 1, SUMMON_ANGEL, SUMMON_ANGEL, blind_msg_default);
break;
}
- /* RF6_S_ANGEL */
- case 160 + 24:
+ case SF_S_DEMON_IDX:
{
- if (disturb_other) disturb(1, 0);
- 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++)
- {
- if (friendly)
- count += summon_specific_friendly(y, x, rlev, SUMMON_ANGEL, TRUE);
- else
- count += summon_specific(y, x, rlev, SUMMON_ANGEL);
- }
- if (blind && count) monster_msg("You hear something appear nearby.");
+ do_summon("summons a demon!", 1, SUMMON_DEMON, SUMMON_DEMON, blind_msg_default);
break;
}
- /* RF6_S_DEMON */
- case 160 + 25:
+ case SF_S_UNDEAD_IDX:
{
- if (disturb_other) disturb(1, 0);
- 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++)
- {
- if (friendly)
- count += summon_specific_friendly(y, x, rlev, SUMMON_DEMON, TRUE);
- else
- count += summon_specific(y, x, rlev, SUMMON_DEMON);
- }
- if (blind && count) monster_msg("You hear something appear nearby.");
+ do_summon("summons an undead adversary!", 1, SUMMON_UNDEAD, SUMMON_UNDEAD, blind_msg_default);
break;
}
- /* RF6_S_UNDEAD */
- case 160 + 26:
+ case SF_S_DRAGON_IDX:
{
- if (disturb_other) disturb(1, 0);
- 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++)
- {
- if (friendly)
- count += summon_specific_friendly(y, x, rlev, SUMMON_UNDEAD, TRUE);
- else
- count += summon_specific(y, x, rlev, SUMMON_UNDEAD);
- }
- if (blind && count) monster_msg("You hear something appear nearby.");
+ do_summon("summons a dragon!", 1, SUMMON_DRAGON, SUMMON_DRAGON, blind_msg_default);
break;
}
- /* RF6_S_DRAGON */
- case 160 + 27:
+ case SF_S_HI_UNDEAD_IDX:
{
- if (disturb_other) disturb(1, 0);
- 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++)
- {
- if (friendly)
- count += summon_specific_friendly(y, x, rlev, SUMMON_DRAGON, TRUE);
- else
- count += summon_specific(y, x, rlev, SUMMON_DRAGON);
- }
- if (blind && count) monster_msg("You hear something appear nearby.");
+ summon_messages blind_msg {
+ "You hear a creepy thing appear nearby.",
+ "You hear many creepy things appear nearby."
+ };
+ do_summon("summons greater undead!", 8, SUMMON_HI_UNDEAD_NO_UNIQUES, SUMMON_HI_UNDEAD, blind_msg);
break;
}
- /* RF6_S_HI_UNDEAD */
- case 160 + 28:
+ case SF_S_HI_DRAGON_IDX:
{
- if (disturb_other) disturb(1, 0);
- 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++)
- {
- if (friendly)
- count += summon_specific_friendly(y, x, rlev, SUMMON_HI_UNDEAD_NO_UNIQUES, TRUE);
- else
- count += summon_specific(y, x, rlev, SUMMON_HI_UNDEAD);
- }
- if (blind && count)
- {
- monster_msg("You hear many creepy things appear nearby.");
- }
+ summon_messages blind_msg {
+ "You hear many a powerful thing appear nearby.",
+ "You hear many powerful things appear nearby."
+ };
+ do_summon("summons ancient dragons!", 8, SUMMON_HI_DRAGON_NO_UNIQUES, SUMMON_HI_DRAGON, blind_msg);
break;
}
- /* RF6_S_HI_DRAGON */
- case 160 + 29:
+ case SF_S_WRAITH_IDX:
{
- if (disturb_other) disturb(1, 0);
- 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++)
- {
- if (friendly)
- count += summon_specific_friendly(y, x, rlev, SUMMON_HI_DRAGON_NO_UNIQUES, TRUE);
- else
- count += summon_specific(y, x, rlev, SUMMON_HI_DRAGON);
- }
- if (blind && count)
- {
- monster_msg("You hear many powerful things appear nearby.");
- }
+ // No summoning Nazgul; see the remapping code above the switch.
+ assert(!friendly);
+ // Summon
+ summon_messages blind_msg {
+ "You hear an immortal being appear nearby.",
+ "You hear immortal beings appear nearby."
+ };
+ do_summon("summons a wraith!", 8, 0 /* not used */, SUMMON_WRAITH, blind_msg);
break;
}
- /* RF6_S_WRAITH */
- case 160 + 30:
+ case SF_S_UNIQUE_IDX:
{
- if (disturb_other) disturb(1, 0);
- if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
- else monster_msg("%^s magically summons a wraith!", m_name);
-
-
- for (k = 0; k < 8; k++)
+ // No summoning uniques; see the remapping code above the switch.
+ assert(!friendly);
+ // Interrupt
+ disturb_on_other();
+ // Message
+ if (blind || !see_m)
{
- count += summon_specific(y, x, rlev, SUMMON_WRAITH);
+ monster_msg("%^s mumbles.", m_name);
}
-
- if (blind && count)
+ else
{
- monster_msg("You hear immortal beings appear nearby.");
+ monster_msg("%^s magically summons special opponents!", m_name);
}
- break;
- }
-
- /* RF6_S_UNIQUE */
- case 160 + 31:
- {
- if (disturb_other) disturb(1, 0);
- 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++)
+ // Summon
+ int count = 0;
+ for (int k = 0; k < 8; k++)
{
- if (!friendly)
- count += summon_specific(y, x, rlev, SUMMON_UNIQUE);
+ count += summon_specific(m_ptr->fy, m_ptr->fx, rlev, SUMMON_UNIQUE);
}
- for (k = 0; k < 8; k++)
+ for (int k = 0; k < 8; k++)
{
- if (friendly)
- count += summon_specific_friendly(y, x, rlev, SUMMON_HI_UNDEAD_NO_UNIQUES, TRUE);
- else
- count += summon_specific(y, x, rlev, SUMMON_HI_UNDEAD);
+ count += summon_specific(m_ptr->fy, m_ptr->fx, rlev, SUMMON_HI_UNDEAD);
}
- if (blind && count)
+ // Message
+ if (blind)
{
- monster_msg("You hear many powerful things appear nearby.");
+ if (count == 1)
+ {
+ monster_msg("You hear a powerful thing appear nearby.");
+ }
+ else if (count > 1)
+ {
+ monster_msg("You hear many powerful things appear nearby.");
+ }
}
break;
}
@@ -2720,39 +2316,6 @@ static bool_ monst_spell_monst(int m_idx)
t_ptr->csleep = 0;
}
-
- /* Remember what the monster did, if we saw it */
- if (seen)
- {
- /* Inate spell */
- if (thrown_spell < 32*4)
- {
- r_ptr->r_flags4 |= (1L << (thrown_spell - 32 * 3));
- if (r_ptr->r_cast_inate < MAX_UCHAR) r_ptr->r_cast_inate++;
- }
-
- /* Bolt or Ball */
- else if (thrown_spell < 32*5)
- {
- r_ptr->r_flags5 |= (1L << (thrown_spell - 32 * 4));
- if (r_ptr->r_cast_spell < MAX_UCHAR) r_ptr->r_cast_spell++;
- }
-
- /* Special spell */
- else if (thrown_spell < 32*6)
- {
- r_ptr->r_flags6 |= (1L << (thrown_spell - 32 * 5));
- if (r_ptr->r_cast_spell < MAX_UCHAR) r_ptr->r_cast_spell++;
- }
- }
-
- /* Always take note of monsters that kill you ---
- * even accidentally */
- if (death && (r_ptr->r_deaths < MAX_SHORT))
- {
- r_ptr->r_deaths++;
- }
-
/* A spell was cast */
return (TRUE);
}
@@ -2765,7 +2328,6 @@ static bool_ monst_spell_monst(int m_idx)
void curse_equipment(int chance, int heavy_chance)
{
bool_ changed = FALSE;
- u32b o1, o2, o3, o4, esp, o5;
object_type * o_ptr =
&p_ptr->inventory[rand_range(INVEN_WIELD, INVEN_TOTAL - 1)];
@@ -2773,11 +2335,11 @@ void curse_equipment(int chance, int heavy_chance)
if (!(o_ptr->k_idx)) return;
- object_flags(o_ptr, &o1, &o2, &o3, &o4, &o5, &esp);
+ auto const flags = object_flags(o_ptr);
/* Extra, biased saving throw for blessed items */
- if ((o3 & (TR3_BLESSED)) && (randint(888) > chance))
+ if ((flags & TR_BLESSED) && (randint(888) > chance))
{
char o_name[256];
object_desc(o_name, o_ptr, FALSE, 0);
@@ -2788,31 +2350,28 @@ void curse_equipment(int chance, int heavy_chance)
}
if ((randint(100) <= heavy_chance) &&
- (o_ptr->name1 || o_ptr->name2 || o_ptr->art_name))
+ (o_ptr->name1 || o_ptr->name2 || (!o_ptr->artifact_name.empty())))
{
- if (!(o3 & TR3_HEAVY_CURSE))
+ if (!(flags & TR_HEAVY_CURSE))
changed = TRUE;
- o_ptr->art_flags3 |= TR3_HEAVY_CURSE;
- o_ptr->art_flags3 |= TR3_CURSED;
+ o_ptr->art_flags |= TR_HEAVY_CURSE;
+ o_ptr->art_flags |= TR_CURSED;
o_ptr->ident |= IDENT_CURSED;
}
else
{
- if (!(o_ptr->ident & (IDENT_CURSED)))
+ if (!(o_ptr->ident & IDENT_CURSED))
changed = TRUE;
- o_ptr->art_flags3 |= TR3_CURSED;
+ o_ptr->art_flags |= TR_CURSED;
o_ptr->ident |= IDENT_CURSED;
}
if (changed)
{
msg_print("There is a malignant black aura surrounding you...");
- if (o_ptr->note)
+ if (o_ptr->inscription == "uncursed")
{
- if (streq(quark_str(o_ptr->note), "uncursed"))
- {
- o_ptr->note = 0;
- }
+ o_ptr->inscription.clear();
}
}
}
@@ -2821,7 +2380,7 @@ void curse_equipment(int chance, int heavy_chance)
void curse_equipment_dg(int chance, int heavy_chance)
{
bool_ changed = FALSE;
- u32b o1, o2, o3, o4, esp, o5;
+
object_type * o_ptr =
&p_ptr->inventory[rand_range(INVEN_WIELD, INVEN_TOTAL - 1)];
@@ -2829,49 +2388,44 @@ void curse_equipment_dg(int chance, int heavy_chance)
if (!(o_ptr->k_idx)) return;
- object_flags(o_ptr, &o1, &o2, &o3, &o4, &o5, &esp);
+ auto const flags = object_flags(o_ptr);
/* Extra, biased saving throw for blessed items */
- if ((o3 & (TR3_BLESSED)) && (randint(888) > chance))
+ if ((flags & TR_BLESSED) && (randint(888) > chance))
{
char o_name[256];
object_desc(o_name, o_ptr, FALSE, 0);
msg_format("Your %s resist%s cursing!", o_name,
((o_ptr->number > 1) ? "" : "s"));
- /* Hmmm -- can we wear multiple items? If not, this is unnecessary */
- /* DG -- Yes we can, in the quiver */
return;
}
if ((randint(100) <= heavy_chance) &&
- (o_ptr->name1 || o_ptr->name2 || o_ptr->art_name))
+ (o_ptr->name1 || o_ptr->name2 || (!o_ptr->artifact_name.empty())))
{
- if (!(o3 & TR3_HEAVY_CURSE))
+ if (!(flags & TR_HEAVY_CURSE))
changed = TRUE;
- o_ptr->art_flags3 |= TR3_HEAVY_CURSE;
- o_ptr->art_flags3 |= TR3_CURSED;
- o_ptr->art_flags4 |= TR4_DG_CURSE;
+ o_ptr->art_flags |= TR_HEAVY_CURSE;
+ o_ptr->art_flags |= TR_CURSED;
+ o_ptr->art_flags |= TR_DG_CURSE;
o_ptr->ident |= IDENT_CURSED;
}
else
{
- if (!(o_ptr->ident & (IDENT_CURSED)))
+ if (!(o_ptr->ident & IDENT_CURSED))
changed = TRUE;
- o_ptr->art_flags3 |= TR3_CURSED;
- o_ptr->art_flags4 |= TR4_DG_CURSE;
+ o_ptr->art_flags |= TR_CURSED;
+ o_ptr->art_flags |= TR_DG_CURSE;
o_ptr->ident |= IDENT_CURSED;
}
if (changed)
{
msg_print("There is a malignant black aura surrounding you...");
- if (o_ptr->note)
+ if (o_ptr->inscription == "uncursed")
{
- if (streq(quark_str(o_ptr->note), "uncursed"))
- {
- o_ptr->note = 0;
- }
+ o_ptr->inscription.clear();
}
}
}
@@ -2896,14 +2450,6 @@ void curse_equipment_dg(int chance, int heavy_chance)
* Perhaps smart monsters should decline to use "bolt" spells if
* there is a monster in the way, unless they wish to kill it.
*
- * Note that, to allow the use of the "track_target" option at some
- * later time, certain non-optimal things are done in the code below,
- * including explicit checks against the "direct" variable, which is
- * currently always true by the time it is checked, but which should
- * really be set according to an explicit "projectable()" test, and
- * the use of generic "x,y" locations instead of the player location,
- * with those values being initialized with the player location.
- *
* It will not be possible to "correctly" handle the case in which a
* monster attempts to attack a location which is thought to contain
* the player, but which in fact is nowhere near the player, since this
@@ -2917,12 +2463,6 @@ void curse_equipment_dg(int chance, int heavy_chance)
* could be left in a bizarre situation after the player ducked behind a
* pillar and then teleported away, for example.
*
- * Note that certain spell attacks do not use the "project()" function
- * but "simulate" it via the "direct" variable, which is always at least
- * as restrictive as the "project()" function. This is necessary to
- * prevent "blindness" attacks and such from bending around walls, etc,
- * and to allow the use of the "track_target" option in the future.
- *
* Note that this function attempts to optimize the use of spells for the
* cases in which the monster has no spells, or has spells but cannot use
* them, or has spells but they will have no "useful" effect. Note that
@@ -2931,46 +2471,33 @@ void curse_equipment_dg(int chance, int heavy_chance)
* Note the special "MFLAG_NICE" flag, which prevents a monster from using
* any spell attacks until the player has had a single chance to move.
*/
-bool_ make_attack_spell(int m_idx)
+static bool_ make_attack_spell(int m_idx)
{
- int k, chance, thrown_spell, rlev, failrate;
- byte spell[96], num = 0;
- u32b f4, f5, f6;
- monster_type *m_ptr = &m_list[m_idx];
- monster_race *r_ptr = race_inf(m_ptr);
+ static const auto SF_BOLT_MASK = compute_bolt_mask();
+ static const auto SF_SUMMON_MASK = compute_summoning_mask();
+ static const auto SF_INT_MASK = compute_smart_mask();
+ static const auto SF_INNATE_MASK = compute_innate_mask();
+
+ int chance, rlev, failrate;
char m_name[80];
bool_ no_inate = FALSE;
- int x, y;
-
- /* Summon count */
- int count = 0;
/* Extract the blind-ness */
bool_ blind = (p_ptr->blind ? TRUE : FALSE);
+ /* Get a pointer to the monster */
+ monster_type *m_ptr = &m_list[m_idx];
+
/* Extract the "see-able-ness" */
bool_ seen = (!blind && m_ptr->ml);
- /* Assume "normal" target */
- bool_ normal = TRUE;
-
- /* Assume "projectable" */
- bool_ direct = TRUE;
-
/* Target location */
- if (m_ptr->target > -1)
+ if (m_ptr->target != 0)
{
- if (!m_ptr->target)
- {
- y = p_ptr->py;
- x = p_ptr->px;
- }
- else
- {
- return (FALSE);
- }
+ return FALSE;
}
- else return FALSE;
+ int y = p_ptr->py;
+ int x = p_ptr->px;
/* Cannot cast spells when confused */
if (m_ptr->confused) return (FALSE);
@@ -2980,7 +2507,8 @@ bool_ make_attack_spell(int m_idx)
if (is_friend(m_ptr) >= 0) return (FALSE);
/* Cannot attack the player if mortal and player fated to never die by the ... */
- if ((r_ptr->flags7 & RF7_MORTAL) && (p_ptr->no_mortal)) return (FALSE);
+ auto const r_ptr = m_ptr->race();
+ if ((r_ptr->flags & RF_MORTAL) && (p_ptr->no_mortal)) return (FALSE);
/* Hack -- Extract the spell probability */
chance = (r_ptr->freq_inate + r_ptr->freq_spell) / 2;
@@ -2988,24 +2516,13 @@ 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);
-
- /* Sometimes forbid inate attacks (breaths) */
- if (rand_int(100) >= (chance * 2)) no_inate = TRUE;
- }
+ /* Only do spells occasionally */
+ if (rand_int(100) >= chance) return (FALSE);
- /* XXX XXX XXX Handle "track_target" option (?) */
+ /* Sometimes forbid inate attacks (breaths) */
+ if (rand_int(100) >= (chance * 2)) no_inate = TRUE;
-
- /* Hack -- require projectable player */
- if (normal)
+ /* Require projectable player */
{
/* Check range */
if (m_ptr->cdis > MAX_RANGE) return (FALSE);
@@ -3018,86 +2535,58 @@ bool_ make_attack_spell(int m_idx)
rlev = ((m_ptr->level >= 1) ? m_ptr->level : 1);
/* Extract the racial spell flags */
- f4 = r_ptr->flags4;
- f5 = r_ptr->flags5;
- f6 = r_ptr->flags6;
+ monster_spell_flag_set allowed_spells = r_ptr->spells;
- if (!stupid_monsters)
+ /* Forbid inate attacks sometimes */
+ if (no_inate)
{
- /* Forbid inate attacks sometimes */
- if (no_inate) f4 = 0L;
+ allowed_spells &= ~SF_INNATE_MASK;
}
/* Hack -- allow "desperate" spells */
- if ((r_ptr->flags2 & (RF2_SMART)) &&
+ if ((r_ptr->flags & RF_SMART) &&
(m_ptr->hp < m_ptr->maxhp / 10) &&
(rand_int(100) < 50))
{
/* Require intelligent spells */
- f4 &= (RF4_INT_MASK);
- f5 &= (RF5_INT_MASK);
- f6 &= (RF6_INT_MASK);
+ allowed_spells &= SF_INT_MASK;
- /* No spells left */
- if (!f4 && !f5 && !f6) return (FALSE);
+ /* No spells left? */
+ if (!allowed_spells) return (FALSE);
}
/* Remove the "ineffective" spells */
- remove_bad_spells(m_idx, &f4, &f5, &f6);
+ remove_bad_spells(m_idx, &allowed_spells);
/* No spells left */
- if (!f4 && !f5 && !f6) return (FALSE);
+ if (!allowed_spells) return (FALSE);
- if (!stupid_monsters)
+ /* Check for a clean bolt shot */
+ if ((allowed_spells & SF_BOLT_MASK) &&
+ !(r_ptr->flags & RF_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);
- }
-
- /* No spells left */
- if (!f4 && !f5 && !f6) return (FALSE);
+ /* Remove spells that will only hurt friends */
+ allowed_spells &= ~SF_BOLT_MASK;
}
- /* Extract the "inate" spells */
- for (k = 0; k < 32; k++)
+ /* Check for a possible summon */
+ if ((allowed_spells & SF_SUMMON_MASK) &&
+ !(r_ptr->flags & RF_STUPID) &&
+ !(summon_possible(y, x)))
{
- if (f4 & (1L << k)) spell[num++] = k + 32 * 3;
+ /* Remove summoning spells */
+ allowed_spells &= ~SF_SUMMON_MASK;
}
- /* Extract the "normal" spells */
- for (k = 0; k < 32; k++)
- {
- if (f5 & (1L << k)) spell[num++] = k + 32 * 4;
- }
+ /* No spells left */
+ if (!allowed_spells) return (FALSE);
- /* Extract the "bizarre" spells */
- for (k = 0; k < 32; k++)
- {
- if (f6 & (1L << k)) spell[num++] = k + 32 * 5;
- }
+ /* Extract the "inate" spells */
+ auto spell = extract_spells(allowed_spells);
/* No spells left */
- if (!num) return (FALSE);
+ if (spell.empty()) return (FALSE);
/* Stop if player is dead or gone */
if (!alive || death) return (FALSE);
@@ -3108,36 +2597,29 @@ 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 */
+ auto thrown_spell = choose_attack_spell(m_idx, spell);
- /* 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->flags & RF_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->is_innate) && (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? */
- if ((p_ptr->antimagic_dis >= m_ptr->cdis) && (magik(p_ptr->antimagic)) && (thrown_spell >= 128))
+ if ((p_ptr->antimagic_dis >= m_ptr->cdis) && magik(p_ptr->antimagic) && thrown_spell->is_magic)
{
char m_poss[80];
@@ -3157,43 +2639,89 @@ bool_ make_attack_spell(int m_idx)
/* Hack -- Get the "died from" name */
monster_desc(ddesc, m_ptr, 0x88);
+ /* Do a breath */
+ auto do_breath = [&](char const *element, int gf, s32b max, int divisor, int smart_learn) -> void {
+ // Interrupt
+ disturb();
+ // Message
+ if (blind)
+ {
+ msg_format("%^s breathes.", m_name);
+ }
+ else
+ {
+ msg_format("%^s breathes %s.", m_name, element);
+ }
+ // Breathe
+ breath(m_idx, gf, std::min(m_ptr->hp / divisor, max), 0);
+ // Update "smart" monster knowledge
+ update_smart_learn(m_idx, smart_learn);
+ };
+
+ /* Messages for summoning */
+ struct summon_messages {
+ char const *singular;
+ char const *plural;
+ };
+
+ /* Default message for summoning when player is blinded */
+ summon_messages blind_msg_default {
+ "You hear something appear nearby.",
+ "You hear many things appear nearby."
+ };
+
+ /* Do a summoning spell */
+ auto do_summon = [&](char const *action, int n, int type, summon_messages const &blind_msg) -> void {
+ // Interrupt
+ disturb();
+ // Message
+ if (blind)
+ {
+ msg_format("%^s mumbles.", m_name);
+ }
+ else
+ {
+ msg_format("%^s magically %s", m_name, action);
+ }
+ // Do the actual summoning
+ int count = 0;
+ for (int k = 0; k < n; k++)
+ {
+ count += summon_specific(m_ptr->fy, m_ptr->fx, rlev, type);
+ }
+ // Message for blinded characters
+ if (blind)
+ {
+ if (count == 1)
+ {
+ msg_print(blind_msg.singular);
+ }
+ else if (count > 1)
+ {
+ msg_print(blind_msg.plural);
+ }
+ }
+ };
+
/* Cast the spell. */
- switch (thrown_spell)
+ switch (thrown_spell->spell_idx)
{
- /* RF4_SHRIEK */
- case 96 + 0:
+ case SF_SHRIEK_IDX:
{
- if (!direct) break;
- disturb(1, 0);
+ disturb();
msg_format("%^s makes a high pitched shriek.", m_name);
aggravate_monsters(m_idx);
break;
}
- /* RF4_MULTIPLY */
- case 96 + 1:
- {
- break;
- }
-
- /* RF4_S_ANIMAL */
- case 96 + 2:
+ case SF_MULTIPLY_IDX:
{
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s magically summons an animal!", m_name);
- for (k = 0; k < 1; k++)
- {
- count += summon_specific(y, x, rlev, SUMMON_ANIMAL);
- }
- if (blind && count) msg_print("You hear something appear nearby.");
break;
}
- /* RF4_ROCKET */
- case 96 + 3:
+ case SF_ROCKET_IDX:
{
- disturb(1, 0);
+ disturb();
if (blind) msg_format("%^s shoots something.", m_name);
else msg_format("%^s fires a rocket.", m_name);
breath(m_idx, GF_ROCKET,
@@ -3202,10 +2730,9 @@ bool_ make_attack_spell(int m_idx)
break;
}
- /* RF4_ARROW_1 */
- case 96 + 4:
+ case SF_ARROW_1_IDX:
{
- disturb(1, 0);
+ disturb();
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));
@@ -3213,10 +2740,9 @@ bool_ make_attack_spell(int m_idx)
break;
}
- /* RF4_ARROW_2 */
- case 96 + 5:
+ case SF_ARROW_2_IDX:
{
- disturb(1, 0);
+ disturb();
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));
@@ -3224,10 +2750,9 @@ bool_ make_attack_spell(int m_idx)
break;
}
- /* RF4_ARROW_3 */
- case 96 + 6:
+ case SF_ARROW_3_IDX:
{
- disturb(1, 0);
+ disturb();
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));
@@ -3235,10 +2760,9 @@ bool_ make_attack_spell(int m_idx)
break;
}
- /* RF4_ARROW_4 */
- case 96 + 7:
+ case SF_ARROW_4_IDX:
{
- disturb(1, 0);
+ disturb();
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));
@@ -3246,245 +2770,129 @@ bool_ make_attack_spell(int m_idx)
break;
}
- /* RF4_BR_ACID */
- case 96 + 8:
+ case SF_BR_ACID_IDX:
{
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes acid.", m_name);
- breath(m_idx, GF_ACID,
- ((m_ptr->hp / 3) > 1600 ? 1600 : (m_ptr->hp / 3)), 0);
- update_smart_learn(m_idx, DRS_ACID);
+ do_breath("acid", GF_ACID, 1600, 3, DRS_ACID);
break;
}
- /* RF4_BR_ELEC */
- case 96 + 9:
+ case SF_BR_ELEC_IDX:
{
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes lightning.", m_name);
- breath(m_idx, GF_ELEC,
- ((m_ptr->hp / 3) > 1600 ? 1600 : (m_ptr->hp / 3)), 0);
- update_smart_learn(m_idx, DRS_ELEC);
+ do_breath("lightning", GF_ELEC, 1600, 3, DRS_ELEC);
break;
}
- /* RF4_BR_FIRE */
- case 96 + 10:
+ case SF_BR_FIRE_IDX:
{
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes fire.", m_name);
- breath(m_idx, GF_FIRE,
- ((m_ptr->hp / 3) > 1600 ? 1600 : (m_ptr->hp / 3)), 0);
- update_smart_learn(m_idx, DRS_FIRE);
+ do_breath("fire", GF_FIRE, 1600, 3, DRS_FIRE);
break;
}
- /* RF4_BR_COLD */
- case 96 + 11:
+ case SF_BR_COLD_IDX:
{
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes frost.", m_name);
- breath(m_idx, GF_COLD,
- ((m_ptr->hp / 3) > 1600 ? 1600 : (m_ptr->hp / 3)), 0);
- update_smart_learn(m_idx, DRS_COLD);
+ do_breath("frost", GF_COLD, 1600, 3, DRS_COLD);
break;
}
- /* RF4_BR_POIS */
- case 96 + 12:
+ case SF_BR_POIS_IDX:
{
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes gas.", m_name);
- breath(m_idx, GF_POIS,
- ((m_ptr->hp / 3) > 800 ? 800 : (m_ptr->hp / 3)), 0);
- update_smart_learn(m_idx, DRS_POIS);
+ do_breath("gas", GF_POIS, 800, 3, DRS_POIS);
break;
}
-
- /* RF4_BR_NETH */
- case 96 + 13:
+ case SF_BR_NETH_IDX:
{
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes nether.", m_name);
- breath(m_idx, GF_NETHER,
- ((m_ptr->hp / 6) > 550 ? 550 : (m_ptr->hp / 6)), 0);
- update_smart_learn(m_idx, DRS_NETH);
+ do_breath("nether", GF_NETHER, 550, 6, DRS_NETH);
break;
}
- /* RF4_BR_LITE */
- case 96 + 14:
+ case SF_BR_LITE_IDX:
{
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes light.", m_name);
- breath(m_idx, GF_LITE,
- ((m_ptr->hp / 6) > 400 ? 400 : (m_ptr->hp / 6)), 0);
- update_smart_learn(m_idx, DRS_LITE);
+ do_breath("light", GF_LITE, 400, 6, DRS_LITE);
break;
}
- /* RF4_BR_DARK */
- case 96 + 15:
+ case SF_BR_DARK_IDX:
{
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes darkness.", m_name);
- breath(m_idx, GF_DARK,
- ((m_ptr->hp / 6) > 400 ? 400 : (m_ptr->hp / 6)), 0);
- update_smart_learn(m_idx, DRS_DARK);
+ do_breath("darkness", GF_DARK, 400, 6, DRS_DARK);
break;
}
- /* RF4_BR_CONF */
- case 96 + 16:
+ case SF_BR_CONF_IDX:
{
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes confusion.", m_name);
- breath(m_idx, GF_CONFUSION,
- ((m_ptr->hp / 6) > 400 ? 400 : (m_ptr->hp / 6)), 0);
- update_smart_learn(m_idx, DRS_CONF);
+ do_breath("confusion", GF_CONFUSION, 400, 6, DRS_CONF);
break;
}
- /* RF4_BR_SOUN */
- case 96 + 17:
+ case SF_BR_SOUN_IDX:
{
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes sound.", m_name);
- breath(m_idx, GF_SOUND,
- ((m_ptr->hp / 6) > 400 ? 400 : (m_ptr->hp / 6)), 0);
- update_smart_learn(m_idx, DRS_SOUND);
+ do_breath("sound", GF_SOUND, 400, 6, DRS_SOUND);
break;
}
- /* RF4_BR_CHAO */
- case 96 + 18:
+ case SF_BR_CHAO_IDX:
{
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes chaos.", m_name);
- breath(m_idx, GF_CHAOS,
- ((m_ptr->hp / 6) > 600 ? 600 : (m_ptr->hp / 6)), 0);
- update_smart_learn(m_idx, DRS_CHAOS);
+ do_breath("chaos", GF_CHAOS, 600, 6, DRS_CHAOS);
break;
}
- /* RF4_BR_DISE */
- case 96 + 19:
+ case SF_BR_DISE_IDX:
{
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes disenchantment.", m_name);
- breath(m_idx, GF_DISENCHANT,
- ((m_ptr->hp / 6) > 500 ? 500 : (m_ptr->hp / 6)), 0);
- update_smart_learn(m_idx, DRS_DISEN);
+ do_breath("disenchantment", GF_DISENCHANT, 500, 6, DRS_DISEN);
break;
}
- /* RF4_BR_NEXU */
- case 96 + 20:
+ case SF_BR_NEXU_IDX:
{
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes nexus.", m_name);
- breath(m_idx, GF_NEXUS,
- ((m_ptr->hp / 3) > 250 ? 250 : (m_ptr->hp / 3)), 0);
- update_smart_learn(m_idx, DRS_NEXUS);
+ do_breath("nexus", GF_NEXUS, 250, 3, DRS_NEXUS);
break;
}
- /* RF4_BR_TIME */
- case 96 + 21:
+ case SF_BR_TIME_IDX:
{
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes time.", m_name);
- breath(m_idx, GF_TIME,
- ((m_ptr->hp / 3) > 150 ? 150 : (m_ptr->hp / 3)), 0);
+ do_breath("time", GF_TIME, 150, 3, DRS_NONE);
break;
}
- /* RF4_BR_INER */
- case 96 + 22:
+ case SF_BR_INER_IDX:
{
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes inertia.", m_name);
- breath(m_idx, GF_INERTIA,
- ((m_ptr->hp / 6) > 200 ? 200 : (m_ptr->hp / 6)), 0);
+ do_breath("inertia", GF_INERTIA, 200, 6, DRS_NONE);
break;
}
- /* RF4_BR_GRAV */
- case 96 + 23:
+ case SF_BR_GRAV_IDX:
{
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes gravity.", m_name);
- breath(m_idx, GF_GRAVITY,
- ((m_ptr->hp / 3) > 200 ? 200 : (m_ptr->hp / 3)), 0);
+ do_breath("gravity", GF_GRAVITY, 200, 3, DRS_NONE);
break;
}
- /* RF4_BR_SHAR */
- case 96 + 24:
+ case SF_BR_SHAR_IDX:
{
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes shards.", m_name);
- breath(m_idx, GF_SHARDS,
- ((m_ptr->hp / 6) > 400 ? 400 : (m_ptr->hp / 6)), 0);
- update_smart_learn(m_idx, DRS_SHARD);
+ do_breath("shards", GF_SHARDS, 400, 6, DRS_SHARD);
break;
}
- /* RF4_BR_PLAS */
- case 96 + 25:
+ case SF_BR_PLAS_IDX:
{
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes plasma.", m_name);
- breath(m_idx, GF_PLASMA,
- ((m_ptr->hp / 6) > 150 ? 150 : (m_ptr->hp / 6)), 0);
+ do_breath("plasma", GF_PLASMA, 150, 6, DRS_NONE);
break;
}
- /* RF4_BR_WALL */
- case 96 + 26:
+ case SF_BR_WALL_IDX:
{
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes force.", m_name);
- breath(m_idx, GF_FORCE,
- ((m_ptr->hp / 6) > 200 ? 200 : (m_ptr->hp / 6)), 0);
+ do_breath("force", GF_FORCE, 200, 6, DRS_NONE);
break;
}
- /* RF4_BR_MANA */
- case 96 + 27:
+ case SF_BR_MANA_IDX:
{
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes magical energy.", m_name);
- breath(m_idx, GF_MANA,
- ((m_ptr->hp / 3) > 250 ? 250 : (m_ptr->hp / 3)), 0);
+ do_breath("magical energy", GF_MANA, 250, 3, DRS_NONE);
break;
}
- /* RF4_BA_NUKE */
- case 96 + 28:
+ case SF_BA_NUKE_IDX:
{
- disturb(1, 0);
+ disturb();
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);
@@ -3492,22 +2900,15 @@ bool_ make_attack_spell(int m_idx)
break;
}
- /* RF4_BR_NUKE */
- case 96 + 29:
+ case SF_BR_NUKE_IDX:
{
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes toxic waste.", m_name);
- breath(m_idx, GF_NUKE,
- ((m_ptr->hp / 3) > 800 ? 800 : (m_ptr->hp / 3)), 0);
- update_smart_learn(m_idx, DRS_POIS);
+ do_breath("toxic waste", GF_NUKE, 800, 3, DRS_POIS);
break;
}
- /* RF4_BA_CHAO */
- case 96 + 30:
+ case SF_BA_CHAO_IDX:
{
- disturb(1, 0);
+ disturb();
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);
@@ -3515,23 +2916,15 @@ bool_ make_attack_spell(int m_idx)
break;
}
- /* RF4_BR_DISI -> Disintegration breath! */
- case 96 + 31:
+ case SF_BR_DISI_IDX:
{
- disturb(1, 0);
- if (blind) msg_format("%^s breathes.", m_name);
- else msg_format("%^s breathes disintegration.", m_name);
- breath(m_idx, GF_DISINTEGRATE,
- ((m_ptr->hp / 3) > 300 ? 300 : (m_ptr->hp / 3)), 0);
+ do_breath("disintegration", GF_DISINTEGRATE, 300, 3, DRS_NONE);
break;
}
-
-
- /* RF5_BA_ACID */
- case 128 + 0:
+ case SF_BA_ACID_IDX:
{
- disturb(1, 0);
+ disturb();
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s casts an acid ball.", m_name);
breath(m_idx, GF_ACID,
@@ -3540,10 +2933,9 @@ bool_ make_attack_spell(int m_idx)
break;
}
- /* RF5_BA_ELEC */
- case 128 + 1:
+ case SF_BA_ELEC_IDX:
{
- disturb(1, 0);
+ disturb();
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s casts a lightning ball.", m_name);
breath(m_idx, GF_ELEC,
@@ -3552,10 +2944,9 @@ bool_ make_attack_spell(int m_idx)
break;
}
- /* RF5_BA_FIRE */
- case 128 + 2:
+ case SF_BA_FIRE_IDX:
{
- disturb(1, 0);
+ disturb();
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s casts a fire ball.", m_name);
breath(m_idx, GF_FIRE,
@@ -3564,10 +2955,9 @@ bool_ make_attack_spell(int m_idx)
break;
}
- /* RF5_BA_COLD */
- case 128 + 3:
+ case SF_BA_COLD_IDX:
{
- disturb(1, 0);
+ disturb();
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s casts a frost ball.", m_name);
breath(m_idx, GF_COLD,
@@ -3576,10 +2966,9 @@ bool_ make_attack_spell(int m_idx)
break;
}
- /* RF5_BA_POIS */
- case 128 + 4:
+ case SF_BA_POIS_IDX:
{
- disturb(1, 0);
+ disturb();
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s casts a stinking cloud.", m_name);
breath(m_idx, GF_POIS,
@@ -3588,10 +2977,9 @@ bool_ make_attack_spell(int m_idx)
break;
}
- /* RF5_BA_NETH */
- case 128 + 5:
+ case SF_BA_NETH_IDX:
{
- disturb(1, 0);
+ disturb();
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s casts a nether ball.", m_name);
breath(m_idx, GF_NETHER,
@@ -3600,10 +2988,9 @@ bool_ make_attack_spell(int m_idx)
break;
}
- /* RF5_BA_WATE */
- case 128 + 6:
+ case SF_BA_WATE_IDX:
{
- disturb(1, 0);
+ disturb();
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s gestures fluidly.", m_name);
msg_print("You are engulfed in a whirlpool.");
@@ -3612,10 +2999,9 @@ bool_ make_attack_spell(int m_idx)
break;
}
- /* RF5_BA_MANA */
- case 128 + 7:
+ case SF_BA_MANA_IDX:
{
- disturb(1, 0);
+ disturb();
if (blind) msg_format("%^s mumbles powerfully.", m_name);
else msg_format("%^s invokes a mana storm.", m_name);
breath(m_idx, GF_MANA,
@@ -3623,10 +3009,9 @@ bool_ make_attack_spell(int m_idx)
break;
}
- /* RF5_BA_DARK */
- case 128 + 8:
+ case SF_BA_DARK_IDX:
{
- disturb(1, 0);
+ disturb();
if (blind) msg_format("%^s mumbles powerfully.", m_name);
else msg_format("%^s invokes a darkness storm.", m_name);
breath(m_idx, GF_DARK,
@@ -3635,16 +3020,14 @@ bool_ make_attack_spell(int m_idx)
break;
}
- /* RF5_DRAIN_MANA */
- case 128 + 9:
+ case SF_DRAIN_MANA_IDX:
{
- if (!direct) break;
if (p_ptr->csp)
{
int r1;
/* Disturb if legal */
- disturb(1, 0);
+ disturb();
/* Basic message */
msg_format("%^s draws psychic energy from you!", m_name);
@@ -3667,7 +3050,7 @@ bool_ make_attack_spell(int m_idx)
}
/* Redraw mana */
- p_ptr->redraw |= (PR_MANA);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
@@ -3680,7 +3063,7 @@ bool_ make_attack_spell(int m_idx)
if (m_ptr->hp > m_ptr->maxhp) m_ptr->hp = m_ptr->maxhp;
/* Redraw (later) if needed */
- if (health_who == m_idx) p_ptr->redraw |= (PR_HEALTH);
+ if (health_who == m_idx) p_ptr->redraw |= (PR_FRAME);
/* Special message */
if (seen)
@@ -3693,11 +3076,9 @@ bool_ make_attack_spell(int m_idx)
break;
}
- /* RF5_MIND_BLAST */
- case 128 + 10:
+ case SF_MIND_BLAST_IDX:
{
- if (!direct) break;
- disturb(1, 0);
+ disturb();
if (!seen)
{
msg_print("You feel something focusing on your mind.");
@@ -3717,12 +3098,12 @@ bool_ make_attack_spell(int m_idx)
if (!p_ptr->resist_conf)
{
- (void)set_confused(p_ptr->confused + rand_int(4) + 4);
+ set_confused(p_ptr->confused + rand_int(4) + 4);
}
if ((!p_ptr->resist_chaos) && (randint(3) == 1))
{
- (void) set_image(p_ptr->image + rand_int(250) + 150);
+ set_image(p_ptr->image + rand_int(250) + 150);
}
take_sanity_hit(damroll(8, 8), ddesc);
@@ -3730,11 +3111,9 @@ bool_ make_attack_spell(int m_idx)
break;
}
- /* RF5_BRAIN_SMASH */
- case 128 + 11:
+ case SF_BRAIN_SMASH_IDX:
{
- if (!direct) break;
- disturb(1, 0);
+ disturb();
if (!seen)
{
msg_print("You feel something focusing on your mind.");
@@ -3754,36 +3133,34 @@ bool_ make_attack_spell(int m_idx)
take_sanity_hit(damroll(12, 15), ddesc);
if (!p_ptr->resist_blind)
{
- (void)set_blind(p_ptr->blind + 8 + rand_int(8));
+ set_blind(p_ptr->blind + 8 + rand_int(8));
}
if (!p_ptr->resist_conf)
{
- (void)set_confused(p_ptr->confused + rand_int(4) + 4);
+ set_confused(p_ptr->confused + rand_int(4) + 4);
}
if (!p_ptr->free_act)
{
- (void)set_paralyzed(p_ptr->paralyzed + rand_int(4) + 4);
+ set_paralyzed(rand_int(4) + 4);
}
- (void)set_slow(p_ptr->slow + rand_int(4) + 4);
+ set_slow(p_ptr->slow + rand_int(4) + 4);
while (rand_int(100) > p_ptr->skill_sav)
- (void)do_dec_stat(A_INT, STAT_DEC_NORMAL);
+ do_dec_stat(A_INT, STAT_DEC_NORMAL);
while (rand_int(100) > p_ptr->skill_sav)
- (void)do_dec_stat(A_WIS, STAT_DEC_NORMAL);
+ do_dec_stat(A_WIS, STAT_DEC_NORMAL);
if (!p_ptr->resist_chaos)
{
- (void) set_image(p_ptr->image + rand_int(250) + 150);
+ set_image(p_ptr->image + rand_int(250) + 150);
}
}
break;
}
- /* RF5_CAUSE_1 */
- case 128 + 12:
+ case SF_CAUSE_1_IDX:
{
- if (!direct) break;
- disturb(1, 0);
+ disturb();
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)
@@ -3798,11 +3175,9 @@ bool_ make_attack_spell(int m_idx)
break;
}
- /* RF5_CAUSE_2 */
- case 128 + 13:
+ case SF_CAUSE_2_IDX:
{
- if (!direct) break;
- disturb(1, 0);
+ disturb();
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)
@@ -3817,11 +3192,9 @@ bool_ make_attack_spell(int m_idx)
break;
}
- /* RF5_CAUSE_3 */
- case 128 + 14:
+ case SF_CAUSE_3_IDX:
{
- if (!direct) break;
- disturb(1, 0);
+ disturb();
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)
@@ -3836,11 +3209,9 @@ bool_ make_attack_spell(int m_idx)
break;
}
- /* RF5_CAUSE_4 */
- case 128 + 15:
+ case SF_CAUSE_4_IDX:
{
- if (!direct) break;
- disturb(1, 0);
+ disturb();
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)
@@ -3850,15 +3221,14 @@ bool_ make_attack_spell(int m_idx)
else
{
take_hit(damroll(15, 15), ddesc);
- (void)set_cut(p_ptr->cut + damroll(10, 10));
+ set_cut(p_ptr->cut + damroll(10, 10));
}
break;
}
- /* RF5_BO_ACID */
- case 128 + 16:
+ case SF_BO_ACID_IDX:
{
- disturb(1, 0);
+ disturb();
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));
@@ -3867,10 +3237,9 @@ bool_ make_attack_spell(int m_idx)
break;
}
- /* RF5_BO_ELEC */
- case 128 + 17:
+ case SF_BO_ELEC_IDX:
{
- disturb(1, 0);
+ disturb();
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));
@@ -3879,10 +3248,9 @@ bool_ make_attack_spell(int m_idx)
break;
}
- /* RF5_BO_FIRE */
- case 128 + 18:
+ case SF_BO_FIRE_IDX:
{
- disturb(1, 0);
+ disturb();
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));
@@ -3891,10 +3259,9 @@ bool_ make_attack_spell(int m_idx)
break;
}
- /* RF5_BO_COLD */
- case 128 + 19:
+ case SF_BO_COLD_IDX:
{
- disturb(1, 0);
+ disturb();
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,17 +3270,15 @@ bool_ make_attack_spell(int m_idx)
break;
}
- /* RF5_BO_POIS */
- case 128 + 20:
+ case SF_BO_POIS_IDX:
{
/* XXX XXX XXX */
break;
}
- /* RF5_BO_NETH */
- case 128 + 21:
+ case SF_BO_NETH_IDX:
{
- disturb(1, 0);
+ disturb();
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);
@@ -3922,10 +3287,9 @@ bool_ make_attack_spell(int m_idx)
break;
}
- /* RF5_BO_WATE */
- case 128 + 22:
+ case SF_BO_WATE_IDX:
{
- disturb(1, 0);
+ disturb();
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));
@@ -3933,10 +3297,9 @@ bool_ make_attack_spell(int m_idx)
break;
}
- /* RF5_BO_MANA */
- case 128 + 23:
+ case SF_BO_MANA_IDX:
{
- disturb(1, 0);
+ disturb();
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);
@@ -3944,10 +3307,9 @@ bool_ make_attack_spell(int m_idx)
break;
}
- /* RF5_BO_PLAS */
- case 128 + 24:
+ case SF_BO_PLAS_IDX:
{
- disturb(1, 0);
+ disturb();
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));
@@ -3955,10 +3317,9 @@ bool_ make_attack_spell(int m_idx)
break;
}
- /* RF5_BO_ICEE */
- case 128 + 25:
+ case SF_BO_ICEE_IDX:
{
- disturb(1, 0);
+ disturb();
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));
@@ -3967,10 +3328,9 @@ bool_ make_attack_spell(int m_idx)
break;
}
- /* RF5_MISSILE */
- case 128 + 26:
+ case SF_MISSILE_IDX:
{
- disturb(1, 0);
+ disturb();
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));
@@ -3978,11 +3338,9 @@ bool_ make_attack_spell(int m_idx)
break;
}
- /* RF5_SCARE */
- case 128 + 27:
+ case SF_SCARE_IDX:
{
- if (!direct) break;
- disturb(1, 0);
+ disturb();
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,17 +3353,15 @@ bool_ make_attack_spell(int m_idx)
}
else
{
- (void)set_afraid(p_ptr->afraid + rand_int(4) + 4);
+ set_afraid(p_ptr->afraid + rand_int(4) + 4);
}
update_smart_learn(m_idx, DRS_FEAR);
break;
}
- /* RF5_BLIND */
- case 128 + 28:
+ case SF_BLIND_IDX:
{
- if (!direct) break;
- disturb(1, 0);
+ disturb();
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,17 +3374,15 @@ bool_ make_attack_spell(int m_idx)
}
else
{
- (void)set_blind(12 + rand_int(4));
+ set_blind(12 + rand_int(4));
}
update_smart_learn(m_idx, DRS_BLIND);
break;
}
- /* RF5_CONF */
- case 128 + 29:
+ case SF_CONF_IDX:
{
- if (!direct) break;
- disturb(1, 0);
+ disturb();
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,17 +3395,15 @@ bool_ make_attack_spell(int m_idx)
}
else
{
- (void)set_confused(p_ptr->confused + rand_int(4) + 4);
+ set_confused(p_ptr->confused + rand_int(4) + 4);
}
update_smart_learn(m_idx, DRS_CONF);
break;
}
- /* RF5_SLOW */
- case 128 + 30:
+ case SF_SLOW_IDX:
{
- if (!direct) break;
- disturb(1, 0);
+ disturb();
msg_format("%^s drains power from your muscles!", m_name);
if (p_ptr->free_act)
{
@@ -4063,17 +3415,15 @@ bool_ make_attack_spell(int m_idx)
}
else
{
- (void)set_slow(p_ptr->slow + rand_int(4) + 4);
+ set_slow(p_ptr->slow + rand_int(4) + 4);
}
update_smart_learn(m_idx, DRS_FREE);
break;
}
- /* RF5_HOLD */
- case 128 + 31:
+ case SF_HOLD_IDX:
{
- if (!direct) break;
- disturb(1, 0);
+ disturb();
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s stares deep into your eyes!", m_name);
if (p_ptr->free_act)
@@ -4086,18 +3436,15 @@ bool_ make_attack_spell(int m_idx)
}
else
{
- (void)set_paralyzed(p_ptr->paralyzed + rand_int(4) + 4);
+ set_paralyzed(rand_int(4) + 4);
}
update_smart_learn(m_idx, DRS_FREE);
break;
}
-
-
- /* RF6_HASTE */
- case 160 + 0:
+ case SF_HASTE_IDX:
{
- disturb(1, 0);
+ disturb();
if (blind)
{
msg_format("%^s mumbles.", m_name);
@@ -4124,10 +3471,9 @@ bool_ make_attack_spell(int m_idx)
break;
}
- /* RF6_HAND_DOOM */
- case 160 + 1:
+ case SF_HAND_DOOM_IDX:
{
- disturb(1, 0);
+ disturb();
msg_format("%^s invokes the Hand of Doom!", m_name);
if (rand_int(100) < p_ptr->skill_sav)
{
@@ -4145,10 +3491,9 @@ bool_ make_attack_spell(int m_idx)
break;
}
- /* RF6_HEAL */
- case 160 + 2:
+ case SF_HEAL_IDX:
{
- disturb(1, 0);
+ disturb();
/* Message */
if (blind)
@@ -4195,7 +3540,7 @@ bool_ make_attack_spell(int m_idx)
}
/* Redraw (later) if needed */
- if (health_who == m_idx) p_ptr->redraw |= (PR_HEALTH);
+ if (health_who == m_idx) p_ptr->redraw |= (PR_FRAME);
/* Cancel fear */
if (m_ptr->monfear)
@@ -4209,63 +3554,41 @@ bool_ make_attack_spell(int m_idx)
break;
}
- /* RF6_S_ANIMALS */
- case 160 + 3:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s magically summons some animals!", m_name);
- for (k = 0; k < 4; k++)
- {
- count += summon_specific(y, x, rlev, SUMMON_ANIMAL);
- }
- if (blind && count) msg_print("You hear something appear nearby.");
- break;
- }
-
- /* RF6_BLINK */
- case 160 + 4:
+ case SF_BLINK_IDX:
{
- disturb(1, 0);
+ disturb();
msg_format("%^s blinks away.", m_name);
teleport_away(m_idx, 10);
break;
}
- /* RF6_TPORT */
- case 160 + 5:
+ case SF_TPORT_IDX:
{
- disturb(1, 0);
+ disturb();
msg_format("%^s teleports away.", m_name);
teleport_away(m_idx, MAX_SIGHT * 2 + 5);
break;
}
- /* RF6_TELE_TO */
- case 160 + 6:
+ case SF_TELE_TO_IDX:
{
- if (!direct) break;
- disturb(1, 0);
+ disturb();
msg_format("%^s commands you to return.", m_name);
teleport_player_to(m_ptr->fy, m_ptr->fx);
break;
}
- /* RF6_TELE_AWAY */
- case 160 + 7:
+ case SF_TELE_AWAY_IDX:
{
- if (!direct) break;
- disturb(1, 0);
+ disturb();
msg_format("%^s teleports you away.", m_name);
teleport_player(100);
break;
}
- /* RF6_TELE_LEVEL */
- case 160 + 8:
+ case SF_TELE_LEVEL_IDX:
{
- if (!direct) break;
- disturb(1, 0);
+ disturb();
if (blind) msg_format("%^s mumbles strangely.", m_name);
else msg_format("%^s gestures at your feet.", m_name);
if (p_ptr->resist_nexus)
@@ -4284,33 +3607,18 @@ bool_ make_attack_spell(int m_idx)
break;
}
- /* RF6_DARKNESS */
- case 160 + 9:
+ case SF_DARKNESS_IDX:
{
- if (!direct) break;
- disturb(1, 0);
+ disturb();
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s gestures in shadow.", m_name);
- (void)unlite_area(0, 3);
- break;
- }
-
- /* RF6_TRAPS */
- case 160 + 10:
- {
- if (!direct) break;
- disturb(1, 0);
- 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();
+ unlite_area(0, 3);
break;
}
- /* RF6_FORGET */
- case 160 + 11:
+ case SF_FORGET_IDX:
{
- if (!direct) break;
- disturb(1, 0);
+ disturb();
msg_format("%^s tries to blank your mind.", m_name);
if (rand_int(100) < p_ptr->skill_sav)
@@ -4324,332 +3632,187 @@ bool_ make_attack_spell(int m_idx)
break;
}
- /* RF6_ANIM_DEAD */
- case 160 + 12:
- break;
+ case SF_S_ANIMAL_IDX:
+ {
+ do_summon("summons an animal!", 1, SUMMON_ANIMAL, blind_msg_default);
+ break;
+ }
- /* RF6_S_BUG */
- case 160 + 13:
+ case SF_S_ANIMALS_IDX:
+ {
+ do_summon("summons some animals!", 4, SUMMON_ANIMAL, blind_msg_default);
+ break;
+ }
+
+ case SF_S_BUG_IDX:
{
- disturb(1, 0);
- 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++)
- {
- count += summon_specific(y, x, rlev, SUMMON_BUG);
- }
- if (blind && count) msg_print("You hear many things appear nearby.");
+ do_summon("codes some software bugs.", 6, SUMMON_BUG, blind_msg_default);
break;
}
- /* RF6_S_RNG */
- case 160 + 14:
+ case SF_S_RNG_IDX:
{
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s magically codes some RNGs.", m_name);
- for (k = 0; k < 6; k++)
- {
- count += summon_specific(y, x, rlev, SUMMON_RNG);
- }
- if (blind && count) msg_print("You hear many things appear nearby.");
+ do_summon("codes some RNGs.", 6, SUMMON_RNG, blind_msg_default);
break;
}
- /* RF6_S_THUNDERLORD */
- case 160 + 15:
+ case SF_S_THUNDERLORD_IDX:
{
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s magically summons a Thunderlord!", m_name);
- for (k = 0; k < 1; k++)
- {
- count += summon_specific(y, x, rlev, SUMMON_THUNDERLORD);
- }
- if (blind && count) msg_print("You hear something appear nearby.");
+ do_summon("summons a Thunderlord!", 1, SUMMON_THUNDERLORD, blind_msg_default);
break;
}
- /* RF6_SUMMON_KIN */
- case 160 + 16:
+ case SF_S_KIN_IDX:
{
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s magically summons %s %s.",
- m_name, m_poss,
- ((r_ptr->flags1) & RF1_UNIQUE ?
- "minions" : "kin"));
- summon_kin_type = r_ptr->d_char; /* Big hack */
-
- for (k = 0; k < 6; k++)
- {
- count += summon_specific(y, x, rlev, SUMMON_KIN);
- }
- if (blind && count) msg_print("You hear many things appear nearby.");
-
+ // Describe the summons
+ char action[256];
+ sprintf(action,
+ "summons %s %s.",
+ m_poss,
+ (r_ptr->flags & RF_UNIQUE) ? "minions" : "kin");
+ // Force the correct type of "kin"
+ summon_kin_type = r_ptr->d_char;
+ // Summon
+ do_summon(action, 6, SUMMON_KIN, blind_msg_default);
break;
}
- /* RF6_S_HI_DEMON */
- case 160 + 17:
+ case SF_S_HI_DEMON_IDX:
{
- disturb(1, 0);
- 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.");
- summon_cyber();
+ do_summon("summons greater demons!", 8, SUMMON_HI_DEMON, blind_msg_default);
break;
}
- /* RF6_S_MONSTER */
- case 160 + 18:
+ case SF_S_MONSTER_IDX:
{
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s magically summons help!", m_name);
- for (k = 0; k < 1; k++)
- {
- count += summon_specific(y, x, rlev, 0);
- }
- if (blind && count) msg_print("You hear something appear nearby.");
+ do_summon("summons help!", 1, 0, blind_msg_default);
break;
}
- /* RF6_S_MONSTERS */
- case 160 + 19:
+ case SF_S_MONSTERS_IDX:
{
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s magically summons monsters!", m_name);
- for (k = 0; k < 8; k++)
- {
- count += summon_specific(y, x, rlev, 0);
- }
- if (blind && count) msg_print("You hear many things appear nearby.");
+ do_summon("summons monsters!", 8, 0, blind_msg_default);
break;
}
- /* RF6_S_ANT */
- case 160 + 20:
+ case SF_S_ANT_IDX:
{
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s magically summons ants.", m_name);
- for (k = 0; k < 6; k++)
- {
- count += summon_specific(y, x, rlev, SUMMON_ANT);
- }
- if (blind && count) msg_print("You hear many things appear nearby.");
+ do_summon("summons ants.", 6, SUMMON_ANT, blind_msg_default);
break;
}
- /* RF6_S_SPIDER */
- case 160 + 21:
+ case SF_S_SPIDER_IDX:
{
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s magically summons spiders.", m_name);
- for (k = 0; k < 6; k++)
- {
- count += summon_specific(y, x, rlev, SUMMON_SPIDER);
- }
- if (blind && count) msg_print("You hear many things appear nearby.");
+ do_summon("summons spiders.", 6, SUMMON_SPIDER, blind_msg_default);
break;
}
- /* RF6_S_HOUND */
- case 160 + 22:
+ case SF_S_HOUND_IDX:
{
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s magically summons hounds.", m_name);
- for (k = 0; k < 6; k++)
- {
- count += summon_specific(y, x, rlev, SUMMON_HOUND);
- }
- if (blind && count) msg_print("You hear many things appear nearby.");
+ do_summon("summons hounds.", 6, SUMMON_HOUND, blind_msg_default);
break;
}
- /* RF6_S_HYDRA */
- case 160 + 23:
+ case SF_S_HYDRA_IDX:
{
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s magically summons hydras.", m_name);
- for (k = 0; k < 6; k++)
- {
- count += summon_specific(y, x, rlev, SUMMON_HYDRA);
- }
- if (blind && count) msg_print("You hear many things appear nearby.");
+ do_summon("summons hydras.", 6, SUMMON_HYDRA, blind_msg_default);
break;
}
- /* RF6_S_ANGEL */
- case 160 + 24:
+ case SF_S_ANGEL_IDX:
{
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s magically summons an angel!", m_name);
- for (k = 0; k < 1; k++)
- {
- count += summon_specific(y, x, rlev, SUMMON_ANGEL);
- }
- if (blind && count) msg_print("You hear something appear nearby.");
+ do_summon("summons an angel!", 1, SUMMON_ANGEL, blind_msg_default);
break;
}
- /* RF6_S_DEMON */
- case 160 + 25:
+ case SF_S_DEMON_IDX:
{
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s magically summons a demon!", m_name);
- for (k = 0; k < 1; k++)
- {
- count += summon_specific(y, x, rlev, SUMMON_DEMON);
- }
- if (blind && count) msg_print("You hear something appear nearby.");
+ do_summon("summons a demon!", 1, SUMMON_DEMON, blind_msg_default);
break;
}
- /* RF6_S_UNDEAD */
- case 160 + 26:
+ case SF_S_UNDEAD_IDX:
{
- disturb(1, 0);
- 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++)
- {
- count += summon_specific(y, x, rlev, SUMMON_UNDEAD);
- }
- if (blind && count) msg_print("You hear something appear nearby.");
+ do_summon("summons an undead adversary!", 1, SUMMON_UNDEAD, blind_msg_default);
break;
}
- /* RF6_S_DRAGON */
- case 160 + 27:
+ case SF_S_DRAGON_IDX:
{
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s magically summons a dragon!", m_name);
- for (k = 0; k < 1; k++)
- {
- count += summon_specific(y, x, rlev, SUMMON_DRAGON);
- }
- if (blind && count) msg_print("You hear something appear nearby.");
+ do_summon("summons a dragon!", 1, SUMMON_DRAGON, blind_msg_default);
break;
}
- /* RF6_S_HI_UNDEAD */
- case 160 + 28:
+ case SF_S_HI_UNDEAD_IDX:
{
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s magically summons greater undead!", m_name);
- for (k = 0; k < 8; k++)
- {
- count += summon_specific(y, x, rlev, SUMMON_HI_UNDEAD);
- }
- if (blind && count)
- {
- msg_print("You hear many creepy things appear nearby.");
- }
+ summon_messages blind_msg {
+ "You hear a creepy thing appear nearby.",
+ "You hear many creepy things appear nearby."
+ };
+ do_summon("summons greater undead!", 8, SUMMON_HI_UNDEAD, blind_msg);
break;
}
- /* RF6_S_HI_DRAGON */
- case 160 + 29:
+ case SF_S_HI_DRAGON_IDX:
{
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s magically summons ancient dragons!", m_name);
- for (k = 0; k < 8; k++)
- {
- count += summon_specific(y, x, rlev, SUMMON_HI_DRAGON);
- }
- if (blind && count)
- {
- msg_print("You hear many powerful things appear nearby.");
- }
+ summon_messages blind_msg {
+ "You hear a powerful thing appear nearby.",
+ "You hear many powerful things appear nearby."
+ };
+ do_summon("summons ancient dragons!", 8, SUMMON_HI_DRAGON, blind_msg);
break;
}
- /* RF6_S_WRAITH */
- case 160 + 30:
+ case SF_S_WRAITH_IDX:
{
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s magically summons Wraith!", m_name);
-
+ summon_messages blind_msg {
+ "You hear an immortal being appear nearby.",
+ "You hear immortal beings appear nearby."
+ };
+ do_summon("summons Wraiths!", 8, SUMMON_WRAITH, blind_msg);
+ break;
+ }
- for (k = 0; k < 8; k++)
+ case SF_S_UNIQUE_IDX:
+ {
+ // Interrupt
+ disturb();
+ // Message
+ if (blind)
{
- count += summon_specific(y, x, rlev, SUMMON_WRAITH);
+ msg_format("%^s mumbles.", m_name);
}
-
- if (blind && count)
+ else
{
- msg_print("You hear immortal beings appear nearby.");
+ msg_format("%^s magically summons special opponents!", m_name);
}
- break;
- }
-
- /* RF6_S_UNIQUE */
- case 160 + 31:
- {
- disturb(1, 0);
- if (blind) msg_format("%^s mumbles.", m_name);
- else msg_format("%^s magically summons special opponents!", m_name);
- for (k = 0; k < 8; k++)
+ // Summon
+ int count = 0;
+ for (int k = 0; k < 8; k++)
{
- count += summon_specific(y, x, rlev, SUMMON_UNIQUE);
+ count += summon_specific(m_ptr->fy, m_ptr->fx, rlev, SUMMON_UNIQUE);
}
- for (k = 0; k < 8; k++)
+ for (int k = 0; k < 8; k++)
{
- count += summon_specific(y, x, rlev, SUMMON_HI_UNDEAD);
+ count += summon_specific(m_ptr->fy, m_ptr->fx, rlev, SUMMON_HI_UNDEAD);
}
- if (blind && count)
+ // Message
+ if (blind)
{
- msg_print("You hear many powerful things appear nearby.");
+ if (count == 1)
+ {
+ msg_print("You hear a powerful thing appear nearby.");
+ }
+ else if (count > 1)
+ {
+ msg_print("You hear many powerful things appear nearby.");
+ }
}
break;
}
}
}
- /* Remember what the monster did to us */
- if (seen)
- {
- /* Inate spell */
- if (thrown_spell < 32*4)
- {
- r_ptr->r_flags4 |= (1L << (thrown_spell - 32 * 3));
- if (r_ptr->r_cast_inate < MAX_UCHAR) r_ptr->r_cast_inate++;
- }
-
- /* Bolt or Ball */
- else if (thrown_spell < 32*5)
- {
- r_ptr->r_flags5 |= (1L << (thrown_spell - 32 * 4));
- if (r_ptr->r_cast_spell < MAX_UCHAR) r_ptr->r_cast_spell++;
- }
-
- /* Special spell */
- else if (thrown_spell < 32*6)
- {
- r_ptr->r_flags6 |= (1L << (thrown_spell - 32 * 5));
- if (r_ptr->r_cast_spell < MAX_UCHAR) r_ptr->r_cast_spell++;
- }
- }
-
-
- /* Always take note of monsters that kill you */
- if (death && (r_ptr->r_deaths < MAX_SHORT))
- {
- r_ptr->r_deaths++;
- }
-
/* A spell was cast */
return (TRUE);
}
@@ -4671,16 +3834,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);
@@ -4690,8 +3848,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);
@@ -4720,8 +3876,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);
}
@@ -4761,23 +3915,20 @@ static int mon_will_run(int m_idx)
*/
static bool_ get_fear_moves_aux(int m_idx, int *yp, int *xp)
{
- int y, x, y1, x1, fy, fx, gy = 0, gx = 0;
- int when = 0, score = -1;
- int i;
-
- monster_type *m_ptr = &m_list[m_idx];
- monster_race *r_ptr = race_inf(m_ptr);
-
/* Monster flowing disabled */
- if (!flow_by_sound) return (FALSE);
+ if (!options->flow_by_sound)
+ {
+ return (FALSE);
+ }
/* Monster location */
- fy = m_ptr->fy;
- fx = m_ptr->fx;
+ monster_type *m_ptr = &m_list[m_idx];
+ const int fy = m_ptr->fy;;
+ const int fx = m_ptr->fx;
/* Desired destination */
- y1 = fy - (*yp);
- x1 = fx - (*xp);
+ int y1 = fy - (*yp);
+ int x1 = fx - (*xp);
/* The player is not currently near the monster grid */
if (cave[fy][fx].when < cave[p_ptr->py][p_ptr->px].when)
@@ -4787,17 +3938,24 @@ static bool_ get_fear_moves_aux(int m_idx, int *yp, int *xp)
}
/* Monster is too far away to use flow information */
+ auto const r_ptr = m_ptr->race();
if (cave[fy][fx].cost > MONSTER_FLOW_DEPTH) return (FALSE);
if (cave[fy][fx].cost > r_ptr->aaf) return (FALSE);
+ /* Loop state */
+ int when = 0;
+ int gy = 0;
+ int gx = 0;
+ int score = -1;
+
/* Check nearby grids, diagonals first */
- for (i = 7; i >= 0; i--)
+ for (int i = 7; i >= 0; i--)
{
int dis, s;
/* Get the location */
- y = fy + ddy_ddd[i];
- x = fx + ddx_ddd[i];
+ const int y = fy + ddy_ddd[i];
+ const int x = fx + ddx_ddd[i];
/* Ignore illegal locations */
if (cave[y][x].when == 0) continue;
@@ -4879,7 +4037,7 @@ static bool_ find_safety(int m_idx, int *yp, int *xp)
if (distance(y, x, fy, fx) != d) continue;
/* Check for "availability" (if monsters can flow) */
- if (flow_by_sound)
+ if (options->flow_by_sound)
{
/* Ignore grids very far from the player */
if (cave[y][x].when < cave[p_ptr->py][p_ptr->px].when) continue;
@@ -4997,19 +4155,20 @@ static bool_ find_hiding(int m_idx, int *yp, int *xp)
/* Find an appropriate corpse */
void find_corpse(monster_type *m_ptr, int *y, int *x)
{
+ auto const &r_info = game->edit_data.r_info;
+
int k, last = -1;
for (k = 0; k < max_o_idx; k++)
{
object_type *o_ptr = &o_list[k];
- monster_race *rt_ptr, *rt2_ptr;
if (!o_ptr->k_idx) continue;
if (o_ptr->tval != TV_CORPSE) continue;
if ((o_ptr->sval != SV_CORPSE_CORPSE) && (o_ptr->sval != SV_CORPSE_SKELETON)) continue;
- rt_ptr = &r_info[o_ptr->pval2];
+ auto rt_ptr = &r_info[o_ptr->pval2];
/* Cannot incarnate into a higher level monster */
if (rt_ptr->level > m_ptr->level) continue;
@@ -5019,9 +4178,16 @@ void find_corpse(monster_type *m_ptr, int *y, int *x)
if (last != -1)
{
- rt2_ptr = &r_info[o_list[last].pval2];
- if (rt_ptr->level > rt2_ptr->level) last = k;
- else continue;
+ auto rt2_ptr = &r_info[o_list[last].pval2];
+
+ if (rt_ptr->level > rt2_ptr->level)
+ {
+ last = k;
+ }
+ else
+ {
+ continue;
+ }
}
else
{
@@ -5042,6 +4208,8 @@ void find_corpse(monster_type *m_ptr, int *y, int *x)
*/
static void get_target_monster(int m_idx)
{
+ auto const &r_info = game->edit_data.r_info;
+
monster_type *m_ptr = &m_list[m_idx];
int i, t = -1, d = 9999;
@@ -5051,7 +4219,7 @@ static void get_target_monster(int m_idx)
/* Access the monster */
monster_type *t_ptr = &m_list[i];
/* hack should call the function for ego monsters ... but no_target i not meant to be added by ego and it speeds up the code */
- monster_race *rt_ptr = &r_info[t_ptr->r_idx];
+ auto rt_ptr = &r_info[t_ptr->r_idx];
int dd;
/* Ignore "dead" monsters */
@@ -5060,7 +4228,7 @@ static void get_target_monster(int m_idx)
if (m_idx == i) continue;
/* Cannot be targeted */
- if (rt_ptr->flags7 & RF7_NO_TARGET) continue;
+ if (rt_ptr->flags & RF_NO_TARGET) continue;
if (is_enemy(m_ptr, t_ptr) && (los(m_ptr->fy, m_ptr->fx, t_ptr->fy, t_ptr->fx) &&
((dd = distance(m_ptr->fy, m_ptr->fx, t_ptr->fy, t_ptr->fx)) < d)))
@@ -5081,9 +4249,6 @@ static void get_target_monster(int m_idx)
static bool_ get_moves(int m_idx, int *mm)
{
monster_type *m_ptr = &m_list[m_idx];
- monster_race *r_ptr = race_inf(m_ptr);
-
- int y, ay, x, ax;
int move_val = 0;
@@ -5119,25 +4284,30 @@ static bool_ get_moves(int m_idx, int *mm)
}
}
+ /* Get the race */
+ const auto r_ptr = m_ptr->race();
+
/* A possessor is not interrested in the player, it only wants a corpse */
- if (r_ptr->flags7 & RF7_POSSESSOR)
+ if (r_ptr->flags & RF_POSSESSOR)
{
find_corpse(m_ptr, &y2, &x2);
}
/* Let quests redefine AI */
- if (r_ptr->flags7 & RF7_AI_SPECIAL)
+ if (r_ptr->flags & RF_AI_SPECIAL)
{
- if (process_hooks_ret(HOOK_MONSTER_AI, "dd", "(d)", m_idx))
+ struct hook_monster_ai_in in = { m_idx, &m_list[m_idx] };
+ struct hook_monster_ai_out out = { 0, 0 };
+ if (process_hooks_new(HOOK_MONSTER_AI, &in, &out))
{
- y2 = process_hooks_return[0].num;
- x2 = process_hooks_return[1].num;
+ y2 = out.y;
+ x2 = out.x;
}
}
if (m_idx == p_ptr->control)
{
- if ((r_ptr->flags7 & RF7_AI_PLAYER) || magik(85))
+ if ((r_ptr->flags & RF_AI_PLAYER) || magik(85))
{
if (distance(p_ptr->py, p_ptr->px, m_ptr->fy, m_ptr->fx) < 50)
{
@@ -5148,11 +4318,11 @@ static bool_ get_moves(int m_idx, int *mm)
}
/* Extract the "pseudo-direction" */
- y = m_ptr->fy - y2;
- x = m_ptr->fx - x2;
+ int y = m_ptr->fy - y2;
+ int x = m_ptr->fx - x2;
/* Tease the player */
- if (r_ptr->flags7 & RF7_AI_ANNOY)
+ if (r_ptr->flags & RF_AI_ANNOY)
{
if (distance(m_ptr->fy, m_ptr->fx, y2, x2) < 4)
{
@@ -5162,7 +4332,7 @@ static bool_ get_moves(int m_idx, int *mm)
}
/* Death orbs .. */
- if (r_ptr->flags2 & RF2_DEATH_ORB)
+ if (r_ptr->flags & RF_DEATH_ORB)
{
if (!los(m_ptr->fy, m_ptr->fx, y2, x2))
{
@@ -5170,7 +4340,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;
@@ -5178,10 +4348,10 @@ static bool_ get_moves(int m_idx, int *mm)
* Animal packs try to get the player out of corridors
* (...unless they can move through walls -- TY)
*/
- if ((r_ptr->flags1 & RF1_FRIENDS) &&
- (r_ptr->flags3 & RF3_ANIMAL) &&
- !((r_ptr->flags2 & (RF2_PASS_WALL)) ||
- (r_ptr->flags2 & (RF2_KILL_WALL))))
+ if ((r_ptr->flags & RF_FRIENDS) &&
+ (r_ptr->flags & RF_ANIMAL) &&
+ !((r_ptr->flags & RF_PASS_WALL) ||
+ (r_ptr->flags & RF_KILL_WALL)))
{
int i, room = 0;
@@ -5205,7 +4375,7 @@ static bool_ get_moves(int m_idx, int *mm)
}
/* Monster groups try to surround the player */
- if (!done && (r_ptr->flags1 & RF1_FRIENDS))
+ if (!done && (r_ptr->flags & RF_FRIENDS))
{
int i;
@@ -5243,7 +4413,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))
{
@@ -5265,25 +4435,22 @@ static bool_ get_moves(int m_idx, int *mm)
else
{
/* Attempt to avoid the player */
- if (flow_by_sound)
+ if (options->flow_by_sound)
{
/* Adjust movement */
- (void)get_fear_moves_aux(m_idx, &y, &x);
+ get_fear_moves_aux(m_idx, &y, &x);
}
}
}
}
- 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);
- ay = ABS(y);
+ int ay = ABS(y);
+ int ax = ABS(x);
/* Do something weird */
if (y < 0) move_val += 8;
@@ -5476,37 +4643,39 @@ int check_hit2(int power, int level, int ac)
/* Monster attacks monster */
static bool_ monst_attack_monst(int m_idx, int t_idx)
{
- monster_type *m_ptr = &m_list[m_idx], *t_ptr = &m_list[t_idx];
- monster_race *r_ptr = race_inf(m_ptr);
- monster_race *tr_ptr = race_inf(t_ptr);
- int ap_cnt;
- int ac, rlev, pt;
- char m_name[80], t_name[80];
- char ddesc[80], temp[80];
- bool_ blinked = FALSE, touched = FALSE;
+ char temp[80];
+ bool_ blinked = FALSE;
+ bool_ touched = FALSE;
bool_ explode = FALSE;
bool_ fear = FALSE;
+ monster_type *t_ptr = &m_list[t_idx];
byte y_saver = t_ptr->fy;
byte x_saver = t_ptr->fx;
+ /* Get the racial information on the two monsters */
+ monster_type *m_ptr = &m_list[m_idx];
+ const auto r_ptr = m_ptr->race();
+ const auto tr_ptr = t_ptr->race();
/* Not allowed to attack */
- if (r_ptr->flags1 & RF1_NEVER_BLOW) return FALSE;
- if (tr_ptr->flags7 & RF7_IM_MELEE) return FALSE;
+ if (r_ptr->flags & RF_NEVER_BLOW) return FALSE;
/* Total armor */
- ac = t_ptr->ac;
+ const int ac = t_ptr->ac;
/* Extract the effective monster level */
- rlev = ((m_ptr->level >= 1) ? m_ptr->level : 1);
+ const int rlev = ((m_ptr->level >= 1) ? m_ptr->level : 1);
/* Get the monster name (or "it") */
+ char m_name[80];
monster_desc(m_name, m_ptr, 0);
/* Get the monster name (or "it") */
+ char t_name[80];
monster_desc(t_name, t_ptr, 0);
/* Get the "died from" information (i.e. "a kobold") */
+ char ddesc[80];
monster_desc(ddesc, m_ptr, 0x88);
/* Assume no blink */
@@ -5518,11 +4687,8 @@ static bool_ monst_attack_monst(int m_idx, int t_idx)
}
/* Scan through all four blows */
- for (ap_cnt = 0; ap_cnt < 4; ap_cnt++)
+ for (int ap_cnt = 0; ap_cnt < 4; ap_cnt++)
{
- bool_ visible = FALSE;
- bool_ obvious = FALSE;
-
int power = 0;
int damage = 0;
@@ -5553,9 +4719,6 @@ static bool_ monst_attack_monst(int m_idx, int t_idx)
/* break; */
}
- /* Extract visibility (before blink) */
- if (m_ptr->ml) visible = TRUE;
-
/* Extract the attack "power" */
power = get_attack_power(effect);
@@ -5564,7 +4727,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);
+ disturb_on_other();
/* Describe the attack method */
switch (method)
@@ -5745,22 +4908,19 @@ static bool_ monst_attack_monst(int m_idx, int t_idx)
/* Message */
if (act)
{
- strfmt(temp, act, t_name);
+ strnfmt(temp, sizeof(temp), act, t_name);
if (m_ptr->ml || t_ptr->ml)
monster_msg("%^s %s", m_name, temp);
}
- /* Hack -- assume all attacks are obvious */
- obvious = TRUE;
-
/* Roll out the damage */
damage = damroll(d_dice, d_side);
/* Hack need more punch against monsters */
damage *= 3;
- pt = GF_MISSILE;
+ int pt = GF_MISSILE;
/* Apply appropriate damage */
switch (effect)
@@ -5910,15 +5070,13 @@ static bool_ monst_attack_monst(int m_idx, int t_idx)
if (touched)
{
/* Aura fire */
- if ((tr_ptr->flags2 & RF2_AURA_FIRE) &&
- !(r_ptr->flags3 & RF3_IM_FIRE))
+ if ((tr_ptr->flags & RF_AURA_FIRE) &&
+ !(r_ptr->flags & RF_IM_FIRE))
{
if (m_ptr->ml || t_ptr->ml)
{
blinked = FALSE;
monster_msg("%^s is suddenly very hot!", m_name);
- if (t_ptr->ml)
- tr_ptr->r_flags2 |= RF2_AURA_FIRE;
}
project(t_idx, 0, m_ptr->fy, m_ptr->fx,
damroll (1 + ((t_ptr->level) / 26),
@@ -5927,14 +5085,12 @@ static bool_ monst_attack_monst(int m_idx, int t_idx)
}
/* Aura elec */
- if ((tr_ptr->flags2 & (RF2_AURA_ELEC)) && !(r_ptr->flags3 & (RF3_IM_ELEC)))
+ if ((tr_ptr->flags & RF_AURA_ELEC) && !(r_ptr->flags & RF_IM_ELEC))
{
if (m_ptr->ml || t_ptr->ml)
{
blinked = FALSE;
monster_msg("%^s gets zapped!", m_name);
- if (t_ptr->ml)
- tr_ptr->r_flags2 |= RF2_AURA_ELEC;
}
project(t_idx, 0, m_ptr->fy, m_ptr->fx,
damroll (1 + ((t_ptr->level) / 26),
@@ -5969,7 +5125,7 @@ static bool_ monst_attack_monst(int m_idx, int t_idx)
if (m_ptr->ml)
{
/* Disturbing */
- disturb(1, 0);
+ disturb();
/* Message */
monster_msg("%^s misses %s.", m_name, t_name);
@@ -5979,26 +5135,10 @@ static bool_ monst_attack_monst(int m_idx, int t_idx)
}
}
}
-
-
- /* 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]++;
- }
- }
- }
}
if (explode)
{
- sound(SOUND_EXPLODE);
mon_take_hit_mon(m_idx, m_idx, m_ptr->hp + 1, &fear, " explodes into tiny shreds.");
blinked = FALSE;
@@ -6032,34 +5172,31 @@ static u32b noise = 0L;
/* Determine whether the player is invisible to a monster */
static bool_ player_invis(monster_type * m_ptr)
{
- s16b inv, mlv;
- monster_race *r_ptr = race_inf(m_ptr);
+ const auto r_ptr = m_ptr->race();
+ s16b inv = p_ptr->invis;
+ s16b mlv = m_ptr->level;
- inv = p_ptr->invis;
-
- mlv = (s16b) m_ptr->level;
-
- if (r_ptr->flags3 & RF3_NO_SLEEP)
+ if (r_ptr->flags & RF_NO_SLEEP)
mlv += 10;
- if (r_ptr->flags3 & RF3_DRAGON)
+ if (r_ptr->flags & RF_DRAGON)
mlv += 20;
- if (r_ptr->flags3 & RF3_UNDEAD)
+ if (r_ptr->flags & RF_UNDEAD)
mlv += 15;
- if (r_ptr->flags3 & RF3_DEMON)
+ if (r_ptr->flags & RF_DEMON)
mlv += 15;
- if (r_ptr->flags3 & RF3_ANIMAL)
+ if (r_ptr->flags & RF_ANIMAL)
mlv += 15;
- if (r_ptr->flags3 & RF3_ORC)
+ if (r_ptr->flags & RF_ORC)
mlv -= 15;
- if (r_ptr->flags3 & RF3_TROLL)
+ if (r_ptr->flags & RF_TROLL)
mlv -= 10;
- if (r_ptr->flags2 & RF2_STUPID)
+ if (r_ptr->flags & RF_STUPID)
mlv /= 2;
- if (r_ptr->flags2 & RF2_SMART)
+ if (r_ptr->flags & RF_SMART)
mlv = (mlv * 5) / 4;
if (m_ptr->mflag & MFLAG_QUEST)
inv = 0;
- if (r_ptr->flags2 & RF2_INVISIBLE)
+ if (r_ptr->flags & RF_INVISIBLE)
inv = 0;
if (m_ptr->mflag & MFLAG_CONTROL)
inv = 0;
@@ -6096,35 +5233,17 @@ static bool_ player_invis(monster_type * m_ptr)
*/
static void process_monster(int m_idx, bool_ is_frien)
{
- monster_type *m_ptr = &m_list[m_idx];
- monster_race *r_ptr = race_inf(m_ptr);
- cave_type *c_ptr = &cave[m_ptr->fy][m_ptr->fx];
+ auto const &f_info = game->edit_data.f_info;
int i, d, oy, ox, ny, nx;
int mm[8];
- monster_type *y_ptr;
-
- bool_ do_turn;
- bool_ do_move;
- bool_ do_view;
-
- bool_ did_open_door;
- bool_ did_bash_door;
- bool_ did_take_item;
- bool_ did_kill_item;
- bool_ did_move_body;
- bool_ did_kill_body;
- bool_ did_pass_wall;
- bool_ did_kill_wall;
- bool_ gets_angry = FALSE;
- bool_ inv;
- bool_ xxx = FALSE;
-
- inv = player_invis(m_ptr);
+ monster_type *m_ptr = &m_list[m_idx];
+ const bool_ inv = player_invis(m_ptr);
- if (r_ptr->flags9 & RF9_DOPPLEGANGER) doppleganger = m_idx;
+ auto const r_ptr = m_ptr->race();
+ if (r_ptr->flags & RF_DOPPLEGANGER) doppleganger = m_idx;
/* Handle "bleeding" */
if (m_ptr->bleeding)
@@ -6133,6 +5252,7 @@ static void process_monster(int m_idx, bool_ is_frien)
if (d > m_ptr->bleeding) d = m_ptr->bleeding;
/* Exit if the monster dies */
+ bool_ xxx = FALSE;
if (mon_take_hit(m_idx, d, &xxx, " bleeds to death.")) return;
/* Hack -- Recover from bleeding */
@@ -6160,7 +5280,7 @@ static void process_monster(int m_idx, bool_ is_frien)
msg_format("%^s is no longer bleeding.", m_name);
/* Hack -- Update the health bar */
- if (health_who == m_idx) p_ptr->redraw |= (PR_HEALTH);
+ if (health_who == m_idx) p_ptr->redraw |= (PR_FRAME);
}
}
}
@@ -6172,6 +5292,7 @@ static void process_monster(int m_idx, bool_ is_frien)
if (d < 1) d = 1;
/* Exit if the monster dies */
+ bool_ xxx = FALSE;
if (mon_take_hit(m_idx, d, &xxx, " dies of poison.")) return;
/* Hack -- Recover from bleeding */
@@ -6199,7 +5320,7 @@ static void process_monster(int m_idx, bool_ is_frien)
msg_format("%^s is no longer poisoned.", m_name);
/* Hack -- Update the health bar */
- if (health_who == m_idx) p_ptr->redraw |= (PR_HEALTH);
+ if (health_who == m_idx) p_ptr->redraw |= (PR_FRAME);
}
}
}
@@ -6229,18 +5350,7 @@ static void process_monster(int m_idx, bool_ is_frien)
{
/* Monster wakes up "a little bit" */
m_ptr->csleep -= d;
-
- /* Notice the "not waking up" */
- if (m_ptr->ml)
- {
- /* Hack -- Count the ignores */
- if (r_ptr->r_ignore < MAX_UCHAR)
- {
- r_ptr->r_ignore++;
- }
- }
}
-
/* Just woke up */
else
{
@@ -6257,12 +5367,6 @@ static void process_monster(int m_idx, bool_ is_frien)
/* Dump a message */
msg_format("%^s wakes up.", m_name);
-
- /* Hack -- Count the wakings */
- if (r_ptr->r_wake < MAX_UCHAR)
- {
- r_ptr->r_wake++;
- }
}
}
}
@@ -6348,13 +5452,16 @@ static void process_monster(int m_idx, bool_ is_frien)
}
}
+ /* Do the monster get angry? */
+ bool_ gets_angry = FALSE;
+
/* No one wants to be your friend if you're aggravating */
- if ((m_ptr->status > MSTATUS_NEUTRAL) && (m_ptr->status < MSTATUS_COMPANION) && (p_ptr->aggravate) && !(r_ptr->flags7 & RF7_PET))
+ if ((m_ptr->status > MSTATUS_NEUTRAL) && (m_ptr->status < MSTATUS_COMPANION) && (p_ptr->aggravate) && !(r_ptr->flags & RF_PET))
gets_angry = TRUE;
/* Paranoia... no friendly uniques outside wizard mode -- TY */
if ((m_ptr->status > MSTATUS_NEUTRAL) && (m_ptr->status < MSTATUS_COMPANION) && !(wizard) &&
- (r_ptr->flags1 & (RF1_UNIQUE)) && !(r_ptr->flags7 & RF7_PET))
+ (r_ptr->flags & RF_UNIQUE) && !(r_ptr->flags & RF_PET))
gets_angry = TRUE;
if (gets_angry)
@@ -6410,46 +5517,44 @@ static void process_monster(int m_idx, bool_ is_frien)
ox = m_ptr->fx;
/* Attempt to "multiply" if able and allowed */
- if ((r_ptr->flags4 & (RF4_MULTIPLY)) && (num_repro < MAX_REPRO))
+ if ((r_ptr->spells & SF_MULTIPLY) && (num_repro < MAX_REPRO))
{
if (ai_multiply(m_idx)) return;
}
- if (speak_unique)
+ if (randint(SPEAK_CHANCE) == 1)
{
- if (randint(SPEAK_CHANCE) == 1)
+ if (player_has_los_bold(oy, ox) && (r_ptr->flags & RF_CAN_SPEAK))
{
- if (player_has_los_bold(oy, ox) && (r_ptr->flags2 & RF2_CAN_SPEAK))
- {
- char m_name[80];
- char monmessage[80];
+ char m_name[80];
+ char monmessage[1024];
- /* Acquire the monster name/poss */
- if (m_ptr->ml)
- monster_desc(m_name, m_ptr, 0);
- else
- strcpy(m_name, "It");
+ /* Acquire the monster name/poss */
+ if (m_ptr->ml)
+ monster_desc(m_name, m_ptr, 0);
+ else
+ strcpy(m_name, "It");
- /* xtra_line function by Matt Graham--allow uniques to */
- /* say "unique" things based on their monster index. */
- /* Try for the unique's lines in "monspeak.txt" first. */
- /* 0 is SUCCESS, of course.... */
+ /* xtra_line function by Matt Graham--allow uniques to */
+ /* say "unique" things based on their monster index. */
+ /* Try for the unique's lines in "monspeak.txt" first. */
+ /* 0 is SUCCESS, of course.... */
- if (!process_hooks(HOOK_MON_SPEAK, "(d,s)", m_idx, m_name))
+ struct hook_mon_speak_in in = { m_idx, m_name };
+ if (!process_hooks_new(HOOK_MON_SPEAK, &in, NULL))
+ {
+ if (get_xtra_line("monspeak.txt", m_ptr, monmessage) != 0)
{
- if (get_xtra_line("monspeak.txt", m_ptr, monmessage) != 0)
- {
- /* Get a message from old defaults if new don't work */
-
- if (is_friend(m_ptr) > 0)
- get_rnd_line("speakpet.txt", monmessage);
- else if (m_ptr->monfear)
- get_rnd_line("monfear.txt", monmessage);
- else
- get_rnd_line("bravado.txt", monmessage);
- }
- msg_format("%^s %s", m_name, monmessage);
+ /* Get a message from old defaults if new don't work */
+
+ if (is_friend(m_ptr) > 0)
+ get_rnd_line("speakpet.txt", monmessage);
+ else if (m_ptr->monfear)
+ get_rnd_line("monfear.txt", monmessage);
+ else
+ get_rnd_line("bravado.txt", monmessage);
}
+ msg_format("%^s %s", m_name, monmessage);
}
}
}
@@ -6486,36 +5591,26 @@ static void process_monster(int m_idx, bool_ is_frien)
}
/* 75% random movement */
- else if ((r_ptr->flags1 & (RF1_RAND_50)) &&
- (r_ptr->flags1 & (RF1_RAND_25)) &&
+ else if ((r_ptr->flags & RF_RAND_50) &&
+ (r_ptr->flags & RF_RAND_25) &&
(rand_int(100) < 75))
{
- /* Memorize flags */
- if (m_ptr->ml) r_ptr->r_flags1 |= (RF1_RAND_50);
- if (m_ptr->ml) r_ptr->r_flags1 |= (RF1_RAND_25);
-
/* Try four "random" directions */
mm[0] = mm[1] = mm[2] = mm[3] = 5;
}
/* 50% random movement */
- else if ((r_ptr->flags1 & (RF1_RAND_50)) &&
+ else if ((r_ptr->flags & RF_RAND_50) &&
(rand_int(100) < 50))
{
- /* Memorize flags */
- if (m_ptr->ml) r_ptr->r_flags1 |= (RF1_RAND_50);
-
/* Try four "random" directions */
mm[0] = mm[1] = mm[2] = mm[3] = 5;
}
/* 25% random movement */
- else if ((r_ptr->flags1 & (RF1_RAND_25)) &&
+ else if ((r_ptr->flags & RF_RAND_25) &&
(rand_int(100) < 25))
{
- /* Memorize flags */
- if (m_ptr->ml) r_ptr->r_flags1 |= (RF1_RAND_25);
-
/* Try four "random" directions */
mm[0] = mm[1] = mm[2] = mm[3] = 5;
}
@@ -6523,36 +5618,22 @@ 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 */
+ cave_type *c_ptr = &cave[m_ptr->fy][m_ptr->fx];
if (!c_ptr->m_idx) return;
/* Assume nothing */
- do_turn = FALSE;
- do_move = FALSE;
- do_view = FALSE;
+ bool_ do_turn = FALSE;
+ bool_ do_move = FALSE;
+ bool_ do_view = FALSE;
/* Assume nothing */
- did_open_door = FALSE;
- did_bash_door = FALSE;
- did_take_item = FALSE;
- did_kill_item = FALSE;
- did_move_body = FALSE;
- did_kill_body = FALSE;
- did_pass_wall = FALSE;
- did_kill_wall = FALSE;
-
+ bool_ did_open_door = FALSE;
+ bool_ did_bash_door = FALSE;
/* Take a zero-terminated array of "directions" */
for (i = 0; mm[i]; i++)
@@ -6571,7 +5652,7 @@ static void process_monster(int m_idx, bool_ is_frien)
c_ptr = &cave[ny][nx];
/* Access that cave grid's contents */
- y_ptr = &m_list[c_ptr->m_idx];
+ monster_type *y_ptr = &m_list[c_ptr->m_idx];
/* Floor is open? */
@@ -6581,16 +5662,9 @@ static void process_monster(int m_idx, bool_ is_frien)
do_move = TRUE;
}
- /* Floor is trapped? */
- else if (c_ptr->feat == FEAT_MON_TRAP)
- {
- /* Go ahead and move */
- do_move = TRUE;
- }
-
/* Hack -- check for Glyph of Warding */
if ((c_ptr->feat == FEAT_GLYPH) &&
- !(r_ptr->flags1 & RF1_NEVER_BLOW))
+ !(r_ptr->flags & RF_NEVER_BLOW))
{
/* Assume no move allowed */
do_move = FALSE;
@@ -6616,7 +5690,7 @@ static void process_monster(int m_idx, bool_ is_frien)
}
/* Hack -- trees are obstacle */
- else if ((cave[ny][nx].feat == FEAT_TREES) && (r_ptr->flags9 & RF9_KILL_TREES))
+ else if ((cave[ny][nx].feat == FEAT_TREES) && (r_ptr->flags & RF_KILL_TREES))
{
do_move = TRUE;
@@ -6640,45 +5714,39 @@ static void process_monster(int m_idx, bool_ is_frien)
}
/* Permanent wall */
- else if (f_info[c_ptr->feat].flags1 & FF1_PERMANENT)
+ else if (f_info[c_ptr->feat].flags & FF_PERMANENT)
{
/* Nothing */
}
/* Some monsters can fly */
- else if ((f_info[c_ptr->feat].flags1 & FF1_CAN_LEVITATE) && (r_ptr->flags7 & (RF7_CAN_FLY)))
+ else if ((f_info[c_ptr->feat].flags & FF_CAN_LEVITATE) && (r_ptr->flags & RF_CAN_FLY))
{
/* Pass through walls/doors/rubble */
do_move = TRUE;
}
/* Some monsters can fly */
- else if ((f_info[c_ptr->feat].flags1 & FF1_CAN_FLY) && (r_ptr->flags7 & (RF7_CAN_FLY)))
+ else if ((f_info[c_ptr->feat].flags & FF_CAN_FLY) && (r_ptr->flags & RF_CAN_FLY))
{
/* Pass through trees/... */
do_move = TRUE;
}
/* Monster moves through walls (and doors) */
- else if ((f_info[c_ptr->feat].flags1 & FF1_CAN_PASS) && (r_ptr->flags2 & (RF2_PASS_WALL)))
+ else if ((f_info[c_ptr->feat].flags & FF_CAN_PASS) && (r_ptr->flags & RF_PASS_WALL))
{
/* Pass through walls/doors/rubble */
do_move = TRUE;
-
- /* Monster went through a wall */
- did_pass_wall = TRUE;
}
/* Monster destroys walls (and doors) */
- else if ((f_info[c_ptr->feat].flags1 & FF1_CAN_PASS) && (r_ptr->flags2 & (RF2_KILL_WALL)))
+ else if ((f_info[c_ptr->feat].flags & FF_CAN_PASS) && (r_ptr->flags & RF_KILL_WALL))
{
/* Eat through walls/doors/rubble */
do_move = TRUE;
- /* Monster destroyed a wall */
- did_kill_wall = TRUE;
-
if (randint(GRINDNOISE) == 1)
{
msg_print("There is a grinding sound.");
@@ -6695,18 +5763,15 @@ static void process_monster(int m_idx, bool_ is_frien)
}
/* Monster moves through walls (and doors) */
- else if ((f_info[c_ptr->feat].flags1 & FF1_CAN_PASS) && (r_ptr->flags2 & (RF2_PASS_WALL)))
+ else if ((f_info[c_ptr->feat].flags & FF_CAN_PASS) && (r_ptr->flags & RF_PASS_WALL))
{
/* Pass through walls/doors/rubble */
do_move = TRUE;
-
- /* Monster went through a wall */
- did_pass_wall = TRUE;
}
/* Monster moves through webs */
- else if ((f_info[c_ptr->feat].flags1 & FF1_WEB) &&
- (r_ptr->flags7 & RF7_SPIDER))
+ else if ((f_info[c_ptr->feat].flags & FF_WEB) &&
+ (r_ptr->flags & RF_SPIDER))
{
/* Pass through webs */
do_move = TRUE;
@@ -6722,7 +5787,7 @@ static void process_monster(int m_idx, bool_ is_frien)
/* Take a turn */
do_turn = TRUE;
- if ((r_ptr->flags2 & (RF2_OPEN_DOOR)) &&
+ if ((r_ptr->flags & RF_OPEN_DOOR) &&
((is_friend(m_ptr) <= 0) || p_ptr->pet_open_doors))
{
/* Closed doors and secret doors */
@@ -6757,7 +5822,7 @@ static void process_monster(int m_idx, bool_ is_frien)
}
/* Stuck doors -- attempt to bash them down if allowed */
- if (may_bash && (r_ptr->flags2 & RF2_BASH_DOOR) &&
+ if (may_bash && (r_ptr->flags & RF_BASH_DOOR) &&
((is_friend(m_ptr) <= 0) || p_ptr->pet_open_doors))
{
int k;
@@ -6772,7 +5837,10 @@ 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 (options->disturb_minor)
+ {
+ disturb();
+ }
/* The door was bashed open */
did_bash_door = TRUE;
@@ -6806,7 +5874,7 @@ static void process_monster(int m_idx, bool_ is_frien)
}
}
else if (do_move && (c_ptr->feat == FEAT_MINOR_GLYPH)
- && !(r_ptr->flags1 & RF1_NEVER_BLOW))
+ && !(r_ptr->flags & RF_NEVER_BLOW))
{
/* Assume no move allowed */
do_move = FALSE;
@@ -6851,7 +5919,7 @@ static void process_monster(int m_idx, bool_ is_frien)
/* Access that cave grid's contents */
y_ptr = &m_list[c_ptr->m_idx];
- if (!(r_ptr->flags3 & RF3_IM_COLD))
+ if (!(r_ptr->flags & RF_IM_COLD))
{
if ((m_ptr->hp - distance(ny, nx, oy, ox)*2) <= 0)
{
@@ -6891,7 +5959,7 @@ static void process_monster(int m_idx, bool_ is_frien)
/* Some monsters never attack */
if (do_move && (ny == p_ptr->py) && (nx == p_ptr->px) &&
- (r_ptr->flags1 & RF1_NEVER_BLOW))
+ (r_ptr->flags & RF_NEVER_BLOW))
{
/* Do not move */
do_move = FALSE;
@@ -6901,7 +5969,7 @@ static void process_monster(int m_idx, bool_ is_frien)
if (do_move && (ny == p_ptr->py) && (nx == p_ptr->px))
{
/* Do the attack */
- (void)make_attack_normal(m_idx, 1);
+ make_attack_normal(m_idx, 1);
/* Do not move */
do_move = FALSE;
@@ -6921,19 +5989,19 @@ static void process_monster(int m_idx, bool_ is_frien)
/* A monster is in the way */
if (do_move && c_ptr->m_idx)
{
- monster_race *z_ptr = race_inf(y_ptr);
+ auto z_ptr = y_ptr->race();
monster_type *m2_ptr = &m_list[c_ptr->m_idx];
/* Assume no movement */
do_move = FALSE;
/* Kill weaker monsters */
- if ((r_ptr->flags2 & RF2_KILL_BODY) &&
+ if ((r_ptr->flags & RF_KILL_BODY) &&
(r_ptr->mexp > z_ptr->mexp) && (cave_floor_bold(ny, nx)) &&
/* Friends don't kill friends... */
!((is_friend(m_ptr) > 0) && (is_friend(m2_ptr) > 0)) &&
/* Uniques aren't faceless monsters in a crowd */
- !(z_ptr->flags1 & RF1_UNIQUE) &&
+ !(z_ptr->flags & RF_UNIQUE) &&
/* Don't wreck quests */
!(m2_ptr->mflag & (MFLAG_QUEST | MFLAG_QUEST2)) &&
/* Don't punish summoners for relying on their friends */
@@ -6942,11 +6010,6 @@ static void process_monster(int m_idx, bool_ is_frien)
/* Allow movement */
do_move = TRUE;
- /* Monster ate another monster */
- did_kill_body = TRUE;
-
- /* XXX XXX XXX Message */
-
/* Kill the monster */
delete_monster(ny, nx);
@@ -6972,17 +6035,12 @@ static void process_monster(int m_idx, bool_ is_frien)
}
/* Push past weaker monsters (unless leaving a wall) */
- else if ((r_ptr->flags2 & RF2_MOVE_BODY) &&
+ else if ((r_ptr->flags & RF_MOVE_BODY) &&
(r_ptr->mexp > z_ptr->mexp) && cave_floor_bold(ny, nx) &&
(cave_floor_bold(m_ptr->fy, m_ptr->fx)))
{
/* Allow movement */
do_move = TRUE;
-
- /* Monster pushed past another monster */
- did_move_body = TRUE;
-
- /* XXX XXX XXX Message */
}
}
@@ -6999,11 +6057,8 @@ static void process_monster(int m_idx, bool_ is_frien)
}
/* Some monsters never move */
- if (do_move && (r_ptr->flags1 & RF1_NEVER_MOVE))
+ if (do_move && (r_ptr->flags & RF_NEVER_MOVE))
{
- /* Hack -- memorize lack of attacks */
- /* if (m_ptr->ml) r_ptr->r_flags1 |= (RF1_NEVER_MOVE); */
-
/* Do not move */
do_move = FALSE;
}
@@ -7013,8 +6068,6 @@ static void process_monster(int m_idx, bool_ is_frien)
/* Creature has been allowed move */
if (do_move)
{
- s16b this_o_idx, next_o_idx = 0;
-
/* Take a turn */
do_turn = TRUE;
@@ -7068,163 +6121,130 @@ static void process_monster(int m_idx, bool_ is_frien)
}
/* Possible disturb */
- if (m_ptr->ml && (disturb_move ||
+ if (m_ptr->ml && (options->disturb_move ||
((m_ptr->mflag & (MFLAG_VIEW)) &&
- disturb_near)))
+ options->disturb_near)))
{
/* Disturb */
- if ((is_friend(m_ptr) < 0) || disturb_pets)
- disturb(0, 0);
+ if ((is_friend(m_ptr) < 0) || options->disturb_pets)
+ disturb();
}
- /* Check for monster trap */
- if (c_ptr->feat == FEAT_MON_TRAP)
- {
- if (mon_hit_trap(m_idx)) return;
- }
- else
- {
- /* 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 gold */
- if (o_ptr->tval == TV_GOLD) continue;
-
- /* Incarnate ? */
- if ((o_ptr->tval == TV_CORPSE) && (r_ptr->flags7 & RF7_POSSESSOR) &&
- ((o_ptr->sval == SV_CORPSE_CORPSE) || (o_ptr->sval == SV_CORPSE_SKELETON)))
- {
- if (ai_possessor(m_idx, this_o_idx)) return;
- }
-
- /* Take or Kill objects on the floor */
- /* rr9: Pets will no longer pick up/destroy items */
- if ((((r_ptr->flags2 & (RF2_TAKE_ITEM)) &&
- ((is_friend(m_ptr) <= 0) || p_ptr->pet_pickup_items)) ||
- (r_ptr->flags2 & (RF2_KILL_ITEM))) &&
- (is_friend(m_ptr) <= 0))
- {
- u32b f1, f2, f3, f4, f5, esp;
- u32b flg3 = 0L;
+ /* Copy list of objects; we need a copy because we're mutating the list. */
+ auto const object_idxs(c_ptr->o_idxs);
- char m_name[80];
- char o_name[80];
+ /* Scan all objects in the grid */
+ for (auto const this_o_idx: object_idxs)
+ {
+ /* Acquire object */
+ object_type * o_ptr = &o_list[this_o_idx];
- /* Extract some flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ /* Skip gold */
+ if (o_ptr->tval == TV_GOLD) continue;
- /* Acquire the object name */
- object_desc(o_name, o_ptr, TRUE, 3);
+ /* Incarnate ? */
+ if ((o_ptr->tval == TV_CORPSE) && (r_ptr->flags & RF_POSSESSOR) &&
+ ((o_ptr->sval == SV_CORPSE_CORPSE) || (o_ptr->sval == SV_CORPSE_SKELETON)))
+ {
+ if (ai_possessor(m_idx, this_o_idx)) return;
+ }
- /* Acquire the monster name */
- monster_desc(m_name, m_ptr, 0x04);
+ /* Take or Kill objects on the floor */
+ /* rr9: Pets will no longer pick up/destroy items */
+ if ((((r_ptr->flags & RF_TAKE_ITEM) &&
+ ((is_friend(m_ptr) <= 0) || p_ptr->pet_pickup_items)) ||
+ (r_ptr->flags & RF_KILL_ITEM)) &&
+ (is_friend(m_ptr) <= 0))
+ {
+ char m_name[80];
+ char o_name[80];
- /* React to objects that hurt the monster */
- if (f5 & (TR5_KILL_DEMON)) flg3 |= (RF3_DEMON);
- if (f5 & (TR5_KILL_UNDEAD)) flg3 |= (RF3_UNDEAD);
- if (f1 & (TR1_SLAY_DRAGON)) flg3 |= (RF3_DRAGON);
- if (f1 & (TR1_SLAY_TROLL)) flg3 |= (RF3_TROLL);
- if (f1 & (TR1_SLAY_GIANT)) flg3 |= (RF3_GIANT);
- if (f1 & (TR1_SLAY_ORC)) flg3 |= (RF3_ORC);
- if (f1 & (TR1_SLAY_DEMON)) flg3 |= (RF3_DEMON);
- if (f1 & (TR1_SLAY_UNDEAD)) flg3 |= (RF3_UNDEAD);
- if (f1 & (TR1_SLAY_ANIMAL)) flg3 |= (RF3_ANIMAL);
- if (f1 & (TR1_SLAY_EVIL)) flg3 |= (RF3_EVIL);
+ /* Extract some flags */
+ auto const flags = object_flags(o_ptr);
- /* The object cannot be picked up by the monster */
- if (artifact_p(o_ptr) || (r_ptr->flags3 & flg3) ||
- (o_ptr->art_name))
- {
- /* Only give a message for "take_item" */
- if (r_ptr->flags2 & (RF2_TAKE_ITEM))
- {
- /* Take note */
- did_take_item = TRUE;
-
- /* Describe observable situations */
- if (m_ptr->ml && player_has_los_bold(ny, nx))
- {
- /* Dump a message */
- msg_format("%^s tries to pick up %s, but fails.",
- m_name, o_name);
- }
- }
- }
+ /* Acquire the object name */
+ object_desc(o_name, o_ptr, TRUE, 3);
- /* Pick up the item */
- else if (r_ptr->flags2 & (RF2_TAKE_ITEM))
+ /* Acquire the monster name */
+ monster_desc(m_name, m_ptr, 0x04);
+
+ /* React to objects that hurt the monster */
+ monster_race_flag_set flg;
+ if (flags & TR_KILL_DEMON) flg |= RF_DEMON;
+ if (flags & TR_KILL_UNDEAD) flg |= RF_UNDEAD;
+ if (flags & TR_SLAY_DRAGON) flg |= RF_DRAGON;
+ if (flags & TR_SLAY_TROLL) flg |= RF_TROLL;
+ if (flags & TR_SLAY_GIANT) flg |= RF_GIANT;
+ if (flags & TR_SLAY_ORC) flg |= RF_ORC;
+ if (flags & TR_SLAY_DEMON) flg |= RF_DEMON;
+ if (flags & TR_SLAY_UNDEAD) flg |= RF_UNDEAD;
+ if (flags & TR_SLAY_ANIMAL) flg |= RF_ANIMAL;
+ if (flags & TR_SLAY_EVIL) flg |= RF_EVIL;
+
+ /* The object cannot be picked up by the monster */
+ if (artifact_p(o_ptr) || (r_ptr->flags & flg))
+ {
+ /* Only give a message for "take_item" */
+ if (r_ptr->flags & RF_TAKE_ITEM)
{
- /* Take note */
- did_take_item = TRUE;
-
/* Describe observable situations */
- if (player_has_los_bold(ny, nx))
+ if (m_ptr->ml && player_has_los_bold(ny, nx))
{
/* Dump a message */
- msg_format("%^s picks up %s.", m_name, o_name);
+ msg_format("%^s tries to pick up %s, but fails.",
+ m_name, o_name);
}
+ }
+ }
- /* Option */
- if (testing_carry)
- {
- /* Excise the object */
- excise_object_idx(this_o_idx);
-
- /* Forget mark */
- o_ptr->marked = FALSE;
+ /* Pick up the item */
+ else if (r_ptr->flags & RF_TAKE_ITEM)
+ {
+ /* Describe observable situations */
+ if (player_has_los_bold(ny, nx))
+ {
+ /* Dump a message */
+ msg_format("%^s picks up %s.", m_name, o_name);
+ }
- /* Forget location */
- o_ptr->iy = o_ptr->ix = 0;
+ /* Put into inventory of monster */
+ {
+ /* Excise the object */
+ excise_object_idx(this_o_idx);
- /* Memorize monster */
- o_ptr->held_m_idx = m_idx;
+ /* Forget mark */
+ o_ptr->marked = FALSE;
- /* Build a stack */
- o_ptr->next_o_idx = m_ptr->hold_o_idx;
+ /* Forget location */
+ o_ptr->iy = o_ptr->ix = 0;
- /* Carry object */
- m_ptr->hold_o_idx = this_o_idx;
- }
+ /* Memorize monster */
+ o_ptr->held_m_idx = m_idx;
- /* Nope */
- else
- {
- /* Delete the object */
- delete_object_idx(this_o_idx);
- }
+ /* Carry object */
+ m_ptr->hold_o_idxs.push_back(this_o_idx);
}
+ }
- /* Destroy the item */
- else
+ /* Destroy the item */
+ else
+ {
+ /* Describe observable situations */
+ if (player_has_los_bold(ny, nx))
{
- /* Take note */
- did_kill_item = TRUE;
-
- /* Describe observable situations */
- if (player_has_los_bold(ny, nx))
- {
- /* Dump a message */
- msg_format("%^s crushes %s.", m_name, o_name);
- }
-
- /* Delete the object */
- delete_object_idx(this_o_idx);
+ /* Dump a message */
+ msg_format("%^s crushes %s.", m_name, o_name);
}
+
+ /* Delete the object */
+ delete_object_idx(this_o_idx);
}
}
}
/* Update monster light */
- if (r_ptr->flags9 & RF9_HAS_LITE) p_ptr->update |= (PU_MON_LITE);
+ if (r_ptr->flags & RF_HAS_LITE) p_ptr->update |= (PU_MON_LITE);
}
/* Stop when done */
@@ -7233,7 +6253,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 */
@@ -7249,35 +6269,6 @@ static void process_monster(int m_idx, bool_ is_frien)
}
- /* Learn things from observable monster */
- if (m_ptr->ml)
- {
- /* Monster opened a door */
- if (did_open_door) r_ptr->r_flags2 |= (RF2_OPEN_DOOR);
-
- /* Monster bashed a door */
- if (did_bash_door) r_ptr->r_flags2 |= (RF2_BASH_DOOR);
-
- /* Monster tried to pick something up */
- if (did_take_item) r_ptr->r_flags2 |= (RF2_TAKE_ITEM);
-
- /* Monster tried to crush something */
- if (did_kill_item) r_ptr->r_flags2 |= (RF2_KILL_ITEM);
-
- /* Monster pushed past another monster */
- if (did_move_body) r_ptr->r_flags2 |= (RF2_MOVE_BODY);
-
- /* Monster ate another monster */
- if (did_kill_body) r_ptr->r_flags2 |= (RF2_KILL_BODY);
-
- /* Monster passed through a wall */
- if (did_pass_wall) r_ptr->r_flags2 |= (RF2_PASS_WALL);
-
- /* Monster destroyed a wall */
- if (did_kill_wall) r_ptr->r_flags2 |= (RF2_KILL_WALL);
- }
-
-
/* Hack -- get "bold" if out of options */
if (!do_turn && !do_move && m_ptr->monfear)
{
@@ -7374,8 +6365,10 @@ void summon_maint(int m_idx)
* changes (flags, attacks, spells), we induce a redraw of the monster
* recall window.
*/
-void process_monsters(void)
+void process_monsters()
{
+ auto const &r_info = game->edit_data.r_info;
+
int i, e;
int fx, fy;
@@ -7383,58 +6376,11 @@ void process_monsters(void)
bool_ is_frien = FALSE;
monster_type *m_ptr;
- monster_race *r_ptr;
-
- int old_monster_race_idx;
-
- u32b old_r_flags1 = 0L;
- u32b old_r_flags2 = 0L;
- u32b old_r_flags3 = 0L;
- u32b old_r_flags4 = 0L;
- u32b old_r_flags5 = 0L;
- u32b old_r_flags6 = 0L;
-
- byte old_r_blows0 = 0;
- byte old_r_blows1 = 0;
- byte old_r_blows2 = 0;
- byte old_r_blows3 = 0;
-
- byte old_r_cast_inate = 0;
- byte old_r_cast_spell = 0;
/* Check the doppleganger */
- if (doppleganger && !(r_info[m_list[doppleganger].r_idx].flags9 & RF9_DOPPLEGANGER))
+ if (doppleganger && !(r_info[m_list[doppleganger].r_idx].flags & RF_DOPPLEGANGER))
doppleganger = 0;
- /* Memorize old race */
- old_monster_race_idx = monster_race_idx;
-
- /* Acquire knowledge */
- if (monster_race_idx)
- {
- /* Acquire current monster */
- r_ptr = &r_info[monster_race_idx];
-
- /* Memorize flags */
- old_r_flags1 = r_ptr->r_flags1;
- old_r_flags2 = r_ptr->r_flags2;
- old_r_flags3 = r_ptr->r_flags3;
- old_r_flags4 = r_ptr->r_flags4;
- old_r_flags5 = r_ptr->r_flags5;
- old_r_flags6 = r_ptr->r_flags6;
-
- /* Memorize blows */
- old_r_blows0 = r_ptr->r_blows[0];
- old_r_blows1 = r_ptr->r_blows[1];
- old_r_blows2 = r_ptr->r_blows[2];
- old_r_blows3 = r_ptr->r_blows[3];
-
- /* Memorize castings */
- old_r_cast_inate = r_ptr->r_cast_inate;
- old_r_cast_spell = r_ptr->r_cast_spell;
- }
-
-
/* Hack -- calculate the "player noise" */
noise = (1L << (30 - p_ptr->skill_stl));
@@ -7489,7 +6435,7 @@ void process_monsters(void)
/* Access the race */
- r_ptr = race_inf(m_ptr);
+ auto const r_ptr = m_ptr->race();
/* Access the location */
fx = m_ptr->fx;
@@ -7527,7 +6473,7 @@ void process_monsters(void)
/* Hack -- Monsters can "smell" the player from far away */
/* Note that most monsters have "aaf" of "20" or so */
- else if (flow_by_sound &&
+ else if (options->flow_by_sound &&
(cave[p_ptr->py][p_ptr->px].when == cave[fy][fx].when) &&
(cave[fy][fx].cost < MONSTER_FLOW_DEPTH) &&
(cave[fy][fx].cost < r_ptr->aaf))
@@ -7562,30 +6508,4 @@ void process_monsters(void)
/* Reset global index */
hack_m_idx = 0;
-
-
- /* Tracking a monster race (the same one we were before) */
- if (monster_race_idx && (monster_race_idx == old_monster_race_idx))
- {
- /* Acquire monster race */
- r_ptr = &r_info[monster_race_idx];
-
- /* Check for knowledge change */
- if ((old_r_flags1 != r_ptr->r_flags1) ||
- (old_r_flags2 != r_ptr->r_flags2) ||
- (old_r_flags3 != r_ptr->r_flags3) ||
- (old_r_flags4 != r_ptr->r_flags4) ||
- (old_r_flags5 != r_ptr->r_flags5) ||
- (old_r_flags6 != r_ptr->r_flags6) ||
- (old_r_blows0 != r_ptr->r_blows[0]) ||
- (old_r_blows1 != r_ptr->r_blows[1]) ||
- (old_r_blows2 != r_ptr->r_blows[2]) ||
- (old_r_blows3 != r_ptr->r_blows[3]) ||
- (old_r_cast_inate != r_ptr->r_cast_inate) ||
- (old_r_cast_spell != r_ptr->r_cast_spell))
- {
- /* Window stuff */
- p_ptr->window |= (PW_MONSTER);
- }
- }
}
diff --git a/src/melee2.hpp b/src/melee2.hpp
new file mode 100644
index 00000000..d5106850
--- /dev/null
+++ b/src/melee2.hpp
@@ -0,0 +1,12 @@
+#pragma once
+
+#include "h-basic.h"
+#include "monster_type_fwd.hpp"
+
+extern int monst_spell_monst_spell;
+bool_ mon_take_hit_mon(int s_idx, int m_idx, int dam, bool_ *fear, cptr note);
+void mon_handle_fear(monster_type *m_ptr, int dam, bool_ *fear);
+int check_hit2(int power, int level, int ac);
+void process_monsters();
+void curse_equipment(int chance, int heavy_chance);
+void curse_equipment_dg(int chance, int heavy_chance);
diff --git a/src/message.cc b/src/message.cc
new file mode 100644
index 00000000..a0f46f22
--- /dev/null
+++ b/src/message.cc
@@ -0,0 +1,15 @@
+#include "message.hpp"
+
+#include <fmt/format.h>
+
+std::string message::text_with_count() const
+{
+ if (count > 1)
+ {
+ return fmt::format("{} <{}x>", text, count);
+ }
+ else
+ {
+ return text;
+ }
+}
diff --git a/src/message.hpp b/src/message.hpp
new file mode 100644
index 00000000..7b47a9db
--- /dev/null
+++ b/src/message.hpp
@@ -0,0 +1,31 @@
+#pragma once
+
+#include "h-basic.h"
+
+#include <string>
+
+/**
+ * Message
+ */
+struct message {
+ /**
+ * Message color.
+ */
+ byte color = 0;
+
+ /**
+ * Repetation count for this message.
+ */
+ u32b count = 0;
+
+ /**
+ * Message text.
+ */
+ std::string text;
+
+ /**
+ * Get message text with count
+ */
+ std::string text_with_count() const;
+
+};
diff --git a/src/messages.cc b/src/messages.cc
new file mode 100644
index 00000000..071dc66e
--- /dev/null
+++ b/src/messages.cc
@@ -0,0 +1,53 @@
+#include "messages.hpp"
+
+#include "game.hpp"
+
+#include <fmt/format.h>
+#include <string>
+
+s16b Messages::size() const
+{
+ return buffer.size();
+}
+
+message const &Messages::at(int age) const
+{
+ assert(age >= 0);
+ assert(age < size());
+
+ // Age indexes backward through history and is zero-based, so...
+ std::size_t i = buffer.size() - 1 - age;
+
+ // Get the message
+ return buffer.at(i);
+}
+
+void Messages::add(cptr msg, byte color)
+{
+ assert(msg != nullptr);
+ add(std::string(msg), color);
+}
+
+void Messages::add(std::string const &msg, byte color)
+{
+ // If the message is the same as the last message,
+ // we just increment the counter instead of adding
+ // the message.
+ if ((!buffer.empty()) && (buffer.back().text == msg))
+ {
+ buffer.back().count += 1;
+ return;
+ }
+
+ // Push onto the end of the buffer.
+ message message;
+ message.color = color;
+ message.count = 1;
+ message.text = msg;
+ buffer.push_back(message);
+}
+
+void Messages::add(message const &m)
+{
+ buffer.push_back(m);
+}
diff --git a/src/messages.hpp b/src/messages.hpp
new file mode 100644
index 00000000..0443a6c8
--- /dev/null
+++ b/src/messages.hpp
@@ -0,0 +1,56 @@
+#pragma once
+
+#include "h-basic.h"
+#include "message.hpp"
+
+#include <boost/circular_buffer.hpp>
+
+/**
+ * Game message buffer
+ */
+class Messages final {
+
+private:
+ boost::circular_buffer<message> buffer;
+
+public:
+
+ /**
+ * Create message buffer with space for given
+ * number of messages.
+ */
+ explicit Messages(std::size_t n)
+ : buffer(n)
+ {
+ }
+
+ /**
+ * Get the current number of messages.
+ */
+ s16b size() const;
+
+ /**
+ * Get message of given age. Age must be
+ * in the half-open interval [0, message_num).
+ *
+ * The reference is only valid as long as
+ * no messages are added.
+ */
+ message const &at(int age) const;
+
+ /**
+ * Add a message.
+ */
+ void add(cptr msg, byte color);
+
+ /**
+ * Add a message.
+ */
+ void add(std::string const &msg, byte color);
+
+ /**
+ * Add a message.
+ */
+ void add(message const &);
+
+};
diff --git a/src/mimic.cc b/src/mimic.cc
new file mode 100644
index 00000000..6ce7b180
--- /dev/null
+++ b/src/mimic.cc
@@ -0,0 +1,725 @@
+#include "mimic.hpp"
+
+#include "game.hpp"
+#include "object_flag.hpp"
+#include "player_type.hpp"
+#include "skill_type.hpp"
+#include "stats.hpp"
+#include "variable.hpp"
+#include "xtra1.hpp"
+#include "z-rand.hpp"
+
+#include <cassert>
+
+/**
+ * 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 */
+};
+
+static s32b abomination_calc()
+{
+ apply_flags(TR_SPEED | TR_STR | TR_INT | TR_WIS | TR_DEX | TR_CON | TR_CHR, -10, 0, 0, 0, 0);
+ p_ptr->xtra_flags |= TR_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_flags |= TR_FLY;
+ p_ptr->xtra_flags |= TR_SEE_INVIS;
+ }
+
+ if (p_ptr->mimic_level >= 25)
+ {
+ p_ptr->xtra_flags |= TR_FREE_ACT;
+ }
+
+ if (p_ptr->mimic_level >= 30)
+ {
+ p_ptr->xtra_flags |= TR_RES_ELEC;
+ }
+
+ if (p_ptr->mimic_level >= 35)
+ {
+ p_ptr->xtra_flags |= TR_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_flags |= TR_FREE_ACT;
+ p_ptr->xtra_flags |= TR_RES_FEAR;
+
+ if (p_ptr->mimic_level >= 10)
+ {
+ p_ptr->xtra_flags |= TR_RES_COLD;
+ }
+
+ if (p_ptr->mimic_level >= 15)
+ {
+ p_ptr->xtra_flags |= TR_SEE_INVIS;
+ }
+
+ if (p_ptr->mimic_level >= 30)
+ {
+ p_ptr->xtra_flags |= TR_RES_DARK;
+ }
+
+ if (p_ptr->mimic_level >= 35)
+ {
+ p_ptr->xtra_flags |= TR_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_flags |= TR_RES_POIS;
+ p_ptr->xtra_flags |= TR_RES_FEAR;
+ p_ptr->xtra_flags |= TR_RES_DARK;
+
+ if (p_ptr->mimic_level >= 40)
+ {
+ p_ptr->xtra_flags |= TR_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_flags |= TR_RES_POIS;
+ p_ptr->xtra_flags |= TR_RES_COLD;
+ p_ptr->xtra_flags |= TR_FREE_ACT;
+ p_ptr->xtra_flags |= TR_REGEN;
+ p_ptr->xtra_flags |= TR_SEE_INVIS;
+ p_ptr->xtra_flags |= TR_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_flags |= TR_RES_POIS;
+ p_ptr->xtra_flags |= TR_RES_SHARDS;
+ p_ptr->xtra_flags |= TR_IM_COLD;
+ p_ptr->xtra_flags |= TR_FREE_ACT;
+ p_ptr->xtra_flags |= TR_REGEN;
+ p_ptr->xtra_flags |= TR_SEE_INVIS;
+ p_ptr->xtra_flags |= TR_SENS_FIRE;
+ p_ptr->xtra_flags |= TR_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_flags |= TR_RES_POIS;
+ if (p_ptr->mimic_level >= 25)
+ {
+ p_ptr->xtra_flags |= TR_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_flags |= TR_RES_FEAR;
+ }
+
+ if (p_ptr->mimic_level >= 25)
+ {
+ p_ptr->xtra_flags |= TR_RES_CONF;
+ }
+
+ if (p_ptr->mimic_level >= 30)
+ {
+ p_ptr->xtra_flags |= TR_FREE_ACT;
+ }
+
+ if (p_ptr->mimic_level >= 35)
+ {
+ p_ptr->xtra_flags |= TR_RES_NEXUS;
+ }
+
+ return 0;
+}
+
+static s32b bear_calc()
+{
+ auto &s_info = game->s_info;
+
+ 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_flags |= TR_FREE_ACT;
+ }
+
+ if (p_ptr->mimic_level >= 20)
+ {
+ p_ptr->xtra_flags |= TR_REGEN;
+ }
+
+ if (p_ptr->mimic_level >= 30)
+ {
+ p_ptr->xtra_flags |= TR_RES_CONF;
+ }
+
+ if (p_ptr->mimic_level >= 35)
+ {
+ p_ptr->xtra_flags |= TR_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_flags |= TR_IM_ACID;
+ p_ptr->xtra_flags |= TR_IM_FIRE;
+ p_ptr->xtra_flags |= TR_IM_ELEC;
+ p_ptr->xtra_flags |= TR_RES_DARK;
+ p_ptr->xtra_flags |= TR_RES_CHAOS;
+ p_ptr->xtra_flags |= TR_RES_POIS;
+ p_ptr->xtra_flags |= TR_HOLD_LIFE;
+ p_ptr->xtra_flags |= TR_FEATHER;
+ p_ptr->xtra_flags |= TR_REGEN;
+ p_ptr->xtra_flags |= TR_SH_FIRE;
+ p_ptr->xtra_flags |= TR_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_flags |= TR_IM_FIRE;
+ p_ptr->xtra_flags |= TR_IM_ELEC;
+ p_ptr->xtra_flags |= TR_IM_ACID;
+ p_ptr->xtra_flags |= TR_IM_COLD;
+ p_ptr->xtra_flags |= TR_RES_POIS;
+ p_ptr->xtra_flags |= TR_RES_LITE;
+ p_ptr->xtra_flags |= TR_RES_DARK;
+ p_ptr->xtra_flags |= TR_RES_CHAOS;
+ p_ptr->xtra_flags |= TR_HOLD_LIFE;
+ p_ptr->xtra_flags |= TR_FEATHER;
+ p_ptr->xtra_flags |= TR_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_flags |= TR_IM_FIRE;
+ p_ptr->xtra_flags |= TR_RES_POIS;
+ p_ptr->xtra_flags |= TR_SH_FIRE;
+ p_ptr->xtra_flags |= TR_LITE1;
+
+ return 0;
+}
+
+/*
+ * Mimicry forms
+ */
+static 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 const *f)
+{
+ for (int 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)
+{
+ for (s16b i = 0; i < MIMIC_FORMS_MAX; i++)
+ {
+ auto const 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)
+ {
+ tries = tries - 1;
+
+ int mf_idx = rand_int(MIMIC_FORMS_MAX);
+ auto const 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)
+{
+ auto const 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()
+{
+ auto const mf_ptr = get_mimic_form(p_ptr->mimic_form);
+ if (mf_ptr->calc != NULL)
+ {
+ return mf_ptr->calc();
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+/*
+ * Calculate powers for player's current mimic form
+ */
+void calc_mimic_power()
+{
+ mimic_form_type *mf_ptr = get_mimic_form(p_ptr->mimic_form);
+ if (mf_ptr->power != NULL)
+ {
+ mf_ptr->power();
+ }
+}
diff --git a/src/mimic.hpp b/src/mimic.hpp
new file mode 100644
index 00000000..4ce9a6e8
--- /dev/null
+++ b/src/mimic.hpp
@@ -0,0 +1,10 @@
+#include "h-basic.h"
+
+s16b resolve_mimic_name(cptr name);
+s16b find_random_mimic_shape(byte level, bool_ limit);
+cptr get_mimic_name(s16b mf_idx);
+cptr get_mimic_object_name(s16b mf_idx);
+byte get_mimic_level(s16b mf_idx);
+s32b get_mimic_random_duration(s16b mf_idx);
+byte calc_mimic();
+void calc_mimic_power();
diff --git a/src/module_type.hpp b/src/module_type.hpp
new file mode 100644
index 00000000..1b75d84c
--- /dev/null
+++ b/src/module_type.hpp
@@ -0,0 +1,61 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * Module descriptor.
+ */
+struct module_type
+{
+ /* Metadata about the module: author, description, etc. */
+ struct {
+ /* 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;
+ } meta;
+
+ /* Random artifact generation chances */
+ struct {
+ s32b weapon_chance;
+ s32b armor_chance;
+ s32b jewelry_chance;
+ } randarts;
+
+ /* 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;
+
+ /* 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);
+};
diff --git a/src/modules.c b/src/modules.c
deleted file mode 100644
index 39b41d20..00000000
--- a/src/modules.c
+++ /dev/null
@@ -1,274 +0,0 @@
-/* File: modules.c */
-
-/* Purpose: T-engine modules */
-
-/*
- * Copyright (c) 2003 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"
-
-static void module_reset_dir_aux(cptr *dir, cptr new_path)
-{
- char buf[1024];
-
- /* Build the new path */
- strnfmt(buf, sizeof (buf), "%s%s%s", *dir, PATH_SEP, new_path);
-
- string_free(*dir);
- *dir = string_make(buf);
-
- /* Make it if needed */
- if (!private_check_user_directory(*dir))
- quit(format("Unable to create module dir %s\n", *dir));
-}
-
-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;
- if (!strcmp(dir, "edit")) d = &ANGBAND_DIR_EDIT;
- if (!strcmp(dir, "file")) d = &ANGBAND_DIR_FILE;
- if (!strcmp(dir, "help")) d = &ANGBAND_DIR_HELP;
- if (!strcmp(dir, "info")) d = &ANGBAND_DIR_INFO;
- if (!strcmp(dir, "scpt")) d = &ANGBAND_DIR_SCPT;
- if (!strcmp(dir, "patch")) d = &ANGBAND_DIR_PATCH;
- if (!strcmp(dir, "pref")) d = &ANGBAND_DIR_PREF;
- if (!strcmp(dir, "xtra")) d = &ANGBAND_DIR_XTRA;
- if (!strcmp(dir, "user")) d = &ANGBAND_DIR_USER;
- 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"))
- {
- char user_path[1024];
- /* copied from init_file_paths */
- path_parse(user_path, 1024, PRIVATE_USER_PATH);
- strcat(user_path, USER_PATH_VERSION);
- strnfmt(buf, 1024, "%s%s%s", user_path, PATH_SEP, new_path);
- string_free(*d);
- *d = string_make(buf);
- }
-#ifdef PRIVATE_USER_PATH_DATA
- else if (!strcmp(dir, "data"))
- {
- module_reset_dir_aux(&ANGBAND_DIR_DATA, new_path);
- }
-#endif
- else if (!strcmp(dir, "save"))
- {
- module_reset_dir_aux(&ANGBAND_DIR_SAVE, new_path);
- }
- else
- {
- /* Build the new path */
- strnfmt(buf, 1024, "%s%s%s%s%s", ANGBAND_DIR_MODULES, PATH_SEP, new_path, PATH_SEP, dir);
-
- string_free(*d);
- *d = string_make(buf);
- }
-}
-
-static void dump_modules(int sel, int max)
-{
- int i;
-
- char buf[40], pre = ' ', post = ')';
- cptr name;
-
- 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 = ')';
- }
-
- call_lua("get_module_name", "(d)", "s", i, &name);
- strnfmt(buf, 40, "%c%c%c %s", pre, ind, post, name);
-
- if (sel == i)
- {
- call_lua("get_module_desc", "(d)", "s", i, &name);
- print_desc_aux(name, 5, 0);
-
- c_put_str(TERM_L_BLUE, buf, 10 + (i / 4), 20 * (i % 4));
- }
- else
- put_str(buf, 10 + (i / 4), 20 * (i % 4));
- }
-}
-
-static void activate_module()
-{
- /* Initialize the module table */
- call_lua("assign_current_module", "(s)", "", game_module);
-
- /* 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);
-
- 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);
-
- 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 = VERSION_MAJOR;
- version_minor = VERSION_MINOR;
- version_patch = VERSION_PATCH;
-
- /* Change window name if needed */
- if (strcmp(game_module, "ToME"))
- {
- strnfmt(angband_term_name[0], 79, "T-Engine: %s", game_module);
- Term_xtra(TERM_XTRA_RENAME_MAIN_WIN, 0);
- }
-
- /* Reprocess the player name, just in case */
- process_player_base();
-}
-
-/* Did the player force a module on command line */
-cptr force_module = NULL;
-
-/* Display possible modules and select one */
-bool_ select_module()
-{
- s32b k, sel, max;
-
- /* 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);
-
- /* 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)
- sel = 0;
- if (sel != -1)
- {
- cptr tmp;
-
- /* Process the module */
- call_lua("init_module", "(d)", "", sel);
- call_lua("get_module_name", "(d)", "s", sel, &tmp);
- game_module = string_make(tmp);
-
- activate_module();
-
- return FALSE;
- }
-
- sel = 0;
-
- /* Preprocess the basic prefs, we need them to have movement keys */
- process_pref_file("pref.prf");
-
- while (TRUE)
- {
- /* Clear screen */
- Term_clear();
-
- /* Let the user choose */
- c_put_str(TERM_YELLOW, "Welcome to ToME, you must select a module to play,", 1, 12);
- c_put_str(TERM_YELLOW, "either ToME official module or third party ones.", 2, 13);
- put_str("Press 8/2/4/6 to move, Return to select and Esc to quit.", 4, 3);
-
- dump_modules(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));
- }
-
- {
- int x;
- cptr tmp;
-
- if (islower(k)) x = A2I(k);
- else x = A2I(tolower(k)) + 26;
-
- if ((x < 0) || (x >= 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);
-
- activate_module();
-
- return (FALSE);
- }
- }
-
- /* Shouldnt happen */
- return (FALSE);
-}
diff --git a/src/modules.cc b/src/modules.cc
new file mode 100644
index 00000000..de9ad1ad
--- /dev/null
+++ b/src/modules.cc
@@ -0,0 +1,1272 @@
+/*
+ * Copyright (c) 2003 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 "modules.hpp"
+
+#include "birth.hpp"
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "corrupt.hpp"
+#include "files.hpp"
+#include "hook_eat_in.hpp"
+#include "hook_give_in.hpp"
+#include "hook_move_in.hpp"
+#include "hook_stair_in.hpp"
+#include "hook_stair_out.hpp"
+#include "hook_new_monster_end_in.hpp"
+#include "hooks.hpp"
+#include "joke.hpp"
+#include "lua_bind.hpp"
+#include "monster2.hpp"
+#include "monster_race.hpp"
+#include "monster_race_flag.hpp"
+#include "monster_type.hpp"
+#include "object2.hpp"
+#include "object_type.hpp"
+#include "player_type.hpp"
+#include "spells2.hpp"
+#include "stats.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "util.h"
+#include "variable.h"
+#include "variable.hpp"
+
+#include <cassert>
+#include <chrono>
+#include <thread>
+
+using std::this_thread::sleep_for;
+using std::chrono::milliseconds;
+
+/*
+ * Check and create if needed the directory dirpath
+ */
+bool_ private_check_user_directory(cptr dirpath)
+{
+ /* Is this used anywhere else in *bands? */
+ struct stat stat_buf;
+
+ int ret;
+
+ /* See if it already exists */
+ ret = stat(dirpath, &stat_buf);
+
+ /* It does */
+ if (ret == 0)
+ {
+ /* Now we see if it's a directory */
+ if ((stat_buf.st_mode & S_IFMT) == S_IFDIR) return (TRUE);
+
+ /*
+ * Something prevents us from create a directory with
+ * the same pathname
+ */
+ return (FALSE);
+ }
+
+ /* No - this maybe the first time. Try to create a directory */
+ else
+ {
+ /* Create the ~/.ToME directory */
+ ret = mkdir(dirpath, 0700);
+
+ /* An error occured */
+ if (ret == -1) return (FALSE);
+
+ /* Success */
+ return (TRUE);
+ }
+}
+
+static void module_reset_dir_aux(char **dir, cptr new_path)
+{
+ char buf[1024];
+
+ /* Build the new path */
+ strnfmt(buf, sizeof (buf), "%s%s%s", *dir, PATH_SEP, new_path);
+
+ free(*dir);
+ *dir = strdup(buf);
+
+ /* Make it if needed */
+ if (!private_check_user_directory(*dir))
+ quit(format("Unable to create module dir %s\n", *dir));
+}
+
+static void module_reset_dir(cptr dir, cptr new_path)
+{
+ char **d = 0;
+ char buf[1025];
+
+ if (!strcmp(dir, "core")) d = &ANGBAND_DIR_CORE;
+ if (!strcmp(dir, "dngn")) d = &ANGBAND_DIR_DNGN;
+ if (!strcmp(dir, "data")) d = &ANGBAND_DIR_DATA;
+ if (!strcmp(dir, "edit")) d = &ANGBAND_DIR_EDIT;
+ if (!strcmp(dir, "file")) d = &ANGBAND_DIR_FILE;
+ if (!strcmp(dir, "help")) d = &ANGBAND_DIR_HELP;
+ if (!strcmp(dir, "info")) d = &ANGBAND_DIR_INFO;
+ if (!strcmp(dir, "pref")) d = &ANGBAND_DIR_PREF;
+ if (!strcmp(dir, "xtra")) d = &ANGBAND_DIR_XTRA;
+ if (!strcmp(dir, "user")) d = &ANGBAND_DIR_USER;
+ if (!strcmp(dir, "note")) d = &ANGBAND_DIR_NOTE;
+
+ if (
+ !strcmp(dir, "user") ||
+ !strcmp(dir, "note"))
+ {
+ char user_path[1024];
+ /* copied from init_file_paths */
+ path_parse(user_path, 1024, PRIVATE_USER_PATH);
+ strcat(user_path, USER_PATH_VERSION);
+ strnfmt(buf, 1024, "%s%s%s", user_path, PATH_SEP, new_path);
+
+ free(*d);
+ *d = strdup(buf);
+
+ // Make it if needed */
+ if (!private_check_user_directory(*d))
+ {
+ quit(format("Unable to create module dir %s\n", *d));
+ }
+ }
+ else if (!strcmp(dir, "save"))
+ {
+ module_reset_dir_aux(&ANGBAND_DIR_SAVE, new_path);
+ }
+ else
+ {
+ /* Build the new path */
+ strnfmt(buf, 1024, "%s%s%s%s%s", ANGBAND_DIR_MODULES, PATH_SEP, new_path, PATH_SEP, dir);
+
+ free(*d);
+ *d = strdup(buf);
+ }
+}
+
+static void dump_modules(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 = ')';
+ }
+
+ strnfmt(buf, 40, "%c%c%c %s", pre, ind, post, modules[i].meta.name);
+
+ if (sel == i)
+ {
+ print_desc_aux(modules[i].meta.desc, 5, 0);
+
+ c_put_str(TERM_L_BLUE, buf, 10 + (i / 4), 20 * (i % 4));
+ }
+ else
+ put_str(buf, 10 + (i / 4), 20 * (i % 4));
+ }
+}
+
+static void activate_module(int module_idx)
+{
+ module_type *module_ptr = &modules[module_idx];
+
+ /* Initialize the module table */
+ game_module_idx = module_idx;
+
+ /* Do misc inits */
+ RANDART_WEAPON = module_ptr->randarts.weapon_chance;
+ RANDART_ARMOR = module_ptr->randarts.armor_chance;
+ RANDART_JEWEL = module_ptr->randarts.jewelry_chance;
+
+ VERSION_MAJOR = module_ptr->meta.version.major;
+ VERSION_MINOR = module_ptr->meta.version.minor;
+ VERSION_PATCH = module_ptr->meta.version.patch;
+
+ /* Change window name if needed */
+ if (strcmp(game_module, "ToME"))
+ {
+ strnfmt(angband_term_name[0], 79, "T-Engine: %s", game_module);
+ Term_xtra(TERM_XTRA_RENAME_MAIN_WIN, 0);
+ }
+
+ /* Reprocess the player name, just in case */
+ 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("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("user", dir);
+ module_reset_dir("pref", dir);
+ }
+}
+
+bool module_savefile_loadable(std::string const &tag)
+{
+ return tag == modules[game_module_idx].meta.save_file_tag;
+}
+
+/* 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<MAX_MODULES; i++)
+ {
+ if (streq(name, modules[i].meta.name))
+ {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+/* Display possible modules and select one */
+bool_ select_module()
+{
+ s32b k, sel, max;
+
+ /* How many modules? */
+ max = MAX_MODULES;
+
+ /* No need to bother the player if there is only one module */
+ sel = -1;
+ if (force_module) {
+ /* Find module by name */
+ sel = find_module(force_module);
+ }
+ /* Only a single choice */
+ if (max == 1) {
+ sel = 0;
+ }
+ /* No module selected */
+ if (sel != -1)
+ {
+ /* Process the module */
+ init_module(&modules[sel]);
+
+ game_module = modules[sel].meta.name;
+
+ activate_module(sel);
+
+ return FALSE;
+ }
+
+ sel = 0;
+
+ /* Preprocess the basic prefs, we need them to have movement keys */
+ process_pref_file("pref.prf");
+
+ while (TRUE)
+ {
+ /* Clear screen */
+ Term_clear();
+
+ /* Let the user choose */
+ c_put_str(TERM_YELLOW, "Welcome to ToME, you must select a module to play,", 1, 12);
+ c_put_str(TERM_YELLOW, "either ToME official module or third party ones.", 2, 13);
+ put_str("Press 8/2/4/6 to move, Return to select and Esc to quit.", 4, 3);
+
+ dump_modules(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));
+ }
+
+ {
+ int x;
+
+ if (islower(k)) x = A2I(k);
+ else x = A2I(tolower(k)) + 26;
+
+ if ((x < 0) || (x >= max)) continue;
+
+ /* Process the module */
+ init_module(&modules[x]);
+
+ game_module = modules[x].meta.name;
+
+ activate_module(x);
+
+ return (FALSE);
+ }
+ }
+
+ /* 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)
+ {
+ sleep_for(milliseconds(1));
+ time = 0;
+ }
+ Term_redraw_section(a - 1, y, a, y);
+ a = a + 1;
+
+ if (inkey_scan()) {
+ return TRUE;
+ }
+ }
+ }
+
+ i = i - 1;
+ }
+ return FALSE;
+}
+
+static bool_ dright(byte c, cptr str, int y, int o)
+{
+ int n = strlen(str); // Conversion to int to avoid warnings
+ int x = 39 - (n / 2) + o;
+ for (int i = 1; i <= n; i++)
+ {
+ 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) {
+ sleep_for(milliseconds(1));
+ time = 0;
+ }
+ Term_redraw_section(a, y, a + 1, y);
+ a = a - 1;
+
+ if (inkey_scan()) {
+ return TRUE;
+ }
+ }
+ }
+ }
+ 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();
+
+ /* 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 , TERM_WHITE , NULL, 0, 0, }
+ };
+ 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 , TERM_WHITE , NULL, 0, 0, }
+ };
+
+ 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 , TERM_WHITE , NULL, 0, 0, },
+ };
+ 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 , TERM_WHITE , NULL, 0, 0, },
+ };
+
+ screen_save();
+
+ /* Intro 1 */
+ if (show_intro(intro1))
+ {
+ goto exit;
+ }
+
+ /* Intro 2 */
+ if (show_intro(intro2))
+ {
+ goto exit;
+ }
+
+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;
+}
+
+static bool drunk_takes_wine(void *, void *in_, void *)
+{
+ 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;
+ }
+}
+
+static bool hobbit_food(void *, void *in_, void *)
+{
+ 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;
+ }
+}
+
+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;
+ }
+}
+
+static bool longbottom_leaf(void *, void *in_, void *)
+{
+ 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;
+}
+
+static bool food_vessel(void *, void *in_, void *ut)
+{
+ 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;
+}
+
+/*
+ * Player must have appropriate keys to enter Erebor.
+ */
+static bool erebor_stair(void *, 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 *, 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;
+}
+
+/*
+ * Movement from Theme
+ */
+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];
+
+ if (c_ptr->m_idx > 0)
+ {
+ monster_type *m_ptr = &m_list[c_ptr->m_idx];
+ auto const mr_ptr = m_ptr->race();
+
+ if (m_ptr->status >= MSTATUS_NEUTRAL)
+ {
+ if (cave_floor_bold(p->y, p->x) ||
+ (mr_ptr->flags == RF_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;
+}
+
+/*
+ * 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.
+ */
+s16b *theme_race_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 *, void *, void *)
+{
+ for (int i = 0; i < m_max; i++)
+ {
+ monster_type *m_ptr = &m_list[i];
+ int r_idx = m_ptr->r_idx;
+ s16b *status = theme_race_status(r_idx);
+ if (status)
+ {
+ m_ptr->status = *status;
+ }
+ }
+
+ return false;
+}
+
+static bool theme_new_monster_end(void *, void *in_, void *)
+{
+ hook_new_monster_end_in *in = (hook_new_monster_end_in *) in_;
+ s16b *status = theme_race_status(in->m_ptr->r_idx);
+
+ if (status)
+ {
+ in->m_ptr->status = *status;
+ }
+
+ return false;
+}
+
+void init_hooks_module()
+{
+ /*
+ * Common hooks
+ */
+ add_hook_new(HOOK_GIVE,
+ drunk_takes_wine,
+ "drunk_takes_wine",
+ NULL);
+
+ add_hook_new(HOOK_LEVEL_END_GEN,
+ gen_joke_monsters,
+ "gen_joke_monsters",
+ NULL);
+
+ /*
+ * Module-specific hooks
+ */
+ switch (game_module_idx)
+ {
+ case MODULE_TOME:
+ {
+ break;
+ }
+
+ case MODULE_THEME:
+ {
+ timer_aggravate_evil_enable();
+
+ add_hook_new(HOOK_PLAYER_LEVEL,
+ auto_stat_gain_hook,
+ "auto_stat_gain",
+ NULL);
+
+ add_hook_new(HOOK_GIVE,
+ hobbit_food,
+ "hobbit_food",
+ NULL);
+
+ add_hook_new(HOOK_GIVE,
+ smeagol_ring,
+ "smeagol_ring",
+ NULL);
+
+ add_hook_new(HOOK_EAT,
+ longbottom_leaf,
+ "longbottom_leaf",
+ NULL);
+
+ add_hook_new(HOOK_EAT,
+ food_vessel,
+ "food_vessel",
+ NULL);
+
+ add_hook_new(HOOK_STAIR,
+ erebor_stair,
+ "erebor_stair",
+ NULL);
+
+ add_hook_new(HOOK_STAIR,
+ orthanc_stair,
+ "orthanc_stair",
+ NULL);
+
+ add_hook_new(HOOK_MOVE,
+ theme_push_past,
+ "__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;
+ }
+
+ default:
+ assert(FALSE);
+ }
+}
diff --git a/src/modules.hpp b/src/modules.hpp
new file mode 100644
index 00000000..867955c9
--- /dev/null
+++ b/src/modules.hpp
@@ -0,0 +1,14 @@
+#pragma once
+
+#include "h-basic.h"
+#include <string>
+
+bool_ select_module();
+bool module_savefile_loadable(std::string const &savefile_mod);
+void tome_intro();
+void theme_intro();
+s16b *theme_race_status(int r_idx);
+void init_hooks_module();
+int find_module(cptr name);
+bool_ private_check_user_directory(cptr dirpath);
+extern cptr force_module;
diff --git a/src/monoid.hpp b/src/monoid.hpp
new file mode 100644
index 00000000..465e58af
--- /dev/null
+++ b/src/monoid.hpp
@@ -0,0 +1,37 @@
+#pragma once
+
+#include <numeric>
+#include <vector>
+
+/**
+ * A monoid is an algebraic structure with a single associative
+ * binary operation ('append') and an identity element ('empty').
+ *
+ * See https://en.wikipedia.org/wiki/Monoid
+ *
+ * Shamelessly adapted from:
+ *
+ * https://gist.github.com/evincarofautumn/2b5f004ca81e33c62ff0
+ */
+template<typename T, T append_(T const&, T const&), const T &empty_>
+struct monoid {
+ /* Access the type the monoid operates on */
+ typedef T type;
+
+ /* Append two T's */
+ static T append(T const& a, T const& b) {
+ return append_(a, b);
+ }
+
+ /* The value of an empty T */
+ static constexpr T empty = empty_;
+};
+
+/**
+ * mconcat :: (Monoid m mappend) -> [m] -> m
+ * mconcat = fold mappend mempty
+ */
+template<typename M>
+typename M::type mconcat(const std::vector<typename M::type>& xs) {
+ return std::accumulate(std::begin(xs), std::end(xs), M::empty, M::append);
+}
diff --git a/src/monster.pkg b/src/monster.pkg
deleted file mode 100644
index a9efd089..00000000
--- a/src/monster.pkg
+++ /dev/null
@@ -1,2324 +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 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.
- * @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
-
-/** @def SUMMON_LUA
- * @note Summon monsters according to a Lua script.
- */
-#define SUMMON_LUA 58
-/** @} */
-
-/** @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/monster1.c b/src/monster1.c
deleted file mode 100644
index 196272ce..00000000
--- a/src/monster1.c
+++ /dev/null
@@ -1,1908 +0,0 @@
-/* File: monster1.c */
-
-/* Purpose: describe monsters (using monster memory) */
-
-/*
- * Copyright (c) 1989 James E. Wilson, Christopher J. Stuart
- *
- * 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"
-
-
-/*
- * Pronoun arrays, by gender.
- */
-static cptr wd_he[3] = { "it", "he", "she" };
-static cptr wd_his[3] = { "its", "his", "her" };
-
-
-/*
- * Pluralizer. Args(count, singular, plural)
- */
-#define plural(c,s,p) \
-(((c) == 1) ? (s) : (p))
-
-
-
-
-
-
-/*
- * Determine if the "armor" is known
- * The higher the level, the fewer kills needed.
- */
-static bool_ know_armour(int r_idx)
-{
- monster_race *r_ptr = &r_info[r_idx];
-
- s32b level = r_ptr->level;
-
- s32b kills = r_ptr->r_tkills;
-
- /* Normal monsters */
- if (kills > 304 / (4 + level)) return (TRUE);
-
- /* Skip non-uniques */
- if (!(r_ptr->flags1 & (RF1_UNIQUE))) return (FALSE);
-
- /* Unique monsters */
- if (kills > 304 / (38 + (5*level) / 4)) return (TRUE);
-
- /* Assume false */
- return (FALSE);
-}
-
-
-/*
- * Determine if the "damage" of the given attack is known
- * the higher the level of the monster, the fewer the attacks you need,
- * the more damage an attack does, the more attacks you need
- */
-static bool_ know_damage(int r_idx, int i)
-{
- monster_race *r_ptr = &r_info[r_idx];
-
- s32b level = r_ptr->level;
-
- s32b a = r_ptr->r_blows[i];
-
- s32b d1 = r_ptr->blow[i].d_dice;
- s32b d2 = r_ptr->blow[i].d_side;
-
- s32b d = d1 * d2;
-
- /* Normal monsters */
- if ((4 + level) * a > 80 * d) return (TRUE);
-
- /* Skip non-uniques */
- if (!(r_ptr->flags1 & (RF1_UNIQUE))) return (FALSE);
-
- /* Unique monsters */
- if ((4 + level) * (2 * a) > 80 * d) return (TRUE);
-
- /* Assume false */
- return (FALSE);
-}
-
-
-/*
- * Hack -- display monster information using "text_out()"
- *
- * Note that there is now a compiler option to only read the monster
- * descriptions from the raw file when they are actually needed, which
- * saves about 60K of memory at the cost of disk access during monster
- * recall, which is optional to the user.
- *
- * This function should only be called with the cursor placed at the
- * left edge of the screen, on a cleared line, in which the recall is
- * to take place. One extra blank line is left after the recall.
- */
-static void roff_aux(int r_idx, int ego, int remem)
-{
- monster_race *r_ptr;
-
- bool_ old = FALSE;
- bool_ sin = FALSE;
-
- int m, n, r;
-
- cptr p, q;
-
- int msex = 0;
-
- bool_ breath = FALSE;
- bool_ magic = FALSE;
-
- u32b flags1;
- u32b flags2;
- u32b flags3;
- u32b flags4;
- u32b flags5;
- u32b flags6;
- u32b flags7;
- u32b flags9;
-
- int vn = 0;
- byte color[64];
- cptr vp[64];
-
- monster_race save_mem;
-
-
-
- /* Access the race and lore */
- r_ptr = race_info_idx(r_idx, ego);
-
-
- /* Cheat -- Know everything */
- if (cheat_know)
- {
- /* XXX XXX XXX */
-
- /* Save the "old" memory */
- save_mem = *r_ptr;
-
- /* Hack -- Maximal kills */
- r_ptr->r_tkills = MAX_SHORT;
-
- /* Hack -- Maximal info */
- 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_flags7 = r_ptr->flags7;
- r_ptr->r_flags8 = r_ptr->flags8;
- r_ptr->r_flags9 = r_ptr->flags9;
- }
-
-
- /* Extract a gender (if applicable) */
- if (r_ptr->flags1 & (RF1_FEMALE)) msex = 2;
- else if (r_ptr->flags1 & (RF1_MALE)) msex = 1;
-
-
- /* Obtain a copy of the "known" flags */
- flags1 = (r_ptr->flags1 & r_ptr->r_flags1);
- flags2 = (r_ptr->flags2 & r_ptr->r_flags2);
- flags3 = (r_ptr->flags3 & r_ptr->r_flags3);
- flags4 = (r_ptr->flags4 & r_ptr->r_flags4);
- flags5 = (r_ptr->flags5 & r_ptr->r_flags5);
- flags6 = (r_ptr->flags6 & r_ptr->r_flags6);
- flags7 = (r_ptr->flags7 & r_ptr->r_flags7);
- flags9 = (r_ptr->flags9 & r_ptr->r_flags9);
-
-
- /* Assume some "obvious" flags */
- if (r_ptr->flags1 & (RF1_UNIQUE)) flags1 |= (RF1_UNIQUE);
- if (r_ptr->flags1 & (RF1_MALE)) flags1 |= (RF1_MALE);
- if (r_ptr->flags1 & (RF1_FEMALE)) flags1 |= (RF1_FEMALE);
-
- /* Assume some "creation" flags */
- if (r_ptr->flags1 & (RF1_FRIEND)) flags1 |= (RF1_FRIEND);
- if (r_ptr->flags1 & (RF1_FRIENDS)) flags1 |= (RF1_FRIENDS);
- if (r_ptr->flags1 & (RF1_ESCORT)) flags1 |= (RF1_ESCORT);
- if (r_ptr->flags1 & (RF1_ESCORTS)) flags1 |= (RF1_ESCORTS);
-
- /* Killing a monster reveals some properties */
- if (r_ptr->r_tkills)
- {
- /* Know "race" flags */
- if (r_ptr->flags3 & (RF3_ORC)) flags3 |= (RF3_ORC);
- if (r_ptr->flags3 & (RF3_TROLL)) flags3 |= (RF3_TROLL);
- if (r_ptr->flags3 & (RF3_GIANT)) flags3 |= (RF3_GIANT);
- if (r_ptr->flags3 & (RF3_DRAGON)) flags3 |= (RF3_DRAGON);
- if (r_ptr->flags3 & (RF3_DEMON)) flags3 |= (RF3_DEMON);
- if (r_ptr->flags3 & (RF3_UNDEAD)) flags3 |= (RF3_UNDEAD);
- if (r_ptr->flags3 & (RF3_EVIL)) flags3 |= (RF3_EVIL);
- if (r_ptr->flags3 & (RF3_GOOD)) flags3 |= (RF3_GOOD);
- if (r_ptr->flags3 & (RF3_ANIMAL)) flags3 |= (RF3_ANIMAL);
- if (r_ptr->flags3 & (RF3_THUNDERLORD)) flags3 |= (RF3_THUNDERLORD);
- if (r_ptr->flags7 & (RF7_SPIDER)) flags7 |= (RF7_SPIDER);
-
- /* Know "forced" flags */
- if (r_ptr->flags1 & (RF1_FORCE_DEPTH)) flags1 |= (RF1_FORCE_DEPTH);
- if (r_ptr->flags1 & (RF1_FORCE_MAXHP)) flags1 |= (RF1_FORCE_MAXHP);
- }
-
-
- /* Require a flag to show kills */
- if (!(show_details))
- {
- /* nothing */
- }
-
- /* Treat uniques differently */
- else if (flags1 & (RF1_UNIQUE))
- {
- /* Hack -- Determine if the unique is "dead" */
- bool_ dead = (r_ptr->max_num == 0) ? TRUE : FALSE;
-
- /* We've been killed... */
- if (r_ptr->r_deaths)
- {
- /* Killed ancestors */
- text_out(format("%^s has slain %d of your ancestors",
- wd_he[msex], r_ptr->r_deaths));
-
- /* But we've also killed it */
- if (dead)
- {
- text_out(format(", but you have avenged them! ") );
- }
-
- /* Unavenged (ever) */
- else
- {
- text_out(format(", who %s unavenged. ",
- plural(r_ptr->r_deaths, "remains", "remain")));
- }
- }
-
- /* Dead unique who never hurt us */
- else if (dead)
- {
- text_out("You have slain this foe. ");
- }
- }
-
- /* Not unique, but killed us */
- else if (r_ptr->r_deaths)
- {
- /* Dead ancestors */
- text_out(format("%d of your ancestors %s been killed by this creature, ",
- r_ptr->r_deaths, plural(r_ptr->r_deaths, "has", "have")));
-
- /* Some kills this life */
- if (r_ptr->r_pkills)
- {
- text_out("and you have exterminated at least ");
- text_out_c(TERM_L_GREEN, format("%d", r_ptr->r_pkills));
- text_out(" of the creatures. ");
- }
-
- /* Some kills past lives */
- else if (r_ptr->r_tkills)
- {
- text_out(format("and %s have exterminated at least %d of the creatures. ",
- "your ancestors", r_ptr->r_tkills));
- }
-
- /* No kills */
- else
- {
- text_out(format("and %s is not ever known to have been defeated. ",
- wd_he[msex]));
- }
- }
-
- /* Normal monsters */
- else
- {
- /* Killed some this life */
- if (r_ptr->r_pkills)
- {
- text_out("You have killed at least ");
- text_out_c(TERM_L_GREEN, format("%d", r_ptr->r_pkills));
- text_out(" of these creatures. ");
- }
-
- /* Killed some last life */
- else if (r_ptr->r_tkills)
- {
- text_out(format("Your ancestors have killed at least %d of these creatures. ",
- r_ptr->r_tkills));
- }
-
- /* Killed none */
- else
- {
- text_out("No battles to the death are recalled. ");
- }
- }
-
-
- /* Descriptions */
- if (show_details)
- {
- char buf[2048];
-
- /* Simple method */
- strcpy(buf, r_text + r_ptr->text);
-
- /* Dump it */
- text_out(buf);
- text_out(" ");
- }
-
-
- /* Nothing yet */
- old = FALSE;
-
- /* Describe location */
- if (r_ptr->flags7 & RF7_PET)
- {
- text_out(format("%^s is ", wd_he[msex]));
- text_out_c(TERM_L_BLUE, "friendly");
- text_out(" to you");
- old = TRUE;
- }
-
- /* Describe location */
- if (r_ptr->level == 0)
- {
- if (old)
- text_out(", ");
- else
- text_out(format("%^s ", wd_he[msex]));
- text_out_c(TERM_L_GREEN, "lives in the town or the wilderness");
- old = TRUE;
- }
- else if (r_ptr->r_tkills)
- {
- if (old)
- text_out(", ");
- else
- text_out(format("%^s ", wd_he[msex]));
- if (depth_in_feet)
- {
- text_out(format("is normally found at depths of ", wd_he[msex]));
- if (dun_level < r_ptr->level) /* out of depth monster */
- {
- text_out_c(TERM_L_RED, format("%d", r_ptr->level * 50));
- }
- else
- {
- text_out_c(TERM_L_GREEN, format("%d", r_ptr->level * 50));
- }
- text_out(" feet");
- }
- else
- {
- text_out(format("is normally found on level ", wd_he[msex]));
- if (dun_level < r_ptr->level) /* out of depth monster */
- {
- text_out_c(TERM_L_RED, format("%d", r_ptr->level));
- }
- else
- {
- text_out_c(TERM_L_GREEN, format("%d", r_ptr->level));
- }
- }
- old = TRUE;
- }
-
-
- /* Describe movement */
- if (TRUE)
- {
- /* Introduction */
- if (old)
- {
- text_out(", and ");
- }
- else
- {
- text_out(format("%^s ", wd_he[msex]));
- old = TRUE;
- }
- text_out("moves");
-
- /* Random-ness */
- if ((flags1 & (RF1_RAND_50)) || (flags1 & (RF1_RAND_25)))
- {
- /* Adverb */
- if ((flags1 & (RF1_RAND_50)) && (flags1 & (RF1_RAND_25)))
- {
- text_out(" extremely");
- }
- else if (flags1 & (RF1_RAND_50))
- {
- text_out(" somewhat");
- }
- else if (flags1 & (RF1_RAND_25))
- {
- text_out(" a bit");
- }
-
- /* Adjective */
- text_out(" erratically");
-
- /* Hack -- Occasional conjunction */
- if (r_ptr->speed != 110) text_out(", and");
- }
-
- /* Speed */
- if (r_ptr->speed > 110)
- {
- if (r_ptr->speed > 130) text_out_c(TERM_RED, " incredibly");
- else if (r_ptr->speed > 120) text_out_c(TERM_ORANGE, " very");
- text_out_c(TERM_L_RED, " quickly");
- }
- else if (r_ptr->speed < 110)
- {
- if (r_ptr->speed < 90) text_out_c(TERM_L_GREEN, " incredibly");
- else if (r_ptr->speed < 100) text_out_c(TERM_BLUE, " very");
- text_out_c(TERM_L_BLUE, " slowly");
- }
- else
- {
- text_out(" at normal speed");
- }
- }
-
- /* The code above includes "attack speed" */
- if (flags1 & (RF1_NEVER_MOVE))
- {
- /* Introduce */
- if (old)
- {
- text_out(", but ");
- }
- else
- {
- text_out(format("%^s ", wd_he[msex]));
- old = TRUE;
- }
-
- /* Describe */
- text_out("does not deign to chase intruders");
- }
-
- /* End this sentence */
- if (old)
- {
- text_out(". ");
- old = FALSE;
- }
-
-
- /* Describe experience if known */
- if (r_ptr->r_tkills)
- {
- /* Introduction */
- if (flags1 & (RF1_UNIQUE))
- {
- text_out("Killing this");
- }
- else
- {
- text_out("A kill of this");
- }
-
- /* Describe the "quality" */
- if (flags2 & (RF2_ELDRITCH_HORROR)) text_out_c(TERM_VIOLET, " sanity-blasting");
- if (flags3 & (RF3_ANIMAL)) text_out_c(TERM_VIOLET, " natural");
- if (flags3 & (RF3_EVIL)) text_out_c(TERM_VIOLET, " evil");
- if (flags3 & (RF3_GOOD)) text_out_c(TERM_VIOLET, " good");
- if (flags3 & (RF3_UNDEAD)) text_out_c(TERM_VIOLET, " undead");
-
- /* Describe the "race" */
- if (flags3 & (RF3_DRAGON)) text_out_c(TERM_VIOLET, " dragon");
- else if (flags3 & (RF3_DEMON)) text_out_c(TERM_VIOLET, " demon");
- else if (flags3 & (RF3_GIANT)) text_out_c(TERM_VIOLET, " giant");
- else if (flags3 & (RF3_TROLL)) text_out_c(TERM_VIOLET, " troll");
- else if (flags3 & (RF3_ORC)) text_out_c(TERM_VIOLET, " orc");
- else if (flags3 & (RF3_THUNDERLORD))text_out_c(TERM_VIOLET, " Thunderlord");
- else if (flags7 & (RF7_SPIDER)) text_out_c(TERM_VIOLET, " spider");
- else if (flags7 & (RF7_NAZGUL)) text_out_c(TERM_VIOLET, " Nazgul");
- else text_out(" creature");
-
- /* Group some variables */
- if (TRUE)
- {
- long i, j;
-
- /* calculate the integer exp part */
- i = (long)r_ptr->mexp * r_ptr->level / p_ptr->lev;
-
- /* calculate the fractional exp part scaled by 100, */
- /* must use long arithmetic to avoid overflow */
- j = ((((long)r_ptr->mexp * r_ptr->level % p_ptr->lev) *
- (long)1000 / p_ptr->lev + 5) / 10);
-
- /* Mention the experience */
- text_out(" is worth ");
- text_out_c(TERM_ORANGE, format("%ld.%02ld", (long)i, (long)j));
- text_out(" point");
- text_out(((i == 1) && (j == 0)) ? "" : "s");
-
- /* Take account of annoying English */
- p = "th";
- i = p_ptr->lev % 10;
- if ((p_ptr->lev / 10) == 1) /* nothing */;
- else if (i == 1) p = "st";
- else if (i == 2) p = "nd";
- else if (i == 3) p = "rd";
-
- /* Take account of "leading vowels" in numbers */
- q = "";
- i = p_ptr->lev;
- if ((i == 8) || (i == 11) || (i == 18)) q = "n";
-
- /* Mention the dependance on the player's level */
- text_out(format(" for a%s %lu%s level character. ",
- q, (long)i, p));
- }
- }
-
- if ((flags2 & (RF2_AURA_FIRE)) && (flags2 & (RF2_AURA_ELEC)))
- {
- text_out(format("%^s is surrounded by ", wd_he[msex]));
- text_out_c(TERM_VIOLET, "flames and electricity");
- text_out(". ");
- }
- else if (flags2 & (RF2_AURA_FIRE))
- {
- text_out(format("%^s is surrounded by ", wd_he[msex]));
- text_out_c(TERM_ORANGE, "flames");
- text_out(". ");
- }
- else if (flags2 & (RF2_AURA_ELEC))
- {
- text_out(format("%^s is surrounded by ", wd_he[msex]));
- text_out_c(TERM_L_BLUE, "electricity");
- text_out(". ");
- }
-
- if (flags2 & (RF2_REFLECTING))
- {
- text_out(format("%^s ", wd_he[msex]));
- text_out_c(TERM_L_UMBER, "reflects");
- text_out(" bolt spells. ");
- }
-
-
- /* Describe escorts */
- if ((flags1 & (RF1_ESCORT)) || (flags1 & (RF1_ESCORTS)))
- {
- text_out(format("%^s usually appears with escorts. ",
- wd_he[msex]));
- }
-
- /* Describe friends */
- else if ((flags1 & (RF1_FRIEND)) || (flags1 & (RF1_FRIENDS)))
- {
- text_out(format("%^s usually appears in groups. ",
- wd_he[msex]));
- }
-
-
- /* Collect inate attacks */
- vn = 0;
- if (flags4 & (RF4_SHRIEK)) vp[vn++] = "shriek for help";
- if (flags4 & (RF4_ROCKET)) vp[vn++] = "shoot a rocket";
- if (flags4 & (RF4_ARROW_1)) vp[vn++] = "fire an arrow";
- if (flags4 & (RF4_ARROW_2)) vp[vn++] = "fire arrows";
- if (flags4 & (RF4_ARROW_3)) vp[vn++] = "fire a missile";
- if (flags4 & (RF4_ARROW_4)) vp[vn++] = "fire missiles";
-
- /* Describe inate attacks */
- if (vn)
- {
- /* Intro */
- text_out(format("%^s", wd_he[msex]));
-
- /* Scan */
- for (n = 0; n < vn; n++)
- {
- /* Intro */
- if (n == 0) text_out(" may ");
- else if (n < vn - 1) text_out(", ");
- else text_out(" or ");
-
- /* Dump */
- text_out_c(TERM_YELLOW, vp[n]);
- }
-
- /* End */
- text_out(". ");
- }
-
-
- /* Collect breaths */
- vn = 0;
- if (flags4 & (RF4_BR_ACID)) vp[vn++] = "acid";
- if (flags4 & (RF4_BR_ELEC)) vp[vn++] = "lightning";
- if (flags4 & (RF4_BR_FIRE)) vp[vn++] = "fire";
- if (flags4 & (RF4_BR_COLD)) vp[vn++] = "frost";
- if (flags4 & (RF4_BR_POIS)) vp[vn++] = "poison";
- if (flags4 & (RF4_BR_NETH)) vp[vn++] = "nether";
- if (flags4 & (RF4_BR_LITE)) vp[vn++] = "light";
- if (flags4 & (RF4_BR_DARK)) vp[vn++] = "darkness";
- if (flags4 & (RF4_BR_CONF)) vp[vn++] = "confusion";
- if (flags4 & (RF4_BR_SOUN)) vp[vn++] = "sound";
- if (flags4 & (RF4_BR_CHAO)) vp[vn++] = "chaos";
- if (flags4 & (RF4_BR_DISE)) vp[vn++] = "disenchantment";
- if (flags4 & (RF4_BR_NEXU)) vp[vn++] = "nexus";
- if (flags4 & (RF4_BR_TIME)) vp[vn++] = "time";
- if (flags4 & (RF4_BR_INER)) vp[vn++] = "inertia";
- if (flags4 & (RF4_BR_GRAV)) vp[vn++] = "gravity";
- if (flags4 & (RF4_BR_SHAR)) vp[vn++] = "shards";
- if (flags4 & (RF4_BR_PLAS)) vp[vn++] = "plasma";
- if (flags4 & (RF4_BR_WALL)) vp[vn++] = "force";
- if (flags4 & (RF4_BR_MANA)) vp[vn++] = "mana";
- if (flags4 & (RF4_BR_NUKE)) vp[vn++] = "toxic waste";
- if (flags4 & (RF4_BR_DISI)) vp[vn++] = "disintegration";
-
- /* Describe breaths */
- if (vn)
- {
- /* Note breath */
- breath = TRUE;
-
- /* Intro */
- text_out(format("%^s", wd_he[msex]));
-
- /* Scan */
- for (n = 0; n < vn; n++)
- {
- /* Intro */
- if (n == 0) text_out(" may breathe ");
- else if (n < vn - 1) text_out(", ");
- else text_out(" or ");
-
- /* Dump */
- text_out_c(TERM_YELLOW, vp[n]);
- }
- }
-
-
- /* Collect spells */
- vn = 0;
- if (flags5 & (RF5_BA_ACID)) vp[vn++] = "produce acid balls";
- if (flags5 & (RF5_BA_ELEC)) vp[vn++] = "produce lightning balls";
- if (flags5 & (RF5_BA_FIRE)) vp[vn++] = "produce fire balls";
- if (flags5 & (RF5_BA_COLD)) vp[vn++] = "produce frost balls";
- if (flags5 & (RF5_BA_POIS)) vp[vn++] = "produce poison balls";
- if (flags5 & (RF5_BA_NETH)) vp[vn++] = "produce nether balls";
- if (flags5 & (RF5_BA_WATE)) vp[vn++] = "produce water balls";
- if (flags4 & (RF4_BA_NUKE)) vp[vn++] = "produce balls of radiation";
- if (flags5 & (RF5_BA_MANA)) vp[vn++] = "invoke mana storms";
- if (flags5 & (RF5_BA_DARK)) vp[vn++] = "invoke darkness storms";
- if (flags4 & (RF4_BA_CHAO)) vp[vn++] = "invoke raw chaos";
- if (flags6 & (RF6_HAND_DOOM)) vp[vn++] = "invoke the Hand of Doom";
- if (flags5 & (RF5_DRAIN_MANA)) vp[vn++] = "drain mana";
- if (flags5 & (RF5_MIND_BLAST)) vp[vn++] = "cause mind blasting";
- if (flags5 & (RF5_BRAIN_SMASH)) vp[vn++] = "cause brain smashing";
- if (flags5 & (RF5_CAUSE_1)) vp[vn++] = "cause light wounds and cursing";
- if (flags5 & (RF5_CAUSE_2)) vp[vn++] = "cause serious wounds and cursing";
- if (flags5 & (RF5_CAUSE_3)) vp[vn++] = "cause critical wounds and cursing";
- if (flags5 & (RF5_CAUSE_4)) vp[vn++] = "cause mortal wounds";
- if (flags5 & (RF5_BO_ACID)) vp[vn++] = "produce acid bolts";
- if (flags5 & (RF5_BO_ELEC)) vp[vn++] = "produce lightning bolts";
- if (flags5 & (RF5_BO_FIRE)) vp[vn++] = "produce fire bolts";
- if (flags5 & (RF5_BO_COLD)) vp[vn++] = "produce frost bolts";
- if (flags5 & (RF5_BO_POIS)) vp[vn++] = "produce poison bolts";
- if (flags5 & (RF5_BO_NETH)) vp[vn++] = "produce nether bolts";
- if (flags5 & (RF5_BO_WATE)) vp[vn++] = "produce water bolts";
- if (flags5 & (RF5_BO_MANA)) vp[vn++] = "produce mana bolts";
- if (flags5 & (RF5_BO_PLAS)) vp[vn++] = "produce plasma bolts";
- if (flags5 & (RF5_BO_ICEE)) vp[vn++] = "produce ice bolts";
- if (flags5 & (RF5_MISSILE)) vp[vn++] = "produce magic missiles";
- if (flags5 & (RF5_SCARE)) vp[vn++] = "terrify";
- if (flags5 & (RF5_BLIND)) vp[vn++] = "blind";
- if (flags5 & (RF5_CONF)) vp[vn++] = "confuse";
- if (flags5 & (RF5_SLOW)) vp[vn++] = "slow";
- if (flags5 & (RF5_HOLD)) vp[vn++] = "paralyze";
- if (flags6 & (RF6_HASTE)) vp[vn++] = "haste-self";
- if (flags6 & (RF6_HEAL)) vp[vn++] = "heal-self";
- if (flags6 & (RF6_BLINK)) vp[vn++] = "blink-self";
- if (flags6 & (RF6_TPORT)) vp[vn++] = "teleport-self";
- if (flags6 & (RF6_S_BUG)) vp[vn++] = "summon software bugs";
- if (flags6 & (RF6_S_RNG)) vp[vn++] = "summon RNG";
- if (flags6 & (RF6_TELE_TO)) vp[vn++] = "teleport to";
- if (flags6 & (RF6_TELE_AWAY)) vp[vn++] = "teleport away";
- if (flags6 & (RF6_TELE_LEVEL)) vp[vn++] = "teleport level";
- if (flags6 & (RF6_S_THUNDERLORD)) vp[vn++] = "summon a Thunderlord";
- if (flags6 & (RF6_DARKNESS)) vp[vn++] = "create darkness";
- if (flags6 & (RF6_TRAPS)) vp[vn++] = "create traps";
- if (flags6 & (RF6_FORGET)) vp[vn++] = "cause amnesia";
- if (flags6 & (RF6_RAISE_DEAD)) vp[vn++] = "raise dead";
- if (flags6 & (RF6_S_MONSTER)) vp[vn++] = "summon a monster";
- if (flags6 & (RF6_S_MONSTERS)) vp[vn++] = "summon monsters";
- if (flags6 & (RF6_S_KIN)) vp[vn++] = "summon aid";
- if (flags6 & (RF6_S_ANT)) vp[vn++] = "summon ants";
- if (flags6 & (RF6_S_SPIDER)) vp[vn++] = "summon spiders";
- if (flags6 & (RF6_S_HOUND)) vp[vn++] = "summon hounds";
- if (flags6 & (RF6_S_HYDRA)) vp[vn++] = "summon hydras";
- if (flags6 & (RF6_S_ANGEL)) vp[vn++] = "summon an angel";
- if (flags6 & (RF6_S_DEMON)) vp[vn++] = "summon a demon";
- if (flags6 & (RF6_S_UNDEAD)) vp[vn++] = "summon an undead";
- if (flags6 & (RF6_S_DRAGON)) vp[vn++] = "summon a dragon";
- if (flags4 & (RF4_S_ANIMAL)) vp[vn++] = "summon animal";
- if (flags6 & (RF6_S_ANIMALS)) vp[vn++] = "summon animals";
- if (flags6 & (RF6_S_HI_UNDEAD)) vp[vn++] = "summon Greater Undead";
- if (flags6 & (RF6_S_HI_DRAGON)) vp[vn++] = "summon Ancient Dragons";
- if (flags6 & (RF6_S_HI_DEMON)) vp[vn++] = "summon Greater Demons";
- if (flags6 & (RF6_S_WRAITH)) vp[vn++] = "summon Ringwraith";
- if (flags6 & (RF6_S_UNIQUE)) vp[vn++] = "summon Unique Monsters";
-
- /* Describe spells */
- if (vn)
- {
- /* Note magic */
- magic = TRUE;
-
- /* Intro */
- if (breath)
- {
- text_out(", and is also");
- }
- else
- {
- text_out(format("%^s is", wd_he[msex]));
- }
-
- /* Verb Phrase */
- text_out(" magical, casting spells");
-
- /* Adverb */
- if (flags2 & (RF2_SMART)) text_out_c(TERM_YELLOW, " intelligently");
-
- /* Scan */
- for (n = 0; n < vn; n++)
- {
- /* Intro */
- if (n == 0) text_out(" which ");
- else if (n < vn - 1) text_out(", ");
- else text_out(" or ");
-
- /* Dump */
- text_out_c(TERM_YELLOW, vp[n]);
- }
- }
-
-
- /* End the sentence about inate/other spells */
- if (breath || magic)
- {
- /* Total casting */
- m = r_ptr->r_cast_inate + r_ptr->r_cast_spell;
-
- /* Average frequency */
- n = (r_ptr->freq_inate + r_ptr->freq_spell) / 2;
-
- /* Describe the spell frequency */
- if (m > 100)
- {
- text_out("; ");
- text_out_c(TERM_L_GREEN, "1");
- text_out(" time in ");
- text_out_c(TERM_L_GREEN, format("%d", 100 / n));
- }
-
- /* Guess at the frequency */
- else if (m)
- {
- n = ((n + 9) / 10) * 10;
- text_out("; about ");
- text_out_c(TERM_L_GREEN, "1");
- text_out(" time in ");
- text_out_c(TERM_L_GREEN, format("%d", 100 / n));
- }
-
- /* End this sentence */
- text_out(". ");
- }
-
-
- /* Describe monster "toughness" */
- if (know_armour(r_idx))
- {
- /* Armor */
- text_out(format("%^s has an armor rating of ", wd_he[msex]));
- text_out_c(TERM_L_GREEN, format("%d", r_ptr->ac));
-
- /* Maximized hitpoints */
- if (flags1 & (RF1_FORCE_MAXHP))
- {
- text_out(" and a life rating of ");
- text_out_c(TERM_L_GREEN, format("%d", r_ptr->hdice * r_ptr->hside));
- text_out(". ");
- }
-
- /* Variable hitpoints */
- else
- {
- text_out(" and a life rating of ");
- text_out_c(TERM_L_GREEN, format("%dd%d", r_ptr->hdice, r_ptr->hside));
- text_out(". ");
- }
- }
-
-
-
- /* Collect special abilities. */
- vn = 0;
- if (flags2 & (RF2_OPEN_DOOR)) vp[vn++] = "open doors";
- if (flags2 & (RF2_BASH_DOOR)) vp[vn++] = "bash down doors";
- if (flags2 & (RF2_PASS_WALL)) vp[vn++] = "pass through walls";
- if (flags2 & (RF2_KILL_WALL)) vp[vn++] = "bore through walls";
- if (flags2 & (RF2_MOVE_BODY)) vp[vn++] = "push past weaker monsters";
- if (flags2 & (RF2_KILL_BODY)) vp[vn++] = "destroy weaker monsters";
- if (flags2 & (RF2_TAKE_ITEM)) vp[vn++] = "pick up objects";
- if (flags2 & (RF2_KILL_ITEM)) vp[vn++] = "destroy objects";
- if (flags9 & (RF9_HAS_LITE)) vp[vn++] = "illuminate the dungeon";
-
- /* Describe special abilities. */
- if (vn)
- {
- /* Intro */
- text_out(format("%^s", wd_he[msex]));
-
- /* Scan */
- for (n = 0; n < vn; n++)
- {
- /* Intro */
- if (n == 0) text_out(" can ");
- else if (n < vn - 1) text_out(", ");
- else text_out(" and ");
-
- /* Dump */
- text_out(vp[n]);
- }
-
- /* End */
- text_out(". ");
- }
-
-
- /* Describe special abilities. */
- if (flags2 & (RF2_INVISIBLE))
- {
- text_out_c(TERM_GREEN, format("%^s is invisible. ", wd_he[msex]));
- }
- if (flags2 & (RF2_COLD_BLOOD))
- {
- text_out(format("%^s is cold blooded. ", wd_he[msex]));
- }
- if (flags2 & (RF2_EMPTY_MIND))
- {
- text_out(format("%^s is not detected by telepathy. ", wd_he[msex]));
- }
- if (flags2 & (RF2_WEIRD_MIND))
- {
- text_out(format("%^s is rarely detected by telepathy. ", wd_he[msex]));
- }
- if (flags4 & (RF4_MULTIPLY))
- {
- text_out_c(TERM_L_UMBER, format("%^s breeds explosively. ", wd_he[msex]));
- }
- if (flags2 & (RF2_REGENERATE))
- {
- text_out_c(TERM_L_WHITE, format("%^s regenerates quickly. ", wd_he[msex]));
- }
- if (r_ptr->flags7 & (RF7_MORTAL))
- {
- text_out_c(TERM_RED, format("%^s is a mortal being. ", wd_he[msex]));
- }
- else
- {
- text_out_c(TERM_L_BLUE, format("%^s is an immortal being. ", wd_he[msex]));
- }
-
-
- /* Collect susceptibilities */
- vn = 0;
- if (flags3 & (RF3_HURT_ROCK))
- {
- vp[vn++] = "rock remover";
- color[vn - 1] = TERM_UMBER;
- }
- if (flags3 & (RF3_HURT_LITE))
- {
- vp[vn++] = "bright light";
- color[vn - 1] = TERM_YELLOW;
- }
- if (flags3 & (RF3_SUSCEP_FIRE))
- {
- vp[vn++] = "fire";
- color[vn - 1] = TERM_RED;
- }
- if (flags3 & (RF3_SUSCEP_COLD))
- {
- vp[vn++] = "cold";
- color[vn - 1] = TERM_L_WHITE;
- }
- if (flags9 & (RF9_SUSCEP_ACID))
- {
- vp[vn++] = "acid";
- color[vn - 1] = TERM_GREEN;
- }
- if (flags9 & (RF9_SUSCEP_ELEC))
- {
- vp[vn++] = "lightning";
- color[vn - 1] = TERM_L_BLUE;
- }
- if (flags9 & (RF9_SUSCEP_POIS))
- {
- vp[vn++] = "poison";
- color[vn - 1] = TERM_L_GREEN;
- }
-
- /* Describe susceptibilities */
- if (vn)
- {
- /* Intro */
- text_out(format("%^s", wd_he[msex]));
-
- /* Scan */
- for (n = 0; n < vn; n++)
- {
- /* Intro */
- if (n == 0) text_out(" is hurt by ");
- else if (n < vn - 1) text_out(", ");
- else text_out(" and ");
-
- /* Dump */
- text_out_c(color[n], vp[n]);
- }
-
- /* End */
- text_out(". ");
- }
-
-
- /* Collect immunities */
- vn = 0;
- if (flags3 & (RF3_IM_ACID))
- {
- vp[vn++] = "acid";
- color[vn - 1] = TERM_L_GREEN;
- }
- if (flags3 & (RF3_IM_ELEC))
- {
- vp[vn++] = "lightning";
- color[vn - 1] = TERM_L_BLUE;
- }
- if (flags3 & (RF3_IM_FIRE))
- {
- vp[vn++] = "fire";
- color[vn - 1] = TERM_L_RED;
- }
- if (flags3 & (RF3_IM_COLD))
- {
- vp[vn++] = "cold";
- color[vn - 1] = TERM_L_BLUE;
- }
- if (flags3 & (RF3_IM_POIS))
- {
- vp[vn++] = "poison";
- color[vn - 1] = TERM_L_GREEN;
- }
-
- /* Describe immunities */
- if (vn)
- {
- /* Intro */
- text_out(format("%^s", wd_he[msex]));
-
- /* Scan */
- for (n = 0; n < vn; n++)
- {
- /* Intro */
- if (n == 0) text_out(" resists ");
- else if (n < vn - 1) text_out(", ");
- else text_out(" and ");
-
- /* Dump */
- text_out_c(color[n], vp[n]);
- }
-
- /* End */
- text_out(". ");
- }
-
-
- /* Collect resistances */
- vn = 0;
- if (flags3 & (RF3_RES_NETH)) vp[vn++] = "nether";
- if (flags3 & (RF3_RES_WATE)) vp[vn++] = "water";
- if (flags3 & (RF3_RES_PLAS)) vp[vn++] = "plasma";
- if (flags3 & (RF3_RES_NEXU)) vp[vn++] = "nexus";
- if (flags3 & (RF3_RES_DISE)) vp[vn++] = "disenchantment";
- if (flags3 & (RF3_RES_TELE)) vp[vn++] = "teleportation";
-
- /* Describe resistances */
- if (vn)
- {
- /* Intro */
- text_out(format("%^s", wd_he[msex]));
-
- /* Scan */
- for (n = 0; n < vn; n++)
- {
- /* Intro */
- if (n == 0) text_out(" resists ");
- else if (n < vn - 1) text_out(", ");
- else text_out(" and ");
-
- /* Dump */
- text_out_c(TERM_L_BLUE, vp[n]);
- }
-
- /* End */
- text_out(". ");
- }
-
-
- /* Collect non-effects */
- vn = 0;
- if (flags3 & (RF3_NO_STUN)) vp[vn++] = "stunned";
- if (flags3 & (RF3_NO_FEAR)) vp[vn++] = "frightened";
- if (flags3 & (RF3_NO_CONF)) vp[vn++] = "confused";
- if (flags3 & (RF3_NO_SLEEP)) vp[vn++] = "slept";
-
- /* Describe non-effects */
- if (vn)
- {
- /* Intro */
- text_out(format("%^s", wd_he[msex]));
-
- /* Scan */
- for (n = 0; n < vn; n++)
- {
- /* Intro */
- if (n == 0) text_out(" cannot be ");
- else if (n < vn - 1) text_out(", ");
- else text_out(" or ");
-
- /* Dump */
- text_out(vp[n]);
- }
-
- /* End */
- text_out(". ");
- }
-
-
- /* Do we know how aware it is? */
- if ((((int)r_ptr->r_wake * (int)r_ptr->r_wake) > r_ptr->sleep) ||
- (r_ptr->r_ignore == MAX_UCHAR) ||
- ((r_ptr->sleep == 0) && (r_ptr->r_tkills >= 10)))
- {
- cptr act;
-
- if (r_ptr->sleep > 200)
- {
- act = "prefers to ignore";
- }
- else if (r_ptr->sleep > 95)
- {
- act = "pays very little attention to";
- }
- else if (r_ptr->sleep > 75)
- {
- act = "pays little attention to";
- }
- else if (r_ptr->sleep > 45)
- {
- act = "tends to overlook";
- }
- else if (r_ptr->sleep > 25)
- {
- act = "takes quite a while to see";
- }
- else if (r_ptr->sleep > 10)
- {
- act = "takes a while to see";
- }
- else if (r_ptr->sleep > 5)
- {
- act = "is fairly observant of";
- }
- else if (r_ptr->sleep > 3)
- {
- act = "is observant of";
- }
- else if (r_ptr->sleep > 1)
- {
- act = "is very observant of";
- }
- else if (r_ptr->sleep > 0)
- {
- act = "is vigilant for";
- }
- else
- {
- act = "is ever vigilant for";
- }
-
- text_out(format("%^s %s intruders, which %s may notice from %d feet. ",
- wd_he[msex], act, wd_he[msex], 10 * r_ptr->aaf));
- }
-
-
- /* Drops gold and/or items */
- if (r_ptr->r_drop_gold || r_ptr->r_drop_item)
- {
- /* No "n" needed */
- sin = FALSE;
-
- /* Intro */
- text_out(format("%^s may carry", wd_he[msex]));
-
- /* Count maximum drop */
- n = MAX(r_ptr->r_drop_gold, r_ptr->r_drop_item);
-
- /* One drop (may need an "n") */
- if (n == 1)
- {
- text_out(" a");
- sin = TRUE;
- }
-
- /* Two drops */
- else if (n == 2)
- {
- text_out(" one or two");
- }
-
- /* Many drops */
- else
- {
- text_out(format(" up to %d", n));
- }
-
-
- /* Great */
- if (flags1 & (RF1_DROP_GREAT))
- {
- p = " exceptional";
- }
-
- /* Good (no "n" needed) */
- else if (flags1 & (RF1_DROP_GOOD))
- {
- p = " good";
- sin = FALSE;
- }
-
- /* Okay */
- else
- {
- p = NULL;
- }
-
-
- /* Objects */
- if (r_ptr->r_drop_item)
- {
- /* Handle singular "an" */
- if (sin) text_out("n");
- sin = FALSE;
-
- /* Dump "object(s)" */
- if (p) text_out_c(TERM_ORANGE, p);
- text_out(" object");
- if (n != 1) text_out("s");
-
- /* Conjunction replaces variety, if needed for "gold" below */
- p = " or";
- }
-
- /* Treasures */
- if (r_ptr->r_drop_gold)
- {
- /* Cancel prefix */
- if (!p) sin = FALSE;
-
- /* Handle singular "an" */
- if (sin) text_out("n");
- sin = FALSE;
-
- /* Dump "treasure(s)" */
- if (p) text_out(p);
- text_out(" treasure");
- if (n != 1) text_out("s");
- }
-
- /* End this sentence */
- text_out(". ");
- }
-
-
- /* Count the number of "known" attacks */
- for (n = 0, m = 0; m < 4; m++)
- {
- /* Skip non-attacks */
- if (!r_ptr->blow[m].method) continue;
-
- /* Count known attacks */
- if (r_ptr->r_blows[m]) n++;
- }
-
- /* Examine (and count) the actual attacks */
- for (r = 0, m = 0; m < 4; m++)
- {
- int method, effect, d1, d2;
-
- /* Skip non-attacks */
- if (!r_ptr->blow[m].method) continue;
-
- /* Skip unknown attacks */
- if (!r_ptr->r_blows[m]) continue;
-
-
- /* Extract the attack info */
- method = r_ptr->blow[m].method;
- effect = r_ptr->blow[m].effect;
- d1 = r_ptr->blow[m].d_dice;
- d2 = r_ptr->blow[m].d_side;
-
-
- /* No method yet */
- p = NULL;
-
- /* Acquire the method */
- switch (method)
- {
- case RBM_HIT:
- p = "hit";
- break;
- case RBM_TOUCH:
- p = "touch";
- break;
- case RBM_PUNCH:
- p = "punch";
- break;
- case RBM_KICK:
- p = "kick";
- break;
- case RBM_CLAW:
- p = "claw";
- break;
- case RBM_BITE:
- p = "bite";
- break;
- case RBM_STING:
- p = "sting";
- break;
- case RBM_XXX1:
- break;
- case RBM_BUTT:
- p = "butt";
- break;
- case RBM_CRUSH:
- p = "crush";
- break;
- case RBM_ENGULF:
- p = "engulf";
- break;
- case RBM_CHARGE:
- p = "charge";
- break;
- case RBM_CRAWL:
- p = "crawl on you";
- break;
- case RBM_DROOL:
- p = "drool on you";
- break;
- case RBM_SPIT:
- p = "spit";
- break;
- case RBM_EXPLODE:
- p = "explode";
- break;
- case RBM_GAZE:
- p = "gaze";
- break;
- case RBM_WAIL:
- p = "wail";
- break;
- case RBM_SPORE:
- p = "release spores";
- break;
- case RBM_XXX4:
- break;
- case RBM_BEG:
- p = "beg";
- break;
- case RBM_INSULT:
- p = "insult";
- break;
- case RBM_MOAN:
- p = "moan";
- break;
- case RBM_SHOW:
- p = "sing";
- break;
- }
-
-
- /* Default effect */
- q = NULL;
-
- /* Acquire the effect */
- switch (effect)
- {
- case RBE_HURT:
- q = "attack";
- break;
- case RBE_POISON:
- q = "poison";
- break;
- case RBE_UN_BONUS:
- q = "disenchant";
- break;
- case RBE_UN_POWER:
- q = "drain charges";
- break;
- case RBE_EAT_GOLD:
- q = "steal gold";
- break;
- case RBE_EAT_ITEM:
- q = "steal items";
- break;
- case RBE_EAT_FOOD:
- q = "eat your food";
- break;
- case RBE_EAT_LITE:
- q = "absorb light";
- break;
- case RBE_ACID:
- q = "shoot acid";
- break;
- case RBE_ELEC:
- q = "electrocute";
- break;
- case RBE_FIRE:
- q = "burn";
- break;
- case RBE_COLD:
- q = "freeze";
- break;
- case RBE_BLIND:
- q = "blind";
- break;
- case RBE_CONFUSE:
- q = "confuse";
- break;
- case RBE_TERRIFY:
- q = "terrify";
- break;
- case RBE_PARALYZE:
- q = "paralyze";
- break;
- case RBE_LOSE_STR:
- q = "reduce strength";
- break;
- case RBE_LOSE_INT:
- q = "reduce intelligence";
- break;
- case RBE_LOSE_WIS:
- q = "reduce wisdom";
- break;
- case RBE_LOSE_DEX:
- q = "reduce dexterity";
- break;
- case RBE_LOSE_CON:
- q = "reduce constitution";
- break;
- case RBE_LOSE_CHR:
- q = "reduce charisma";
- break;
- case RBE_LOSE_ALL:
- q = "reduce all stats";
- break;
- case RBE_SHATTER:
- q = "shatter";
- break;
- case RBE_EXP_10:
- q = "lower experience (by 10d6+)";
- break;
- case RBE_EXP_20:
- q = "lower experience (by 20d6+)";
- break;
- case RBE_EXP_40:
- q = "lower experience (by 40d6+)";
- break;
- case RBE_EXP_80:
- q = "lower experience (by 80d6+)";
- break;
- case RBE_DISEASE:
- q = "disease";
- break;
- case RBE_TIME:
- q = "time";
- break;
- case RBE_SANITY:
- q = "blast sanity";
- break;
- case RBE_HALLU:
- q = "cause hallucinations";
- break;
- case RBE_PARASITE:
- q = "parasite";
- break;
- }
-
-
- /* Introduce the attack description */
- if (!r)
- {
- text_out(format("%^s can ", wd_he[msex]));
- }
- else if (r < n - 1)
- {
- text_out(", ");
- }
- else
- {
- text_out(", and ");
- }
-
-
- /* Hack -- force a method */
- if (!p) p = "do something weird";
-
- /* Describe the method */
- text_out(p);
-
-
- /* Describe the effect (if any) */
- if (q)
- {
- /* Describe the attack type */
- text_out(" to ");
- text_out_c(TERM_YELLOW, q);
-
- /* Describe damage (if known) */
- if (d1 && d2 && know_damage(r_idx, m))
- {
- /* Display the damage */
- text_out(" with damage");
- text_out_c(TERM_L_GREEN, format(" %dd%d", d1, d2));
- }
- }
-
-
- /* Count the attacks as printed */
- r++;
- }
-
- /* Finish sentence above */
- if (r)
- {
- text_out(". ");
- }
-
- /* Notice lack of attacks */
- else if (flags1 & (RF1_NEVER_BLOW))
- {
- text_out(format("%^s has no physical attacks. ", wd_he[msex]));
- }
-
- /* Or describe the lack of knowledge */
- else
- {
- text_out(format("Nothing is known about %s attack. ", wd_his[msex]));
- }
-
-
- /* All done */
- text_out("\n");
-
- /* Cheat -- know everything */
- if ((cheat_know) && (remem == 0))
- {
- /* Hack -- restore memory */
- COPY(r_ptr, &save_mem, monster_race);
- }
-}
-
-/*
- * Hack -- Display the "name" and "attr/chars" of a monster race
- */
-static void roff_name(int r_idx, int ego)
-{
- monster_race *r_ptr = race_info_idx(r_idx, ego);
-
- 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;
-
- /* A title (use "The" for non-uniques) */
- if (!(r_ptr->flags1 & (RF1_UNIQUE)))
- {
- Term_addstr( -1, TERM_WHITE, "The ");
- }
-
- /* Dump the name */
- if (ego)
- {
- if (re_info[ego].before) Term_addstr( -1, TERM_WHITE, format("%s %s", re_name + re_info[ego].name, r_name + r_ptr->name));
- else Term_addstr( -1, TERM_WHITE, format("%s %s", r_name + r_ptr->name, re_name + re_info[ego].name));
- }
- else
- {
- 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, "'):");
-}
-
-/*
- * Hack -- Display the "name" and "attr/chars" of a monster race on top
- */
-static void roff_top(int r_idx, int ego)
-{
- /* Clear the top line */
- Term_erase(0, 0, 255);
-
- /* Reset the cursor */
- Term_gotoxy(0, 0);
-
- roff_name(r_idx, ego);
-}
-
-/*
- * Hack -- describe the given monster race at the top of the screen
- */
-void screen_roff(int r_idx, int ego, int remember)
-{
- /* Flush messages */
- msg_print(NULL);
-
- /* Begin recall */
- Term_erase(0, 1, 255);
-
- /* Recall monster */
- roff_aux(r_idx, ego, remember);
-
- /* Describe monster */
- roff_top(r_idx, ego);
-}
-
-/*
- * Ddescribe the given monster race at the current pos of the "term" window
- */
-void monster_description_out(int r_idx, int ego)
-{
- roff_name(r_idx, ego);
- roff_aux(r_idx, ego, 0);
-}
-
-/*
- * Hack -- describe the given monster race in the current "term" window
- */
-void display_roff(int r_idx, int ego)
-{
- int y;
-
- /* Erase the window */
- for (y = 0; y < Term->hgt; y++)
- {
- /* Erase the line */
- Term_erase(0, y, 255);
- }
-
- /* Begin recall */
- Term_gotoxy(0, 1);
-
- /* Recall monster */
- roff_aux(r_idx, ego, 0);
-
- /* Describe monster */
- roff_top(r_idx, ego);
-}
-
-
-bool_ monster_quest(int r_idx)
-{
- monster_race *r_ptr = &r_info[r_idx];
-
- /* Random quests are in the dungeon */
- if (!(r_ptr->flags8 & RF8_DUNGEON)) return FALSE;
-
- /* No random quests for aquatic monsters */
- if (r_ptr->flags7 & RF7_AQUATIC) return FALSE;
-
- /* No random quests for multiplying monsters */
- if (r_ptr->flags4 & RF4_MULTIPLY) return FALSE;
-
- return TRUE;
-}
-
-
-bool_ monster_dungeon(int r_idx)
-{
- monster_race *r_ptr = &r_info[r_idx];
-
- if (r_ptr->flags8 & RF8_DUNGEON)
- return TRUE;
- else
- return FALSE;
-}
-
-
-bool_ monster_ocean(int r_idx)
-{
- monster_race *r_ptr = &r_info[r_idx];
-
- if (r_ptr->flags8 & RF8_WILD_OCEAN)
- return TRUE;
- else
- return FALSE;
-}
-
-
-bool_ monster_shore(int r_idx)
-{
- monster_race *r_ptr = &r_info[r_idx];
-
- if (r_ptr->flags8 & RF8_WILD_SHORE)
- return TRUE;
- else
- return FALSE;
-}
-
-
-bool_ monster_waste(int r_idx)
-{
- monster_race *r_ptr = &r_info[r_idx];
-
- if (r_ptr->flags8 & RF8_WILD_WASTE)
- return TRUE;
- else
- return FALSE;
-}
-
-
-bool_ monster_town(int r_idx)
-{
- monster_race *r_ptr = &r_info[r_idx];
-
- if (r_ptr->flags8 & RF8_WILD_TOWN)
- return TRUE;
- else
- return FALSE;
-}
-
-
-bool_ monster_wood(int r_idx)
-{
- monster_race *r_ptr = &r_info[r_idx];
-
- if (r_ptr->flags8 & RF8_WILD_WOOD)
- return TRUE;
- else
- return FALSE;
-}
-
-
-bool_ monster_volcano(int r_idx)
-{
- monster_race *r_ptr = &r_info[r_idx];
-
- if (r_ptr->flags8 & RF8_WILD_VOLCANO)
- return TRUE;
- else
- return FALSE;
-}
-
-
-bool_ monster_mountain(int r_idx)
-{
- monster_race *r_ptr = &r_info[r_idx];
-
- if (r_ptr->flags8 & RF8_WILD_MOUNTAIN)
- return TRUE;
- else
- return FALSE;
-}
-
-
-bool_ monster_grass(int r_idx)
-{
- monster_race *r_ptr = &r_info[r_idx];
-
- if (r_ptr->flags8 & RF8_WILD_GRASS)
- return TRUE;
- else
- return FALSE;
-}
-
-
-bool_ monster_deep_water(int r_idx)
-{
- monster_race *r_ptr = &r_info[r_idx];
-
- if (!monster_dungeon(r_idx)) return FALSE;
-
- if (r_ptr->flags7 & RF7_AQUATIC)
- return TRUE;
- else
- return FALSE;
-}
-
-
-bool_ monster_shallow_water(int r_idx)
-{
- monster_race *r_ptr = &r_info[r_idx];
-
- if (!monster_dungeon(r_idx)) return FALSE;
-
- if (r_ptr->flags2 & RF2_AURA_FIRE)
- return FALSE;
- else
- return TRUE;
-}
-
-
-bool_ monster_lava(int r_idx)
-{
- monster_race *r_ptr = &r_info[r_idx];
-
- if (!monster_dungeon(r_idx)) return FALSE;
-
- if (((r_ptr->flags3 & RF3_IM_FIRE) ||
- (r_ptr->flags7 & RF7_CAN_FLY)) &&
- !(r_ptr->flags3 & RF3_AURA_COLD))
- return TRUE;
- else
- return FALSE;
-}
-
-
-void set_mon_num_hook(void)
-{
- if (!dun_level)
- {
- switch (wf_info[wild_map[p_ptr->wilderness_y][p_ptr->wilderness_x].feat].terrain_idx)
- {
- case TERRAIN_TOWN:
- get_mon_num_hook = monster_town;
- break;
- case TERRAIN_DEEP_WATER:
- get_mon_num_hook = monster_ocean;
- break;
- case TERRAIN_SHALLOW_WATER:
- get_mon_num_hook = monster_shore;
- break;
- case TERRAIN_DIRT:
- get_mon_num_hook = monster_waste;
- break;
- case TERRAIN_GRASS:
- get_mon_num_hook = monster_grass;
- break;
- case TERRAIN_TREES:
- get_mon_num_hook = monster_wood;
- break;
- case TERRAIN_SHALLOW_LAVA:
- case TERRAIN_DEEP_LAVA:
- get_mon_num_hook = monster_volcano;
- break;
- case TERRAIN_MOUNTAIN:
- get_mon_num_hook = monster_mountain;
- break;
- default:
- get_mon_num_hook = monster_dungeon;
- break;
- }
- }
- else
- {
- get_mon_num_hook = monster_dungeon;
- }
-}
-
-
-/*
- * Check if monster can cross terrain
- */
-bool_ monster_can_cross_terrain(byte feat, monster_race *r_ptr)
-{
- /* Deep water */
- if (feat == FEAT_DEEP_WATER)
- {
- if ((r_ptr->flags7 & RF7_AQUATIC) ||
- (r_ptr->flags7 & RF7_CAN_FLY) ||
- (r_ptr->flags7 & RF7_CAN_SWIM))
- return TRUE;
- else
- return FALSE;
- }
- /* Shallow water */
- else if (feat == FEAT_SHAL_WATER)
- {
- if (r_ptr->flags2 & RF2_AURA_FIRE)
- return FALSE;
- else
- return TRUE;
- }
- /* Aquatic monster */
- else if ((r_ptr->flags7 & RF7_AQUATIC) &&
- !(r_ptr->flags7 & RF7_CAN_FLY))
- {
- return FALSE;
- }
- /* Lava */
- else if ((feat == FEAT_SHAL_LAVA) ||
- (feat == FEAT_DEEP_LAVA))
- {
- if ((r_ptr->flags3 & RF3_IM_FIRE) ||
- (r_ptr->flags7 & RF7_CAN_FLY))
- return TRUE;
- else
- return FALSE;
- }
-
- return TRUE;
-}
-
-
-void set_mon_num2_hook(int y, int x)
-{
- /* Set the monster list */
- switch (cave[y][x].feat)
- {
- case FEAT_SHAL_WATER:
- get_mon_num2_hook = monster_shallow_water;
- break;
- case FEAT_DEEP_WATER:
- get_mon_num2_hook = monster_deep_water;
- break;
- case FEAT_DEEP_LAVA:
- case FEAT_SHAL_LAVA:
- get_mon_num2_hook = monster_lava;
- break;
- default:
- get_mon_num2_hook = NULL;
- break;
- }
-}
diff --git a/src/monster1.cc b/src/monster1.cc
new file mode 100644
index 00000000..50c8c548
--- /dev/null
+++ b/src/monster1.cc
@@ -0,0 +1,1671 @@
+/*
+ * Copyright (c) 1989 James E. Wilson, Christopher J. Stuart
+ *
+ * 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 "monster1.hpp"
+
+#include "cave_type.hpp"
+#include "game.hpp"
+#include "monster2.hpp"
+#include "monster_ego.hpp"
+#include "monster_race.hpp"
+#include "monster_race_flag.hpp"
+#include "monster_spell_flag.hpp"
+#include "player_type.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+#include "wilderness_map.hpp"
+#include "wilderness_type_info.hpp"
+
+/*
+ * Pronoun arrays, by gender.
+ */
+static cptr wd_he[3] = { "it", "he", "she" };
+static cptr wd_his[3] = { "its", "his", "her" };
+
+
+/*
+ * Pluralizer. Args(count, singular, plural)
+ */
+#define plural(c,s,p) \
+(((c) == 1) ? (s) : (p))
+
+
+
+/*
+ * Hack -- display monster information using "text_out()"
+ *
+ * Note that there is now a compiler option to only read the monster
+ * descriptions from the raw file when they are actually needed, which
+ * saves about 60K of memory at the cost of disk access during monster
+ * recall, which is optional to the user.
+ *
+ * This function should only be called with the cursor placed at the
+ * left edge of the screen, on a cleared line, in which the recall is
+ * to take place. One extra blank line is left after the recall.
+ */
+static void roff_aux(std::shared_ptr<monster_race const> r_ptr)
+{
+ bool_ old = FALSE;
+ bool_ sin = FALSE;
+
+ int m, n, r;
+
+ cptr p, q;
+
+ bool_ breath = FALSE;
+ bool_ magic = FALSE;
+
+ int vn = 0;
+ byte color[64];
+ cptr vp[64];
+
+ /* Shorthand */
+ auto const flags = r_ptr->flags;
+ monster_spell_flag_set spells = r_ptr->spells;
+
+ /* Extract a gender (if applicable) */
+ int msex = 0;
+ if (flags & RF_FEMALE)
+ {
+ msex = 2;
+ }
+ else if (flags & RF_MALE)
+ {
+ msex = 1;
+ }
+
+ /* Treat uniques differently */
+ if (flags & RF_UNIQUE)
+ {
+ if (r_ptr->max_num == 0)
+ {
+ text_out("You have slain this foe. ");
+ }
+ }
+
+ /* Normal monsters */
+ else
+ {
+ /* Killed some this life */
+ if (r_ptr->r_pkills)
+ {
+ text_out("You have killed at least ");
+ text_out_c(TERM_L_GREEN, format("%d", r_ptr->r_pkills));
+ text_out(" of these creatures. ");
+ }
+
+ /* Killed none */
+ else
+ {
+ text_out("No battles to the death are recalled. ");
+ }
+ }
+
+
+ /* Descriptions */
+ {
+ text_out(r_ptr->text);
+ text_out(" ");
+ }
+
+
+ /* Nothing yet */
+ old = FALSE;
+
+ /* Describe location */
+ if (r_ptr->flags & RF_PET)
+ {
+ text_out(format("%^s is ", wd_he[msex]));
+ text_out_c(TERM_L_BLUE, "friendly");
+ text_out(" to you");
+ old = TRUE;
+ }
+
+ /* Describe location */
+ if (r_ptr->level == 0)
+ {
+ if (old)
+ text_out(", ");
+ else
+ text_out(format("%^s ", wd_he[msex]));
+ text_out_c(TERM_L_GREEN, "lives in the town or the wilderness");
+ old = TRUE;
+ }
+ else
+ {
+ if (old)
+ text_out(", ");
+ else
+ text_out(format("%^s ", wd_he[msex]));
+
+ text_out(format("is normally found on level ", wd_he[msex]));
+ if (dun_level < r_ptr->level) /* out of depth monster */
+ {
+ text_out_c(TERM_L_RED, format("%d", r_ptr->level));
+ }
+ else
+ {
+ text_out_c(TERM_L_GREEN, format("%d", r_ptr->level));
+ }
+
+ old = TRUE;
+ }
+
+
+ /* Describe movement */
+ {
+ /* Introduction */
+ if (old)
+ {
+ text_out(", and ");
+ }
+ else
+ {
+ text_out(format("%^s ", wd_he[msex]));
+ old = TRUE;
+ }
+ text_out("moves");
+
+ /* Random-ness */
+ if ((flags & RF_RAND_50) || (flags & RF_RAND_25))
+ {
+ /* Adverb */
+ if ((flags & RF_RAND_50) && (flags & RF_RAND_25))
+ {
+ text_out(" extremely");
+ }
+ else if (flags & RF_RAND_50)
+ {
+ text_out(" somewhat");
+ }
+ else if (flags & RF_RAND_25)
+ {
+ text_out(" a bit");
+ }
+
+ /* Adjective */
+ text_out(" erratically");
+
+ /* Hack -- Occasional conjunction */
+ if (r_ptr->speed != 110) text_out(", and");
+ }
+
+ /* Speed */
+ if (r_ptr->speed > 110)
+ {
+ if (r_ptr->speed > 130) text_out_c(TERM_RED, " incredibly");
+ else if (r_ptr->speed > 120) text_out_c(TERM_ORANGE, " very");
+ text_out_c(TERM_L_RED, " quickly");
+ }
+ else if (r_ptr->speed < 110)
+ {
+ if (r_ptr->speed < 90) text_out_c(TERM_L_GREEN, " incredibly");
+ else if (r_ptr->speed < 100) text_out_c(TERM_BLUE, " very");
+ text_out_c(TERM_L_BLUE, " slowly");
+ }
+ else
+ {
+ text_out(" at normal speed");
+ }
+ }
+
+ /* The code above includes "attack speed" */
+ if (flags & RF_NEVER_MOVE)
+ {
+ /* Introduce */
+ if (old)
+ {
+ text_out(", but ");
+ }
+ else
+ {
+ text_out(format("%^s ", wd_he[msex]));
+ old = TRUE;
+ }
+
+ /* Describe */
+ text_out("does not deign to chase intruders");
+ }
+
+ /* End this sentence */
+ if (old)
+ {
+ text_out(". ");
+ old = FALSE;
+ }
+
+
+ /* Describe experience if known */
+ {
+ /* Introduction */
+ if (flags & RF_UNIQUE)
+ {
+ text_out("Killing this");
+ }
+ else
+ {
+ text_out("A kill of this");
+ }
+
+ /* Describe the "quality" */
+ if (flags & RF_ELDRITCH_HORROR) text_out_c(TERM_VIOLET, " sanity-blasting");
+ if (flags & RF_ANIMAL) text_out_c(TERM_VIOLET, " natural");
+ if (flags & RF_EVIL) text_out_c(TERM_VIOLET, " evil");
+ if (flags & RF_GOOD) text_out_c(TERM_VIOLET, " good");
+ if (flags & RF_UNDEAD) text_out_c(TERM_VIOLET, " undead");
+
+ /* Describe the "race" */
+ if (flags & RF_DRAGON) text_out_c(TERM_VIOLET, " dragon");
+ else if (flags & RF_DEMON) text_out_c(TERM_VIOLET, " demon");
+ else if (flags & RF_GIANT) text_out_c(TERM_VIOLET, " giant");
+ else if (flags & RF_TROLL) text_out_c(TERM_VIOLET, " troll");
+ else if (flags & RF_ORC) text_out_c(TERM_VIOLET, " orc");
+ else if (flags & RF_THUNDERLORD)text_out_c(TERM_VIOLET, " Thunderlord");
+ else if (flags & RF_SPIDER) text_out_c(TERM_VIOLET, " spider");
+ else if (flags & RF_NAZGUL) text_out_c(TERM_VIOLET, " Nazgul");
+ else text_out(" creature");
+
+ /* Group some variables */
+ if (TRUE)
+ {
+ long i, j;
+
+ /* calculate the integer exp part */
+ i = static_cast<long>(r_ptr->mexp) * r_ptr->level / p_ptr->lev;
+
+ /* calculate the fractional exp part scaled by 100, */
+ /* must use long arithmetic to avoid overflow */
+ j = (((static_cast<long>(r_ptr->mexp) * r_ptr->level % p_ptr->lev) *
+ 1000L / p_ptr->lev + 5) / 10);
+
+ /* Mention the experience */
+ text_out(" is worth ");
+ text_out_c(TERM_ORANGE, format("%ld.%02ld", i, j));
+ text_out(" point");
+ text_out(((i == 1) && (j == 0)) ? "" : "s");
+
+ /* Take account of annoying English */
+ p = "th";
+ i = p_ptr->lev % 10;
+ if ((p_ptr->lev / 10) == 1) /* nothing */;
+ else if (i == 1) p = "st";
+ else if (i == 2) p = "nd";
+ else if (i == 3) p = "rd";
+
+ /* Take account of "leading vowels" in numbers */
+ q = "";
+ i = p_ptr->lev;
+ if ((i == 8) || (i == 11) || (i == 18)) q = "n";
+
+ /* Mention the dependance on the player's level */
+ text_out(format(" for a%s %lu%s level character. ",
+ q, i, p));
+ }
+ }
+
+ if ((flags & RF_AURA_FIRE) && (flags & RF_AURA_ELEC))
+ {
+ text_out(format("%^s is surrounded by ", wd_he[msex]));
+ text_out_c(TERM_VIOLET, "flames and electricity");
+ text_out(". ");
+ }
+ else if (flags & RF_AURA_FIRE)
+ {
+ text_out(format("%^s is surrounded by ", wd_he[msex]));
+ text_out_c(TERM_ORANGE, "flames");
+ text_out(". ");
+ }
+ else if (flags & RF_AURA_ELEC)
+ {
+ text_out(format("%^s is surrounded by ", wd_he[msex]));
+ text_out_c(TERM_L_BLUE, "electricity");
+ text_out(". ");
+ }
+
+ if (flags & RF_REFLECTING)
+ {
+ text_out(format("%^s ", wd_he[msex]));
+ text_out_c(TERM_L_UMBER, "reflects");
+ text_out(" bolt spells. ");
+ }
+
+
+ /* Describe escorts */
+ if ((flags & RF_ESCORT) || (flags & RF_ESCORTS))
+ {
+ text_out(format("%^s usually appears with escorts. ",
+ wd_he[msex]));
+ }
+
+ /* Describe friends */
+ else if ((flags & RF_FRIEND) || (flags & RF_FRIENDS))
+ {
+ text_out(format("%^s usually appears in groups. ",
+ wd_he[msex]));
+ }
+
+
+ /* Collect inate attacks */
+ vn = 0;
+ if (spells & SF_SHRIEK) vp[vn++] = "shriek for help";
+ if (spells & SF_ROCKET) vp[vn++] = "shoot a rocket";
+ if (spells & SF_ARROW_1) vp[vn++] = "fire an arrow";
+ if (spells & SF_ARROW_2) vp[vn++] = "fire arrows";
+ if (spells & SF_ARROW_3) vp[vn++] = "fire a missile";
+ if (spells & SF_ARROW_4) vp[vn++] = "fire missiles";
+
+ /* Describe inate attacks */
+ if (vn)
+ {
+ /* Intro */
+ text_out(format("%^s", wd_he[msex]));
+
+ /* Scan */
+ for (n = 0; n < vn; n++)
+ {
+ /* Intro */
+ if (n == 0) text_out(" may ");
+ else if (n < vn - 1) text_out(", ");
+ else text_out(" or ");
+
+ /* Dump */
+ text_out_c(TERM_YELLOW, vp[n]);
+ }
+
+ /* End */
+ text_out(". ");
+ }
+
+
+ /* Collect breaths */
+ vn = 0;
+ if (spells & SF_BR_ACID) vp[vn++] = "acid";
+ if (spells & SF_BR_ELEC) vp[vn++] = "lightning";
+ if (spells & SF_BR_FIRE) vp[vn++] = "fire";
+ if (spells & SF_BR_COLD) vp[vn++] = "frost";
+ if (spells & SF_BR_POIS) vp[vn++] = "poison";
+ if (spells & SF_BR_NETH) vp[vn++] = "nether";
+ if (spells & SF_BR_LITE) vp[vn++] = "light";
+ if (spells & SF_BR_DARK) vp[vn++] = "darkness";
+ if (spells & SF_BR_CONF) vp[vn++] = "confusion";
+ if (spells & SF_BR_SOUN) vp[vn++] = "sound";
+ if (spells & SF_BR_CHAO) vp[vn++] = "chaos";
+ if (spells & SF_BR_DISE) vp[vn++] = "disenchantment";
+ if (spells & SF_BR_NEXU) vp[vn++] = "nexus";
+ if (spells & SF_BR_TIME) vp[vn++] = "time";
+ if (spells & SF_BR_INER) vp[vn++] = "inertia";
+ if (spells & SF_BR_GRAV) vp[vn++] = "gravity";
+ if (spells & SF_BR_SHAR) vp[vn++] = "shards";
+ if (spells & SF_BR_PLAS) vp[vn++] = "plasma";
+ if (spells & SF_BR_WALL) vp[vn++] = "force";
+ if (spells & SF_BR_MANA) vp[vn++] = "mana";
+ if (spells & SF_BR_NUKE) vp[vn++] = "toxic waste";
+ if (spells & SF_BR_DISI) vp[vn++] = "disintegration";
+
+ /* Describe breaths */
+ if (vn)
+ {
+ /* Note breath */
+ breath = TRUE;
+
+ /* Intro */
+ text_out(format("%^s", wd_he[msex]));
+
+ /* Scan */
+ for (n = 0; n < vn; n++)
+ {
+ /* Intro */
+ if (n == 0) text_out(" may breathe ");
+ else if (n < vn - 1) text_out(", ");
+ else text_out(" or ");
+
+ /* Dump */
+ text_out_c(TERM_YELLOW, vp[n]);
+ }
+ }
+
+
+ /* Collect spells */
+ vn = 0;
+ if (spells & SF_BA_ACID) vp[vn++] = "produce acid balls";
+ if (spells & SF_BA_ELEC) vp[vn++] = "produce lightning balls";
+ if (spells & SF_BA_FIRE) vp[vn++] = "produce fire balls";
+ if (spells & SF_BA_COLD) vp[vn++] = "produce frost balls";
+ if (spells & SF_BA_POIS) vp[vn++] = "produce poison balls";
+ if (spells & SF_BA_NETH) vp[vn++] = "produce nether balls";
+ if (spells & SF_BA_WATE) vp[vn++] = "produce water balls";
+ if (spells & SF_BA_NUKE) vp[vn++] = "produce balls of radiation";
+ if (spells & SF_BA_MANA) vp[vn++] = "invoke mana storms";
+ if (spells & SF_BA_DARK) vp[vn++] = "invoke darkness storms";
+ if (spells & SF_BA_CHAO) vp[vn++] = "invoke raw chaos";
+ if (spells & SF_HAND_DOOM) vp[vn++] = "invoke the Hand of Doom";
+ if (spells & SF_DRAIN_MANA) vp[vn++] = "drain mana";
+ if (spells & SF_MIND_BLAST) vp[vn++] = "cause mind blasting";
+ if (spells & SF_BRAIN_SMASH) vp[vn++] = "cause brain smashing";
+ if (spells & (SF_CAUSE_1)) vp[vn++] = "cause light wounds and cursing";
+ if (spells & (SF_CAUSE_2)) vp[vn++] = "cause serious wounds and cursing";
+ if (spells & (SF_CAUSE_3)) vp[vn++] = "cause critical wounds and cursing";
+ if (spells & (SF_CAUSE_4)) vp[vn++] = "cause mortal wounds";
+ if (spells & SF_BO_ACID) vp[vn++] = "produce acid bolts";
+ if (spells & SF_BO_ELEC) vp[vn++] = "produce lightning bolts";
+ if (spells & SF_BO_FIRE) vp[vn++] = "produce fire bolts";
+ if (spells & SF_BO_COLD) vp[vn++] = "produce frost bolts";
+ if (spells & SF_BO_POIS) vp[vn++] = "produce poison bolts";
+ if (spells & SF_BO_NETH) vp[vn++] = "produce nether bolts";
+ if (spells & SF_BO_WATE) vp[vn++] = "produce water bolts";
+ if (spells & SF_BO_MANA) vp[vn++] = "produce mana bolts";
+ if (spells & SF_BO_PLAS) vp[vn++] = "produce plasma bolts";
+ if (spells & SF_BO_ICEE) vp[vn++] = "produce ice bolts";
+ if (spells & SF_MISSILE) vp[vn++] = "produce magic missiles";
+ if (spells & SF_SCARE) vp[vn++] = "terrify";
+ if (spells & SF_BLIND) vp[vn++] = "blind";
+ if (spells & SF_CONF) vp[vn++] = "confuse";
+ if (spells & SF_SLOW) vp[vn++] = "slow";
+ if (spells & SF_HOLD) vp[vn++] = "paralyze";
+ if (spells & SF_HASTE) vp[vn++] = "haste-self";
+ if (spells & SF_HEAL) vp[vn++] = "heal-self";
+ if (spells & SF_BLINK) vp[vn++] = "blink-self";
+ if (spells & SF_TPORT) vp[vn++] = "teleport-self";
+ if (spells & SF_S_BUG) vp[vn++] = "summon software bugs";
+ if (spells & SF_S_RNG) vp[vn++] = "summon RNG";
+ if (spells & SF_TELE_TO) vp[vn++] = "teleport to";
+ if (spells & SF_TELE_AWAY) vp[vn++] = "teleport away";
+ if (spells & SF_TELE_LEVEL) vp[vn++] = "teleport level";
+ if (spells & SF_S_THUNDERLORD) vp[vn++] = "summon a Thunderlord";
+ if (spells & SF_DARKNESS) vp[vn++] = "create darkness";
+ if (spells & SF_FORGET) vp[vn++] = "cause amnesia";
+ if (spells & SF_RAISE_DEAD) vp[vn++] = "raise dead";
+ if (spells & SF_S_MONSTER) vp[vn++] = "summon a monster";
+ if (spells & SF_S_MONSTERS) vp[vn++] = "summon monsters";
+ if (spells & SF_S_KIN) vp[vn++] = "summon aid";
+ if (spells & SF_S_ANT) vp[vn++] = "summon ants";
+ if (spells & SF_S_SPIDER) vp[vn++] = "summon spiders";
+ if (spells & SF_S_HOUND) vp[vn++] = "summon hounds";
+ if (spells & SF_S_HYDRA) vp[vn++] = "summon hydras";
+ if (spells & SF_S_ANGEL) vp[vn++] = "summon an angel";
+ if (spells & SF_S_DEMON) vp[vn++] = "summon a demon";
+ if (spells & SF_S_UNDEAD) vp[vn++] = "summon an undead";
+ if (spells & SF_S_DRAGON) vp[vn++] = "summon a dragon";
+ if (spells & SF_S_ANIMAL) vp[vn++] = "summon animal";
+ if (spells & SF_S_ANIMALS) vp[vn++] = "summon animals";
+ if (spells & SF_S_HI_UNDEAD) vp[vn++] = "summon Greater Undead";
+ if (spells & SF_S_HI_DRAGON) vp[vn++] = "summon Ancient Dragons";
+ if (spells & SF_S_HI_DEMON) vp[vn++] = "summon Greater Demons";
+ if (spells & SF_S_WRAITH) vp[vn++] = "summon Ringwraith";
+ if (spells & SF_S_UNIQUE) vp[vn++] = "summon Unique Monsters";
+
+ /* Describe spells */
+ if (vn)
+ {
+ /* Note magic */
+ magic = TRUE;
+
+ /* Intro */
+ if (breath)
+ {
+ text_out(", and is also");
+ }
+ else
+ {
+ text_out(format("%^s is", wd_he[msex]));
+ }
+
+ /* Verb Phrase */
+ text_out(" magical, casting spells");
+
+ /* Adverb */
+ if (flags & RF_SMART) text_out_c(TERM_YELLOW, " intelligently");
+
+ /* Scan */
+ for (n = 0; n < vn; n++)
+ {
+ /* Intro */
+ if (n == 0) text_out(" which ");
+ else if (n < vn - 1) text_out(", ");
+ else text_out(" or ");
+
+ /* Dump */
+ text_out_c(TERM_YELLOW, vp[n]);
+ }
+ }
+
+
+ /* End the sentence about inate/other spells */
+ if (breath || magic)
+ {
+ /* Average frequency */
+ n = (r_ptr->freq_inate + r_ptr->freq_spell) / 2;
+
+ /* Describe the spell frequency */
+ text_out("; ");
+ text_out_c(TERM_L_GREEN, "1");
+ text_out(" time in ");
+ text_out_c(TERM_L_GREEN, format("%d", 100 / n));
+
+ /* End this sentence */
+ text_out(". ");
+ }
+
+
+ /* Describe monster "toughness" */
+ {
+ /* Armor */
+ text_out(format("%^s has an armor rating of ", wd_he[msex]));
+ text_out_c(TERM_L_GREEN, format("%d", r_ptr->ac));
+
+ /* Maximized hitpoints */
+ if (flags & RF_FORCE_MAXHP)
+ {
+ text_out(" and a life rating of ");
+ text_out_c(TERM_L_GREEN, format("%d", r_ptr->hdice * r_ptr->hside));
+ text_out(". ");
+ }
+
+ /* Variable hitpoints */
+ else
+ {
+ text_out(" and a life rating of ");
+ text_out_c(TERM_L_GREEN, format("%dd%d", r_ptr->hdice, r_ptr->hside));
+ text_out(". ");
+ }
+ }
+
+
+
+ /* Collect special abilities. */
+ vn = 0;
+ if (flags & RF_OPEN_DOOR) vp[vn++] = "open doors";
+ if (flags & RF_BASH_DOOR) vp[vn++] = "bash down doors";
+ if (flags & RF_PASS_WALL) vp[vn++] = "pass through walls";
+ if (flags & RF_KILL_WALL) vp[vn++] = "bore through walls";
+ if (flags & RF_MOVE_BODY) vp[vn++] = "push past weaker monsters";
+ if (flags & RF_KILL_BODY) vp[vn++] = "destroy weaker monsters";
+ if (flags & RF_TAKE_ITEM) vp[vn++] = "pick up objects";
+ if (flags & RF_KILL_ITEM) vp[vn++] = "destroy objects";
+ if (flags & RF_HAS_LITE) vp[vn++] = "illuminate the dungeon";
+
+ /* Describe special abilities. */
+ if (vn)
+ {
+ /* Intro */
+ text_out(format("%^s", wd_he[msex]));
+
+ /* Scan */
+ for (n = 0; n < vn; n++)
+ {
+ /* Intro */
+ if (n == 0) text_out(" can ");
+ else if (n < vn - 1) text_out(", ");
+ else text_out(" and ");
+
+ /* Dump */
+ text_out(vp[n]);
+ }
+
+ /* End */
+ text_out(". ");
+ }
+
+
+ /* Describe special abilities. */
+ if (flags & RF_INVISIBLE)
+ {
+ text_out_c(TERM_GREEN, format("%^s is invisible. ", wd_he[msex]));
+ }
+ if (flags & RF_COLD_BLOOD)
+ {
+ text_out(format("%^s is cold blooded. ", wd_he[msex]));
+ }
+ if (flags & RF_EMPTY_MIND)
+ {
+ text_out(format("%^s is not detected by telepathy. ", wd_he[msex]));
+ }
+ if (flags & RF_WEIRD_MIND)
+ {
+ text_out(format("%^s is rarely detected by telepathy. ", wd_he[msex]));
+ }
+ if (spells & SF_MULTIPLY)
+ {
+ text_out_c(TERM_L_UMBER, format("%^s breeds explosively. ", wd_he[msex]));
+ }
+ if (flags & RF_REGENERATE)
+ {
+ text_out_c(TERM_L_WHITE, format("%^s regenerates quickly. ", wd_he[msex]));
+ }
+
+ if (r_ptr->flags & RF_MORTAL)
+ {
+ text_out_c(TERM_RED, format("%^s is a mortal being. ", wd_he[msex]));
+ }
+ else
+ {
+ text_out_c(TERM_L_BLUE, format("%^s is an immortal being. ", wd_he[msex]));
+ }
+
+
+ /* Collect susceptibilities */
+ vn = 0;
+ if (flags & RF_HURT_ROCK)
+ {
+ vp[vn++] = "rock remover";
+ color[vn - 1] = TERM_UMBER;
+ }
+ if (flags & RF_HURT_LITE)
+ {
+ vp[vn++] = "bright light";
+ color[vn - 1] = TERM_YELLOW;
+ }
+ if (flags & RF_SUSCEP_FIRE)
+ {
+ vp[vn++] = "fire";
+ color[vn - 1] = TERM_RED;
+ }
+ if (flags & RF_SUSCEP_COLD)
+ {
+ vp[vn++] = "cold";
+ color[vn - 1] = TERM_L_WHITE;
+ }
+ if (flags & RF_SUSCEP_ACID)
+ {
+ vp[vn++] = "acid";
+ color[vn - 1] = TERM_GREEN;
+ }
+ if (flags & RF_SUSCEP_ELEC)
+ {
+ vp[vn++] = "lightning";
+ color[vn - 1] = TERM_L_BLUE;
+ }
+ if (flags & RF_SUSCEP_POIS)
+ {
+ vp[vn++] = "poison";
+ color[vn - 1] = TERM_L_GREEN;
+ }
+
+ /* Describe susceptibilities */
+ if (vn)
+ {
+ /* Intro */
+ text_out(format("%^s", wd_he[msex]));
+
+ /* Scan */
+ for (n = 0; n < vn; n++)
+ {
+ /* Intro */
+ if (n == 0) text_out(" is hurt by ");
+ else if (n < vn - 1) text_out(", ");
+ else text_out(" and ");
+
+ /* Dump */
+ text_out_c(color[n], vp[n]);
+ }
+
+ /* End */
+ text_out(". ");
+ }
+
+
+ /* Collect immunities */
+ vn = 0;
+ if (flags & RF_IM_ACID)
+ {
+ vp[vn++] = "acid";
+ color[vn - 1] = TERM_L_GREEN;
+ }
+ if (flags & RF_IM_ELEC)
+ {
+ vp[vn++] = "lightning";
+ color[vn - 1] = TERM_L_BLUE;
+ }
+ if (flags & RF_IM_FIRE)
+ {
+ vp[vn++] = "fire";
+ color[vn - 1] = TERM_L_RED;
+ }
+ if (flags & RF_IM_COLD)
+ {
+ vp[vn++] = "cold";
+ color[vn - 1] = TERM_L_BLUE;
+ }
+ if (flags & RF_IM_POIS)
+ {
+ vp[vn++] = "poison";
+ color[vn - 1] = TERM_L_GREEN;
+ }
+
+ /* Describe immunities */
+ if (vn)
+ {
+ /* Intro */
+ text_out(format("%^s", wd_he[msex]));
+
+ /* Scan */
+ for (n = 0; n < vn; n++)
+ {
+ /* Intro */
+ if (n == 0) text_out(" resists ");
+ else if (n < vn - 1) text_out(", ");
+ else text_out(" and ");
+
+ /* Dump */
+ text_out_c(color[n], vp[n]);
+ }
+
+ /* End */
+ text_out(". ");
+ }
+
+
+ /* Collect resistances */
+ vn = 0;
+ if (flags & RF_RES_NETH) vp[vn++] = "nether";
+ if (flags & RF_RES_WATE) vp[vn++] = "water";
+ if (flags & RF_RES_PLAS) vp[vn++] = "plasma";
+ if (flags & RF_RES_NEXU) vp[vn++] = "nexus";
+ if (flags & RF_RES_DISE) vp[vn++] = "disenchantment";
+ if (flags & RF_RES_TELE) vp[vn++] = "teleportation";
+
+ /* Describe resistances */
+ if (vn)
+ {
+ /* Intro */
+ text_out(format("%^s", wd_he[msex]));
+
+ /* Scan */
+ for (n = 0; n < vn; n++)
+ {
+ /* Intro */
+ if (n == 0) text_out(" resists ");
+ else if (n < vn - 1) text_out(", ");
+ else text_out(" and ");
+
+ /* Dump */
+ text_out_c(TERM_L_BLUE, vp[n]);
+ }
+
+ /* End */
+ text_out(". ");
+ }
+
+
+ /* Collect non-effects */
+ vn = 0;
+ if (flags & RF_NO_STUN) vp[vn++] = "stunned";
+ if (flags & RF_NO_FEAR) vp[vn++] = "frightened";
+ if (flags & RF_NO_CONF) vp[vn++] = "confused";
+ if (flags & RF_NO_SLEEP) vp[vn++] = "slept";
+
+ /* Describe non-effects */
+ if (vn)
+ {
+ /* Intro */
+ text_out(format("%^s", wd_he[msex]));
+
+ /* Scan */
+ for (n = 0; n < vn; n++)
+ {
+ /* Intro */
+ if (n == 0) text_out(" cannot be ");
+ else if (n < vn - 1) text_out(", ");
+ else text_out(" or ");
+
+ /* Dump */
+ text_out(vp[n]);
+ }
+
+ /* End */
+ text_out(". ");
+ }
+
+
+ /* How aware is it? */
+ {
+ cptr act;
+
+ if (r_ptr->sleep > 200)
+ {
+ act = "prefers to ignore";
+ }
+ else if (r_ptr->sleep > 95)
+ {
+ act = "pays very little attention to";
+ }
+ else if (r_ptr->sleep > 75)
+ {
+ act = "pays little attention to";
+ }
+ else if (r_ptr->sleep > 45)
+ {
+ act = "tends to overlook";
+ }
+ else if (r_ptr->sleep > 25)
+ {
+ act = "takes quite a while to see";
+ }
+ else if (r_ptr->sleep > 10)
+ {
+ act = "takes a while to see";
+ }
+ else if (r_ptr->sleep > 5)
+ {
+ act = "is fairly observant of";
+ }
+ else if (r_ptr->sleep > 3)
+ {
+ act = "is observant of";
+ }
+ else if (r_ptr->sleep > 1)
+ {
+ act = "is very observant of";
+ }
+ else if (r_ptr->sleep > 0)
+ {
+ act = "is vigilant for";
+ }
+ else
+ {
+ act = "is ever vigilant for";
+ }
+
+ text_out(format("%^s %s intruders, which %s may notice from %d feet. ",
+ wd_he[msex], act, wd_he[msex], 10 * r_ptr->aaf));
+ }
+
+
+ /* Drops gold and/or items */
+ {
+ /* Calculate drops */
+ byte drop_gold;
+ byte drop_item;
+
+ drop_gold = drop_item =
+ (((r_ptr->flags & RF_DROP_4D2) ? 8 : 0) +
+ ((r_ptr->flags & RF_DROP_3D2) ? 6 : 0) +
+ ((r_ptr->flags & RF_DROP_2D2) ? 4 : 0) +
+ ((r_ptr->flags & RF_DROP_1D2) ? 2 : 0) +
+ ((r_ptr->flags & RF_DROP_90) ? 1 : 0) +
+ ((r_ptr->flags & RF_DROP_60) ? 1 : 0));
+
+ if (r_ptr->flags & RF_ONLY_GOLD) drop_item = 0;
+ if (r_ptr->flags & RF_ONLY_ITEM) drop_gold = 0;
+
+ /* No "n" needed */
+ sin = FALSE;
+
+ /* Count maximum drop */
+ n = MAX(drop_gold, drop_item);
+
+ /* Intro text */
+ if (n == 0)
+ {
+ text_out(format("%^s carries no items", wd_he[msex]));
+
+ }
+ else if (n == 1)
+ {
+ text_out(format("%^s may carry a", wd_he[msex]));
+ sin = TRUE;
+ }
+ else if (n == 2)
+ {
+ text_out(format("%^s may carry one or two", wd_he[msex]));
+ }
+ else
+ {
+ text_out(format("%^s may carry up to %d", wd_he[msex], n));
+ }
+
+
+ /* Great */
+ if (flags & RF_DROP_GREAT)
+ {
+ p = " exceptional";
+ }
+
+ /* Good (no "n" needed) */
+ else if (flags & RF_DROP_GOOD)
+ {
+ p = " good";
+ sin = FALSE;
+ }
+
+ /* Okay */
+ else
+ {
+ p = NULL;
+ }
+
+
+ /* Objects */
+ if (drop_item)
+ {
+ /* Handle singular "an" */
+ if (sin) text_out("n");
+ sin = FALSE;
+
+ /* Dump "object(s)" */
+ if (p) text_out_c(TERM_ORANGE, p);
+ text_out(" object");
+ if (n != 1) text_out("s");
+
+ /* Conjunction replaces variety, if needed for "gold" below */
+ p = " or";
+ }
+
+ /* Treasures */
+ if (drop_gold)
+ {
+ /* Cancel prefix */
+ if (!p) sin = FALSE;
+
+ /* Handle singular "an" */
+ if (sin) text_out("n");
+ sin = FALSE;
+
+ /* Dump "treasure(s)" */
+ if (p) text_out(p);
+ text_out(" treasure");
+ if (n != 1) text_out("s");
+ }
+
+ /* End this sentence */
+ text_out(". ");
+ }
+
+
+ /* Count the number of attacks */
+ for (n = 0, m = 0; m < 4; m++)
+ {
+ /* Skip non-attacks */
+ if (!r_ptr->blow[m].method) continue;
+
+ /* Count known attacks */
+ n++;
+ }
+
+ /* Examine the actual attacks */
+ for (r = 0, m = 0; m < 4; m++)
+ {
+ /* Skip non-attacks */
+ if (!r_ptr->blow[m].method) continue;
+
+ /* Extract the attack info */
+ int method = r_ptr->blow[m].method;
+ int effect = r_ptr->blow[m].effect;
+ int d1 = r_ptr->blow[m].d_dice;
+ int d2 = r_ptr->blow[m].d_side;
+
+
+ /* No method yet */
+ p = NULL;
+
+ /* Acquire the method */
+ switch (method)
+ {
+ case RBM_HIT:
+ p = "hit";
+ break;
+ case RBM_TOUCH:
+ p = "touch";
+ break;
+ case RBM_PUNCH:
+ p = "punch";
+ break;
+ case RBM_KICK:
+ p = "kick";
+ break;
+ case RBM_CLAW:
+ p = "claw";
+ break;
+ case RBM_BITE:
+ p = "bite";
+ break;
+ case RBM_STING:
+ p = "sting";
+ break;
+ case RBM_XXX1:
+ break;
+ case RBM_BUTT:
+ p = "butt";
+ break;
+ case RBM_CRUSH:
+ p = "crush";
+ break;
+ case RBM_ENGULF:
+ p = "engulf";
+ break;
+ case RBM_CHARGE:
+ p = "charge";
+ break;
+ case RBM_CRAWL:
+ p = "crawl on you";
+ break;
+ case RBM_DROOL:
+ p = "drool on you";
+ break;
+ case RBM_SPIT:
+ p = "spit";
+ break;
+ case RBM_EXPLODE:
+ p = "explode";
+ break;
+ case RBM_GAZE:
+ p = "gaze";
+ break;
+ case RBM_WAIL:
+ p = "wail";
+ break;
+ case RBM_SPORE:
+ p = "release spores";
+ break;
+ case RBM_XXX4:
+ break;
+ case RBM_BEG:
+ p = "beg";
+ break;
+ case RBM_INSULT:
+ p = "insult";
+ break;
+ case RBM_MOAN:
+ p = "moan";
+ break;
+ case RBM_SHOW:
+ p = "sing";
+ break;
+ }
+
+
+ /* Default effect */
+ q = NULL;
+
+ /* Acquire the effect */
+ switch (effect)
+ {
+ case RBE_HURT:
+ q = "attack";
+ break;
+ case RBE_POISON:
+ q = "poison";
+ break;
+ case RBE_UN_BONUS:
+ q = "disenchant";
+ break;
+ case RBE_UN_POWER:
+ q = "drain charges";
+ break;
+ case RBE_EAT_GOLD:
+ q = "steal gold";
+ break;
+ case RBE_EAT_ITEM:
+ q = "steal items";
+ break;
+ case RBE_EAT_FOOD:
+ q = "eat your food";
+ break;
+ case RBE_EAT_LITE:
+ q = "absorb light";
+ break;
+ case RBE_ACID:
+ q = "shoot acid";
+ break;
+ case RBE_ELEC:
+ q = "electrocute";
+ break;
+ case RBE_FIRE:
+ q = "burn";
+ break;
+ case RBE_COLD:
+ q = "freeze";
+ break;
+ case RBE_BLIND:
+ q = "blind";
+ break;
+ case RBE_CONFUSE:
+ q = "confuse";
+ break;
+ case RBE_TERRIFY:
+ q = "terrify";
+ break;
+ case RBE_PARALYZE:
+ q = "paralyze";
+ break;
+ case RBE_LOSE_STR:
+ q = "reduce strength";
+ break;
+ case RBE_LOSE_INT:
+ q = "reduce intelligence";
+ break;
+ case RBE_LOSE_WIS:
+ q = "reduce wisdom";
+ break;
+ case RBE_LOSE_DEX:
+ q = "reduce dexterity";
+ break;
+ case RBE_LOSE_CON:
+ q = "reduce constitution";
+ break;
+ case RBE_LOSE_CHR:
+ q = "reduce charisma";
+ break;
+ case RBE_LOSE_ALL:
+ q = "reduce all stats";
+ break;
+ case RBE_SHATTER:
+ q = "shatter";
+ break;
+ case RBE_EXP_10:
+ q = "lower experience (by 10d6+)";
+ break;
+ case RBE_EXP_20:
+ q = "lower experience (by 20d6+)";
+ break;
+ case RBE_EXP_40:
+ q = "lower experience (by 40d6+)";
+ break;
+ case RBE_EXP_80:
+ q = "lower experience (by 80d6+)";
+ break;
+ case RBE_DISEASE:
+ q = "disease";
+ break;
+ case RBE_TIME:
+ q = "time";
+ break;
+ case RBE_SANITY:
+ q = "blast sanity";
+ break;
+ case RBE_HALLU:
+ q = "cause hallucinations";
+ break;
+ case RBE_PARASITE:
+ q = "parasite";
+ break;
+ }
+
+
+ /* Introduce the attack description */
+ if (!r)
+ {
+ text_out(format("%^s can ", wd_he[msex]));
+ }
+ else if (r < n - 1)
+ {
+ text_out(", ");
+ }
+ else
+ {
+ text_out(", and ");
+ }
+
+
+ /* Hack -- force a method */
+ if (!p) p = "do something weird";
+
+ /* Describe the method */
+ text_out(p);
+
+
+ /* Describe the effect (if any) */
+ if (q)
+ {
+ /* Describe the attack type */
+ text_out(" to ");
+ text_out_c(TERM_YELLOW, q);
+
+ /* Describe damage (if known) */
+ if (d1 && d2)
+ {
+ /* Display the damage */
+ text_out(" with damage");
+ text_out_c(TERM_L_GREEN, format(" %dd%d", d1, d2));
+ }
+ }
+
+
+ /* Count the attacks as printed */
+ r++;
+ }
+
+ /* Finish sentence above */
+ if (r)
+ {
+ text_out(". ");
+ }
+
+ /* Notice lack of attacks */
+ else if (flags & RF_NEVER_BLOW)
+ {
+ text_out(format("%^s has no physical attacks. ", wd_he[msex]));
+ }
+
+ /* Or describe the lack of knowledge */
+ else
+ {
+ text_out(format("Nothing is known about %s attack. ", wd_his[msex]));
+ }
+
+
+ /* All done */
+ text_out("\n");
+}
+
+/*
+ * Hack -- Display the "name" and "attr/chars" of a monster race
+ */
+static void roff_name(int r_idx, int ego)
+{
+ const auto &re_info = game->edit_data.re_info;
+
+ const auto r_ptr = race_info_idx(r_idx, ego);
+
+ /* Access the chars */
+ const char c1 = r_ptr->d_char;
+ const char c2 = r_ptr->x_char;
+
+ /* Access the attrs */
+ const byte a1 = r_ptr->d_attr;
+ const byte a2 = r_ptr->x_attr;
+
+ /* A title (use "The" for non-uniques) */
+ if (!(r_ptr->flags & RF_UNIQUE))
+ {
+ Term_addstr( -1, TERM_WHITE, "The ");
+ }
+
+ /* Dump the name */
+ if (ego)
+ {
+ if (re_info[ego].before)
+ {
+ Term_addstr( -1, TERM_WHITE, format("%s %s", re_info[ego].name, r_ptr->name));
+ }
+ else
+ {
+ Term_addstr( -1, TERM_WHITE, format("%s %s", r_ptr->name, re_info[ego].name));
+ }
+ }
+ else
+ {
+ Term_addstr( -1, TERM_WHITE, r_ptr->name);
+ }
+
+ /* Append the "standard" attr/char info */
+ Term_addstr( -1, TERM_WHITE, " ('");
+ Term_addch(a1, c1);
+ Term_addstr( -1, TERM_WHITE, "')");
+
+ /* Append the "optional" attr/char info */
+ Term_addstr( -1, TERM_WHITE, "/('");
+ Term_addch(a2, c2);
+ Term_addstr( -1, TERM_WHITE, "'):");
+}
+
+/*
+ * Hack -- Display the "name" and "attr/chars" of a monster race on top
+ */
+static void roff_top(int r_idx, int ego)
+{
+ /* Clear the top line */
+ Term_erase(0, 0, 255);
+
+ /* Reset the cursor */
+ Term_gotoxy(0, 0);
+
+ roff_name(r_idx, ego);
+}
+
+/*
+ * Hack -- describe the given monster race at the top of the screen
+ */
+void screen_roff(int r_idx, int ego)
+{
+ auto r_ptr = race_info_idx(r_idx, ego);
+
+ /* Flush messages */
+ msg_print(NULL);
+
+ /* Begin recall */
+ Term_erase(0, 1, 255);
+
+ /* Recall monster */
+ roff_aux(r_ptr);
+
+ /* Describe monster */
+ roff_top(r_idx, ego);
+}
+
+/*
+ * Describe the given monster race at the current pos of the "term" window
+ */
+void monster_description_out(int r_idx, int ego)
+{
+ auto r_ptr = race_info_idx(r_idx, ego);
+ roff_name(r_idx, ego);
+ roff_aux(r_ptr);
+}
+
+/*
+ * Hack -- describe the given monster race in the current "term" window
+ */
+void display_roff(int r_idx, int ego)
+{
+ int y;
+ int hgt;
+ Term_get_size(nullptr, &hgt);
+
+ /* Erase the window */
+ for (y = 0; y < hgt; y++)
+ {
+ /* Erase the line */
+ Term_erase(0, y, 255);
+ }
+
+ /* Begin recall */
+ Term_gotoxy(0, 1);
+
+ /* Recall monster */
+ auto r_ptr = race_info_idx(r_idx, ego);
+ roff_aux(r_ptr);
+
+ /* Describe monster */
+ roff_top(r_idx, ego);
+}
+
+
+bool_ monster_quest(int r_idx)
+{
+ auto const &r_info = game->edit_data.r_info;
+
+ auto r_ptr = &r_info[r_idx];
+
+ /* Random quests are in the dungeon */
+ if (r_ptr->flags & RF_WILD_ONLY) return FALSE;
+
+ /* No random quests for aquatic monsters */
+ if (r_ptr->flags & RF_AQUATIC) return FALSE;
+
+ /* No random quests for multiplying monsters */
+ if (r_ptr->spells & SF_MULTIPLY) return FALSE;
+
+ return TRUE;
+}
+
+
+bool_ monster_dungeon(int r_idx)
+{
+ auto const &r_info = game->edit_data.r_info;
+
+ auto r_ptr = &r_info[r_idx];
+
+ if (!(r_ptr->flags & RF_WILD_ONLY))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+
+static bool_ monster_ocean(int r_idx)
+{
+ auto const &r_info = game->edit_data.r_info;
+
+ auto r_ptr = &r_info[r_idx];
+
+ if (r_ptr->flags & RF_WILD_OCEAN)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+
+static bool_ monster_shore(int r_idx)
+{
+ auto const &r_info = game->edit_data.r_info;
+
+ auto r_ptr = &r_info[r_idx];
+
+ if (r_ptr->flags & RF_WILD_SHORE)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+
+static bool_ monster_waste(int r_idx)
+{
+ auto const &r_info = game->edit_data.r_info;
+
+ auto r_ptr = &r_info[r_idx];
+
+ if (r_ptr->flags & RF_WILD_WASTE)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+
+static bool_ monster_town(int r_idx)
+{
+ auto const &r_info = game->edit_data.r_info;
+
+ auto r_ptr = &r_info[r_idx];
+
+ if (r_ptr->flags & RF_WILD_TOWN)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+
+static bool_ monster_wood(int r_idx)
+{
+ auto const &r_info = game->edit_data.r_info;
+
+ auto r_ptr = &r_info[r_idx];
+
+ if (r_ptr->flags & RF_WILD_WOOD)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+
+static bool_ monster_volcano(int r_idx)
+{
+ auto const &r_info = game->edit_data.r_info;
+
+ auto r_ptr = &r_info[r_idx];
+
+ if (r_ptr->flags & RF_WILD_VOLCANO)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+
+static bool_ monster_mountain(int r_idx)
+{
+ auto const &r_info = game->edit_data.r_info;
+
+ auto r_ptr = &r_info[r_idx];
+
+ if (r_ptr->flags & RF_WILD_MOUNTAIN)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+
+static bool_ monster_grass(int r_idx)
+{
+ auto const &r_info = game->edit_data.r_info;
+
+ auto r_ptr = &r_info[r_idx];
+
+ if (r_ptr->flags & RF_WILD_GRASS)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+
+static bool_ monster_deep_water(int r_idx)
+{
+ auto const &r_info = game->edit_data.r_info;
+
+ auto r_ptr = &r_info[r_idx];
+
+ if (!monster_dungeon(r_idx)) return FALSE;
+
+ if (r_ptr->flags & RF_AQUATIC)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+
+static bool_ monster_shallow_water(int r_idx)
+{
+ auto const &r_info = game->edit_data.r_info;
+
+ auto r_ptr = &r_info[r_idx];
+
+ if (!monster_dungeon(r_idx)) return FALSE;
+
+ if (r_ptr->flags & RF_AURA_FIRE)
+ return FALSE;
+ else
+ return TRUE;
+}
+
+
+static bool_ monster_lava(int r_idx)
+{
+ auto const &r_info = game->edit_data.r_info;
+
+ auto r_ptr = &r_info[r_idx];
+
+ if (!monster_dungeon(r_idx)) return FALSE;
+
+ if (((r_ptr->flags & RF_IM_FIRE) ||
+ (r_ptr->flags & RF_CAN_FLY)) &&
+ !(r_ptr->flags & RF_AURA_COLD))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+
+void set_mon_num_hook()
+{
+ auto const &wf_info = game->edit_data.wf_info;
+
+ if (!dun_level)
+ {
+ auto const &wilderness = game->wilderness;
+ switch (wf_info[wilderness(p_ptr->wilderness_x, p_ptr->wilderness_y).feat].terrain_idx)
+ {
+ case TERRAIN_TOWN:
+ get_mon_num_hook = monster_town;
+ break;
+ case TERRAIN_DEEP_WATER:
+ get_mon_num_hook = monster_ocean;
+ break;
+ case TERRAIN_SHALLOW_WATER:
+ get_mon_num_hook = monster_shore;
+ break;
+ case TERRAIN_DIRT:
+ get_mon_num_hook = monster_waste;
+ break;
+ case TERRAIN_GRASS:
+ get_mon_num_hook = monster_grass;
+ break;
+ case TERRAIN_TREES:
+ get_mon_num_hook = monster_wood;
+ break;
+ case TERRAIN_SHALLOW_LAVA:
+ case TERRAIN_DEEP_LAVA:
+ get_mon_num_hook = monster_volcano;
+ break;
+ case TERRAIN_MOUNTAIN:
+ get_mon_num_hook = monster_mountain;
+ break;
+ default:
+ get_mon_num_hook = monster_dungeon;
+ break;
+ }
+ }
+ else
+ {
+ get_mon_num_hook = monster_dungeon;
+ }
+}
+
+
+/*
+ * Check if monster can cross terrain
+ */
+bool_ monster_can_cross_terrain(byte feat, std::shared_ptr<monster_race> r_ptr)
+{
+ /* Deep water */
+ if (feat == FEAT_DEEP_WATER)
+ {
+ if ((r_ptr->flags & RF_AQUATIC) ||
+ (r_ptr->flags & RF_CAN_FLY) ||
+ (r_ptr->flags & RF_CAN_SWIM))
+ return TRUE;
+ else
+ return FALSE;
+ }
+ /* Shallow water */
+ else if (feat == FEAT_SHAL_WATER)
+ {
+ if (r_ptr->flags & RF_AURA_FIRE)
+ return FALSE;
+ else
+ return TRUE;
+ }
+ /* Aquatic monster */
+ else if ((r_ptr->flags & RF_AQUATIC) &&
+ !(r_ptr->flags & RF_CAN_FLY))
+ {
+ return FALSE;
+ }
+ /* Lava */
+ else if ((feat == FEAT_SHAL_LAVA) ||
+ (feat == FEAT_DEEP_LAVA))
+ {
+ if ((r_ptr->flags & RF_IM_FIRE) ||
+ (r_ptr->flags & RF_CAN_FLY))
+ return TRUE;
+ else
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+void set_mon_num2_hook(int y, int x)
+{
+ /* Set the monster list */
+ switch (cave[y][x].feat)
+ {
+ case FEAT_SHAL_WATER:
+ get_mon_num2_hook = monster_shallow_water;
+ break;
+ case FEAT_DEEP_WATER:
+ get_mon_num2_hook = monster_deep_water;
+ break;
+ case FEAT_DEEP_LAVA:
+ case FEAT_SHAL_LAVA:
+ get_mon_num2_hook = monster_lava;
+ break;
+ default:
+ get_mon_num2_hook = NULL;
+ break;
+ }
+}
diff --git a/src/monster1.hpp b/src/monster1.hpp
new file mode 100644
index 00000000..34f54346
--- /dev/null
+++ b/src/monster1.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+void screen_roff(int r_idx, int ego);
+void display_roff(int r_idx, int ego);
+void monster_description_out(int r_idx, int ego);
diff --git a/src/monster2.c b/src/monster2.cc
index b0753244..624dca53 100644
--- a/src/monster2.c
+++ b/src/monster2.cc
@@ -1,7 +1,3 @@
-/* File: monster2.c */
-
-/* Purpose: misc code for monsters */
-
/*
* Copyright (c) 1989 James E. Wilson, Robert A. Koeneke
*
@@ -9,18 +5,70 @@
* not for profit purposes provided that this copyright and statement are
* included in all such copies.
*/
-
-#include "angband.h"
+#include "monster2.hpp"
+
+#include "alloc_entry.hpp"
+#include "artifact_type.hpp"
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "dungeon_flag.hpp"
+#include "dungeon_info_type.hpp"
+#include "files.hpp"
+#include "game.hpp"
+#include "hook_new_monster_in.hpp"
+#include "hook_new_monster_end_in.hpp"
+#include "hooks.hpp"
+#include "levels.hpp"
+#include "mimic.hpp"
+#include "monster3.hpp"
+#include "monster_ego.hpp"
+#include "monster_race.hpp"
+#include "monster_race_flag.hpp"
+#include "monster_spell_flag.hpp"
+#include "monster_type.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_flag.hpp"
+#include "object_kind.hpp"
+#include "object_type.hpp"
+#include "options.hpp"
+#include "player_race_flag.hpp"
+#include "player_type.hpp"
+#include "randart.hpp"
+#include "spells1.hpp"
+#include "spells2.hpp"
+#include "stats.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+#include "wilderness_map.hpp"
+#include "xtra1.hpp"
+#include "xtra2.hpp"
+#include "z-rand.hpp"
+
+#include <algorithm>
+#include <string>
#define MAX_HORROR 20
#define MAX_FUNNY 22
#define MAX_COMMENT 5
+#define MODIFY_AUX(o, n) ((o) = modify_aux((o), (n) >> 2, (n) & 3))
+#define MODIFY(o, n, min) MODIFY_AUX(o, n); (o) = ((o) < (min))?(min):(o)
+
+s32b monster_exp(s16b level)
+{
+ s32b capped_level = std::min(level, static_cast<s16b>(MONSTER_LEVEL_MAX));
+ return (capped_level * capped_level * capped_level * 6);
+}
+
/* Monster gain a few levels ? */
void monster_check_experience(int m_idx, bool_ silent)
{
+ auto const &r_info = game->edit_data.r_info;
+
monster_type *m_ptr = &m_list[m_idx];
- monster_race *r_ptr = &r_info[m_ptr->r_idx];
+ auto r_ptr = &r_info[m_ptr->r_idx];
char m_name[80];
/* Get the name */
@@ -28,7 +76,7 @@ void monster_check_experience(int m_idx, bool_ silent)
/* Gain levels while possible */
while ((m_ptr->level < MONSTER_LEVEL_MAX) &&
- (m_ptr->exp >= (u32b)(MONSTER_EXP(m_ptr->level + 1))))
+ (m_ptr->exp >= monster_exp(m_ptr->level + 1)))
{
/* Gain a level */
m_ptr->level++;
@@ -95,7 +143,7 @@ void monster_set_level(int m_idx, int level)
if (m_ptr->level < level)
{
- m_ptr->exp = MONSTER_EXP(level);
+ m_ptr->exp = monster_exp(level);
monster_check_experience(m_idx, TRUE);
}
}
@@ -124,28 +172,19 @@ s32b modify_aux(s32b a, s32b b, char mod)
}
/* Is this ego ok for this monster ? */
-bool_ mego_ok(int r_idx, int ego)
+bool_ mego_ok(monster_race const *r_ptr, int ego)
{
- monster_ego *re_ptr = &re_info[ego];
- monster_race *r_ptr = &r_info[r_idx];
+ const auto &re_info = game->edit_data.re_info;
+
+ auto re_ptr = &re_info[ego];
bool_ ok = FALSE;
int i;
/* needed flags */
- if (re_ptr->flags1 && ((re_ptr->flags1 & r_ptr->flags1) != re_ptr->flags1)) return FALSE;
- if (re_ptr->flags2 && ((re_ptr->flags2 & r_ptr->flags2) != re_ptr->flags2)) return FALSE;
- if (re_ptr->flags3 && ((re_ptr->flags3 & r_ptr->flags3) != re_ptr->flags3)) return FALSE;
- if (re_ptr->flags7 && ((re_ptr->flags7 & r_ptr->flags7) != re_ptr->flags7)) return FALSE;
- if (re_ptr->flags8 && ((re_ptr->flags8 & r_ptr->flags8) != re_ptr->flags8)) return FALSE;
- if (re_ptr->flags9 && ((re_ptr->flags9 & r_ptr->flags9) != re_ptr->flags9)) return FALSE;
+ if (re_ptr->flags && ((re_ptr->flags & r_ptr->flags) != re_ptr->flags)) return FALSE;
/* unwanted flags */
- if (re_ptr->hflags1 && (re_ptr->hflags1 & r_ptr->flags1)) return FALSE;
- if (re_ptr->hflags2 && (re_ptr->hflags2 & r_ptr->flags2)) return FALSE;
- if (re_ptr->hflags3 && (re_ptr->hflags3 & r_ptr->flags3)) return FALSE;
- if (re_ptr->hflags7 && (re_ptr->hflags7 & r_ptr->flags7)) return FALSE;
- if (re_ptr->hflags8 && (re_ptr->hflags8 & r_ptr->flags8)) return FALSE;
- if (re_ptr->hflags9 && (re_ptr->hflags9 & r_ptr->flags9)) return FALSE;
+ if (re_ptr->hflags && (re_ptr->hflags & r_ptr->flags)) return FALSE;
/* Need good race -- IF races are specified */
if (re_ptr->r_char[0])
@@ -169,17 +208,18 @@ bool_ mego_ok(int r_idx, int ego)
}
/* Choose an ego type */
-int pick_ego_monster(int r_idx)
+static int pick_ego_monster(monster_race const *r_ptr)
{
+ const auto &re_info = game->edit_data.re_info;
+
/* Assume no ego */
int ego = 0, lvl;
- int tries = max_re_idx + 10;
- monster_ego *re_ptr;
+ int tries = re_info.size() + 10;
- if ((!(dungeon_flags2 & DF2_ELVEN)) && (!(dungeon_flags2 & DF2_DWARVEN)))
+ if ((!(dungeon_flags & DF_ELVEN)) && (!(dungeon_flags & DF_DWARVEN)))
{
/* No townspeople ego */
- if (!r_info[r_idx].level) return 0;
+ if (!r_ptr->level) return 0;
/* First are we allowed to find an ego */
if (!magik(MEGO_CHANCE)) return 0;
@@ -188,14 +228,14 @@ int pick_ego_monster(int r_idx)
while (tries--)
{
/* Pick one */
- ego = rand_range(1, max_re_idx - 1);
- re_ptr = &re_info[ego];
+ ego = rand_range(1, re_info.size() - 1);
+ auto re_ptr = &re_info[ego];
/* No hope so far */
- if (!mego_ok(r_idx, ego)) continue;
+ if (!mego_ok(r_ptr, ego)) continue;
/* Not too much OoD */
- lvl = r_info[r_idx].level;
+ lvl = r_ptr->level;
MODIFY(lvl, re_ptr->level, 0);
lvl -= ((dun_level / 2) + (rand_int(dun_level / 2)));
if (lvl < 1) lvl = 1;
@@ -211,12 +251,12 @@ int pick_ego_monster(int r_idx)
/* Bypass restrictions for themed townspeople */
else
{
- if (dungeon_flags2 & DF2_ELVEN)
+ if (dungeon_flags & DF_ELVEN)
ego = test_mego_name("Elven");
- else if (dungeon_flags2 & DF2_DWARVEN)
+ else if (dungeon_flags & DF_DWARVEN)
ego = test_mego_name("Dwarven");
- if (mego_ok(r_idx, ego))
+ if (mego_ok(r_ptr, ego))
return ego;
}
@@ -228,34 +268,48 @@ int pick_ego_monster(int r_idx)
* Return a (monster_race*) with the combination of the monster
* properties and the ego type
*/
-monster_race* race_info_idx(int r_idx, int ego)
+std::shared_ptr<monster_race> race_info_idx(int r_idx, int ego)
{
- static monster_race race;
- monster_ego *re_ptr = &re_info[ego];
- monster_race *r_ptr = &r_info[r_idx], *nr_ptr = &race;
- int i;
+ auto const &re_info = game->edit_data.re_info;
+ auto &r_info = game->edit_data.r_info;
+
+ auto r_ptr = &r_info[r_idx];
+
+ /* We don't need to allocate anything if it's an ordinary monster. */
+ if (!ego) {
+ return std::shared_ptr<monster_race>(r_ptr, [](monster_race *) {
+ // No need to delete -- will be freed when the r_info array is freed.
+ });
+ }
- /* No work needed */
- if (!ego) return r_ptr;
+ /* We allocate a copy of the "base" monster race to refer to. */
+ auto nr_ptr = std::make_shared<monster_race>();
+ *nr_ptr = *r_ptr;
- /* Copy the base monster */
- COPY(nr_ptr, r_ptr, monster_race);
+ /* Get a reference to the ego monster modifiers */
+ auto re_ptr = &re_info[ego];
/* Adjust the values */
- for (i = 0; i < 4; i++)
+ for (int i = 0; i < 4; i++)
{
- s32b j, k;
-
- j = modify_aux(nr_ptr->blow[i].d_dice, re_ptr->blow[i].d_dice, re_ptr->blowm[i][0]);
+ s32b j = modify_aux(nr_ptr->blow[i].d_dice, re_ptr->blow[i].d_dice, re_ptr->blowm[i][0]);
if (j < 0) j = 0;
- k = modify_aux(nr_ptr->blow[i].d_side, re_ptr->blow[i].d_side, re_ptr->blowm[i][1]);
+
+ s32b k = modify_aux(nr_ptr->blow[i].d_side, re_ptr->blow[i].d_side, re_ptr->blowm[i][1]);
if (k < 0) k = 0;
nr_ptr->blow[i].d_dice = j;
nr_ptr->blow[i].d_side = k;
- if (re_ptr->blow[i].method) nr_ptr->blow[i].method = re_ptr->blow[i].method;
- if (re_ptr->blow[i].effect) nr_ptr->blow[i].effect = re_ptr->blow[i].effect;
+ if (re_ptr->blow[i].method)
+ {
+ nr_ptr->blow[i].method = re_ptr->blow[i].method;
+ }
+
+ if (re_ptr->blow[i].effect)
+ {
+ nr_ptr->blow[i].effect = re_ptr->blow[i].effect;
+ }
}
MODIFY(nr_ptr->hdice, re_ptr->hdice, 1);
@@ -279,26 +333,12 @@ monster_race* race_info_idx(int r_idx, int ego)
MODIFY(nr_ptr->level, re_ptr->level, 1);
/* Take off some flags */
- nr_ptr->flags1 &= ~(re_ptr->nflags1);
- nr_ptr->flags2 &= ~(re_ptr->nflags2);
- nr_ptr->flags3 &= ~(re_ptr->nflags3);
- nr_ptr->flags4 &= ~(re_ptr->nflags4);
- nr_ptr->flags5 &= ~(re_ptr->nflags5);
- nr_ptr->flags6 &= ~(re_ptr->nflags6);
- nr_ptr->flags7 &= ~(re_ptr->nflags7);
- nr_ptr->flags8 &= ~(re_ptr->nflags8);
- nr_ptr->flags9 &= ~(re_ptr->nflags9);
+ nr_ptr->flags &= ~re_ptr->nflags;
+ nr_ptr->spells &= ~(re_ptr->nspells);
/* Add some flags */
- nr_ptr->flags1 |= re_ptr->mflags1;
- nr_ptr->flags2 |= re_ptr->mflags2;
- nr_ptr->flags3 |= re_ptr->mflags3;
- nr_ptr->flags4 |= re_ptr->mflags4;
- nr_ptr->flags5 |= re_ptr->mflags5;
- nr_ptr->flags6 |= re_ptr->mflags6;
- nr_ptr->flags7 |= re_ptr->mflags7;
- nr_ptr->flags8 |= re_ptr->mflags8;
- nr_ptr->flags9 |= re_ptr->mflags9;
+ nr_ptr->flags |= re_ptr->mflags;
+ nr_ptr->spells |= re_ptr->mspells;
/* Change the char/attr is needed */
if (re_ptr->d_char != MEGO_CHAR_ANY)
@@ -383,18 +423,6 @@ static cptr funny_comments[MAX_COMMENT] =
};
-int get_wilderness_flag(void)
-{
- int x = p_ptr->wilderness_x;
- int y = p_ptr->wilderness_y;
-
- if (dun_level)
- return (RF8_DUNGEON);
- else
- return (1L << wf_info[wild_map[y][x].feat].terrain_idx);
-}
-
-
/*
* Delete a monster by index.
*
@@ -402,31 +430,26 @@ int get_wilderness_flag(void)
*/
void delete_monster_idx(int i)
{
- int x, y, j;
-
- monster_type *m_ptr = &m_list[i];
-
- monster_race *r_ptr = race_inf(m_ptr);
-
- s16b this_o_idx, next_o_idx = 0;
-
- bool_ had_lite = FALSE;
- ;
-
+ auto &k_info = game->edit_data.k_info;
+ auto &a_info = game->edit_data.a_info;
+ auto &random_artifacts = game->random_artifacts;
/* Get location */
- y = m_ptr->fy;
- x = m_ptr->fx;
+ monster_type *m_ptr = &m_list[i];
+ int y = m_ptr->fy;
+ int x = m_ptr->fx;
/* Hack -- Reduce the racial counter */
+ auto const r_ptr = m_ptr->race();
r_ptr->cur_num--;
r_ptr->on_saved = FALSE;
/* Hack -- count the number of "reproducers" */
- if (r_ptr->flags4 & (RF4_MULTIPLY)) num_repro--;
+ if (r_ptr->spells & SF_MULTIPLY) num_repro--;
/* XXX XXX XXX remove monster light source */
- if (r_ptr->flags9 & (RF9_HAS_LITE)) had_lite = TRUE;
+ bool_ had_lite = FALSE;
+ if (r_ptr->flags & RF_HAS_LITE) had_lite = TRUE;
/* Hack -- remove target monster */
@@ -438,7 +461,8 @@ void delete_monster_idx(int i)
/* Hack -- remove tracked monster */
if (i == p_ptr->control) p_ptr->control = 0;
- for (j = m_max - 1; j >= 1; j--)
+
+ for (int j = m_max - 1; j >= 1; j--)
{
/* Access the monster */
monster_type *t_ptr = &m_list[j];
@@ -452,22 +476,20 @@ void delete_monster_idx(int i)
/* Monster is gone */
cave[y][x].m_idx = 0;
+ /* Copy list of objects; need a copy since we're
+ * manipulating the list itself below. */
+ auto const object_idxs(m_ptr->hold_o_idxs);
/* Delete objects */
- for (this_o_idx = m_ptr->hold_o_idx; this_o_idx; this_o_idx = next_o_idx)
+ for (auto const this_o_idx: object_idxs)
{
- object_type * o_ptr;
-
/* Acquire object */
- o_ptr = &o_list[this_o_idx];
-
- /* Acquire next object */
- next_o_idx = o_ptr->next_o_idx;
+ object_type *o_ptr = &o_list[this_o_idx];
/* Hack -- efficiency */
o_ptr->held_m_idx = 0;
- if ( p_ptr->preserve )
+ if (options->preserve)
{
/* Hack -- Preserve unknown artifacts */
if (artifact_p(o_ptr) && !object_known_p(o_ptr))
@@ -477,7 +499,7 @@ void delete_monster_idx(int i)
{
random_artifacts[o_ptr->sval].generated = FALSE;
}
- else if (k_info[o_ptr->k_idx].flags3 & TR3_NORM_ART)
+ else if (k_info[o_ptr->k_idx].flags & TR_NORM_ART)
{
k_info[o_ptr->k_idx].artifact = FALSE;
}
@@ -487,18 +509,13 @@ void delete_monster_idx(int i)
}
}
}
+
/* Delete the object */
delete_object_idx(this_o_idx);
}
- /* 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);
+ m_ptr->wipe();
/* Count monsters */
m_cnt--;
@@ -548,42 +565,27 @@ void delete_monster(int y, int x)
*/
static void compact_monsters_aux(int i1, int i2)
{
- int y, x, j;
-
- cave_type *c_ptr;
-
- monster_type *m_ptr;
-
- s16b this_o_idx, next_o_idx = 0;
-
-
/* Do nothing */
if (i1 == i2) return;
-
/* Old monster */
- m_ptr = &m_list[i1];
+ monster_type *m_ptr = &m_list[i1];
/* Location */
- y = m_ptr->fy;
- x = m_ptr->fx;
+ int y = m_ptr->fy;
+ int x = m_ptr->fx;
/* Cave grid */
- c_ptr = &cave[y][x];
+ cave_type *c_ptr = &cave[y][x];
/* Update the cave */
c_ptr->m_idx = i2;
/* Repair objects being carried by monster */
- for (this_o_idx = m_ptr->hold_o_idx; this_o_idx; this_o_idx = next_o_idx)
+ for (auto const this_o_idx: m_ptr->hold_o_idxs)
{
- object_type * o_ptr;
-
/* Acquire object */
- o_ptr = &o_list[this_o_idx];
-
- /* Acquire next object */
- next_o_idx = o_ptr->next_o_idx;
+ object_type *o_ptr = &o_list[this_o_idx];
/* Reset monster pointer */
o_ptr->held_m_idx = i2;
@@ -601,7 +603,7 @@ static void compact_monsters_aux(int i1, int i2)
/* Hack -- Update the health bar */
if (health_who == i1) health_track(i2);
- for (j = m_max - 1; j >= 1; j--)
+ for (int j = m_max - 1; j >= 1; j--)
{
/* Access the monster */
monster_type *t_ptr = &m_list[j];
@@ -613,16 +615,10 @@ 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);
- if (m_list[i1].mind)
- KILL(m_list[i1].mind, monster_mind);
+ m_list[i2] = m_list[i1];
/* Wipe the hole */
- m_ptr = WIPE(&m_list[i1], monster_type);
+ m_list[i1].wipe();
}
@@ -661,8 +657,7 @@ void compact_monsters(int size)
for (i = 1; i < m_max; i++)
{
monster_type *m_ptr = &m_list[i];
-
- monster_race *r_ptr = race_inf(m_ptr);
+ auto const r_ptr = m_ptr->race();
/* Paranoia -- skip "dead" monsters */
if (!m_ptr->r_idx) continue;
@@ -680,7 +675,7 @@ void compact_monsters(int size)
if ((m_ptr->mflag & MFLAG_QUEST) && (cnt < 1000)) chance = 100;
/* Try not to compact Unique Monsters */
- if (r_ptr->flags1 & (RF1_UNIQUE)) chance = 99;
+ if (r_ptr->flags & RF_UNIQUE) chance = 99;
/* All monsters get a saving throw */
if (rand_int(100) < chance) continue;
@@ -717,7 +712,7 @@ void compact_monsters(int size)
* This is an efficient method of simulating multiple calls to the
* "delete_monster()" function, with no visual effects.
*/
-void wipe_m_list(void)
+void wipe_m_list()
{
int i;
@@ -726,28 +721,18 @@ void wipe_m_list(void)
{
monster_type *m_ptr = &m_list[i];
- monster_race *r_ptr = race_inf(m_ptr);
-
/* Skip dead monsters */
if (!m_ptr->r_idx) continue;
- /* Mega-Hack -- preserve Unique's XXX XXX XXX */
-
/* Hack -- Reduce the racial counter */
+ auto r_ptr = m_ptr->race();
r_ptr->cur_num--;
/* 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);
- if (m_ptr->mind)
- KILL(m_ptr->mind, monster_mind);
-
-
/* Wipe the Monster */
- m_ptr = WIPE(m_ptr, monster_type);
+ m_ptr->wipe();
}
/* Reset "m_max" */
@@ -775,7 +760,7 @@ void wipe_m_list(void)
*
* This routine should almost never fail, but it *can* happen.
*/
-s16b m_pop(void)
+s16b m_pop()
{
int i;
@@ -829,29 +814,26 @@ s16b m_pop(void)
/*
* Apply a "monster restriction function" to the "monster allocation table"
*/
-errr get_mon_num_prep(void)
+errr get_mon_num_prep()
{
- int i;
+ auto &alloc = game->alloc;
/* Scan the allocation table */
- for (i = 0; i < alloc_race_size; i++)
+ for (auto &&entry: alloc.race_table)
{
- /* Get the entry */
- alloc_entry *entry = &alloc_race_table[i];
-
/* Accept monsters which pass the restriction, if any */
- if ((!get_mon_num_hook || (*get_mon_num_hook)(entry->index)) &&
- (!get_mon_num2_hook || (*get_mon_num2_hook)(entry->index)))
+ if ((!get_mon_num_hook || (*get_mon_num_hook)(entry.index)) &&
+ (!get_mon_num2_hook || (*get_mon_num2_hook)(entry.index)))
{
/* Accept this monster */
- entry->prob2 = entry->prob1;
+ entry.prob2 = entry.prob1;
}
/* Do not use this monster */
else
{
/* Decline this monster */
- entry->prob2 = 0;
+ entry.prob2 = 0;
}
}
@@ -863,9 +845,11 @@ errr get_mon_num_prep(void)
* Some dungeon types restrict the possible monsters.
* Return TRUE is the monster is OK and FALSE otherwise
*/
-bool_ apply_rule(monster_race *r_ptr, byte rule)
+static bool_ apply_rule(monster_race const *r_ptr, byte rule)
{
- dungeon_info_type *d_ptr = &d_info[dungeon_type];
+ auto const &d_info = game->edit_data.d_info;
+
+ auto d_ptr = &d_info[dungeon_type];
if (d_ptr->rules[rule].mode == DUNGEON_MODE_NONE)
{
@@ -875,49 +859,14 @@ bool_ apply_rule(monster_race *r_ptr, byte rule)
{
int a;
- if (d_ptr->rules[rule].mflags1)
- {
- if ((d_ptr->rules[rule].mflags1 & r_ptr->flags1) != d_ptr->rules[rule].mflags1)
- return FALSE;
- }
- if (d_ptr->rules[rule].mflags2)
- {
- if ((d_ptr->rules[rule].mflags2 & r_ptr->flags2) != d_ptr->rules[rule].mflags2)
- return FALSE;
- }
- if (d_ptr->rules[rule].mflags3)
+ if (d_ptr->rules[rule].mflags)
{
- if ((d_ptr->rules[rule].mflags3 & r_ptr->flags3) != d_ptr->rules[rule].mflags3)
+ if ((d_ptr->rules[rule].mflags & r_ptr->flags) != d_ptr->rules[rule].mflags)
return FALSE;
}
- if (d_ptr->rules[rule].mflags4)
+ if (d_ptr->rules[rule].mspells)
{
- if ((d_ptr->rules[rule].mflags4 & r_ptr->flags4) != d_ptr->rules[rule].mflags4)
- return FALSE;
- }
- if (d_ptr->rules[rule].mflags5)
- {
- if ((d_ptr->rules[rule].mflags5 & r_ptr->flags5) != d_ptr->rules[rule].mflags5)
- return FALSE;
- }
- if (d_ptr->rules[rule].mflags6)
- {
- if ((d_ptr->rules[rule].mflags6 & r_ptr->flags6) != d_ptr->rules[rule].mflags6)
- return FALSE;
- }
- if (d_ptr->rules[rule].mflags7)
- {
- if ((d_ptr->rules[rule].mflags7 & r_ptr->flags7) != d_ptr->rules[rule].mflags7)
- return FALSE;
- }
- if (d_ptr->rules[rule].mflags8)
- {
- if ((d_ptr->rules[rule].mflags8 & r_ptr->flags8) != d_ptr->rules[rule].mflags8)
- return FALSE;
- }
- if (d_ptr->rules[rule].mflags9)
- {
- if ((d_ptr->rules[rule].mflags9 & r_ptr->flags9) != d_ptr->rules[rule].mflags9)
+ if ((d_ptr->rules[rule].mspells & r_ptr->spells) != d_ptr->rules[rule].mspells)
return FALSE;
}
for (a = 0; a < 5; a++)
@@ -932,15 +881,8 @@ bool_ apply_rule(monster_race *r_ptr, byte rule)
{
int a;
- if (d_ptr->rules[rule].mflags1 && (r_ptr->flags1 & d_ptr->rules[rule].mflags1)) return TRUE;
- if (d_ptr->rules[rule].mflags2 && (r_ptr->flags2 & d_ptr->rules[rule].mflags2)) return TRUE;
- if (d_ptr->rules[rule].mflags3 && (r_ptr->flags3 & d_ptr->rules[rule].mflags3)) return TRUE;
- if (d_ptr->rules[rule].mflags4 && (r_ptr->flags4 & d_ptr->rules[rule].mflags4)) return TRUE;
- if (d_ptr->rules[rule].mflags5 && (r_ptr->flags5 & d_ptr->rules[rule].mflags5)) return TRUE;
- if (d_ptr->rules[rule].mflags6 && (r_ptr->flags6 & d_ptr->rules[rule].mflags6)) return TRUE;
- if (d_ptr->rules[rule].mflags7 && (r_ptr->flags7 & d_ptr->rules[rule].mflags7)) return TRUE;
- if (d_ptr->rules[rule].mflags8 && (r_ptr->flags8 & d_ptr->rules[rule].mflags8)) return TRUE;
- if (d_ptr->rules[rule].mflags9 && (r_ptr->flags9 & d_ptr->rules[rule].mflags9)) return TRUE;
+ if (d_ptr->rules[rule].mflags && (r_ptr->flags & d_ptr->rules[rule].mflags)) return TRUE;
+ if (d_ptr->rules[rule].mspells && (r_ptr->spells & d_ptr->rules[rule].mspells)) return TRUE;
for (a = 0; a < 5; a++)
if (d_ptr->rules[rule].r_char[a] == r_ptr->d_char) return TRUE;
@@ -955,8 +897,11 @@ bool_ apply_rule(monster_race *r_ptr, byte rule)
bool_ restrict_monster_to_dungeon(int r_idx)
{
- dungeon_info_type *d_ptr = &d_info[dungeon_type];
- monster_race *r_ptr = &r_info[r_idx];
+ auto const &d_info = game->edit_data.d_info;
+ auto const &r_info = game->edit_data.r_info;
+
+ auto d_ptr = &d_info[dungeon_type];
+ auto r_ptr = &r_info[r_idx];
/* Select a random rule */
byte rule = d_ptr->rule_percents[rand_int(100)];
@@ -1001,15 +946,13 @@ bool_ summon_hack = FALSE;
*/
s16b get_mon_num(int level)
{
- int i, j, p;
-
- int r_idx;
+ auto const &r_info = game->edit_data.r_info;
+ auto &alloc = game->alloc;
- long value, total;
-
- monster_race *r_ptr;
-
- alloc_entry *table = alloc_race_table;
+ std::size_t i, j;
+ int p;
+ int r_idx;
+ long value, total;
int in_tome;
@@ -1045,59 +988,52 @@ s16b get_mon_num(int level)
in_tome = strcmp(game_module, "ToME") == 0;
/* Process probabilities */
- for (i = 0; i < alloc_race_size; i++)
+ for (i = 0; i < alloc.race_table.size(); i++)
{
+ auto &entry = alloc.race_table[i];
+
/* Monsters are sorted by depth */
- if (table[i].level > level) break;
+ if (entry.level > level) break;
/* Default */
- table[i].prob3 = 0;
+ entry.prob3 = 0;
/* Access the "r_idx" of the chosen monster */
- r_idx = table[i].index;
+ r_idx = entry.index;
/* Access the actual race */
- r_ptr = &r_info[r_idx];
+ auto r_ptr = &r_info[r_idx];
/* Hack -- "unique" monsters must be "unique" */
- if ((r_ptr->flags1 & (RF1_UNIQUE)) &&
+ if ((r_ptr->flags & RF_UNIQUE) &&
(r_ptr->cur_num >= r_ptr->max_num))
{
continue;
}
/* Depth Monsters never appear out of depth */
- if ((r_ptr->flags1 & (RF1_FORCE_DEPTH)) && (r_ptr->level > dun_level))
+ if ((r_ptr->flags & RF_FORCE_DEPTH) && (r_ptr->level > dun_level))
{
continue;
}
/* Depth Monsters never appear out of their depth */
- if ((r_ptr->flags9 & (RF9_ONLY_DEPTH)) && (r_ptr->level != dun_level))
+ if ((r_ptr->flags & RF_ONLY_DEPTH) && (r_ptr->level != dun_level))
{
continue;
}
- if(in_tome)
- {
- /* Zangbandish monsters not allowed */
- if (r_ptr->flags8 & RF8_ZANGBAND) continue;
-
- /* Lovecraftian monsters not allowed */
- if (r_ptr->flags8 & RF8_CTHANGBAND) continue;
- }
-
/* Joke monsters allowed ? or not ? */
- if (!joke_monsters && (r_ptr->flags8 & RF8_JOKEANGBAND)) continue;
+ if (!options->joke_monsters && (r_ptr->flags & RF_JOKEANGBAND)) continue;
/* Some dungeon types restrict the possible monsters */
if (!summon_hack && !restrict_monster_to_dungeon(r_idx) && dun_level) continue;
/* Accept */
- table[i].prob3 = table[i].prob2;
+ entry.prob3 = entry.prob2;
/* Total */
- total += table[i].prob3;
+ total += entry.prob3;
}
/* No legal monsters */
@@ -1108,19 +1044,24 @@ s16b get_mon_num(int level)
value = rand_int(total);
/* Find the monster */
- for (i = 0; i < alloc_race_size; i++)
+ for (i = 0; i < alloc.race_table.size(); i++)
{
+ auto &entry = alloc.race_table[i];
+
/* Found the entry */
- if (value < table[i].prob3) break;
+ if (value < entry.prob3) break;
/* Decrement */
- value = value - table[i].prob3;
+ value = value - entry.prob3;
}
/* Power boost */
p = rand_int(100);
+ /* Shorthand */
+ auto &table = alloc.race_table;
+
/* Try for a "harder" monster once (50%) or twice (10%) */
if (p < 60)
{
@@ -1131,7 +1072,7 @@ s16b get_mon_num(int level)
value = rand_int(total);
/* Find the monster */
- for (i = 0; i < alloc_race_size; i++)
+ for (i = 0; i < table.size(); i++)
{
/* Found the entry */
if (value < table[i].prob3) break;
@@ -1154,7 +1095,7 @@ s16b get_mon_num(int level)
value = rand_int(total);
/* Find the monster */
- for (i = 0; i < alloc_race_size; i++)
+ for (i = 0; i < table.size(); i++)
{
/* Found the entry */
if (value < table[i].prob3) break;
@@ -1224,21 +1165,30 @@ s16b get_mon_num(int level)
*/
void monster_desc(char *desc, monster_type *m_ptr, int mode)
{
- cptr res;
- monster_race *r_ptr = race_inf(m_ptr);
- cptr b_name = (r_name + r_ptr->name);
+ auto const &re_info = game->edit_data.re_info;
+ auto const &r_info = game->edit_data.r_info;
+
+ auto r_ptr = m_ptr->race();
char silly_name[80], name[100];
bool_ seen, pron;
int insanity = (p_ptr->msane - p_ptr->csane) * 100 / p_ptr->msane;
if (m_ptr->ego)
{
- if (re_info[m_ptr->ego].before) sprintf(name, "%s %s", re_name + re_info[m_ptr->ego].name, b_name);
- else sprintf(name, "%s %s", b_name, re_name + re_info[m_ptr->ego].name);
+ auto const &monster_ego = re_info[m_ptr->ego];
+
+ if (monster_ego.before)
+ {
+ sprintf(name, "%s %s", monster_ego.name, r_ptr->name);
+ }
+ else
+ {
+ sprintf(name, "%s %s", r_ptr->name, monster_ego.name);
+ }
}
else
{
- sprintf(name, "%s", b_name);
+ sprintf(name, "%s", r_ptr->name);
}
/*
@@ -1249,15 +1199,15 @@ void monster_desc(char *desc, monster_type *m_ptr, int mode)
{
if (rand_int(2) == 0)
{
- monster_race *hallu_race;
+ monster_race const *hallu_race;
do
{
- hallu_race = &r_info[randint(max_r_idx - 2)];
+ hallu_race = &*uniform_element(r_info);
}
- while (hallu_race->flags1 & RF1_UNIQUE);
+ while ((!hallu_race->name) || (hallu_race->flags & RF_UNIQUE));
- strcpy(silly_name, (r_name + hallu_race->name));
+ strcpy(silly_name, hallu_race->name);
}
else
{
@@ -1273,7 +1223,6 @@ void monster_desc(char *desc, monster_type *m_ptr, int mode)
/* Sexed Pronouns (seen and allowed, or unseen and allowed) */
pron = (m_ptr && ((seen && (mode & 0x20)) || (!seen && (mode & 0x10))));
-
/* First, try using pronouns, or describing hidden monsters */
if (!seen || pron)
{
@@ -1281,15 +1230,15 @@ void monster_desc(char *desc, monster_type *m_ptr, int mode)
int kind = 0x00;
/* Extract the gender (if applicable) */
- if (r_ptr->flags1 & (RF1_FEMALE)) kind = 0x20;
- else if (r_ptr->flags1 & (RF1_MALE)) kind = 0x10;
+ if (r_ptr->flags & RF_FEMALE) kind = 0x20;
+ else if (r_ptr->flags & RF_MALE) kind = 0x10;
/* Ignore the gender (if desired) */
if (!m_ptr || !pron) kind = 0x00;
/* Assume simple result */
- res = "it";
+ cptr res = "it";
/* Brute force: split on the possibilities */
switch (kind | (mode & 0x07))
@@ -1374,7 +1323,7 @@ void monster_desc(char *desc, monster_type *m_ptr, int mode)
}
/* Copy the result */
- (void)strcpy(desc, res);
+ strcpy(desc, res);
}
@@ -1382,8 +1331,8 @@ void monster_desc(char *desc, monster_type *m_ptr, int mode)
else if ((mode & 0x02) && (mode & 0x01))
{
/* The monster is visible, so use its gender */
- if (r_ptr->flags1 & (RF1_FEMALE)) strcpy(desc, "herself");
- else if (r_ptr->flags1 & (RF1_MALE)) strcpy(desc, "himself");
+ if (r_ptr->flags & RF_FEMALE) strcpy(desc, "herself");
+ else if (r_ptr->flags & RF_MALE) strcpy(desc, "himself");
else strcpy(desc, "itself");
}
@@ -1392,10 +1341,10 @@ void monster_desc(char *desc, monster_type *m_ptr, int mode)
else
{
/* It could be a Unique */
- if ((r_ptr->flags1 & (RF1_UNIQUE)) && !(p_ptr->image))
+ if ((r_ptr->flags & RF_UNIQUE) && !(p_ptr->image))
{
/* Start with the name (thus nominative and objective) */
- (void)strcpy(desc, name);
+ strcpy(desc, name);
}
/* It could be an indefinite monster */
@@ -1404,8 +1353,8 @@ void monster_desc(char *desc, monster_type *m_ptr, int mode)
/* XXX Check plurality for "some" */
/* Indefinite monsters need an indefinite article */
- (void)strcpy(desc, is_a_vowel(name[0]) ? "an " : "a ");
- (void)strcat(desc, name);
+ strcpy(desc, is_a_vowel(name[0]) ? "an " : "a ");
+ strcat(desc, name);
}
/* It could be a normal, definite, monster */
@@ -1413,11 +1362,11 @@ void monster_desc(char *desc, monster_type *m_ptr, int mode)
{
/* Definite monsters need a definite article */
if (m_ptr->status >= MSTATUS_PET)
- (void)strcpy(desc, "your ");
+ strcpy(desc, "your ");
else
- (void)strcpy(desc, "the ");
+ strcpy(desc, "the ");
- (void)strcat(desc, name);
+ strcat(desc, name);
}
/* Handle the Possessive as a special afterthought */
@@ -1426,128 +1375,79 @@ void monster_desc(char *desc, monster_type *m_ptr, int mode)
/* XXX Check for trailing "s" */
/* Simply append "apostrophe" and "s" */
- (void)strcat(desc, "'s");
+ strcat(desc, "'s");
}
}
}
void monster_race_desc(char *desc, int r_idx, int ego)
{
- monster_race *r_ptr = &r_info[r_idx];
- cptr b_name = (r_name + r_ptr->name);
+ auto const &re_info = game->edit_data.re_info;
+ auto const &r_info = game->edit_data.r_info;
+
+ auto r_ptr = &r_info[r_idx];
char name[80];
if (ego)
{
- if (re_info[ego].before) sprintf(name, "%s %s", re_name + re_info[ego].name, b_name);
- else sprintf(name, "%s %s", b_name, re_name + re_info[ego].name);
+ auto const &monster_ego = re_info[ego];
+
+ if (monster_ego.before)
+ {
+ sprintf(name, "%s %s", monster_ego.name, r_ptr->name);
+ }
+ else
+ {
+ sprintf(name, "%s %s", r_ptr->name, monster_ego.name);
+ }
}
else
{
- sprintf(name, "%s", b_name);
+ sprintf(name, "%s", r_ptr->name);
}
/* It could be a Unique */
- if (r_ptr->flags1 & RF1_UNIQUE)
+ if (r_ptr->flags & RF_UNIQUE)
{
/* Start with the name (thus nominative and objective) */
- (void)strcpy(desc, name);
+ strcpy(desc, name);
}
/* It could be a normal, definite, monster */
else
{
/* Definite monsters need a definite article */
- (void)strcpy(desc, is_a_vowel(name[0]) ? "an " : "a ");
-
- (void)strcat(desc, name);
- }
-}
-
-
-
-/*
- * Learn about a monster (by "probing" it)
- */
-void lore_do_probe(int m_idx)
-{
- monster_type *m_ptr = &m_list[m_idx];
-
- monster_race *r_ptr = &r_info[m_ptr->r_idx];
-
- /* Hack -- Memorize some flags */
- r_ptr->r_flags1 = r_ptr->flags1;
- r_ptr->r_flags2 = r_ptr->flags2;
- r_ptr->r_flags3 = r_ptr->flags3;
-
- /* Update monster recall window */
- if (monster_race_idx == m_ptr->r_idx)
- {
- /* Window stuff */
- p_ptr->window |= (PW_MONSTER);
- }
-}
-
-
-/*
- * Take note that the given monster just dropped some treasure
- *
- * Note that learning the "GOOD"/"GREAT" flags gives information
- * about the treasure (even when the monster is killed for the first
- * time, such as uniques, and the treasure has not been examined yet).
- *
- * This "indirect" method is used to prevent the player from learning
- * exactly how much treasure a monster can drop from observing only
- * a single example of a drop. This method actually observes how much
- * gold and items are dropped, and remembers that information to be
- * described later by the monster recall code.
- */
-void lore_treasure(int m_idx, int num_item, int num_gold)
-{
- monster_type *m_ptr = &m_list[m_idx];
-
- monster_race *r_ptr = &r_info[m_ptr->r_idx];
-
- /* Note the number of things dropped */
- if (num_item > r_ptr->r_drop_item) r_ptr->r_drop_item = num_item;
- if (num_gold > r_ptr->r_drop_gold) r_ptr->r_drop_gold = num_gold;
+ strcpy(desc, is_a_vowel(name[0]) ? "an " : "a ");
- /* Hack -- memorize the good/great flags */
- if (r_ptr->flags1 & (RF1_DROP_GOOD)) r_ptr->r_flags1 |= (RF1_DROP_GOOD);
- if (r_ptr->flags1 & (RF1_DROP_GREAT)) r_ptr->r_flags1 |= (RF1_DROP_GREAT);
-
- /* Update monster recall window */
- if (monster_race_idx == m_ptr->r_idx)
- {
- /* Window stuff */
- p_ptr->window |= (PW_MONSTER);
+ strcat(desc, name);
}
}
-void sanity_blast(monster_type * m_ptr, bool_ necro)
+static void sanity_blast(monster_type * m_ptr, bool_ necro)
{
bool_ happened = FALSE;
int power = 100;
if (!necro)
{
- char m_name[80];
- monster_race *r_ptr;
+ if (m_ptr == nullptr) {
+ return;
+ }
- if (m_ptr != NULL) r_ptr = race_inf(m_ptr);
- else return;
+ auto const r_ptr = m_ptr->race();
power = (m_ptr->level) + 10;
if (m_ptr != NULL)
{
+ char m_name[80];
monster_desc(m_name, m_ptr, 0);
- if (!(r_ptr->flags1 & RF1_UNIQUE))
+ if (!(r_ptr->flags & RF_UNIQUE))
{
- if (r_ptr->flags1 & RF1_FRIENDS)
+ if (r_ptr->flags & RF_FRIENDS)
power /= 2;
}
else power *= 2;
@@ -1558,7 +1458,7 @@ void sanity_blast(monster_type * m_ptr, bool_ necro)
if (!(m_ptr->ml))
return ; /* Cannot see it for some reason */
- if (!(r_ptr->flags2 & RF2_ELDRITCH_HORROR))
+ if (!(r_ptr->flags & RF_ELDRITCH_HORROR))
return ; /* oops */
@@ -1589,13 +1489,10 @@ void sanity_blast(monster_type * m_ptr, bool_ necro)
/* Something frightening happens... */
msg_format("You behold the %s visage of %s!",
horror_desc[(randint(MAX_HORROR)) - 1], m_name);
-
- r_ptr->r_flags2 |= RF2_ELDRITCH_HORROR;
-
}
/* Undead characters are 50% likely to be unaffected */
- if ((PRACE_FLAG(PR1_UNDEAD)) || (p_ptr->mimic_form == resolve_mimic_name("Vampire")))
+ if ((race_flags_p(PR_UNDEAD)) || (p_ptr->mimic_form == resolve_mimic_name("Vampire")))
{
if (randint(100) < (25 + (p_ptr->lev))) return;
}
@@ -1604,15 +1501,16 @@ void sanity_blast(monster_type * m_ptr, bool_ necro)
{
msg_print("Your sanity is shaken by reading the Necronomicon!");
}
+
if (randint(power) < p_ptr->skill_sav) /* Mind blast */
{
if (!p_ptr->resist_conf)
{
- (void)set_confused(p_ptr->confused + rand_int(4) + 4);
+ set_confused(p_ptr->confused + rand_int(4) + 4);
}
if ((!p_ptr->resist_chaos) && (randint(3) == 1))
{
- (void) set_image(p_ptr->image + rand_int(250) + 150);
+ set_image(p_ptr->image + rand_int(250) + 150);
}
return;
}
@@ -1629,19 +1527,19 @@ void sanity_blast(monster_type * m_ptr, bool_ necro)
{
if (!p_ptr->resist_conf)
{
- (void)set_confused(p_ptr->confused + rand_int(4) + 4);
+ set_confused(p_ptr->confused + rand_int(4) + 4);
}
if (!p_ptr->free_act)
{
- (void)set_paralyzed(p_ptr->paralyzed + rand_int(4) + 4);
+ set_paralyzed(rand_int(4) + 4);
}
while (rand_int(100) > p_ptr->skill_sav)
- (void)do_dec_stat(A_INT, STAT_DEC_NORMAL);
+ do_dec_stat(A_INT, STAT_DEC_NORMAL);
while (rand_int(100) > p_ptr->skill_sav)
- (void)do_dec_stat(A_WIS, STAT_DEC_NORMAL);
+ do_dec_stat(A_WIS, STAT_DEC_NORMAL);
if (!p_ptr->resist_chaos)
{
- (void) set_image(p_ptr->image + rand_int(250) + 150);
+ set_image(p_ptr->image + rand_int(250) + 150);
}
return;
}
@@ -1726,13 +1624,11 @@ void update_mon(int m_idx, bool_ full)
{
monster_type *m_ptr = &m_list[m_idx];
- monster_race *r_ptr = race_inf(m_ptr);
-
/* The current monster location */
- int fy = m_ptr->fy;
- int fx = m_ptr->fx;
+ const int fy = m_ptr->fy;
+ const int fx = m_ptr->fx;
- bool_ old_ml = m_ptr->ml;
+ const bool_ old_ml = m_ptr->ml;
/* Seen at all */
bool_ flag = FALSE;
@@ -1740,27 +1636,17 @@ void update_mon(int m_idx, bool_ full)
/* Seen by vision */
bool_ easy = FALSE;
- /* Seen by telepathy */
- bool_ hard = FALSE;
-
- /* Various extra flags */
- bool_ do_empty_mind = FALSE;
- bool_ do_weird_mind = FALSE;
- bool_ do_invisible = FALSE;
- bool_ do_cold_blood = FALSE;
-
+ auto const r_ptr = m_ptr->race();
/* Calculate distance */
if (full)
{
- int d, dy, dx;
-
/* Distance components */
- dy = (p_ptr->py > fy) ? (p_ptr->py - fy) : (fy - p_ptr->py);
- dx = (p_ptr->px > fx) ? (p_ptr->px - fx) : (fx - p_ptr->px);
+ const int dy = (p_ptr->py > fy) ? (p_ptr->py - fy) : (fy - p_ptr->py);
+ const int dx = (p_ptr->px > fx) ? (p_ptr->px - fx) : (fx - p_ptr->px);
/* Approximate distance */
- d = (dy > dx) ? (dy + (dx >> 1)) : (dx + (dy >> 1));
+ const int d = (dy > dx) ? (dy + (dx >> 1)) : (dx + (dy >> 1));
/* Save the distance (in a byte) */
m_ptr->cdis = (d < 255) ? d : 255;
@@ -1777,7 +1663,6 @@ void update_mon(int m_idx, bool_ full)
if (m_ptr->mflag & (MFLAG_MARK)) flag = TRUE;
}
-
/* Process "nearby" monsters on the current "panel" */
else if (panel_contains(fy, fx))
{
@@ -1789,61 +1674,59 @@ void update_mon(int m_idx, bool_ full)
{
/* Infravision only works on "warm" creatures */
/* Below, we will need to know that infravision failed */
- if (r_ptr->flags2 & (RF2_COLD_BLOOD)) do_cold_blood = TRUE;
-
- /* Infravision works */
- if (!do_cold_blood) easy = flag = TRUE;
+ if (!(r_ptr->flags & RF_COLD_BLOOD))
+ {
+ /* Infravision works */
+ easy = flag = TRUE;
+ }
}
/* Use "illumination" */
if (player_can_see_bold(fy, fx))
{
- /* Take note of invisibility */
- if (r_ptr->flags2 & (RF2_INVISIBLE)) do_invisible = TRUE;
-
/* Visible, or detectable, monsters get seen */
- if (!do_invisible || p_ptr->see_inv) easy = flag = TRUE;
+ if (p_ptr->see_inv || !(r_ptr->flags & RF_INVISIBLE))
+ {
+ easy = flag = TRUE;
+ }
}
}
/* Telepathy can see all "nearby" monsters with "minds" */
- if (p_ptr->telepathy)
{
/* Assume we cant see */
- bool_ can_esp = FALSE;
+ bool can_esp = false;
/* Different ESP */
- if ((p_ptr->telepathy & ESP_ORC) && (r_ptr->flags3 & RF3_ORC)) can_esp = TRUE;
- if ((p_ptr->telepathy & ESP_SPIDER) && (r_ptr->flags7 & RF7_SPIDER)) can_esp = TRUE;
- if ((p_ptr->telepathy & ESP_TROLL) && (r_ptr->flags3 & RF3_TROLL)) can_esp = TRUE;
- if ((p_ptr->telepathy & ESP_DRAGON) && (r_ptr->flags3 & RF3_DRAGON)) can_esp = TRUE;
- if ((p_ptr->telepathy & ESP_GIANT) && (r_ptr->flags3 & RF3_GIANT)) can_esp = TRUE;
- if ((p_ptr->telepathy & ESP_DEMON) && (r_ptr->flags3 & RF3_DEMON)) can_esp = TRUE;
- if ((p_ptr->telepathy & ESP_UNDEAD) && (r_ptr->flags3 & RF3_UNDEAD)) can_esp = TRUE;
- if ((p_ptr->telepathy & ESP_EVIL) && (r_ptr->flags3 & RF3_EVIL)) can_esp = TRUE;
- if ((p_ptr->telepathy & ESP_ANIMAL) && (r_ptr->flags3 & RF3_ANIMAL)) can_esp = TRUE;
- if ((p_ptr->telepathy & ESP_THUNDERLORD) && (r_ptr->flags3 & RF3_THUNDERLORD)) can_esp = TRUE;
- if ((p_ptr->telepathy & ESP_GOOD) && (r_ptr->flags3 & RF3_GOOD)) can_esp = TRUE;
- if ((p_ptr->telepathy & ESP_NONLIVING) && (r_ptr->flags3 & RF3_NONLIVING)) can_esp = TRUE;
- if ((p_ptr->telepathy & ESP_UNIQUE) && ((r_ptr->flags1 & RF1_UNIQUE) || (r_ptr->flags3 & RF3_UNIQUE_4))) can_esp = TRUE;
- if (p_ptr->telepathy & ESP_ALL) can_esp = TRUE;
+ can_esp |= ((p_ptr->computed_flags & ESP_ORC) && (r_ptr->flags & RF_ORC));
+ can_esp |= ((p_ptr->computed_flags & ESP_SPIDER) && (r_ptr->flags & RF_SPIDER));
+ can_esp |= ((p_ptr->computed_flags & ESP_TROLL) && (r_ptr->flags & RF_TROLL));
+ can_esp |= ((p_ptr->computed_flags & ESP_DRAGON) && (r_ptr->flags & RF_DRAGON));
+ can_esp |= ((p_ptr->computed_flags & ESP_GIANT) && (r_ptr->flags & RF_GIANT));
+ can_esp |= ((p_ptr->computed_flags & ESP_DEMON) && (r_ptr->flags & RF_DEMON));
+ can_esp |= ((p_ptr->computed_flags & ESP_UNDEAD) && (r_ptr->flags & RF_UNDEAD));
+ can_esp |= ((p_ptr->computed_flags & ESP_EVIL) && (r_ptr->flags & RF_EVIL));
+ can_esp |= ((p_ptr->computed_flags & ESP_ANIMAL) && (r_ptr->flags & RF_ANIMAL));
+ can_esp |= ((p_ptr->computed_flags & ESP_THUNDERLORD) && (r_ptr->flags & RF_THUNDERLORD));
+ can_esp |= ((p_ptr->computed_flags & ESP_GOOD) && (r_ptr->flags & RF_GOOD));
+ can_esp |= ((p_ptr->computed_flags & ESP_NONLIVING) && (r_ptr->flags & RF_NONLIVING));
+ can_esp |= ((p_ptr->computed_flags & ESP_UNIQUE) && ((r_ptr->flags & RF_UNIQUE)));
+ can_esp |= bool(p_ptr->computed_flags & ESP_ALL);
/* Only do this when we can really detect monster */
if (can_esp)
{
/* Empty mind, no telepathy */
- if (r_ptr->flags2 & (RF2_EMPTY_MIND))
+ if (r_ptr->flags & RF_EMPTY_MIND)
{
- do_empty_mind = TRUE;
+ /* No telepathy */
}
/* Weird mind, occasional telepathy */
- else if (r_ptr->flags2 & (RF2_WEIRD_MIND))
+ else if (r_ptr->flags & RF_WEIRD_MIND)
{
- do_weird_mind = TRUE;
if (rand_int(100) < 10)
{
- hard = TRUE;
flag = TRUE;
}
}
@@ -1851,7 +1734,6 @@ void update_mon(int m_idx, bool_ full)
/* Normal mind, allow telepathy */
else
{
- hard = TRUE;
flag = TRUE;
}
}
@@ -1878,34 +1760,20 @@ void update_mon(int m_idx, bool_ full)
lite_spot(fy, fx);
/* Update health bar as needed */
- if (health_who == m_idx) p_ptr->redraw |= (PR_HEALTH);
+ if (health_who == m_idx) p_ptr->redraw |= (PR_FRAME);
/* Update monster list window */
p_ptr->window |= (PW_M_LIST);
- /* Hack -- Count "fresh" sightings */
- if (r_ptr->r_sights < MAX_SHORT) r_ptr->r_sights++;
-
/* Disturb on appearance */
- if (disturb_move)
+ if (options->disturb_move)
{
- if (disturb_pets || (is_friend(m_ptr) <= 0)) disturb(1, 0);
+ if (options->disturb_pets || (is_friend(m_ptr) <= 0))
+ {
+ disturb();
+ }
}
}
-
- /* Apply telepathy */
- if (hard)
- {
- /* Hack -- Memorize mental flags */
- if (r_ptr->flags2 & (RF2_SMART)) r_ptr->r_flags2 |= (RF2_SMART);
- if (r_ptr->flags2 & (RF2_STUPID)) r_ptr->r_flags2 |= (RF2_STUPID);
- }
-
- /* Memorize various observable flags */
- if (do_empty_mind) r_ptr->r_flags2 |= (RF2_EMPTY_MIND);
- if (do_weird_mind) r_ptr->r_flags2 |= (RF2_WEIRD_MIND);
- if (do_cold_blood) r_ptr->r_flags2 |= (RF2_COLD_BLOOD);
- if (do_invisible) r_ptr->r_flags2 |= (RF2_INVISIBLE);
}
/* The monster is not visible */
@@ -1921,15 +1789,18 @@ void update_mon(int m_idx, bool_ full)
lite_spot(fy, fx);
/* Update health bar as needed */
- if (health_who == m_idx) p_ptr->redraw |= (PR_HEALTH);
+ if (health_who == m_idx) p_ptr->redraw |= (PR_FRAME);
/* Update monster list window */
p_ptr->window |= (PW_M_LIST);
/* Disturb on disappearance*/
- if (disturb_move)
+ if (options->disturb_move)
{
- if (disturb_pets || (is_friend(m_ptr) <= 0)) disturb(1, 0);
+ if (options->disturb_pets || (is_friend(m_ptr) <= 0))
+ {
+ disturb();
+ }
}
}
}
@@ -1941,7 +1812,7 @@ void update_mon(int m_idx, bool_ full)
if (m_ptr->ml != old_ml)
{
- if (r_ptr->flags2 & RF2_ELDRITCH_HORROR)
+ if (r_ptr->flags & RF_ELDRITCH_HORROR)
{
sanity_blast(m_ptr, FALSE);
}
@@ -1954,9 +1825,12 @@ void update_mon(int m_idx, bool_ full)
m_ptr->mflag |= (MFLAG_VIEW);
/* Disturb on appearance */
- if (disturb_near)
+ if (options->disturb_near)
{
- if (disturb_pets || (is_friend(m_ptr) <= 0)) disturb(1, 0);
+ if (options->disturb_pets || (is_friend(m_ptr) <= 0))
+ {
+ disturb();
+ }
}
}
@@ -1975,9 +1849,12 @@ void update_mon(int m_idx, bool_ full)
p_ptr->window |= (PW_M_LIST);
/* Disturb on disappearance */
- if (disturb_near)
+ if (options->disturb_near)
{
- if (disturb_pets || (is_friend(m_ptr) <= 0)) disturb(1, 0);
+ if (options->disturb_pets || (is_friend(m_ptr) <= 0))
+ {
+ disturb();
+ }
}
}
}
@@ -2009,7 +1886,9 @@ void update_monsters(bool_ full)
void monster_carry(monster_type *m_ptr, int m_idx, object_type *q_ptr)
{
- object_type *o_ptr;
+ auto &k_info = game->edit_data.k_info;
+ auto &a_info = game->edit_data.a_info;
+ auto &random_artifacts = game->random_artifacts;
/* Get new object */
int o_idx = o_pop();
@@ -2017,19 +1896,17 @@ void monster_carry(monster_type *m_ptr, int m_idx, object_type *q_ptr)
if (o_idx)
{
/* Get the item */
- o_ptr = &o_list[o_idx];
+ object_type *o_ptr = &o_list[o_idx];
/* Structure copy */
object_copy(o_ptr, q_ptr);
/* Build a stack */
- o_ptr->next_o_idx = m_ptr->hold_o_idx;
-
o_ptr->held_m_idx = m_idx;
o_ptr->ix = 0;
o_ptr->iy = 0;
- m_ptr->hold_o_idx = o_idx;
+ m_ptr->hold_o_idxs.push_back(o_idx);
}
else
@@ -2039,7 +1916,7 @@ void monster_carry(monster_type *m_ptr, int m_idx, object_type *q_ptr)
{
a_info[q_ptr->name1].cur_num = 0;
}
- else if (k_info[q_ptr->k_idx].flags3 & TR3_NORM_ART)
+ else if (k_info[q_ptr->k_idx].flags & TR_NORM_ART)
{
k_info[q_ptr->k_idx].artifact = 0;
}
@@ -2077,8 +1954,10 @@ static int possible_randart[] =
bool_ kind_is_randart(int k_idx)
{
+ auto const &k_info = game->edit_data.k_info;
+
int max;
- object_kind *k_ptr = &k_info[k_idx];
+ auto k_ptr = &k_info[k_idx];
if (!kind_is_legal(k_idx)) return (FALSE);
@@ -2109,41 +1988,28 @@ bool_ kind_is_randart(int k_idx)
* except for the savefile loading code.
*/
bool_ bypass_r_ptr_max_num = FALSE;
-int place_monster_result = 0;
+static int place_monster_result = 0;
bool_ place_monster_one_no_drop = FALSE;
-monster_race *place_monster_one_race = NULL;
+static s16b hack_m_idx_ii = 0;
s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status)
{
+ auto &r_info = game->edit_data.r_info;
+ auto &alloc = game->alloc;
+
int i;
char dummy[5];
bool_ add_level = FALSE;
int min_level = 0, max_level = 0;
- cave_type *c_ptr;
-
- monster_type *m_ptr;
-
- monster_race *r_ptr = &r_info[r_idx];
-
- 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;
}
@@ -2151,7 +2017,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;
}
@@ -2159,26 +2024,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;
}
@@ -2186,7 +2047,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;
}
@@ -2194,86 +2054,77 @@ 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)
+ /* Check for original monster race flags */
{
- if (place_monster_one_race) KILL(place_monster_one_race, monster_race);
- return 0;
- }
+ auto r_ptr = &r_info[r_idx];
- /* 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;
- }
+ /* Paranoia */
+ if (!r_ptr->name)
+ {
+ 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;
+ /* Are we allowed to continue ? */
+ {
+ struct hook_new_monster_in in = { r_idx };
+ if (process_hooks_new(HOOK_NEW_MONSTER, &in, NULL))
+ {
+ return 0;
+ }
+ }
+
+ /* Ego Uniques are NOT to be created */
+ if ((r_ptr->flags & RF_UNIQUE) && ego)
+ {
+ 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);
- }
+ auto 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;
}
/* Unallow some uniques to be generated outside of their quests/special levels/dungeons */
- if ((r_ptr->flags9 & RF9_SPECIAL_GENE) && (!m_allow_special[r_idx]))
+ if ((r_ptr->flags & RF_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;
}
/* Disallow Spirits in The Void, now this *IS* an ugly hack, I hate to do it ... */
- if ((r_ptr->flags7 & RF7_SPIRIT) && (dungeon_type != DUNGEON_VOID))
+ if ((r_ptr->flags & RF_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;
}
/* Fully forbid it */
- if (r_ptr->flags9 & RF9_NEVER_GENE)
+ if (r_ptr->flags & RF_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;
}
/* Hack -- "unique" monsters must be "unique" */
- if ((r_ptr->flags1 & (RF1_UNIQUE)) && (r_ptr->max_num == -1) && (!m_allow_special[r_idx]))
+ if ((r_ptr->flags & RF_UNIQUE) && (r_ptr->max_num == -1) && (!m_allow_special[r_idx]))
{
/* 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;
}
@@ -2281,25 +2132,22 @@ 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;
}
/* Hack -- "unique" monsters must be "unique" */
- if ((r_ptr->flags1 & (RF1_UNIQUE)) && (r_ptr->cur_num >= r_ptr->max_num) && (r_ptr->max_num != -1) && (!bypass_r_ptr_max_num))
+ if ((r_ptr->flags & RF_UNIQUE) && (r_ptr->cur_num >= r_ptr->max_num) && (r_ptr->max_num != -1) && (!bypass_r_ptr_max_num))
{
/* 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;
}
/* Depth monsters may NOT be created out of depth */
- if ((r_ptr->flags1 & (RF1_FORCE_DEPTH)) && (dun_level < r_ptr->level))
+ if ((r_ptr->flags & RF_FORCE_DEPTH) && (dun_level < r_ptr->level))
{
/* 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;
}
@@ -2307,10 +2155,13 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status)
if (r_ptr->level > dun_level)
{
/* Unique monsters */
- if (r_ptr->flags1 & (RF1_UNIQUE))
+ if (r_ptr->flags & RF_UNIQUE)
{
/* Message for cheaters */
- if ((cheat_hear) || (p_ptr->precognition)) msg_format("Deep Unique (%s).", name);
+ if (options->cheat_hear || p_ptr->precognition)
+ {
+ msg_format("Deep Unique (%s).", r_ptr->name);
+ }
/* Boost rating by twice delta-depth */
rating += (r_ptr->level - dun_level) * 2;
@@ -2320,7 +2171,10 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status)
else
{
/* Message for cheaters */
- if ((cheat_hear) || (p_ptr->precognition)) msg_format("Deep Monster (%s).", name);
+ if (options->cheat_hear || p_ptr->precognition)
+ {
+ msg_format("Deep Monster (%s).", r_ptr->name);
+ }
/* Boost rating by delta-depth */
rating += (r_ptr->level - dun_level);
@@ -2328,15 +2182,18 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status)
}
/* Note the monster */
- else if (r_ptr->flags1 & (RF1_UNIQUE))
+ else if (r_ptr->flags & RF_UNIQUE)
{
/* Unique monsters induce message */
- if ((cheat_hear) || (p_ptr->precognition)) msg_format("Unique (%s).", name);
+ if (options->cheat_hear || p_ptr->precognition)
+ {
+ msg_format("Unique (%s).", r_ptr->name);
+ }
}
/* Access the location */
- c_ptr = &cave[y][x];
+ cave_type *c_ptr = &cave[y][x];
/* Make a new monster */
c_ptr->m_idx = m_pop();
@@ -2345,22 +2202,17 @@ 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;
}
/* Get a new monster record */
- m_ptr = &m_list[c_ptr->m_idx];
+ monster_type *m_ptr = &m_list[c_ptr->m_idx];
/* Save the race */
m_ptr->r_idx = r_idx;
m_ptr->ego = ego;
- /* 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;
m_ptr->fx = x;
@@ -2383,16 +2235,16 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status)
m_ptr->ml = FALSE;
/* No objects yet */
- m_ptr->hold_o_idx = 0;
+ m_ptr->hold_o_idxs.clear();
m_ptr->status = status;
/* Friendly? */
- if (m_ptr->status < MSTATUS_FRIEND && r_ptr->flags7 & RF7_PET)
+ if (m_ptr->status < MSTATUS_FRIEND && r_ptr->flags & RF_PET)
{
m_ptr->status = MSTATUS_FRIEND;
}
- if (m_ptr->status < MSTATUS_NEUTRAL && r_ptr->flags7 & RF7_NEUTRAL)
+ if (m_ptr->status < MSTATUS_NEUTRAL && r_ptr->flags & RF_NEUTRAL)
{
m_ptr->status = MSTATUS_NEUTRAL;
}
@@ -2411,15 +2263,14 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status)
/* Only if not fated to die */
if ((dungeon_type != DUNGEON_DEATH) && (!place_monster_one_no_drop))
{
- bool_ good = (r_ptr->flags1 & (RF1_DROP_GOOD)) ? TRUE : FALSE;
- bool_ great = (r_ptr->flags1 & (RF1_DROP_GREAT)) ? TRUE : FALSE;
+ const bool_ good = (r_ptr->flags & RF_DROP_GOOD) ? TRUE : FALSE;
+ const bool_ great = (r_ptr->flags & RF_DROP_GREAT) ? TRUE : FALSE;
- bool_ do_gold = (!(r_ptr->flags1 & (RF1_ONLY_ITEM)));
- bool_ do_item = (!(r_ptr->flags1 & (RF1_ONLY_GOLD)));
- bool_ do_mimic = (r_ptr->flags9 & (RF9_MIMIC));
- int j;
+ auto const do_gold = (r_ptr->flags & RF_ONLY_ITEM).empty();
+ auto const do_item = (r_ptr->flags & RF_ONLY_GOLD).empty();
+ auto const do_mimic = bool(r_ptr->flags & RF_MIMIC);
- int force_coin = get_coin_type(r_ptr);
+ const int force_coin = get_coin_type(r_ptr);
int dump_item = 0;
int dump_gold = 0;
@@ -2432,32 +2283,25 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status)
object_level = (dun_level + r_ptr->level) / 2;
/* Determine how much we can drop */
- if ((r_ptr->flags1 & (RF1_DROP_60)) && (rand_int(100) < 60)) number++;
- if ((r_ptr->flags1 & (RF1_DROP_90)) && (rand_int(100) < 90)) number++;
- if (r_ptr->flags1 & (RF1_DROP_1D2)) number += damroll(1, 2);
- if (r_ptr->flags1 & (RF1_DROP_2D2)) number += damroll(2, 2);
- if (r_ptr->flags1 & (RF1_DROP_3D2)) number += damroll(3, 2);
- if (r_ptr->flags1 & (RF1_DROP_4D2)) number += damroll(4, 2);
- if (r_ptr->flags9 & (RF9_MIMIC)) number = 1;
+ if ((r_ptr->flags & RF_DROP_60) && (rand_int(100) < 60)) number++;
+ if ((r_ptr->flags & RF_DROP_90) && (rand_int(100) < 90)) number++;
+ if (r_ptr->flags & RF_DROP_1D2) number += damroll(1, 2);
+ if (r_ptr->flags & RF_DROP_2D2) number += damroll(2, 2);
+ if (r_ptr->flags & RF_DROP_3D2) number += damroll(3, 2);
+ if (r_ptr->flags & RF_DROP_4D2) number += damroll(4, 2);
+ if (r_ptr->flags & RF_MIMIC) number = 1;
/* Hack -- handle creeping coins */
coin_type = force_coin;
- if (r_ptr->flags7 & RF7_DROP_RANDART)
+ if (r_ptr->flags & RF_DROP_RANDART)
{
int tries = 1000;
- obj_theme theme;
- int i;
-
/* Get local object */
q_ptr = &forge;
- theme.treasure = 101;
- theme.combat = 101;
- theme.magic = 101;
- theme.tools = 101;
-
- init_match_theme(theme);
+ /* No theme */
+ init_match_theme(obj_theme::no_theme());
/* Apply restriction */
get_obj_num_hook = kind_is_legal;
@@ -2465,7 +2309,7 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status)
/* Rebuild allocation table */
get_obj_num_prep();
- i = 0;
+ int i = 0;
while (tries)
{
tries--;
@@ -2477,7 +2321,7 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status)
}
/* Invalidate the cached allocation table */
- alloc_kind_table_valid = FALSE;
+ alloc.kind_table_valid = false;
if (tries)
{
@@ -2494,7 +2338,7 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status)
}
/* Drop some objects */
- for (j = 0; j < number; j++)
+ for (int j = 0; j < number; j++)
{
/* Get local object */
q_ptr = &forge;
@@ -2555,7 +2399,7 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status)
/* Assign maximal hitpoints */
- if (r_ptr->flags1 & (RF1_FORCE_MAXHP))
+ if (r_ptr->flags & RF_FORCE_MAXHP)
{
m_ptr->maxhp = maxroll(r_ptr->hdice, r_ptr->hside);
}
@@ -2578,13 +2422,13 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status)
m_ptr->ac = r_ptr->ac;
m_ptr->level = r_ptr->level;
m_ptr->speed = r_ptr->speed;
- m_ptr->exp = MONSTER_EXP(m_ptr->level);
+ m_ptr->exp = monster_exp(m_ptr->level);
/* Extract the monster base speed */
m_ptr->mspeed = m_ptr->speed;
/* Hack -- small racial variety */
- if (!(r_ptr->flags1 & (RF1_UNIQUE)))
+ if (!(r_ptr->flags & RF_UNIQUE))
{
/* Allow some small variation per monster */
i = extract_energy[m_ptr->speed] / 10;
@@ -2592,18 +2436,18 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status)
}
- if (dungeon_flags2 & DF2_ADJUST_LEVEL_1_2)
+ if (dungeon_flags & DF_ADJUST_LEVEL_1_2)
{
min_level = max_level = dun_level / 2;
add_level = TRUE;
}
- if (dungeon_flags1 & DF1_ADJUST_LEVEL_1)
+ if (dungeon_flags & DF_ADJUST_LEVEL_1)
{
if (!min_level) min_level = dun_level;
max_level = dun_level;
add_level = TRUE;
}
- if (dungeon_flags1 & DF1_ADJUST_LEVEL_2)
+ if (dungeon_flags & DF_ADJUST_LEVEL_2)
{
if (!min_level) min_level = dun_level * 2;
max_level = dun_level * 2;
@@ -2615,7 +2459,7 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status)
m_ptr->energy = (byte)rand_int(100);
/* Force monster to wait for player */
- if (r_ptr->flags1 & (RF1_FORCE_SLEEP))
+ if (r_ptr->flags & RF_FORCE_SLEEP)
{
/* Monster is still being nice */
m_ptr->mflag |= (MFLAG_NICE);
@@ -2637,25 +2481,32 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status)
/* Hack -- Count the number of "reproducers" */
- if (r_ptr->flags4 & (RF4_MULTIPLY)) num_repro++;
+ if (r_ptr->spells & SF_MULTIPLY) num_repro++;
/* Hack -- Notice new multi-hued monsters */
- if (r_ptr->flags1 & (RF1_ATTR_MULTI)) shimmer_monsters = TRUE;
+ if (r_ptr->flags & RF_ATTR_MULTI) shimmer_monsters = TRUE;
- /* Hack -- we need to modify the REAL r_info, not the fake one */
- r_ptr = &r_info[r_idx];
+ /* Count monsters on the level */
+ {
+ /* Hack -- we need to modify the REAL r_info, not the fake one */
+ auto r_ptr = &r_info[r_idx];
- /* Hack -- Count the monsters on the level */
- r_ptr->cur_num++;
+ /* Hack -- Count the monsters on the level */
+ r_ptr->cur_num++;
+ }
/* Unique monsters on saved levels should be "marked" */
- if ((r_ptr->flags1 & RF1_UNIQUE) && get_dungeon_save(dummy))
+ if ((r_ptr->flags & RF_UNIQUE) && get_dungeon_save(dummy))
{
r_ptr->on_saved = TRUE;
}
- 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;
@@ -2673,7 +2524,9 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status)
*/
static bool_ place_monster_group(int y, int x, int r_idx, bool_ slp, int status)
{
- monster_race *r_ptr = &r_info[r_idx];
+ auto const &r_info = game->edit_data.r_info;
+
+ auto r_ptr = &r_info[r_idx];
int old, n, i;
int total = 0, extra = 0;
@@ -2739,7 +2592,7 @@ static bool_ place_monster_group(int y, int x, int r_idx, bool_ slp, int status)
if (!cave_empty_bold(my, mx)) continue;
/* Attempt to place another monster */
- if (place_monster_one(my, mx, r_idx, pick_ego_monster(r_idx), slp, status))
+ if (place_monster_one(my, mx, r_idx, pick_ego_monster(r_ptr), slp, status))
{
/* Add it to the "hack" set */
hack_y[hack_n] = my;
@@ -2768,9 +2621,10 @@ static int place_monster_idx = 0;
*/
static bool_ place_monster_okay(int r_idx)
{
- monster_race *r_ptr = &r_info[place_monster_idx];
+ auto const &r_info = game->edit_data.r_info;
- monster_race *z_ptr = &r_info[r_idx];
+ auto r_ptr = &r_info[place_monster_idx];
+ auto z_ptr = &r_info[r_idx];
/* Hack - Escorts have to have the same dungeon flag */
if (monster_dungeon(place_monster_idx) != monster_dungeon(r_idx)) return (FALSE);
@@ -2782,7 +2636,7 @@ static bool_ place_monster_okay(int r_idx)
if (z_ptr->level > r_ptr->level) return (FALSE);
/* Skip unique monsters */
- if (z_ptr->flags1 & (RF1_UNIQUE)) return (FALSE);
+ if (z_ptr->flags & RF_UNIQUE) return (FALSE);
/* Paranoia -- Skip identical monsters */
if (place_monster_idx == r_idx) return (FALSE);
@@ -2812,13 +2666,15 @@ static bool_ place_monster_okay(int r_idx)
*/
bool_ place_monster_aux(int y, int x, int r_idx, bool_ slp, bool_ grp, int status)
{
+ auto const &r_info = game->edit_data.r_info;
+
int i;
- monster_race *r_ptr = &r_info[r_idx];
+ auto r_ptr = &r_info[r_idx];
bool_ (*old_get_mon_num_hook)(int r_idx);
/* Place one monster, or fail */
- if (!place_monster_one(y, x, r_idx, pick_ego_monster(r_idx), slp, status)) return (FALSE);
+ if (!place_monster_one(y, x, r_idx, pick_ego_monster(r_ptr), slp, status)) return (FALSE);
/* Require the "group" flag */
@@ -2826,15 +2682,15 @@ bool_ place_monster_aux(int y, int x, int r_idx, bool_ slp, bool_ grp, int statu
/* Friends for certain monsters */
- if (r_ptr->flags1 & (RF1_FRIENDS))
+ if (r_ptr->flags & RF_FRIENDS)
{
/* Attempt to place a group */
- (void)place_monster_group(y, x, r_idx, slp, status);
+ place_monster_group(y, x, r_idx, slp, status);
}
/* Escorts for certain monsters */
- if (r_ptr->flags1 & (RF1_ESCORT))
+ if (r_ptr->flags & RF_ESCORT)
{
old_get_mon_num_hook = get_mon_num_hook;
@@ -2876,14 +2732,14 @@ bool_ place_monster_aux(int y, int x, int r_idx, bool_ slp, bool_ grp, int statu
if (!z) break;
/* Place a single escort */
- place_monster_one(ny, nx, z, pick_ego_monster(z), slp, status);
+ place_monster_one(ny, nx, z, pick_ego_monster(&r_info[z]), slp, status);
/* Place a "group" of escorts if needed */
- if ((r_info[z].flags1 & (RF1_FRIENDS)) ||
- (r_ptr->flags1 & (RF1_ESCORTS)))
+ if ((r_info[z].flags & RF_FRIENDS) ||
+ (r_ptr->flags & RF_ESCORTS))
{
/* Place a group of monsters */
- (void)place_monster_group(ny, nx, z, slp, status);
+ place_monster_group(ny, nx, z, slp, status);
}
}
@@ -2934,13 +2790,13 @@ bool_ place_monster(int y, int x, bool_ slp, bool_ grp)
}
-#ifdef MONSTER_HORDES
-
bool_ alloc_horde(int y, int x)
{
+ auto const &r_info = game->edit_data.r_info;
+
int r_idx = 0;
- monster_race * r_ptr = NULL;
- monster_type * m_ptr;
+ monster_race const *r_ptr = NULL;
+ monster_type *m_ptr;
int attempts = 1000;
set_mon_num2_hook(y, x);
@@ -2958,8 +2814,8 @@ bool_ alloc_horde(int y, int x)
r_ptr = &r_info[r_idx];
- if (!(r_ptr->flags1 & (RF1_UNIQUE))
- && !(r_ptr->flags1 & (RF1_ESCORTS)))
+ if (!(r_ptr->flags & RF_UNIQUE)
+ && !(r_ptr->flags & RF_ESCORTS))
break;
}
@@ -2987,14 +2843,12 @@ bool_ alloc_horde(int y, int x)
for (attempts = randint(10) + 5; attempts; attempts--)
{
- (void) summon_specific(m_ptr->fy, m_ptr->fx, dun_level, SUMMON_KIN);
+ summon_specific(m_ptr->fy, m_ptr->fx, dun_level, SUMMON_KIN);
}
return TRUE;
}
-#endif /* MONSTER_HORDES */
-
/*
* Attempt to allocate a random monster in the dungeon.
*
@@ -3025,7 +2879,7 @@ bool_ alloc_monster(int dis, bool_ slp)
if (!attempts_left)
{
- if (cheat_xtra || cheat_hear)
+ if (options->cheat_xtra || options->cheat_hear)
{
msg_print("Warning! Could not allocate a new monster. Small level?");
}
@@ -3034,25 +2888,24 @@ bool_ alloc_monster(int dis, bool_ slp)
}
-#ifdef MONSTER_HORDES
if (randint(5000) <= dun_level)
{
if (alloc_horde(y, x))
{
- if ((cheat_hear) || (p_ptr->precognition)) msg_print("Monster horde.");
+ if (options->cheat_hear || p_ptr->precognition)
+ {
+ msg_print("Monster horde.");
+ }
return (TRUE);
}
}
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);
@@ -3070,9 +2923,11 @@ static int summon_specific_type = 0;
/*
* Hack -- help decide if a monster race is "okay" to summon
*/
-bool_ summon_specific_okay(int r_idx)
+static bool_ summon_specific_okay(int r_idx)
{
- monster_race *r_ptr = &r_info[r_idx];
+ auto const &r_info = game->edit_data.r_info;
+
+ auto r_ptr = &r_info[r_idx];
bool_ okay = FALSE;
@@ -3088,56 +2943,56 @@ bool_ summon_specific_okay(int r_idx)
case SUMMON_ANT:
{
okay = ((r_ptr->d_char == 'a') &&
- !(r_ptr->flags1 & (RF1_UNIQUE)));
+ !(r_ptr->flags & RF_UNIQUE));
break;
}
case SUMMON_SPIDER:
{
okay = ((r_ptr->d_char == 'S') &&
- !(r_ptr->flags1 & (RF1_UNIQUE)));
+ !(r_ptr->flags & RF_UNIQUE));
break;
}
case SUMMON_HOUND:
{
okay = (((r_ptr->d_char == 'C') || (r_ptr->d_char == 'Z')) &&
- !(r_ptr->flags1 & (RF1_UNIQUE)));
+ !(r_ptr->flags & RF_UNIQUE));
break;
}
case SUMMON_HYDRA:
{
okay = ((r_ptr->d_char == 'M') &&
- !(r_ptr->flags1 & (RF1_UNIQUE)));
+ !(r_ptr->flags & RF_UNIQUE));
break;
}
case SUMMON_ANGEL:
{
okay = ((r_ptr->d_char == 'A') &&
- !(r_ptr->flags1 & (RF1_UNIQUE)));
+ !(r_ptr->flags & RF_UNIQUE));
break;
}
case SUMMON_DEMON:
{
- okay = ((r_ptr->flags3 & (RF3_DEMON)) &&
- !(r_ptr->flags1 & (RF1_UNIQUE)));
+ okay = ((r_ptr->flags & RF_DEMON) &&
+ !(r_ptr->flags & RF_UNIQUE));
break;
}
case SUMMON_UNDEAD:
{
- okay = ((r_ptr->flags3 & (RF3_UNDEAD)) &&
- !(r_ptr->flags1 & (RF1_UNIQUE)));
+ okay = ((r_ptr->flags & RF_UNDEAD) &&
+ !(r_ptr->flags & RF_UNIQUE));
break;
}
case SUMMON_DRAGON:
{
- okay = ((r_ptr->flags3 & (RF3_DRAGON)) &&
- !(r_ptr->flags1 & (RF1_UNIQUE)));
+ okay = ((r_ptr->flags & RF_DRAGON) &&
+ !(r_ptr->flags & RF_UNIQUE));
break;
}
@@ -3169,40 +3024,40 @@ bool_ summon_specific_okay(int r_idx)
case SUMMON_UNIQUE:
{
- okay = (r_ptr->flags1 & (RF1_UNIQUE)) ? TRUE : FALSE;
+ okay = (r_ptr->flags & RF_UNIQUE) ? TRUE : FALSE;
break;
}
case SUMMON_BIZARRE1:
{
okay = ((r_ptr->d_char == 'm') &&
- !(r_ptr->flags1 & (RF1_UNIQUE)));
+ !(r_ptr->flags & RF_UNIQUE));
break;
}
case SUMMON_BIZARRE2:
{
okay = ((r_ptr->d_char == 'b') &&
- !(r_ptr->flags1 & (RF1_UNIQUE)));
+ !(r_ptr->flags & RF_UNIQUE));
break;
}
case SUMMON_BIZARRE3:
{
okay = ((r_ptr->d_char == 'Q') &&
- !(r_ptr->flags1 & (RF1_UNIQUE)));
+ !(r_ptr->flags & RF_UNIQUE));
break;
}
case SUMMON_BIZARRE4:
{
okay = ((r_ptr->d_char == 'v') &&
- !(r_ptr->flags1 & (RF1_UNIQUE)));
+ !(r_ptr->flags & RF_UNIQUE));
break;
}
case SUMMON_BIZARRE5:
{
okay = ((r_ptr->d_char == '$') &&
- !(r_ptr->flags1 & (RF1_UNIQUE)));
+ !(r_ptr->flags & RF_UNIQUE));
break;
}
@@ -3213,15 +3068,15 @@ bool_ summon_specific_okay(int r_idx)
(r_ptr->d_char == '=') ||
(r_ptr->d_char == '$') ||
(r_ptr->d_char == '|')) &&
- !(r_ptr->flags1 & (RF1_UNIQUE)));
+ !(r_ptr->flags & RF_UNIQUE));
break;
}
case SUMMON_HI_DEMON:
{
- okay = ((r_ptr->flags3 & (RF3_DEMON)) &&
+ okay = ((r_ptr->flags & RF_DEMON) &&
(r_ptr->d_char == 'U') &&
- !(r_ptr->flags1 & RF1_UNIQUE));
+ !(r_ptr->flags & RF_UNIQUE));
break;
}
@@ -3229,34 +3084,34 @@ bool_ summon_specific_okay(int r_idx)
case SUMMON_KIN:
{
okay = ((r_ptr->d_char == summon_kin_type) &&
- !(r_ptr->flags1 & (RF1_UNIQUE)));
+ !(r_ptr->flags & RF_UNIQUE));
break;
}
case SUMMON_DAWN:
{
- okay = ((strstr((r_name + r_ptr->name), "the Dawn")) &&
- !(r_ptr->flags1 & (RF1_UNIQUE)));
+ okay = ((strstr(r_ptr->name, "the Dawn")) &&
+ !(r_ptr->flags & RF_UNIQUE));
break;
}
case SUMMON_ANIMAL:
{
- okay = ((r_ptr->flags3 & (RF3_ANIMAL)) &&
- !(r_ptr->flags1 & (RF1_UNIQUE)));
+ okay = ((r_ptr->flags & RF_ANIMAL) &&
+ !(r_ptr->flags & RF_UNIQUE));
break;
}
case SUMMON_ANIMAL_RANGER:
{
- okay = ((r_ptr->flags3 & (RF3_ANIMAL)) &&
+ okay = ((r_ptr->flags & RF_ANIMAL) &&
(strchr("abcflqrwBCIJKMRS", r_ptr->d_char)) &&
- !(r_ptr->flags3 & (RF3_DRAGON)) &&
- !(r_ptr->flags3 & (RF3_EVIL)) &&
- !(r_ptr->flags3 & (RF3_UNDEAD)) &&
- !(r_ptr->flags3 & (RF3_DEMON)) &&
- !(r_ptr->flags4 || r_ptr->flags5 || r_ptr->flags6) &&
- !(r_ptr->flags1 & (RF1_UNIQUE)));
+ !(r_ptr->flags & RF_DRAGON) &&
+ !(r_ptr->flags & RF_EVIL) &&
+ !(r_ptr->flags & RF_UNDEAD) &&
+ !(r_ptr->flags & RF_DEMON) &&
+ !r_ptr->spells &&
+ !(r_ptr->flags & RF_UNIQUE));
break;
}
@@ -3265,95 +3120,90 @@ bool_ summon_specific_okay(int r_idx)
okay = (((r_ptr->d_char == 'L') ||
(r_ptr->d_char == 'V') ||
(r_ptr->d_char == 'W')) &&
- !(r_ptr->flags1 & (RF1_UNIQUE)));
+ !(r_ptr->flags & RF_UNIQUE));
break;
}
case SUMMON_HI_DRAGON_NO_UNIQUES:
{
okay = ((r_ptr->d_char == 'D') &&
- !(r_ptr->flags1 & (RF1_UNIQUE)));
+ !(r_ptr->flags & RF_UNIQUE));
break;
}
case SUMMON_NO_UNIQUES:
{
- okay = (!(r_ptr->flags1 & (RF1_UNIQUE)));
+ okay = (!(r_ptr->flags & RF_UNIQUE));
break;
}
case SUMMON_PHANTOM:
{
- okay = ((strstr((r_name + r_ptr->name), "Phantom")) &&
- !(r_ptr->flags1 & (RF1_UNIQUE)));
+ okay = ((strstr(r_ptr->name, "Phantom")) &&
+ !(r_ptr->flags & RF_UNIQUE));
break;
}
case SUMMON_ELEMENTAL:
{
- okay = ((strstr((r_name + r_ptr->name), "lemental")) &&
- !(r_ptr->flags1 & (RF1_UNIQUE)));
+ okay = ((strstr(r_ptr->name, "lemental")) &&
+ !(r_ptr->flags & RF_UNIQUE));
break;
}
case SUMMON_THUNDERLORD:
{
- okay = (r_ptr->flags3 & RF3_THUNDERLORD) ? TRUE : FALSE;
+ okay = (r_ptr->flags & RF_THUNDERLORD) ? TRUE : FALSE;
break;
}
case SUMMON_BLUE_HORROR:
{
- okay = ((strstr((r_name + r_ptr->name), "lue horror")) &&
- !(r_ptr->flags1 & (RF1_UNIQUE)));
+ okay = ((strstr(r_ptr->name, "lue horror")) &&
+ !(r_ptr->flags & RF_UNIQUE));
break;
}
case SUMMON_BUG:
{
- okay = ((strstr((r_name + r_ptr->name), "Software bug")) &&
- !(r_ptr->flags1 & (RF1_UNIQUE)));
+ okay = ((strstr(r_ptr->name, "Software bug")) &&
+ !(r_ptr->flags & RF_UNIQUE));
break;
}
case SUMMON_RNG:
{
- okay = ((strstr((r_name + r_ptr->name), "Random Number Generator")) &&
- !(r_ptr->flags1 & (RF1_UNIQUE)));
+ okay = ((strstr(r_ptr->name, "Random Number Generator")) &&
+ !(r_ptr->flags & RF_UNIQUE));
break;
}
case SUMMON_MINE:
{
- okay = (r_ptr->flags1 & RF1_NEVER_MOVE) ? TRUE : FALSE;
+ okay = (r_ptr->flags & RF_NEVER_MOVE) ? TRUE : FALSE;
break;
}
case SUMMON_HUMAN:
{
okay = ((r_ptr->d_char == 'p') &&
- !(r_ptr->flags1 & (RF1_UNIQUE)));
+ !(r_ptr->flags & RF_UNIQUE));
break;
}
case SUMMON_SHADOWS:
{
okay = ((r_ptr->d_char == 'G') &&
- !(r_ptr->flags1 & (RF1_UNIQUE)));
+ !(r_ptr->flags & RF_UNIQUE));
break;
}
case SUMMON_QUYLTHULG:
{
okay = ((r_ptr->d_char == 'Q') &&
- !(r_ptr->flags1 & (RF1_UNIQUE)));
+ !(r_ptr->flags & RF_UNIQUE));
break;
}
- case SUMMON_LUA:
- {
- okay = summon_lua_okay(r_idx);
- break;
- }
}
/* Result */
@@ -3441,10 +3291,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;
@@ -3525,10 +3371,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;
@@ -3660,14 +3502,16 @@ void monster_swap(int y1, int x1, int y2, int x2)
*/
static bool_ mutate_monster_okay(int r_idx)
{
- monster_race *r_ptr = &r_info[r_idx];
+ auto const &r_info = game->edit_data.r_info;
+
+ auto r_ptr = &r_info[r_idx];
bool_ okay = FALSE;
/* Hack - Only summon dungeon monsters */
if (!monster_dungeon(r_idx)) return (FALSE);
- okay = ((r_ptr->d_char == summon_kin_type) && !(r_ptr->flags1 & (RF1_UNIQUE))
+ okay = ((r_ptr->d_char == summon_kin_type) && !(r_ptr->flags & RF_UNIQUE)
&& (r_ptr->level >= dun_level));
return okay;
@@ -3681,10 +3525,8 @@ static bool_ mutate_monster_okay(int r_idx)
*/
bool_ multiply_monster(int m_idx, bool_ charm, bool_ clone)
{
- monster_type *m_ptr = &m_list[m_idx];
- monster_race *r_ptr = race_inf(m_ptr);
-
- int i, y, x, new_race;
+ monster_type *m_ptr = &m_list[m_idx];
+ auto const r_ptr = m_ptr->race();
bool_ result = FALSE;
@@ -3695,18 +3537,17 @@ bool_ multiply_monster(int m_idx, bool_ charm, bool_ clone)
}
/* Try up to 18 times */
- for (i = 0; i < 18; i++)
+ for (int i = 0; i < 18; i++)
{
- int d = 1;
-
-
/* Pick a location */
- scatter(&y, &x, m_ptr->fy, m_ptr->fx, d);
+ int x;
+ int y;
+ scatter(&y, &x, m_ptr->fy, m_ptr->fx, 1);
/* Require an "empty" floor grid */
if (!cave_empty_bold(y, x)) continue;
- new_race = m_ptr->r_idx;
+ int new_race = m_ptr->r_idx;
/* It can mutate into a nastier monster */
if ((rand_int(100) < 3) && (!clone))
@@ -3757,126 +3598,122 @@ bool_ multiply_monster(int m_idx, bool_ charm, bool_ clone)
* Technically should attempt to treat "Beholder"'s as jelly's
*/
bool_ hack_message_pain_may_silent = FALSE;
-void message_pain_hook(cptr fmt, ...)
+void message_pain_hook(cptr message, cptr name)
{
- va_list vp;
-
- char buf[1024];
-
- /* Begin the Varargs Stuff */
- va_start(vp, fmt);
-
- /* Format the args, save the length */
- (void)vstrnfmt(buf, 1024, fmt, vp);
-
- /* End the Varargs Stuff */
- va_end(vp);
+ std::string buf;
+ buf += name;
+ buf += " ";
+ buf += message;
if (hack_message_pain_may_silent)
- monster_msg(buf);
+ {
+ monster_msg_simple(buf.c_str());
+ }
else
- msg_print(buf);
+ {
+ msg_print(buf.c_str());
+ }
}
void message_pain(int m_idx, int dam)
{
- long oldhp, newhp, tmp;
- int percentage;
monster_type *m_ptr = &m_list[m_idx];
- monster_race *r_ptr = race_inf(m_ptr);
- char m_name[80];
/* Get the monster name */
+ char m_name[80];
monster_desc(m_name, m_ptr, 0);
+ capitalize(m_name);
/* Notice non-damage */
if (dam == 0)
{
- message_pain_hook("%^s is unharmed.", m_name);
+ message_pain_hook("is unharmed.", m_name);
return;
}
/* Note -- subtle fix -CFT */
- newhp = (long)(m_ptr->hp);
- oldhp = newhp + (long)(dam);
- tmp = (newhp * 100L) / oldhp;
- percentage = (int)(tmp);
+ long newhp = (long)(m_ptr->hp);
+ long oldhp = newhp + (long)(dam);
+ long tmp = (newhp * 100L) / oldhp;
+ int percentage = (int)(tmp);
+ /* Get racial information */
+ auto const r_ptr = m_ptr->race();
/* Jelly's, Mold's, Vortex's, Quthl's */
if (strchr("jmvQ", r_ptr->d_char))
{
if (percentage > 95)
- message_pain_hook("%^s barely notices.", m_name);
+ message_pain_hook("barely notices.", m_name);
else if (percentage > 75)
- message_pain_hook("%^s flinches.", m_name);
+ message_pain_hook("flinches.", m_name);
else if (percentage > 50)
- message_pain_hook("%^s squelches.", m_name);
+ message_pain_hook("squelches.", m_name);
else if (percentage > 35)
- message_pain_hook("%^s quivers in pain.", m_name);
+ message_pain_hook("quivers in pain.", m_name);
else if (percentage > 20)
- message_pain_hook("%^s writhes about.", m_name);
+ message_pain_hook("writhes about.", m_name);
else if (percentage > 10)
- message_pain_hook("%^s writhes in agony.", m_name);
+ message_pain_hook("writhes in agony.", m_name);
else
- message_pain_hook("%^s jerks limply.", m_name);
+ message_pain_hook("jerks limply.", m_name);
}
/* Dogs and Hounds */
else if (strchr("CZ", r_ptr->d_char))
{
if (percentage > 95)
- message_pain_hook("%^s shrugs off the attack.", m_name);
+ message_pain_hook("shrugs off the attack.", m_name);
else if (percentage > 75)
- message_pain_hook("%^s snarls with pain.", m_name);
+ message_pain_hook("snarls with pain.", m_name);
else if (percentage > 50)
- message_pain_hook("%^s yelps in pain.", m_name);
+ message_pain_hook("yelps in pain.", m_name);
else if (percentage > 35)
- message_pain_hook("%^s howls in pain.", m_name);
+ message_pain_hook("howls in pain.", m_name);
else if (percentage > 20)
- message_pain_hook("%^s howls in agony.", m_name);
+ message_pain_hook("howls in agony.", m_name);
else if (percentage > 10)
- message_pain_hook("%^s writhes in agony.", m_name);
+ message_pain_hook("writhes in agony.", m_name);
else
- message_pain_hook("%^s yelps feebly.", m_name);
+ message_pain_hook("yelps feebly.", m_name);
}
/* One type of monsters (ignore,squeal,shriek) */
else if (strchr("FIKMRSXabclqrst", r_ptr->d_char))
{
if (percentage > 95)
- message_pain_hook("%^s ignores the attack.", m_name);
+ message_pain_hook("ignores the attack.", m_name);
else if (percentage > 75)
- message_pain_hook("%^s grunts with pain.", m_name);
+ message_pain_hook("grunts with pain.", m_name);
else if (percentage > 50)
- message_pain_hook("%^s squeals in pain.", m_name);
+ message_pain_hook("squeals in pain.", m_name);
else if (percentage > 35)
- message_pain_hook("%^s shrieks in pain.", m_name);
+ message_pain_hook("shrieks in pain.", m_name);
else if (percentage > 20)
- message_pain_hook("%^s shrieks in agony.", m_name);
+ message_pain_hook("shrieks in agony.", m_name);
else if (percentage > 10)
- message_pain_hook("%^s writhes in agony.", m_name);
+ message_pain_hook("writhes in agony.", m_name);
else
- message_pain_hook("%^s cries out feebly.", m_name);
+ message_pain_hook("cries out feebly.", m_name);
}
/* Another type of monsters (shrug,cry,scream) */
else
{
if (percentage > 95)
- message_pain_hook("%^s shrugs off the attack.", m_name);
+ message_pain_hook("shrugs off the attack.", m_name);
else if (percentage > 75)
- message_pain_hook("%^s grunts with pain.", m_name);
+ message_pain_hook("grunts with pain.", m_name);
else if (percentage > 50)
- message_pain_hook("%^s cries out in pain.", m_name);
+ message_pain_hook("cries out in pain.", m_name);
else if (percentage > 35)
- message_pain_hook("%^s screams in pain.", m_name);
+ message_pain_hook("screams in pain.", m_name);
else if (percentage > 20)
- message_pain_hook("%^s screams in agony.", m_name);
+ message_pain_hook("screams in agony.", m_name);
else if (percentage > 10)
- message_pain_hook("%^s writhes in agony.", m_name);
+ message_pain_hook("writhes in agony.", m_name);
else
- message_pain_hook("%^s cries out feebly.", m_name);
+ message_pain_hook("cries out feebly.", m_name);
}
}
@@ -3887,22 +3724,33 @@ void message_pain(int m_idx, int dam)
*/
void update_smart_learn(int m_idx, int what)
{
- monster_type *m_ptr = &m_list[m_idx];
-
- monster_race *r_ptr = race_inf(m_ptr);
+ /* Not allowed to learn */
+ if (!options->smart_learn)
+ {
+ return;
+ }
+ /* Fast path for DRS_NONE */
+ if (what == DRS_NONE)
+ {
+ return;
+ }
- /* Not allowed to learn */
- if (!smart_learn) return;
+ /* Get racial flags */
+ auto m_ptr = &m_list[m_idx];
+ auto const r_ptr = m_ptr->race();
/* Too stupid to learn anything */
- if (r_ptr->flags2 & (RF2_STUPID)) return;
+ if (r_ptr->flags & RF_STUPID)
+ {
+ return;
+ }
/* Not intelligent, only learn sometimes */
- if (!(r_ptr->flags2 & (RF2_SMART)) && (rand_int(100) < 50)) return;
-
-
- /* XXX XXX XXX */
+ if (!(r_ptr->flags & RF_SMART) && magik(50))
+ {
+ return;
+ }
/* Analyze the knowledge */
switch (what)
@@ -4018,26 +3866,22 @@ s16b player_place(int y, int x)
*/
void monster_drop_carried_objects(monster_type *m_ptr)
{
- s16b this_o_idx, next_o_idx = 0;
- object_type forge;
- object_type *o_ptr;
- object_type *q_ptr;
-
+ /* Copy list of objects; we need a copy since
+ we're manipulating the list itself below. */
+ auto const object_idxs(m_ptr->hold_o_idxs);
/* Drop objects being carried */
- for (this_o_idx = m_ptr->hold_o_idx; this_o_idx; this_o_idx = next_o_idx)
+ for (auto const this_o_idx: object_idxs)
{
/* Acquire object */
- o_ptr = &o_list[this_o_idx];
-
- /* Acquire next object */
- next_o_idx = o_ptr->next_o_idx;
+ object_type *o_ptr = &o_list[this_o_idx];
/* Paranoia */
o_ptr->held_m_idx = 0;
/* Get local object */
- q_ptr = &forge;
+ object_type forge;
+ object_type *q_ptr = &forge;
/* Copy the object */
object_copy(q_ptr, o_ptr);
@@ -4050,5 +3894,5 @@ void monster_drop_carried_objects(monster_type *m_ptr)
}
/* Forget objects */
- m_ptr->hold_o_idx = 0;
+ m_ptr->hold_o_idxs.clear();
}
diff --git a/src/monster2.hpp b/src/monster2.hpp
new file mode 100644
index 00000000..ddd0b6bc
--- /dev/null
+++ b/src/monster2.hpp
@@ -0,0 +1,50 @@
+#pragma once
+
+#include "h-basic.h"
+#include "monster_race_fwd.hpp"
+#include "monster_type_fwd.hpp"
+#include "object_type_fwd.hpp"
+#include <memory>
+
+s32b monster_exp(s16b level);
+void monster_set_level(int m_idx, int level);
+s32b modify_aux(s32b a, s32b b, char mod);
+void monster_msg_simple(cptr s);
+bool_ mego_ok(monster_race const *r_ptr, int ego);
+void monster_check_experience(int m_idx, bool_ silent);
+void monster_gain_exp(int m_idx, u32b exp, bool_ silent);
+std::shared_ptr<monster_race> race_info_idx(int r_idx, int ego);
+void delete_monster_idx(int i);
+void delete_monster(int y, int x);
+void compact_monsters(int size);
+void wipe_m_list();
+s16b m_pop();
+errr get_mon_num_prep();
+s16b get_mon_num(int level);
+void monster_desc(char *desc, monster_type *m_ptr, int mode);
+void monster_race_desc(char *desc, int r_idx, int ego);
+void update_mon(int m_idx, bool_ full);
+void update_monsters(bool_ full);
+void monster_carry(monster_type *m_ptr, int m_idx, object_type *q_ptr);
+extern bool_ bypass_r_ptr_max_num ;
+bool_ place_monster_aux(int y, int x, int r_idx, bool_ slp, bool_ grp, int status);
+bool_ place_monster(int y, int x, bool_ slp, bool_ grp);
+bool_ alloc_horde(int y, int x);
+bool_ alloc_monster(int dis, bool_ slp);
+extern int summon_specific_level;
+bool_ summon_specific(int y1, int x1, int lev, int type);
+void monster_swap(int y1, int x1, int y2, int x2);
+bool_ multiply_monster(int m_idx, bool_ charm, bool_ clone);
+extern bool_ hack_message_pain_may_silent;
+void message_pain(int m_idx, int dam);
+void update_smart_learn(int m_idx, int what);
+bool_ summon_specific_friendly(int y1, int x1, int lev, int type, bool_ Group_ok);
+extern bool_ place_monster_one_no_drop;
+s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status);
+s16b player_place(int y, int x);
+void monster_drop_carried_objects(monster_type *m_ptr);
+bool_ monster_dungeon(int r_idx);
+bool_ monster_quest(int r_idx);
+void set_mon_num_hook();
+void set_mon_num2_hook(int y, int x);
+bool_ monster_can_cross_terrain(byte feat, std::shared_ptr<monster_race> r_ptr);
diff --git a/src/monster3.c b/src/monster3.cc
index a2b5fb38..6dd1f74e 100644
--- a/src/monster3.c
+++ b/src/monster3.cc
@@ -1,7 +1,3 @@
-/* File: monster3.c */
-
-/* Purpose: Monsters AI */
-
/*
* Copyright (c) 1989 James E. Wilson, Robert A. Koeneke
*
@@ -10,7 +6,29 @@
* included in all such copies.
*/
-#include "angband.h"
+#include "monster3.hpp"
+
+#include "cave_type.hpp"
+#include "cmd2.hpp"
+#include "cmd5.hpp"
+#include "game.hpp"
+#include "gods.hpp"
+#include "melee2.hpp"
+#include "monster2.hpp"
+#include "monster_race.hpp"
+#include "monster_race_flag.hpp"
+#include "monster_spell_flag.hpp"
+#include "monster_type.hpp"
+#include "object2.hpp"
+#include "player_type.hpp"
+#include "skills.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "util.h"
+#include "variable.h"
+#include "variable.hpp"
+#include "xtra2.hpp"
+#include "z-rand.hpp"
/*
* Is the mon,ster in friendly state(pet, friend, ..)
@@ -43,12 +61,16 @@ int is_friend(monster_type *m_ptr)
/* Should they attack each others */
bool_ is_enemy(monster_type *m_ptr, monster_type *t_ptr)
{
- monster_race *r_ptr = &r_info[m_ptr->r_idx], *rt_ptr = &r_info[t_ptr->r_idx];
+ auto const &r_info = game->edit_data.r_info;
+
+ auto r_ptr = &r_info[m_ptr->r_idx];
+ auto rt_ptr = &r_info[t_ptr->r_idx];
+
int s1 = is_friend(m_ptr), s2 = is_friend(t_ptr);
/* Monsters hates breeders */
- if ((m_ptr->status != MSTATUS_NEUTRAL) && (rt_ptr->flags4 & RF4_MULTIPLY) && (num_repro > MAX_REPRO * 2 / 3) && (r_ptr->d_char != rt_ptr->d_char)) return TRUE;
- if ((t_ptr->status != MSTATUS_NEUTRAL) && (r_ptr->flags4 & RF4_MULTIPLY) && (num_repro > MAX_REPRO * 2 / 3) && (r_ptr->d_char != rt_ptr->d_char)) return TRUE;
+ if ((m_ptr->status != MSTATUS_NEUTRAL) && (rt_ptr->spells & SF_MULTIPLY) && (num_repro > MAX_REPRO * 2 / 3) && (r_ptr->d_char != rt_ptr->d_char)) return TRUE;
+ if ((t_ptr->status != MSTATUS_NEUTRAL) && (r_ptr->spells & SF_MULTIPLY) && (num_repro > MAX_REPRO * 2 / 3) && (r_ptr->d_char != rt_ptr->d_char)) return TRUE;
/* No special conditions, lets test normal flags */
if (s1 && s2 && (s1 == -s2)) return TRUE;
@@ -59,14 +81,14 @@ bool_ is_enemy(monster_type *m_ptr, monster_type *t_ptr)
bool_ change_side(monster_type *m_ptr)
{
- monster_race *r_ptr = race_inf(m_ptr);
+ auto const r_ptr = m_ptr->race();
/* neutrals and companions */
switch (m_ptr->status)
{
case MSTATUS_FRIEND:
m_ptr->status = MSTATUS_ENEMY;
- if ((r_ptr->flags3 & RF3_ANIMAL) && (!(r_ptr->flags3 & RF3_EVIL)))
+ if ((r_ptr->flags & RF_ANIMAL) && (!(r_ptr->flags & RF_EVIL)))
inc_piety(GOD_YAVANNA, -m_ptr->level * 4);
break;
case MSTATUS_NEUTRAL_P:
@@ -77,7 +99,7 @@ bool_ change_side(monster_type *m_ptr)
break;
case MSTATUS_PET:
m_ptr->status = MSTATUS_ENEMY;
- if ((r_ptr->flags3 & RF3_ANIMAL) && (!(r_ptr->flags3 & RF3_EVIL)))
+ if ((r_ptr->flags & RF_ANIMAL) && (!(r_ptr->flags & RF_EVIL)))
inc_piety(GOD_YAVANNA, -m_ptr->level * 4);
break;
case MSTATUS_COMPANION:
@@ -92,7 +114,6 @@ bool_ change_side(monster_type *m_ptr)
bool_ ai_multiply(int m_idx)
{
monster_type *m_ptr = &m_list[m_idx];
- monster_race *r_ptr = &r_info[m_ptr->r_idx];
int k, y, x, oy = m_ptr->fy, ox = m_ptr->fx;
bool_ is_frien = (is_friend(m_ptr) > 0);
@@ -120,12 +141,6 @@ bool_ ai_multiply(int m_idx)
/* Try to multiply */
if (multiply_monster(m_idx, (is_frien), FALSE))
{
- /* Take note if visible */
- if (m_ptr->ml)
- {
- r_ptr->r_flags4 |= (RF4_MULTIPLY);
- }
-
/* Multiplying takes energy */
return TRUE;
}
@@ -136,11 +151,13 @@ bool_ ai_multiply(int m_idx)
/* Possessor incarnates */
bool_ ai_possessor(int m_idx, int o_idx)
{
+ auto &r_info = game->edit_data.r_info;
+
object_type *o_ptr = &o_list[o_idx];
monster_type *m_ptr = &m_list[m_idx];
int r_idx = m_ptr->r_idx, r2_idx = o_ptr->pval2;
int i;
- monster_race *r_ptr = &r_info[r2_idx];
+ auto r_ptr = &r_info[r2_idx];
char m_name[80], m_name2[80];
monster_desc(m_name, m_ptr, 0x00);
@@ -166,7 +183,7 @@ bool_ ai_possessor(int m_idx, int o_idx)
m_ptr->csleep = 0;
/* Assign maximal hitpoints */
- if (r_ptr->flags1 & (RF1_FORCE_MAXHP))
+ if (r_ptr->flags & RF_FORCE_MAXHP)
{
m_ptr->maxhp = maxroll(r_ptr->hdice, r_ptr->hside);
}
@@ -189,7 +206,7 @@ bool_ ai_possessor(int m_idx, int o_idx)
m_ptr->ac = r_ptr->ac;
m_ptr->level = r_ptr->level;
m_ptr->speed = r_ptr->speed;
- m_ptr->exp = MONSTER_EXP(m_ptr->level);
+ m_ptr->exp = monster_exp(m_ptr->level);
/* Extract the monster base speed */
m_ptr->mspeed = m_ptr->speed;
@@ -197,10 +214,10 @@ bool_ ai_possessor(int m_idx, int o_idx)
m_ptr->energy = 0;
/* Hack -- Count the number of "reproducers" */
- if (r_ptr->flags4 & (RF4_MULTIPLY)) num_repro++;
+ if (r_ptr->spells & SF_MULTIPLY) num_repro++;
/* Hack -- Notice new multi-hued monsters */
- if (r_ptr->flags1 & (RF1_ATTR_MULTI)) shimmer_monsters = TRUE;
+ if (r_ptr->flags & RF_ATTR_MULTI) shimmer_monsters = TRUE;
/* Hack -- Count the monsters on the level */
r_ptr->cur_num++;
@@ -216,9 +233,11 @@ bool_ ai_possessor(int m_idx, int o_idx)
void ai_deincarnate(int m_idx)
{
+ auto &r_info = game->edit_data.r_info;
+
monster_type *m_ptr = &m_list[m_idx];
int r2_idx = m_ptr->possessor, r_idx = m_ptr->r_idx;
- monster_race *r_ptr = &r_info[r2_idx];
+ auto r_ptr = &r_info[r2_idx];
int i;
char m_name[80];
@@ -241,7 +260,7 @@ void ai_deincarnate(int m_idx)
m_ptr->csleep = 0;
/* Assign maximal hitpoints */
- if (r_ptr->flags1 & (RF1_FORCE_MAXHP))
+ if (r_ptr->flags & RF_FORCE_MAXHP)
{
m_ptr->maxhp = maxroll(r_ptr->hdice, r_ptr->hside);
}
@@ -264,7 +283,7 @@ void ai_deincarnate(int m_idx)
m_ptr->ac = r_ptr->ac;
m_ptr->level = r_ptr->level;
m_ptr->speed = r_ptr->speed;
- m_ptr->exp = MONSTER_EXP(m_ptr->level);
+ m_ptr->exp = monster_exp(m_ptr->level);
/* Extract the monster base speed */
m_ptr->mspeed = m_ptr->speed;
@@ -272,10 +291,10 @@ void ai_deincarnate(int m_idx)
m_ptr->energy = 0;
/* Hack -- Count the number of "reproducers" */
- if (r_ptr->flags4 & (RF4_MULTIPLY)) num_repro++;
+ if (r_ptr->spells & SF_MULTIPLY) num_repro++;
/* Hack -- Notice new multi-hued monsters */
- if (r_ptr->flags1 & (RF1_ATTR_MULTI)) shimmer_monsters = TRUE;
+ if (r_ptr->flags & RF_ATTR_MULTI) shimmer_monsters = TRUE;
/* Hack -- Count the monsters on the level */
r_ptr->cur_num++;
@@ -288,7 +307,7 @@ void ai_deincarnate(int m_idx)
}
/* Returns if a new companion is allowed */
-bool_ can_create_companion(void)
+bool_ can_create_companion()
{
int i, mcnt = 0;
@@ -309,7 +328,7 @@ bool_ can_create_companion(void)
/* Player controlled monsters */
-bool_ do_control_walk(void)
+bool_ do_control_walk()
{
/* Get a "repeated" direction */
if (p_ptr->control)
@@ -330,39 +349,36 @@ bool_ do_control_walk(void)
return FALSE;
}
-bool_ do_control_inven(void)
+bool_ do_control_inven()
{
- int monst_list[23];
-
if (!p_ptr->control) return FALSE;
screen_save();
prt("Carried items", 0, 0);
- show_monster_inven(p_ptr->control, monst_list);
+ show_monster_inven(p_ptr->control);
inkey();
screen_load();
return TRUE;
}
-bool_ do_control_pickup(void)
+bool_ do_control_pickup()
{
- int this_o_idx, next_o_idx = 0;
+ if (!p_ptr->control) return FALSE;
+
monster_type *m_ptr = &m_list[p_ptr->control];
- cave_type *c_ptr;
- bool_ done = FALSE;
- if (!p_ptr->control) return FALSE;
+ cave_type *c_ptr = &cave[m_ptr->fy][m_ptr->fx];
+
+ /* Copy list of all objects in the grid; we need a
+ * copy since we're going to be excising objects
+ * from lists. */
+ auto const object_idxs(c_ptr->o_idxs);
/* Scan all objects in the grid */
- c_ptr = &cave[m_ptr->fy][m_ptr->fx];
- for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
+ bool done = false;
+ for (auto const this_o_idx: object_idxs)
{
- object_type * o_ptr;
-
/* Acquire object */
- o_ptr = &o_list[this_o_idx];
-
- /* Acquire next object */
- next_o_idx = o_ptr->next_o_idx;
+ object_type *o_ptr = &o_list[this_o_idx];
/* Skip gold */
if (o_ptr->tval == TV_GOLD) continue;
@@ -379,18 +395,23 @@ bool_ do_control_pickup(void)
/* Memorize monster */
o_ptr->held_m_idx = p_ptr->control;
- /* Build a stack */
- o_ptr->next_o_idx = m_ptr->hold_o_idx;
-
/* Carry object */
- m_ptr->hold_o_idx = this_o_idx;
- done = TRUE;
+ m_ptr->hold_o_idxs.push_back(this_o_idx);
+
+ /* Picked up at least one object */
+ done = true;
+ }
+
+ /* Feedback */
+ if (done)
+ {
+ msg_print("You pick up all objects on the floor.");
}
- if (done) msg_print("You pick up all objects on the floor.");
+
return TRUE;
}
-bool_ do_control_drop(void)
+bool_ do_control_drop()
{
monster_type *m_ptr = &m_list[p_ptr->control];
@@ -399,16 +420,16 @@ bool_ do_control_drop(void)
return TRUE;
}
-bool_ do_control_magic(void)
+bool_ do_control_magic()
{
- int power = -1;
- int num = 0, i;
- int powers[96];
+ auto const &r_info = game->edit_data.r_info;
+
+ int i;
bool_ flag, redraw;
int ask;
char choice;
char out_val[160];
- monster_race *r_ptr = &r_info[m_list[p_ptr->control].r_idx];
+ auto r_ptr = &r_info[m_list[p_ptr->control].r_idx];
int label;
if (!p_ptr->control) return FALSE;
@@ -421,36 +442,11 @@ bool_ do_control_magic(void)
return TRUE;
}
- /* List the monster powers -- RF4_* */
- for (i = 0; i < 32; i++)
- {
- if (r_ptr->flags4 & BIT(i))
- {
- 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].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].power) continue;
- powers[num++] = i + 64;
- }
- }
+ /* Extract available monster powers */
+ auto powers = extract_monster_powers(r_ptr, true);
+ int const num = powers.size(); // Avoid signed/unsigned warnings
+ /* Are any powers available? */
if (!num)
{
msg_print("You have no powers you can use.");
@@ -459,6 +455,7 @@ bool_ do_control_magic(void)
/* Nothing chosen yet */
flag = FALSE;
+ monster_power const *power = nullptr;
/* No redraw yet */
redraw = FALSE;
@@ -497,7 +494,7 @@ bool_ do_control_magic(void)
while (ctr < num)
{
- monster_power *mp_ptr = &monster_powers[powers[ctr]];
+ monster_power const *mp_ptr = powers[ctr];
label = (ctr < 26) ? I2A(ctr) : I2D(ctr - 26);
@@ -581,7 +578,7 @@ bool_ do_control_magic(void)
char tmp_val[160];
/* Prompt */
- strnfmt(tmp_val, 78, "Use %s? ", monster_powers[power].name);
+ strnfmt(tmp_val, 78, "Use %s? ", power->name);
/* Belay that order */
if (!get_check(tmp_val)) continue;
@@ -602,7 +599,7 @@ bool_ do_control_magic(void)
if (flag)
{
energy_use = 100;
- monst_spell_monst_spell = power + 96;
+ monst_spell_monst_spell = power->monster_spell_index;
}
return TRUE;
}
diff --git a/src/monster3.hpp b/src/monster3.hpp
new file mode 100644
index 00000000..ac26b102
--- /dev/null
+++ b/src/monster3.hpp
@@ -0,0 +1,20 @@
+#pragma once
+
+#include "h-basic.h"
+#include "monster_type_fwd.hpp"
+
+void dump_companions(FILE *outfile);
+void do_cmd_companion();
+bool_ do_control_reconnect();
+bool_ do_control_drop();
+bool_ do_control_magic();
+bool_ do_control_pickup();
+bool_ do_control_inven();
+bool_ do_control_walk();
+bool_ can_create_companion();
+void ai_deincarnate(int m_idx);
+bool_ ai_possessor(int m_idx, int o_idx);
+bool_ ai_multiply(int m_idx);
+bool_ change_side(monster_type *m_ptr);
+int is_friend(monster_type *m_ptr);
+bool_ is_enemy(monster_type *m_ptr, monster_type *t_ptr);
diff --git a/src/monster_blow.hpp b/src/monster_blow.hpp
new file mode 100644
index 00000000..6e0ee6e5
--- /dev/null
+++ b/src/monster_blow.hpp
@@ -0,0 +1,19 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * Monster blow descriptor.
+ *
+ * - Method (RBM_*)
+ * - Effect (RBE_*)
+ * - Damage Dice
+ * - Damage Sides
+ */
+struct monster_blow
+{
+ byte method = 0;
+ byte effect = 0;
+ byte d_dice = 0;
+ byte d_side = 0;
+};
diff --git a/src/monster_ego.hpp b/src/monster_ego.hpp
new file mode 100644
index 00000000..b578d03e
--- /dev/null
+++ b/src/monster_ego.hpp
@@ -0,0 +1,69 @@
+#pragma once
+
+#include "h-basic.h"
+#include "monster_blow.hpp"
+#include "monster_race_flag_set.hpp"
+#include "monster_spell_flag_set.hpp"
+
+#include <array>
+
+/**
+ * Monster ego descriptors.
+ */
+struct monster_ego
+{
+ const char *name = nullptr; /* Name */
+ bool_ before = false; /* Display ego before or after */
+
+ std::array<monster_blow, 4> blow { }; /* Up to four blows per round */
+ byte blowm[4][2] = {
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 }
+ };
+
+ s16b hdice = 0; /* Creatures hit dice count */
+ s16b hside = 0; /* Creatures hit dice sides */
+
+ s16b ac = 0; /* Armour Class */
+
+ s16b sleep = 0; /* Inactive counter (base) */
+ s16b aaf = 0; /* Area affect radius (1-100) */
+ s16b speed = 0; /* Speed (normally 110) */
+
+ s32b mexp = 0; /* Exp value for kill */
+
+ s32b weight = 0; /* Weight of the monster */
+
+ byte freq_inate = 0; /* Inate spell frequency */
+ byte freq_spell = 0; /* Other spell frequency */
+
+ /* Ego flags */
+ monster_race_flag_set flags;
+ monster_race_flag_set hflags;
+
+ /* Monster flags */
+ monster_race_flag_set mflags;
+
+ /* Monster spells */
+ monster_spell_flag_set mspells;
+
+ /* Negative flags, to be removed from the monster flags */
+ monster_race_flag_set nflags;
+
+ /* Negative spells; to be removed from the monster spells */
+ monster_spell_flag_set nspells;
+
+ s16b level = 0; /* Level of creature */
+ s16b rarity = 0; /* Rarity of creature */
+
+ byte d_attr = 0; /* Default monster attribute */
+ char d_char = '\0'; /* Default monster character */
+
+ byte g_attr = 0; /* Overlay graphic attribute */
+ char g_char = '\0'; /* Overlay graphic character */
+
+ char r_char[5] = { '\0' }; /* Monster race allowed */
+ char nr_char[5] = { '\0' }; /* Monster race not allowed */
+};
diff --git a/src/monster_power.hpp b/src/monster_power.hpp
new file mode 100644
index 00000000..440d5ba1
--- /dev/null
+++ b/src/monster_power.hpp
@@ -0,0 +1,16 @@
+#pragma once
+
+#include "monster_power_fwd.hpp"
+
+#include "h-basic.h"
+
+/**
+ * Monster powers that players can use via e.g. Symbiosis.
+ */
+struct monster_power
+{
+ u32b monster_spell_index;
+ cptr name; /* Name of it */
+ int mana; /* Mana needed */
+ bool_ great; /* Need the use of great spells */
+};
diff --git a/src/monster_power_fwd.hpp b/src/monster_power_fwd.hpp
new file mode 100644
index 00000000..975d2d2f
--- /dev/null
+++ b/src/monster_power_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct monster_power;
diff --git a/src/monster_race.hpp b/src/monster_race.hpp
new file mode 100644
index 00000000..eb398a3d
--- /dev/null
+++ b/src/monster_race.hpp
@@ -0,0 +1,84 @@
+#pragma once
+
+#include "body.hpp"
+#include "h-basic.h"
+#include "monster_blow.hpp"
+#include "monster_race_flag_set.hpp"
+#include "monster_spell_flag_set.hpp"
+#include "obj_theme.hpp"
+
+#include <array>
+
+/**
+ * Monster race descriptors and runtime data, including racial memories.
+ *
+ * Note that "d_attr" and "d_char" are used for MORE than "visual" stuff.
+ *
+ * Note that "x_attr" and "x_char" are used ONLY for "visual" stuff.
+ *
+ * Note that "cur_num" (and "max_num") represent the number of monsters
+ * of the given race currently on (and allowed on) the current level.
+ * This information yields the "dead" flag for Unique monsters.
+ *
+ * Note that "max_num" is reset when a new player is created.
+ * Note that "cur_num" is reset when a new level is created.
+ *
+ * Note that several of these fields, related to "recall", can be
+ * scrapped if space becomes an issue, resulting in less "complete"
+ * monster recall (no knowledge of spells, etc). All of the "recall"
+ * fields have a special prefix to aid in searching for them.
+ */
+struct monster_race
+{
+ const char *name = nullptr; /* Name */
+ char *text = nullptr; /* Text */
+
+ u16b hdice = 0; /* Creatures hit dice count */
+ u16b hside = 0; /* Creatures hit dice sides */
+
+ s16b ac = 0; /* Armour Class */
+
+ s16b sleep = 0; /* Inactive counter (base) */
+ byte aaf = 0; /* Area affect radius (1-100) */
+ byte speed = 0; /* Speed (normally 110) */
+
+ s32b mexp = 0; /* Exp value for kill */
+
+ s32b weight = 0; /* Weight of the monster */
+
+ byte freq_inate = 0; /* Inate spell frequency */
+ byte freq_spell = 0; /* Other spell frequency */
+
+ monster_race_flag_set flags; /* Flags */
+
+ monster_spell_flag_set spells; /* Spells */
+
+ std::array<monster_blow, 4> blow { }; /* Up to four blows per round */
+
+ byte body_parts[BODY_MAX] = { 0 }; /* To help to decide what to use when body changing */
+
+ byte artifact_idx = 0; /* Artifact index of standard artifact dropped; 0 if none. */
+ int artifact_chance = 0; /* Percentage chance of dropping the artifact. */
+
+ byte level = 0; /* Level of creature */
+ byte rarity = 0; /* Rarity of creature */
+
+ byte d_attr = 0; /* Default monster attribute */
+ char d_char = 0; /* Default monster character */
+
+
+ byte x_attr = 0; /* Desired monster attribute */
+ char x_char = 0; /* Desired monster character */
+
+ s16b max_num = 0; /* Maximum population allowed per level */
+ byte cur_num = 0; /* Monster population on current level */
+
+ s16b r_pkills = 0; /* Count monsters killed in this life */
+
+ bool_ on_saved = 0; /* Is the (unique) on a saved level ? */
+
+ obj_theme drops; /* The drops type */
+
+};
+
+
diff --git a/src/monster_race_flag.hpp b/src/monster_race_flag.hpp
new file mode 100644
index 00000000..098e8176
--- /dev/null
+++ b/src/monster_race_flag.hpp
@@ -0,0 +1,12 @@
+#pragma once
+
+#include "monster_race_flag_set.hpp"
+#include <boost/preprocessor/cat.hpp>
+
+//
+// Define flag set for each flag.
+//
+#define RF(tier, index, name) \
+ DECLARE_FLAG(monster_race_flag_set, BOOST_PP_CAT(RF_,name), tier, index)
+#include "monster_race_flag_list.hpp"
+#undef RF
diff --git a/src/monster_race_flag_list.hpp b/src/monster_race_flag_list.hpp
new file mode 100644
index 00000000..b9d2b079
--- /dev/null
+++ b/src/monster_race_flag_list.hpp
@@ -0,0 +1,152 @@
+/**
+ * X-macro list of all the monster race flags
+ */
+
+/* RF(<tier>, <index>, <name>) */
+
+RF(1, 0, UNIQUE)
+RF(1, 1, QUESTOR)
+RF(1, 2, MALE)
+RF(1, 3, FEMALE)
+RF(1, 4, CHAR_CLEAR)
+RF(1, 5, CHAR_MULTI)
+RF(1, 6, ATTR_CLEAR)
+RF(1, 7, ATTR_MULTI)
+RF(1, 8, FORCE_DEPTH)
+RF(1, 9, FORCE_MAXHP)
+RF(1, 10, FORCE_SLEEP)
+RF(1, 11, FORCE_EXTRA)
+RF(1, 12, FRIEND)
+RF(1, 13, FRIENDS)
+RF(1, 14, ESCORT)
+RF(1, 15, ESCORTS)
+RF(1, 16, NEVER_BLOW)
+RF(1, 17, NEVER_MOVE)
+RF(1, 18, RAND_25)
+RF(1, 19, RAND_50)
+RF(1, 20, ONLY_GOLD)
+RF(1, 21, ONLY_ITEM)
+RF(1, 22, DROP_60)
+RF(1, 23, DROP_90)
+RF(1, 24, DROP_1D2)
+RF(1, 25, DROP_2D2)
+RF(1, 26, DROP_3D2)
+RF(1, 27, DROP_4D2)
+RF(1, 28, DROP_GOOD)
+RF(1, 29, DROP_GREAT)
+RF(1, 30, DROP_USEFUL)
+RF(1, 31, DROP_CHOSEN)
+
+RF(2, 0, STUPID)
+RF(2, 1, SMART)
+RF(2, 2, CAN_SPEAK)
+RF(2, 3, REFLECTING)
+RF(2, 4, INVISIBLE)
+RF(2, 5, COLD_BLOOD)
+RF(2, 6, EMPTY_MIND)
+RF(2, 7, WEIRD_MIND)
+RF(2, 8, DEATH_ORB)
+RF(2, 9, REGENERATE)
+RF(2, 10, SHAPECHANGER)
+RF(2, 11, ATTR_ANY)
+RF(2, 12, POWERFUL)
+RF(2, 13, ELDRITCH_HORROR)
+RF(2, 14, AURA_FIRE)
+RF(2, 15, AURA_ELEC)
+RF(2, 16, OPEN_DOOR)
+RF(2, 17, BASH_DOOR)
+RF(2, 18, PASS_WALL)
+RF(2, 19, KILL_WALL)
+RF(2, 20, MOVE_BODY)
+RF(2, 21, KILL_BODY)
+RF(2, 22, TAKE_ITEM)
+RF(2, 23, KILL_ITEM)
+RF(2, 24, BRAIN_1)
+RF(2, 25, BRAIN_2)
+RF(2, 26, BRAIN_3)
+RF(2, 27, BRAIN_4)
+RF(2, 28, BRAIN_5)
+RF(2, 29, BRAIN_6)
+RF(2, 30, BRAIN_7)
+RF(2, 31, BRAIN_8)
+
+RF(3, 0, ORC)
+RF(3, 1, TROLL)
+RF(3, 2, GIANT)
+RF(3, 3, DRAGON)
+RF(3, 4, DEMON)
+RF(3, 5, UNDEAD)
+RF(3, 6, EVIL)
+RF(3, 7, ANIMAL)
+RF(3, 8, THUNDERLORD)
+RF(3, 9, GOOD)
+RF(3, 10, AURA_COLD)
+RF(3, 11, NONLIVING)
+RF(3, 12, HURT_LITE)
+RF(3, 13, HURT_ROCK)
+RF(3, 14, SUSCEP_FIRE)
+RF(3, 15, SUSCEP_COLD)
+RF(3, 16, IM_ACID)
+RF(3, 17, IM_ELEC)
+RF(3, 18, IM_FIRE)
+RF(3, 19, IM_COLD)
+RF(3, 20, IM_POIS)
+RF(3, 21, RES_TELE)
+RF(3, 22, RES_NETH)
+RF(3, 23, RES_WATE)
+RF(3, 24, RES_PLAS)
+RF(3, 25, RES_NEXU)
+RF(3, 26, RES_DISE)
+RF(3, 28, NO_FEAR)
+RF(3, 29, NO_STUN)
+RF(3, 30, NO_CONF)
+RF(3, 31, NO_SLEEP)
+
+RF(4, 0, AQUATIC)
+RF(4, 1, CAN_SWIM)
+RF(4, 2, CAN_FLY)
+RF(4, 3, FRIENDLY)
+RF(4, 4, PET)
+RF(4, 5, MORTAL)
+RF(4, 6, SPIDER)
+RF(4, 7, NAZGUL)
+RF(4, 8, DG_CURSE)
+RF(4, 9, POSSESSOR)
+RF(4, 10, NO_DEATH)
+RF(4, 11, NO_TARGET)
+RF(4, 12, AI_ANNOY)
+RF(4, 13, AI_SPECIAL)
+RF(4, 14, NEUTRAL)
+RF(4, 16, DROP_RANDART)
+RF(4, 17, AI_PLAYER)
+RF(4, 18, NO_THEFT)
+RF(4, 19, SPIRIT)
+
+RF(5, 0, WILD_ONLY)
+RF(5, 1, WILD_TOWN)
+RF(5, 3, WILD_SHORE)
+RF(5, 4, WILD_OCEAN)
+RF(5, 5, WILD_WASTE)
+RF(5, 6, WILD_WOOD)
+RF(5, 7, WILD_VOLCANO)
+RF(5, 9, WILD_MOUNTAIN)
+RF(5, 10, WILD_GRASS)
+RF(5, 11, NO_CUT)
+RF(5, 15, JOKEANGBAND)
+RF(5, 31, WILD_TOO)
+
+RF(6, 0, DROP_CORPSE)
+RF(6, 1, DROP_SKELETON)
+RF(6, 2, HAS_LITE)
+RF(6, 3, MIMIC)
+RF(6, 4, HAS_EGG)
+RF(6, 5, IMPRESED)
+RF(6, 6, SUSCEP_ACID)
+RF(6, 7, SUSCEP_ELEC)
+RF(6, 8, SUSCEP_POIS)
+RF(6, 9, KILL_TREES)
+RF(6, 10, WYRM_PROTECT)
+RF(6, 11, DOPPLEGANGER)
+RF(6, 12, ONLY_DEPTH)
+RF(6, 13, SPECIAL_GENE)
+RF(6, 14, NEVER_GENE)
diff --git a/src/monster_race_flag_set.hpp b/src/monster_race_flag_set.hpp
new file mode 100644
index 00000000..958201b1
--- /dev/null
+++ b/src/monster_race_flag_set.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "flag_set.hpp"
+
+constexpr std::size_t RF_MAX_TIERS = 6;
+
+typedef flag_set<RF_MAX_TIERS> monster_race_flag_set;
diff --git a/src/monster_race_fwd.hpp b/src/monster_race_fwd.hpp
new file mode 100644
index 00000000..9ee9658a
--- /dev/null
+++ b/src/monster_race_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct monster_race;
diff --git a/src/monster_spell.cc b/src/monster_spell.cc
new file mode 100644
index 00000000..08627916
--- /dev/null
+++ b/src/monster_spell.cc
@@ -0,0 +1,36 @@
+#include "monster_spell.hpp"
+
+#include "monster_spell_flag.hpp"
+
+#include <boost/preprocessor/cat.hpp>
+
+std::vector<monster_spell const *> const &monster_spells()
+{
+ // Static instance for one-time initialization.
+ static std::vector<monster_spell const *> instance;
+
+ if (instance.empty())
+ {
+#define SF(tier, index, name, is_summon, is_annoy, is_damage, is_bolt, is_smart, is_innate, is_escape, is_tactic, is_haste, is_heal) \
+ instance.emplace_back(new monster_spell { \
+ BOOST_PP_CAT(SF_, BOOST_PP_CAT(name, _IDX)), \
+ BOOST_PP_CAT(SF_, name), \
+ #name, \
+ is_summon, \
+ is_annoy, \
+ is_damage, \
+ is_bolt, \
+ is_smart, \
+ is_innate, \
+ is_escape, \
+ is_tactic, \
+ is_haste, \
+ is_heal, \
+ !is_innate, \
+ });
+#include "monster_spell_flag_list.hpp"
+#undef SF
+ };
+
+ return instance;
+}
diff --git a/src/monster_spell.hpp b/src/monster_spell.hpp
new file mode 100644
index 00000000..4dfaf974
--- /dev/null
+++ b/src/monster_spell.hpp
@@ -0,0 +1,91 @@
+#pragma once
+
+#include "monster_spell_flag_set.hpp"
+
+#include <vector>
+
+struct monster_spell {
+
+ /**
+ * The global index of the spell.
+ */
+ const std::size_t spell_idx;
+
+ /**
+ * Flag set representation of the spell.
+ */
+ const monster_spell_flag_set flag_set;
+
+ /**
+ * System name of the spell as a string.
+ */
+ const char *name;
+
+ /**
+ * Is the spell a summoning spell?
+ */
+ const bool is_summon;
+
+ /**
+ * Is the spell an "annoyance" spell?
+ */
+ const bool is_annoy;
+
+ /**
+ * Is the spell a direct damage spell?
+ */
+ const bool is_damage;
+
+ /**
+ * Is the spell a bolt spell, i.e. would it
+ * affect any creature along the trajectory from
+ * the source to its target?
+ */
+ const bool is_bolt;
+
+ /**
+ * Does the spell require an intelligent caster?
+ */
+ const bool is_smart;
+
+ /**
+ * Is the spell an innate attack? For example, breaths
+ * are innate attacks.
+ */
+ const bool is_innate;
+
+ /**
+ * Is the spell an escape spell?
+ */
+ const bool is_escape;
+
+ /**
+ * Is the spell a "tactical" spell?
+ */
+ const bool is_tactic;
+
+ /**
+ * Does the spell apply haste?
+ */
+ const bool is_haste;
+
+ /**
+ * Does the spell apply any healing?
+ */
+ const bool is_heal;
+
+ /**
+ * Is the spell "magical" in nature? Magical spells
+ * can be stopped by the anti-magic field, and non-magical
+ * ones cannot.
+ *
+ * This is the inverse of the "innate" flag.
+ */
+ const bool is_magic;
+
+};
+
+/**
+ * Get a vector of all the spells.
+ */
+std::vector<monster_spell const *> const &monster_spells();
diff --git a/src/monster_spell_flag.hpp b/src/monster_spell_flag.hpp
new file mode 100644
index 00000000..3de649ec
--- /dev/null
+++ b/src/monster_spell_flag.hpp
@@ -0,0 +1,20 @@
+#pragma once
+
+#include "monster_spell_flag_set.hpp"
+#include <boost/preprocessor/cat.hpp>
+
+//
+// Define flag set for each flag.
+//
+#define SF(tier, index, name, is_summon, is_annoy, is_damage, is_bolt, is_smart, is_innate, is_escape, is_tactic, is_haste, is_heal) \
+ DECLARE_FLAG(monster_spell_flag_set, BOOST_PP_CAT(SF_,name), tier, index)
+#include "monster_spell_flag_list.hpp"
+#undef SF
+
+//
+// Define index for each flag.
+//
+#define SF(tier, index, name, is_summon, is_annoy, is_damage, is_bolt, is_smart, is_innate, is_escape, is_tactic, is_haste, is_heal) \
+ constexpr std::size_t BOOST_PP_CAT(BOOST_PP_CAT(SF_,name), _IDX) = (tier - 1) * 32 + index;
+#include "monster_spell_flag_list.hpp"
+#undef SF
diff --git a/src/monster_spell_flag_list.hpp b/src/monster_spell_flag_list.hpp
new file mode 100644
index 00000000..42d8a5e9
--- /dev/null
+++ b/src/monster_spell_flag_list.hpp
@@ -0,0 +1,101 @@
+/**
+ * X-macro list of all the monster race flags
+ */
+
+/* SF(tier, index, name, is_summon, is_annoy, is_damage, is_bolt, is_smart, is_innate, is_escape, is_tactic, is_haste, is_heal) */
+
+SF(1, 0, SHRIEK , false, true , false, false, false, true , false, false, false, false)
+SF(1, 1, MULTIPLY , false, false, false, false, false, true , false, false, false, false)
+SF(1, 2, S_ANIMAL , true , false, false, false, true , false, false, false, false, false)
+SF(1, 3, ROCKET , false, false, true , false, false, true , false, false, false, false)
+SF(1, 4, ARROW_1 , false, false, true , true , false, true , false, false, false, false)
+SF(1, 5, ARROW_2 , false, false, true , true , false, true , false, false, false, false)
+SF(1, 6, ARROW_3 , false, false, true , true , false, true , false, false, false, false)
+SF(1, 7, ARROW_4 , false, false, true , true , false, true , false, false, false, false)
+SF(1, 8, BR_ACID , false, false, true , false, false, true , false, false, false, false)
+SF(1, 9, BR_ELEC , false, false, true , false, false, true , false, false, false, false)
+SF(1, 10, BR_FIRE , false, false, true , false, false, true , false, false, false, false)
+SF(1, 11, BR_COLD , false, false, true , false, false, true , false, false, false, false)
+SF(1, 12, BR_POIS , false, false, true , false, false, true , false, false, false, false)
+SF(1, 13, BR_NETH , false, false, true , false, false, true , false, false, false, false)
+SF(1, 14, BR_LITE , false, false, true , false, false, true , false, false, false, false)
+SF(1, 15, BR_DARK , false, false, true , false, false, true , false, false, false, false)
+SF(1, 16, BR_CONF , false, false, true , false, false, true , false, false, false, false)
+SF(1, 17, BR_SOUN , false, false, true , false, false, true , false, false, false, false)
+SF(1, 18, BR_CHAO , false, false, true , false, false, true , false, false, false, false)
+SF(1, 19, BR_DISE , false, false, true , false, false, true , false, false, false, false)
+SF(1, 20, BR_NEXU , false, false, true , false, false, true , false, false, false, false)
+SF(1, 21, BR_TIME , false, false, true , false, false, true , false, false, false, false)
+SF(1, 22, BR_INER , false, false, true , false, false, true , false, false, false, false)
+SF(1, 23, BR_GRAV , false, false, true , false, false, true , false, false, false, false)
+SF(1, 24, BR_SHAR , false, false, true , false, false, true , false, false, false, false)
+SF(1, 25, BR_PLAS , false, false, true , false, false, true , false, false, false, false)
+SF(1, 26, BR_WALL , false, false, true , false, false, true , false, false, false, false)
+SF(1, 27, BR_MANA , false, false, true , false, false, true , false, false, false, false)
+SF(1, 28, BA_NUKE , false, false, true , false, false, false, false, false, false, false)
+SF(1, 29, BR_NUKE , false, false, true , false, false, true , false, false, false, false)
+SF(1, 30, BA_CHAO , false, false, true , false, false, false, false, false, false, false)
+SF(1, 31, BR_DISI , false, false, true , false, false, true , false, false, false, false)
+SF(2, 0, BA_ACID , false, false, true , false, false, false, false, false, false, false)
+SF(2, 1, BA_ELEC , false, false, true , false, false, false, false, false, false, false)
+SF(2, 2, BA_FIRE , false, false, true , false, false, false, false, false, false, false)
+SF(2, 3, BA_COLD , false, false, true , false, false, false, false, false, false, false)
+SF(2, 4, BA_POIS , false, false, true , false, false, false, false, false, false, false)
+SF(2, 5, BA_NETH , false, false, true , false, false, false, false, false, false, false)
+SF(2, 6, BA_WATE , false, false, true , false, false, false, false, false, false, false)
+SF(2, 7, BA_MANA , false, false, true , false, false, false, false, false, false, false)
+SF(2, 8, BA_DARK , false, false, true , false, false, false, false, false, false, false)
+SF(2, 9, DRAIN_MANA , false, true , false, false, false, false, false, false, false, false)
+SF(2, 10, MIND_BLAST , false, true , false, false, false, false, false, false, false, false)
+SF(2, 11, BRAIN_SMASH , false, true , false, false, false, false, false, false, false, false)
+SF(2, 12, CAUSE_1 , false, true , true , false, false, false, false, false, false, false)
+SF(2, 13, CAUSE_2 , false, true , true , false, false, false, false, false, false, false)
+SF(2, 14, CAUSE_3 , false, true , true , false, false, false, false, false, false, false)
+SF(2, 15, CAUSE_4 , false, true , true , false, false, false, false, false, false, false)
+SF(2, 16, BO_ACID , false, false, true , true , false, false, false, false, false, false)
+SF(2, 17, BO_ELEC , false, false, true , true , false, false, false, false, false, false)
+SF(2, 18, BO_FIRE , false, false, true , true , false, false, false, false, false, false)
+SF(2, 19, BO_COLD , false, false, true , true , false, false, false, false, false, false)
+SF(2, 20, BO_POIS , false, false, true , true , false, false, false, false, false, false)
+SF(2, 21, BO_NETH , false, false, true , true , false, false, false, false, false, false)
+SF(2, 22, BO_WATE , false, false, true , true , false, false, false, false, false, false)
+SF(2, 23, BO_MANA , false, false, true , true , false, false, false, false, false, false)
+SF(2, 24, BO_PLAS , false, false, true , true , false, false, false, false, false, false)
+SF(2, 25, BO_ICEE , false, false, true , true , false, false, false, false, false, false)
+SF(2, 26, MISSILE , false, false, true , true , false, false, false, false, false, false)
+SF(2, 27, SCARE , false, true , false, false, true , false, false, false, false, false)
+SF(2, 28, BLIND , false, true , false, false, true , false, false, false, false, false)
+SF(2, 29, CONF , false, true , false, false, true , false, false, false, false, false)
+SF(2, 30, SLOW , false, true , false, false, true , false, false, false, false, false)
+SF(2, 31, HOLD , false, true , false, false, true , false, false, false, false, false)
+SF(3, 0, HASTE , false, false, false, false, true , false, false, false, true , false)
+SF(3, 1, HAND_DOOM , false, false, true , false, false, false, false, false, false, false)
+SF(3, 2, HEAL , false, false, false, false, true , false, false, false, false, true )
+SF(3, 3, S_ANIMALS , true , false, false, false, true , false, false, false, false, false)
+SF(3, 4, BLINK , false, false, false, false, true , false, true , true , false, false)
+SF(3, 5, TPORT , false, false, false, false, true , false, true , false, false, false)
+SF(3, 6, TELE_TO , false, true , false, false, false, false, false, false, false, false)
+SF(3, 7, TELE_AWAY , false, false, false, false, true , false, true , false, false, false)
+SF(3, 8, TELE_LEVEL , false, false, false, false, true , false, true , false, false, false)
+SF(3, 9, DARKNESS , false, true , false, false, false, false, false, false, false, false)
+SF(3, 11, FORGET , false, true , false, false, false, false, false, false, false, false)
+SF(3, 12, RAISE_DEAD , false, false, false, false, false, false, false, false, false, false)
+SF(3, 13, S_BUG , true , false, false, false, true , false, false, false, false, false)
+SF(3, 14, S_RNG , true , false, false, false, true , false, false, false, false, false)
+SF(3, 15, S_THUNDERLORD, true , false, false, false, true , false, false, false, false, false)
+SF(3, 16, S_KIN , true , false, false, false, true , false, false, false, false, false)
+SF(3, 17, S_HI_DEMON , true , false, false, false, true , false, false, false, false, false)
+SF(3, 18, S_MONSTER , true , false, false, false, true , false, false, false, false, false)
+SF(3, 19, S_MONSTERS , true , false, false, false, true , false, false, false, false, false)
+SF(3, 20, S_ANT , true , false, false, false, true , false, false, false, false, false)
+SF(3, 21, S_SPIDER , true , false, false, false, true , false, false, false, false, false)
+SF(3, 22, S_HOUND , true , false, false, false, true , false, false, false, false, false)
+SF(3, 23, S_HYDRA , true , false, false, false, true , false, false, false, false, false)
+SF(3, 24, S_ANGEL , true , false, false, false, true , false, false, false, false, false)
+SF(3, 25, S_DEMON , true , false, false, false, true , false, false, false, false, false)
+SF(3, 26, S_UNDEAD , true , false, false, false, true , false, false, false, false, false)
+SF(3, 27, S_DRAGON , true , false, false, false, true , false, false, false, false, false)
+SF(3, 28, S_HI_UNDEAD , true , false, false, false, true , false, false, false, false, false)
+SF(3, 29, S_HI_DRAGON , true , false, false, false, true , false, false, false, false, false)
+SF(3, 30, S_WRAITH , true , false, false, false, true , false, false, false, false, false)
+SF(3, 31, S_UNIQUE , true , false, false, false, true , false, false, false, false, false)
diff --git a/src/monster_spell_flag_set.hpp b/src/monster_spell_flag_set.hpp
new file mode 100644
index 00000000..37d31665
--- /dev/null
+++ b/src/monster_spell_flag_set.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "flag_set.hpp"
+
+constexpr std::size_t SF_MAX_TIERS = 3;
+
+typedef flag_set<SF_MAX_TIERS> monster_spell_flag_set;
diff --git a/src/monster_type.cc b/src/monster_type.cc
new file mode 100644
index 00000000..5731e430
--- /dev/null
+++ b/src/monster_type.cc
@@ -0,0 +1,8 @@
+#include "monster_type_fwd.hpp"
+#include "monster_type.hpp"
+#include "monster2.hpp"
+
+std::shared_ptr<monster_race> monster_type::race() const
+{
+ return race_info_idx(r_idx, ego);
+}
diff --git a/src/monster_type.hpp b/src/monster_type.hpp
new file mode 100644
index 00000000..ed6d3d2a
--- /dev/null
+++ b/src/monster_type.hpp
@@ -0,0 +1,94 @@
+#pragma once
+
+#include "h-basic.h"
+#include "monster_blow.hpp"
+#include "monster_race_fwd.hpp"
+
+#include <array>
+#include <cassert>
+#include <vector>
+#include <memory>
+
+/**
+ * Monster information for a specific monster.
+ *
+ * Note: fy, fx constrain dungeon size to 256x256
+ *
+ * The "hold_o_idx" field points to the first object of a stack
+ * of objects (if any) being carried by the monster (see above).
+ */
+struct monster_type
+{
+ s16b r_idx = 0; /* Monster race index */
+
+ u16b ego = 0; /* Ego monster type */
+
+ byte fy = 0; /* Y location on map */
+ byte fx = 0; /* X location on map */
+
+ s32b hp = 0; /* Current Hit points */
+ s32b maxhp = 0; /* Max Hit points */
+
+ std::array<monster_blow, 4> blow {};/* Up to four blows per round */
+
+ byte speed = 0; /* Speed (normally 110) */
+ byte level = 0; /* Level of creature */
+ s16b ac = 0; /* Armour Class */
+ s32b exp = 0; /* Experience */
+
+ s16b csleep = 0; /* Inactive counter */
+
+ byte mspeed = 0; /* Monster "speed" */
+ byte energy = 0; /* Monster "energy" */
+
+ byte stunned = 0; /* Monster is stunned */
+ byte confused = 0; /* Monster is confused */
+ byte monfear = 0; /* Monster is afraid */
+
+ s16b bleeding = 0; /* Monster is bleeding */
+ s16b poisoned = 0; /* Monster is poisoned */
+
+ byte cdis = 0; /* Current dis from player */
+
+ s32b mflag = 0; /* Extra monster flags */
+
+ bool_ ml = FALSE; /* Monster is "visible" */
+
+ std::vector<s16b> hold_o_idxs { }; /* Objects being held */
+
+ u32b smart = 0; /* Field for "smart_learn" */
+
+ s16b status = 0; /* Status(friendly, pet, companion, ..) */
+
+ s16b target = 0; /* Monster target */
+
+ s16b possessor = 0; /* Is it under the control of a possessor ? */
+
+ /**
+ * @brief get the "effective race" of the monster. This incorporates
+ * the effects of the "ego" of the monster, if any.
+ */
+ std::shared_ptr<monster_race> race() const;
+
+ /**
+ * @brief wipe the object's state
+ */
+ void wipe()
+ {
+ /* Reset to defaults */
+ *this = monster_type();
+ }
+
+ /**
+ * Get the o_idx of the object being mimicked
+ */
+ s16b mimic_o_idx() const
+ {
+ // We *should* also assert that the monster has flag RF9_MIMIC,
+ // but it's currently not safe since the functions we need for
+ // that are a) expensive, and b) side-effecting via statics.
+ assert(hold_o_idxs.size() == 1); // Mimics are defined by exactly one object
+ return hold_o_idxs.front();
+ }
+
+};
diff --git a/src/monster_type_fwd.hpp b/src/monster_type_fwd.hpp
new file mode 100644
index 00000000..a44baa9d
--- /dev/null
+++ b/src/monster_type_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct monster_type;
diff --git a/src/move_info_type.hpp b/src/move_info_type.hpp
new file mode 100644
index 00000000..5f8aa3d8
--- /dev/null
+++ b/src/move_info_type.hpp
@@ -0,0 +1,15 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * Movement typse
+ */
+struct move_info_type
+{
+ s16b to_speed;
+ s16b to_search;
+ s16b to_stealth;
+ s16b to_percep;
+ cptr name;
+};
diff --git a/src/music.hpp b/src/music.hpp
new file mode 100644
index 00000000..5f37c570
--- /dev/null
+++ b/src/music.hpp
@@ -0,0 +1,17 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * Music descriptor.
+ */
+struct music
+{
+ char desc[80]; /* Desc of the music */
+ s16b music; /* Music. */
+ s16b dur; /* Duration(if any) */
+ s16b init_recharge; /* Minimal recharge time */
+ s16b turn_recharge; /* Recharge time for each more turn */
+ byte min_inst; /* Minimum instrument for the music */
+ byte rarity; /* Rarity of the music(use 100 to unallow to be randomly generated) */
+};
diff --git a/src/notes.c b/src/notes.cc
index 3504f61c..17990992 100644
--- a/src/notes.c
+++ b/src/notes.cc
@@ -1,7 +1,3 @@
-/* File: notes.c */
-
-/* Purpose: Note taking to a file */
-
/*
* Copyright (c) 1989, 1999 James E. Wilson, Robert A. Koeneke,
* Robert Ruehlmann
@@ -11,19 +7,28 @@
* included in all such copies.
*/
-#include "angband.h"
+#include "notes.hpp"
+
+#include "files.hpp"
+#include "game.hpp"
+#include "player_class.hpp"
+#include "player_type.hpp"
+#include "util.hpp"
+#include "util.h"
+#include "variable.h"
+#include "variable.hpp"
/*
* Show the notes file on the screen
*/
-void show_notes_file(void)
+void show_notes_file()
{
char basename[13];
char buf[1024];
char caption[10 + 13];
/* Hack -- extract first 8 characters of name and append an extension */
- (void)strnfmt(basename, sizeof(basename), "%.8s.nte", player_base);
+ strnfmt(basename, sizeof(basename), "%.8s.nte", game->player_base.c_str());
basename[sizeof(basename) - 1] = '\0';
/* Build the path */
@@ -33,7 +38,7 @@ void show_notes_file(void)
sprintf(caption, "Note file %s", basename);
/* Invoke show_file */
- (void)show_file(buf, caption, 0, 0);
+ show_file(buf, caption);
/* Done */
return;
@@ -43,17 +48,14 @@ void show_notes_file(void)
* Output a string to the notes file.
* This is the only function that references that file.
*/
-void output_note(char *final_note)
+void output_note(const char *final_note)
{
FILE *fff;
char basename[13];
char buf[1024];
- /* File type is "TEXT" */
- FILE_TYPE(FILE_TYPE_TEXT);
-
/* Hack -- extract first 8 characters of name and append an extension */
- (void)strnfmt(basename, sizeof(basename), "%.8s.nte", player_base);
+ strnfmt(basename, sizeof(basename), "%.8s.nte", game->player_base.c_str());
basename[sizeof(basename) - 1] = '\0';
/* Build the path */
@@ -66,7 +68,7 @@ void output_note(char *final_note)
if (!fff) return;
/* Add note, and close note file */
- my_fputs(fff, final_note, 0);
+ fprintf(fff, "%s\n", final_note);
/* Close the handle */
my_fclose(fff);
@@ -85,25 +87,22 @@ void add_note(char *note, char code)
{
char buf[100];
char final_note[100];
- char long_day[50];
+ char turn_s[50];
char depths[32];
/* Get the first 60 chars - so do not have an overflow */
- C_WIPE(buf, 100, char);
+ memset(buf, 0, sizeof(buf));
strncpy(buf, note, 60);
/* Get date and time */
- sprintf(long_day, "%ld:%02ld %s, %s", (long int) ((bst(HOUR, turn) % 12 == 0) ? 12 : (bst(HOUR, turn) % 12)),
- (long int) bst(MINUTE, turn), (bst(HOUR, turn) < 12) ? "AM" : "PM", get_month_name(bst(DAY, turn), FALSE,
- FALSE));
+ sprintf(turn_s, "Turn % 12ld", static_cast<long int>(turn));
/* Get depth */
if (!dun_level) strcpy(depths, " Town");
- else if (depth_in_feet) sprintf(depths, "%4dft", dun_level * 50);
else sprintf(depths, "Lev%3d", dun_level);
/* Make note */
- sprintf(final_note, "%-20s %s %c: %s", long_day, depths, code, buf);
+ sprintf(final_note, "%-20s %s %c: %s", turn_s, depths, code, buf);
/* Output to the notes file */
output_note(final_note);
@@ -115,17 +114,15 @@ void add_note(char *note, char code)
*/
void add_note_type(int note_number)
{
- char long_day[50], true_long_day[50];
+ auto const &class_info = game->edit_data.class_info;
+
+ char true_long_day[50];
char buf[1024];
time_t ct = time((time_t*)0);
/* Get the date */
strftime(true_long_day, 30, "%Y-%m-%d at %H:%M:%S", localtime(&ct));
- /* Get the date */
- sprintf(buf, "%ld", (long int) (bst(YEAR, turn) + START_YEAR));
- sprintf(long_day, "%ld:%02ld %s the %s of III %s", (long int) ((bst(HOUR, turn) % 12 == 0) ? 12 : (bst(HOUR, turn) % 12)), (long int) bst(MINUTE, turn), (bst(HOUR, turn) < 12) ? "AM" : "PM", get_month_name(bst(DAY, turn), FALSE, FALSE), buf);
-
/* Work out what to do */
switch (note_number)
{
@@ -135,7 +132,11 @@ void add_note_type(int note_number)
char player[100];
/* Build the string containing the player information */
- sprintf(player, "the %s %s", get_player_race_name(p_ptr->prace, p_ptr->pracem), class_info[p_ptr->pclass].spec[p_ptr->pspec].title + c_name);
+ auto const player_race_name = get_player_race_name(p_ptr->prace, p_ptr->pracem);
+ sprintf(player,
+ "the %s %s",
+ player_race_name.c_str(),
+ class_info[p_ptr->pclass].spec[p_ptr->pspec].title);
/* Add in "character start" information */
sprintf(buf,
@@ -144,7 +145,7 @@ void add_note_type(int note_number)
"%s %s\n"
"Born on %s\n"
"================================================\n",
- player_name, player, true_long_day);
+ game->player_name.c_str(), player, true_long_day);
break;
}
@@ -155,7 +156,7 @@ void add_note_type(int note_number)
"%s slew Morgoth on %s\n"
"Long live %s!\n"
"================================================",
- player_name, long_day, player_name);
+ game->player_name.c_str(), true_long_day, game->player_name.c_str());
break;
}
diff --git a/src/notes.hpp b/src/notes.hpp
new file mode 100644
index 00000000..5c182858
--- /dev/null
+++ b/src/notes.hpp
@@ -0,0 +1,6 @@
+#pragma once
+
+void show_notes_file();
+void output_note(char const *final_note);
+void add_note(char *note, char code);
+void add_note_type(int note_number);
diff --git a/src/obj_theme.hpp b/src/obj_theme.hpp
new file mode 100644
index 00000000..d10d17fa
--- /dev/null
+++ b/src/obj_theme.hpp
@@ -0,0 +1,52 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * Object theme. Probability in percent for each class of
+ * objects to be dropped.
+ */
+struct obj_theme
+{
+ byte treasure = 0;
+ byte combat = 0;
+ byte magic = 0;
+ byte tools = 0;
+
+ bool operator == (obj_theme const &other) const
+ {
+ return
+ (treasure == other.treasure) &&
+ (combat == other.combat) &&
+ (magic == other.magic) &&
+ (tools == other.tools);
+ }
+
+ bool operator != (obj_theme const &other) const
+ {
+ return !(*this == other);
+ }
+
+ static constexpr obj_theme no_theme()
+ {
+ return equal_spread(100);
+ }
+
+ static constexpr obj_theme defaults()
+ {
+ return equal_spread(20);
+ }
+
+private:
+
+ static constexpr obj_theme equal_spread(byte v)
+ {
+ obj_theme ot;
+ ot.treasure = v;
+ ot.combat = v;
+ ot.magic = v;
+ ot.tools = v;
+ return ot;
+ }
+
+};
diff --git a/src/obj_theme_fwd.hpp b/src/obj_theme_fwd.hpp
new file mode 100644
index 00000000..6c0d19a3
--- /dev/null
+++ b/src/obj_theme_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct obj_theme;
diff --git a/src/object.pkg b/src/object.pkg
deleted file mode 100644
index a89dad9a..00000000
--- a/src/object.pkg
+++ /dev/null
@@ -1,1169 +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
-
-/* The "sval" codes for TV_DAEMON_BOOK */
-#define SV_DEMONBLADE 55
-#define SV_DEMONSHIELD 56
-#define SV_DEMONHORN 57
-
-/*
- * 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 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);
-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/object1.c b/src/object1.cc
index fef7fb85..3fb2ef26 100644
--- a/src/object1.c
+++ b/src/object1.cc
@@ -1,7 +1,3 @@
-/* File: object1.c */
-
-/* Purpose: Object code, part 1 */
-
/*
* Copyright (c) 1989 James E. Wilson, Robert A. Koeneke
*
@@ -10,8 +6,64 @@
* included in all such copies.
*/
-#include "angband.h"
-
+#include "object1.hpp"
+
+#include "artifact_type.hpp"
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "cmd2.hpp"
+#include "cmd6.hpp"
+#include "dungeon.hpp"
+#include "dungeon_info_type.hpp"
+#include "ego_item_type.hpp"
+#include "feature_type.hpp"
+#include "files.hpp"
+#include "game.hpp"
+#include "hook_get_in.hpp"
+#include "hooks.hpp"
+#include "lua_bind.hpp"
+#include "mimic.hpp"
+#include "monster1.hpp"
+#include "monster2.hpp"
+#include "monster_ego.hpp"
+#include "monster_race.hpp"
+#include "monster_race_flag.hpp"
+#include "monster_type.hpp"
+#include "object2.hpp"
+#include "object_flag.hpp"
+#include "object_flag_meta.hpp"
+#include "object_flag_set.hpp"
+#include "object_kind.hpp"
+#include "object_type.hpp"
+#include "options.hpp"
+#include "player_race.hpp"
+#include "player_race_mod.hpp"
+#include "player_type.hpp"
+#include "set_type.hpp"
+#include "skills.hpp"
+#include "spell_type.hpp"
+#include "spells5.hpp"
+#include "squeltch.hpp"
+#include "stats.hpp"
+#include "store_info_type.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "util.h"
+#include "variable.h"
+#include "variable.hpp"
+#include "wilderness_type_info.hpp"
+#include "xtra1.hpp"
+#include "z-rand.hpp"
+
+#include <boost/algorithm/string/join.hpp>
+#include <boost/algorithm/string/predicate.hpp>
+#include <cassert>
+#include <fmt/format.h>
+#include <utility>
+
+using boost::starts_with;
+
+static void apply_flags_set(s16b a_idx, s16b set_idx, object_flag_set *f);
/*
* Hack -- note that "TERM_MULTI" is now just "TERM_VIOLET".
@@ -24,6 +76,12 @@
#define TERM_MULTI TERM_VIOLET
+/**
+ * Show all equipment/inventory slots, even when empty?
+ */
+static bool item_tester_full;
+
+
/*
* Max sizes of the following arrays
*/
@@ -272,14 +330,8 @@ static char scroll_adj[MAX_TITLES][16];
static byte scroll_col[MAX_TITLES];
-/*
- * Certain items have a flavor
- * This function is used only by "flavor_init()"
- */
-static bool_ object_flavor(int k_idx)
+static byte object_flavor(object_kind const *k_ptr)
{
- object_kind *k_ptr = &k_info[k_idx];
-
/* Analyze the item */
switch (k_ptr->tval)
{
@@ -331,40 +383,7 @@ static bool_ object_flavor(int k_idx)
}
/* No flavor */
- return (0);
-}
-
-
-void get_table_name(char *out_string)
-{
- int testcounter = (randint(3)) + 1;
-
- strcpy(out_string, "'");
-
- if (randint(3) == 2)
- {
- while (testcounter--)
- strcat(out_string, syllables[(randint(MAX_SYLLABLES)) - 1]);
- }
-
- else
- {
- char Syllable[80];
- testcounter = (randint(2)) + 1;
- while (testcounter--)
- {
- get_rnd_line("elvish.txt", Syllable);
- strcat(out_string, Syllable);
- }
- }
-
- out_string[1] = toupper(out_string[1]);
-
- strcat(out_string, "'");
-
- out_string[18] = '\0';
-
- return;
+ return 0;
}
@@ -374,10 +393,8 @@ void get_table_name(char *out_string)
*
* XXX XXX XXX Add "EASY_KNOW" flag to "k_info.txt" file
*/
-static bool_ object_easy_know(int i)
+static bool_ object_easy_know(object_kind const *k_ptr)
{
- object_kind *k_ptr = &k_info[i];
-
/* Analyze the "tval" */
switch (k_ptr->tval)
{
@@ -409,9 +426,8 @@ static bool_ object_easy_know(int i)
case TV_SCROLL:
case TV_ROD:
case TV_ROD_MAIN:
- case TV_BATERIE:
{
- if (k_ptr->flags3 & TR3_NORM_ART)
+ if (k_ptr->flags & TR_NORM_ART)
return ( FALSE );
return (TRUE);
}
@@ -421,7 +437,7 @@ static bool_ object_easy_know(int i)
case TV_AMULET:
case TV_LITE:
{
- if (k_ptr->flags3 & (TR3_EASY_KNOW)) return (TRUE);
+ if (k_ptr->flags & TR_EASY_KNOW) return (TRUE);
return (FALSE);
}
}
@@ -430,6 +446,25 @@ static bool_ object_easy_know(int i)
return (FALSE);
}
+
+
+/**
+ * Shuffle flavor arrays into a random permutation
+ */
+template <std::size_t N>
+static void shuffle_flavors(cptr adj[], byte col[])
+{
+ // The classic Fisher-Yates shuffle
+ for (std::size_t i = N - 1; i > 0; i--)
+ {
+ int j = rand_int(i + 1);
+ std::swap(adj[i], adj[j]);
+ std::swap(col[i], col[j]);
+ }
+}
+
+
+
/*
* Prepare the "variable" part of the "k_info" array.
*
@@ -461,165 +496,73 @@ static bool_ object_easy_know(int i)
*
* Note that the "hacked seed" may provide an RNG with alternating parity!
*/
-void flavor_init(void)
+void flavor_init()
{
- int i, j;
-
- byte temp_col;
-
- cptr temp_adj;
-
-
- /* Hack -- Use the "simple" RNG */
- Rand_quick = TRUE;
+ auto &k_info = game->edit_data.k_info;
/* Hack -- Induce consistant flavors */
- Rand_value = seed_flavor;
-
+ set_quick_rng(seed_flavor());
/* Efficiency -- Rods/Wands share initial array */
- for (i = 0; i < MAX_METALS; i++)
+ for (std::size_t i = 0; i < MAX_METALS; i++)
{
rod_adj[i] = wand_adj[i];
rod_col[i] = wand_col[i];
}
- /* Rings have "ring colors" */
- for (i = 0; i < MAX_ROCKS; i++)
- {
- j = rand_int(MAX_ROCKS);
- temp_adj = ring_adj[i];
- ring_adj[i] = ring_adj[j];
- ring_adj[j] = temp_adj;
- temp_col = ring_col[i];
- ring_col[i] = ring_col[j];
- ring_col[j] = temp_col;
- }
-
- /* Amulets have "amulet colors" */
- for (i = 0; i < MAX_AMULETS; i++)
- {
- j = rand_int(MAX_AMULETS);
- temp_adj = amulet_adj[i];
- amulet_adj[i] = amulet_adj[j];
- amulet_adj[j] = temp_adj;
- temp_col = amulet_col[i];
- amulet_col[i] = amulet_col[j];
- amulet_col[j] = temp_col;
- }
-
- /* Staffs */
- for (i = 0; i < MAX_WOODS; i++)
- {
- j = rand_int(MAX_WOODS);
- temp_adj = staff_adj[i];
- staff_adj[i] = staff_adj[j];
- staff_adj[j] = temp_adj;
- temp_col = staff_col[i];
- staff_col[i] = staff_col[j];
- staff_col[j] = temp_col;
- }
-
- /* Wands */
- for (i = 0; i < MAX_METALS; i++)
- {
- j = rand_int(MAX_METALS);
- temp_adj = wand_adj[i];
- wand_adj[i] = wand_adj[j];
- wand_adj[j] = temp_adj;
- temp_col = wand_col[i];
- wand_col[i] = wand_col[j];
- wand_col[j] = temp_col;
- }
-
- /* Rods */
- for (i = 0; i < MAX_METALS; i++)
- {
- j = rand_int(MAX_METALS);
- temp_adj = rod_adj[i];
- rod_adj[i] = rod_adj[j];
- rod_adj[j] = temp_adj;
- temp_col = rod_col[i];
- rod_col[i] = rod_col[j];
- rod_col[j] = temp_col;
- }
-
- /* Foods (Mushrooms) */
- for (i = 0; i < MAX_SHROOM; i++)
- {
- j = rand_int(MAX_SHROOM);
- temp_adj = food_adj[i];
- food_adj[i] = food_adj[j];
- food_adj[j] = temp_adj;
- temp_col = food_col[i];
- food_col[i] = food_col[j];
- food_col[j] = temp_col;
- }
-
- /* Potions */
- for (i = 4; i < MAX_COLORS; i++)
- {
- j = rand_int(MAX_COLORS - 4) + 4;
- temp_adj = potion_adj[i];
- potion_adj[i] = potion_adj[j];
- potion_adj[j] = temp_adj;
- temp_col = potion_col[i];
- potion_col[i] = potion_col[j];
- potion_col[j] = temp_col;
- }
+ /* Object flavors */
+ shuffle_flavors<MAX_ROCKS>(ring_adj, ring_col);
+ shuffle_flavors<MAX_AMULETS>(amulet_adj, amulet_col);
+ shuffle_flavors<MAX_WOODS>(staff_adj, staff_col);
+ shuffle_flavors<MAX_METALS>(wand_adj, wand_col);
+ shuffle_flavors<MAX_METALS>(rod_adj, rod_col);
+ shuffle_flavors<MAX_SHROOM>(food_adj, food_col);
+ shuffle_flavors<MAX_COLORS - 4>(potion_adj + 4, potion_col + 4);
/* Scrolls (random titles, always white) */
- for (i = 0; i < MAX_TITLES; i++)
+ for (std::size_t i = 0; i < MAX_TITLES; i++)
{
/* Get a new title */
while (TRUE)
{
- char buf[80];
-
- bool_ okay;
-
- /* Start a new title */
- buf[0] = '\0';
+ std::string buf;
/* Collect words until done */
while (1)
{
- int q, s;
-
- char tmp[80];
-
- /* Start a new word */
- tmp[0] = '\0';
-
/* Choose one or two syllables */
- s = ((rand_int(100) < 30) ? 1 : 2);
+ int s = ((rand_int(100) < 30) ? 1 : 2);
/* Add a one or two syllable word */
- for (q = 0; q < s; q++)
+ std::string tmp;
+ for (int q = 0; q < s; q++)
{
- /* Add the syllable */
- strcat(tmp, syllables[rand_int(MAX_SYLLABLES)]);
+ tmp += syllables[rand_int(MAX_SYLLABLES)];
}
/* Stop before getting too long */
- if (strlen(buf) + 1 + strlen(tmp) > 15) break;
-
- /* Add a space */
- strcat(buf, " ");
+ if (buf.size() + tmp.size() + 1 > 15)
+ {
+ break;
+ }
- /* Add the word */
- strcat(buf, tmp);
+ /* Add the word with separator */
+ if (buf.size() > 0)
+ {
+ buf += " ";
+ }
+ buf += tmp;
}
/* Save the title */
- strcpy(scroll_adj[i], buf + 1);
+ strcpy(scroll_adj[i], buf.c_str());
/* Assume okay */
- okay = TRUE;
+ bool_ okay = TRUE;
/* Check for "duplicate" scroll titles */
- for (j = 0; j < i; j++)
+ for (std::size_t j = 0; j < i; j++)
{
cptr hack1 = scroll_adj[j];
cptr hack2 = scroll_adj[i];
@@ -645,26 +588,28 @@ void flavor_init(void)
scroll_col[i] = TERM_WHITE;
}
-
/* Hack -- Use the "complex" RNG */
- Rand_quick = FALSE;
+ set_complex_rng();
/* Analyze every object */
- for (i = 1; i < max_k_idx; i++)
+ for (auto &k_ref: k_info)
{
- object_kind *k_ptr = &k_info[i];
+ auto k_ptr = &k_ref;
/* Skip "empty" objects */
if (!k_ptr->name) continue;
/* Extract "flavor" (if any) */
- k_ptr->flavor = object_flavor(i);
+ k_ptr->flavor = object_flavor(k_ptr);
/* No flavor yields aware */
- if ((!k_ptr->flavor) && (k_ptr->tval != TV_ROD_MAIN)) k_ptr->aware = TRUE;
+ if ((!k_ptr->flavor) && (k_ptr->tval != TV_ROD_MAIN))
+ {
+ k_ptr->aware = TRUE;
+ }
/* Check for "easily known" */
- k_ptr->easy_know = object_easy_know(i);
+ k_ptr->easy_know = object_easy_know(k_ptr);
}
}
@@ -678,152 +623,83 @@ void flavor_init(void)
* flag. This is useful for switching "graphics" on/off.
*
* The features, objects, and monsters, should all be encoded in the
- * relevant "font.pref" and/or "graf.prf" files. XXX XXX XXX
+ * relevant "font.pref". XXX XXX XXX
*
* The "prefs" parameter is no longer meaningful. XXX XXX XXX
*/
-void reset_visuals(void)
+void reset_visuals()
{
- int i;
+ auto &st_info = game->edit_data.st_info;
+ auto &race_mod_info = game->edit_data.race_mod_info;
+ auto &re_info = game->edit_data.re_info;
+ auto &r_info = game->edit_data.r_info;
+ auto &f_info = game->edit_data.f_info;
+ auto &k_info = game->edit_data.k_info;
/* Extract some info about terrain features */
- for (i = 0; i < max_f_idx; i++)
+ for (auto &f_ref: f_info)
{
- feature_type *f_ptr = &f_info[i];
-
- /* Assume we will use the underlying values */
- f_ptr->x_attr = f_ptr->d_attr;
- f_ptr->x_char = f_ptr->d_char;
+ f_ref.x_attr = f_ref.d_attr;
+ f_ref.x_char = f_ref.d_char;
}
/* Extract default attr/char code for stores */
- for (i = 0; i < max_st_idx; i++)
+ for (auto &st_ref: st_info)
{
- store_info_type *st_ptr = &st_info[i];
-
/* Default attr/char */
- st_ptr->x_attr = st_ptr->d_attr;
- st_ptr->x_char = st_ptr->d_char;
+ st_ref.x_attr = st_ref.d_attr;
+ st_ref.x_char = st_ref.d_char;
}
/* Extract default attr/char code for objects */
- for (i = 0; i < max_k_idx; i++)
+ for (auto &k_ref: k_info)
{
- object_kind *k_ptr = &k_info[i];
-
/* Default attr/char */
- k_ptr->x_attr = k_ptr->d_attr;
- k_ptr->x_char = k_ptr->d_char;
+ k_ref.x_attr = k_ref.d_attr;
+ k_ref.x_char = k_ref.d_char;
}
/* Extract default attr/char code for monsters */
- for (i = 0; i < max_r_idx; i++)
+ for (auto &r_ref: r_info)
{
- monster_race *r_ptr = &r_info[i];
-
/* Default attr/char */
- r_ptr->x_attr = r_ptr->d_attr;
- r_ptr->x_char = r_ptr->d_char;
+ r_ref.x_attr = r_ref.d_attr;
+ r_ref.x_char = r_ref.d_char;
}
/* Reset attr/char code for ego monster overlay graphics */
- for (i = 0; i < max_re_idx; i++)
+ for (auto &re_ref: re_info)
{
- monster_ego *re_ptr = &re_info[i];
-
/* Default attr/char */
- re_ptr->g_attr = 0;
- re_ptr->g_char = 0;
+ re_ref.g_attr = 0;
+ re_ref.g_char = 0;
}
/* Reset attr/char code for race modifier overlay graphics */
- for (i = 0; i < max_rmp_idx; i++)
+ for (auto &rmp: race_mod_info)
{
- player_race_mod *rmp_ptr = &race_mod_info[i];
-
/* Default attr/char */
- rmp_ptr->g_attr = 0;
- rmp_ptr->g_char = 0;
- }
-
- /* Reset attr/char code for trap overlay graphics */
- for (i = 0; i < max_rmp_idx; i++)
- {
- trap_type *t_ptr = &t_info[i];
-
- /* Default attr/char */
- t_ptr->g_attr = 0;
- t_ptr->g_char = 0;
- }
-
-
- if (use_graphics)
- {
- /* Process "graf.prf" */
- process_pref_file("graf.prf");
-
- /*
- * Hack -- remember graphics mode as an integer value,
- * for faster processing of map_info()
- */
-
- /* IBM-PC pseudo-graphics -- not maintained, but the code is there */
- if (streq(ANGBAND_SYS, "ibm"))
- {
- graphics_mode = GRAPHICS_IBM;
- }
-
- /*
- * Isometric view. Also assumes all the attributes of the "new"
- * graphics.
- */
- else if (streq(ANGBAND_GRAF, "iso"))
- {
- graphics_mode = GRAPHICS_ISO;
- }
-
- /*
- * "New" graphics -- supports graphics overlay for traps, ego monsters
- * and player subraces, and has tiles for lighting effects (row + 1
- * and row + 2 for "darker" versions of terrain features)
- */
- else if (streq(ANGBAND_GRAF, "new"))
- {
- graphics_mode = GRAPHICS_NEW;
- }
-
- /*
- * "Old" graphics -- doesn't support graphics overlay and lighting
- * effects
- */
- else if (streq(ANGBAND_GRAF, "old"))
- {
- graphics_mode = GRAPHICS_OLD;
- }
-
- /* ??? */
- else
- {
- graphics_mode = GRAPHICS_UNKNOWN;
- }
+ rmp.g_attr = 0;
+ rmp.g_char = 0;
}
/* Normal symbols */
- else
- {
- /* Process "font.prf" */
- process_pref_file("font.prf");
-
- graphics_mode = GRAPHICS_NONE;
- }
+ process_pref_file("font.prf");
}
/*
* Extract "xtra" flags from object.
*/
-void object_flags_xtra(object_type *o_ptr, u32b *f2, u32b *f3, u32b *esp)
+static void object_flags_xtra(object_type const *o_ptr, object_flag_set *f)
{
+ // Artifacts don't get *ego* extra powers.
+ if (!o_ptr->artifact_name.empty())
+ {
+ return;
+ }
+
+ // Add sustain or power.
switch (o_ptr->xtra1)
{
case EGO_XTRA_SUSTAIN:
@@ -832,22 +708,22 @@ void object_flags_xtra(object_type *o_ptr, u32b *f2, u32b *f3, u32b *esp)
switch (o_ptr->xtra2 % 6)
{
case 0:
- (*f2) |= (TR2_SUST_STR);
+ (*f) |= TR_SUST_STR;
break;
case 1:
- (*f2) |= (TR2_SUST_INT);
+ (*f) |= TR_SUST_INT;
break;
case 2:
- (*f2) |= (TR2_SUST_WIS);
+ (*f) |= TR_SUST_WIS;
break;
case 3:
- (*f2) |= (TR2_SUST_DEX);
+ (*f) |= TR_SUST_DEX;
break;
case 4:
- (*f2) |= (TR2_SUST_CON);
+ (*f) |= TR_SUST_CON;
break;
case 5:
- (*f2) |= (TR2_SUST_CHR);
+ (*f) |= TR_SUST_CHR;
break;
}
@@ -860,135 +736,94 @@ void object_flags_xtra(object_type *o_ptr, u32b *f2, u32b *f3, u32b *esp)
switch (o_ptr->xtra2 % 11)
{
case 0:
- (*f2) |= (TR2_RES_BLIND);
+ (*f) |= TR_RES_BLIND;
break;
case 1:
- (*f2) |= (TR2_RES_CONF);
+ (*f) |= TR_RES_CONF;
break;
case 2:
- (*f2) |= (TR2_RES_SOUND);
+ (*f) |= TR_RES_SOUND;
break;
case 3:
- (*f2) |= (TR2_RES_SHARDS);
+ (*f) |= TR_RES_SHARDS;
break;
case 4:
- (*f2) |= (TR2_RES_NETHER);
+ (*f) |= TR_RES_NETHER;
break;
case 5:
- (*f2) |= (TR2_RES_NEXUS);
+ (*f) |= TR_RES_NEXUS;
break;
case 6:
- (*f2) |= (TR2_RES_CHAOS);
+ (*f) |= TR_RES_CHAOS;
break;
case 7:
- (*f2) |= (TR2_RES_DISEN);
+ (*f) |= TR_RES_DISEN;
break;
case 8:
- (*f2) |= (TR2_RES_POIS);
+ (*f) |= TR_RES_POIS;
break;
case 9:
- (*f2) |= (TR2_RES_DARK);
+ (*f) |= TR_RES_DARK;
break;
case 10:
- (*f2) |= (TR2_RES_LITE);
+ (*f) |= TR_RES_LITE;
break;
}
break;
}
- case EGO_XTRA_ABILITY:
- {
- /* Choose an ability */
- switch (o_ptr->xtra2 % 8)
- {
- case 0:
- (*f3) |= (TR3_FEATHER);
- break;
- case 1:
- (*f3) |= (TR3_LITE1);
- break;
- case 2:
- (*f3) |= (TR3_SEE_INVIS);
- break;
- case 3:
- (*esp) |= (ESP_ALL);
- break;
- case 4:
- (*f3) |= (TR3_SLOW_DIGEST);
- break;
- case 5:
- (*f3) |= (TR3_REGEN);
- break;
- case 6:
- (*f2) |= (TR2_FREE_ACT);
- break;
- case 7:
- (*f2) |= (TR2_HOLD_LIFE);
- break;
- }
-
- break;
- }
-
}
}
+/*
+ * Disregard sets when calculating flags?
+ */
+bool_ object_flags_no_set = FALSE;
/*
* Obtain the "flags" for an item
*/
-bool_ object_flags_no_set = FALSE;
-void object_flags(object_type *o_ptr, u32b *f1, u32b *f2, u32b *f3, u32b *f4, u32b *f5, u32b *esp)
+object_flag_set object_flags(object_type const *o_ptr)
{
- object_kind *k_ptr = &k_info[o_ptr->k_idx];
+ auto const &k_info = game->edit_data.k_info;
+ auto const &a_info = game->edit_data.a_info;
+
+ auto k_ptr = &k_info[o_ptr->k_idx];
/* Base object */
- (*f1) = k_ptr->flags1;
- (*f2) = k_ptr->flags2;
- (*f3) = k_ptr->flags3;
- (*f4) = k_ptr->flags4;
- (*f5) = k_ptr->flags5;
- (*esp) = k_ptr->esp;
+ auto f = k_ptr->flags;
/* Artifact */
if (o_ptr->name1)
{
- artifact_type *a_ptr = &a_info[o_ptr->name1];
+ auto a_ptr = &a_info[o_ptr->name1];
- (*f1) = a_ptr->flags1;
- (*f2) = a_ptr->flags2;
- (*f3) = a_ptr->flags3;
- (*f4) = a_ptr->flags4;
- (*f5) = a_ptr->flags5;
- (*esp) = a_ptr->esp;
+ f = a_ptr->flags;
if ((!object_flags_no_set) && (a_ptr->set != -1))
- apply_flags_set(o_ptr->name1, a_ptr->set, f1, f2, f3, f4, f5, esp);
+ {
+ apply_flags_set(o_ptr->name1, a_ptr->set, &f);
+ }
}
- /* Random artifact ! */
- 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)
- {
- (*f1) |= o_ptr->art_flags1;
- (*f2) |= o_ptr->art_flags2;
- (*f3) |= o_ptr->art_flags3;
- (*f4) |= o_ptr->art_flags4;
- (*f5) |= o_ptr->art_flags5;
- (*esp) |= o_ptr->art_esp;
- }
+ /* Mix in art_{flags,esp} */
+ f |= o_ptr->art_flags;
/* Extra powers */
- if (!(o_ptr->art_name))
- {
- object_flags_xtra(o_ptr, f2, f3, esp);
- }
+ object_flags_xtra(o_ptr, &f);
+
+ return f;
}
/* Return object granted power */
int object_power(object_type *o_ptr)
{
- object_kind *k_ptr = &k_info[o_ptr->k_idx];
+ auto const &k_info = game->edit_data.k_info;
+ auto const &a_info = game->edit_data.a_info;
+ auto const &e_info = game->edit_data.e_info;
+
+ auto k_ptr = &k_info[o_ptr->k_idx];
int power = -1;
/* Base object */
@@ -997,24 +832,33 @@ int object_power(object_type *o_ptr)
/* Ego-item */
if (o_ptr->name2)
{
- ego_item_type *e_ptr = &e_info[o_ptr->name2];
+ auto e_ptr = &e_info[o_ptr->name2];
- if (power == -1) power = e_ptr->power;
+ if (power == -1)
+ {
+ power = e_ptr->power;
+ }
if (o_ptr->name2b)
{
- ego_item_type *e_ptr = &e_info[o_ptr->name2b];
+ auto e_ptr = &e_info[o_ptr->name2b];
- if (power == -1) power = e_ptr->power;
+ if (power == -1)
+ {
+ power = e_ptr->power;
+ }
}
}
/* Artifact */
if (o_ptr->name1)
{
- artifact_type *a_ptr = &a_info[o_ptr->name1];
+ auto a_ptr = &a_info[o_ptr->name1];
- if (power == -1) power = a_ptr->power;
+ if (power == -1)
+ {
+ power = a_ptr->power;
+ }
}
return (power);
@@ -1025,222 +869,107 @@ int object_power(object_type *o_ptr)
/*
* Obtain the "flags" for an item which are known to the player
*/
-void object_flags_known(object_type *o_ptr, u32b *f1, u32b *f2, u32b *f3, u32b *f4, u32b *f5, u32b *esp)
+object_flag_set object_flags_known(object_type const *o_ptr)
{
- bool_ spoil = FALSE;
+ auto const &k_info = game->edit_data.k_info;
+ auto const &a_info = game->edit_data.a_info;
- object_kind *k_ptr = &k_info[o_ptr->k_idx];
-
- /* Clear */
- (*f1) = (*f2) = (*f3) = (*f4) = (*esp) = (*f5) = 0L;
+ auto k_ptr = &k_info[o_ptr->k_idx];
/* Must be identified */
- if (!object_known_p(o_ptr)) return;
+ if (!object_known_p(o_ptr))
+ {
+ return object_flag_set();
+ }
/* Base object */
- (*f1) = k_ptr->flags1;
- (*f2) = k_ptr->flags2;
- (*f3) = k_ptr->flags3;
- (*f4) = k_ptr->flags4;
- (*f5) = k_ptr->flags5;
- (*esp) = k_ptr->esp;
-
- (*f1) |= k_ptr->oflags1;
- (*f2) |= k_ptr->oflags2;
- (*f3) |= k_ptr->oflags3;
- (*f4) |= k_ptr->oflags4;
- (*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 */
+ auto flags = k_ptr->flags;
+
+ /* Obvious flags */
+ flags |= k_ptr->oflags;
/* Artifact */
if (o_ptr->name1)
{
- artifact_type *a_ptr = &a_info[o_ptr->name1];
+ auto 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;
- (*f3) = a_ptr->flags3;
- (*f4) = a_ptr->flags4;
- (*f5) = a_ptr->flags5;
- (*esp) = a_ptr->esp;
+ flags = a_ptr->flags;
if ((!object_flags_no_set) && (a_ptr->set != -1))
- apply_flags_set(o_ptr->name1, a_ptr->set, f1, f2, f3, f4, f5, esp);
+ {
+ apply_flags_set(o_ptr->name1, a_ptr->set, &flags);
+ }
}
else
{
- (*f1) = (*f2) = (*f3) = (*f4) = (*esp) = (*f5) = 0L;
+ flags = object_flag_set();
}
- (*f1) |= a_ptr->oflags1;
- (*f2) |= a_ptr->oflags2;
- (*f3) |= a_ptr->oflags3;
- (*f4) |= a_ptr->oflags4;
- (*f5) |= a_ptr->oflags5;
- (*esp) |= a_ptr->oesp;
+ flags |= a_ptr->oflags;
}
/* Random artifact or ego item! */
- 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)
+ if (o_ptr->art_flags)
{
/* 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;
- (*f3) |= o_ptr->art_flags3;
- (*f4) |= o_ptr->art_flags4;
- (*f5) |= o_ptr->art_flags5;
- (*esp) |= o_ptr->art_esp;
+ flags |= o_ptr->art_flags;
}
- (*f1) |= o_ptr->art_oflags1;
- (*f2) |= o_ptr->art_oflags2;
- (*f3) |= o_ptr->art_oflags3;
- (*f4) |= o_ptr->art_oflags4;
- (*f5) |= o_ptr->art_oflags5;
- (*esp) |= o_ptr->art_oesp;
+ flags |= o_ptr->art_oflags;
}
/* Full knowledge for *identified* objects */
- if (!(o_ptr->ident & IDENT_MENTAL)) return;
-
- if (!(o_ptr->art_name))
+ if (!(o_ptr->ident & IDENT_MENTAL))
{
- object_flags_xtra(o_ptr, f2, f3, esp);
+ return flags;
}
- /* Hack - Res Chaos -> Res Confusion */
- if (*f2 & TR2_RES_CHAOS) (*f2) |= (TR2_RES_CONF);
-}
-
-
-
-
-
-/*
- * Print a char "c" into a string "t", as if by sprintf(t, "%c", c),
- * and return a pointer to the terminator (t + 1).
- */
-static char *object_desc_chr(char *t, char c)
-{
- /* Copy the char */
- *t++ = c;
+ /* Extra powers */
+ object_flags_xtra(o_ptr, &flags);
- /* Terminate */
- *t = '\0';
+ /* Hack - Res Chaos -> Res Confusion */
+ if (flags & TR_RES_CHAOS)
+ {
+ flags |= TR_RES_CONF;
+ }
- /* Result */
- return (t);
+ // Done
+ return flags;
}
-/*
- * Print a string "s" into a string "t", as if by strcpy(t, s),
- * and return a pointer to the terminator.
+/**
+ * Calculate amount of EXP needed for the given object to
+ * level, assuming it's a sentient object.
*/
-static char *object_desc_str(char *t, cptr s)
+s32b calc_object_need_exp(object_type const *o_ptr)
{
- /* Copy the string */
- while (*s) *t++ = *s++;
-
- /* Terminate */
- *t = '\0';
-
- /* Result */
- return (t);
+ return (player_exp[o_ptr->elevel - 1] * 5 / 2);
}
-/*
- * Do the actual conversion of a number for object_desc_num() and
- * object_desc_int().
- */
-static char *convert_number(char *result, u32b num)
-{
- char *tp;
- char temp[11];
-
- tp = temp;
- *tp = '0' + (num % 10);
- for (num /= 10; num != 0; num /= 10)
- {
- *++tp = '0' + (num % 10);
- }
-
- while (tp != temp)
- {
- *result++ = *tp--;
- }
- *result++ = *tp;
- *result = '\0';
-
- return result;
-}
-/*
- * Print a nnumber "n" into a string "t", as if by
- * sprintf(t, "%u", n), and return a pointer to the terminator.
+/**
+ * Calculate the PVAL mask.
*/
-static char *object_desc_num(char *result, s32b num)
+static object_flag_set compute_pval_mask()
{
- u32b n;
-
- if (num < 0)
+ object_flag_set f;
+ for (auto const object_flag_meta: object_flags_meta())
{
- *result++ = '-';
- n = -num;
+ if (object_flag_meta->is_pval)
+ {
+ f |= object_flag_meta->flag_set;
+ }
}
- else
- n = num;
-
- /* Result */
- return convert_number(result, n);
+ return f;
}
-/*
- * Print an signed number "num" into a string "result", as if by
- * sprintf(t, "%+d", n), and return a pointer to the terminator.
- * Note that we always print a sign, either "+" or "-".
- */
-static char *object_desc_int(char *result, s32b num)
-{
- u32b n;
-
- /* Negative */
- if (num < 0)
- {
- /* Take the absolute value */
- n = -num;
-
- /* Use a "minus" sign */
- *result++ = '-';
- }
- /* Positive (or zero) */
- else
- {
- /* Use the actual number */
- n = num;
-
- /* Use a "plus" sign */
- *result++ = '+';
- }
- /* Result */
- return convert_number(result, n);
-}
/*
* Creates a description of the item "o_ptr", and stores it in "out_val".
@@ -1287,55 +1016,41 @@ static char *object_desc_int(char *result, s32b num)
* 2 -- The Cloak of Death [1,+3] (+2 to Stealth)
* 3 -- The Cloak of Death [1,+3] (+2 to Stealth) {nifty}
*/
-void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
+static std::string object_desc_aux(object_type const *o_ptr, int pref, int mode)
{
- bool_ hack_name = FALSE;
- cptr basenm, modstr;
- int indexx;
+ auto const &r_info = game->edit_data.r_info;
+ auto const &k_info = game->edit_data.k_info;
+ auto const &a_info = game->edit_data.a_info;
+ auto const &e_info = game->edit_data.e_info;
+ auto const &random_artifacts = game->random_artifacts;
+ static auto const TR_PVAL_MASK = compute_pval_mask();
- bool_ aware = FALSE;
- bool_ known = FALSE;
+ bool_ hack_name = FALSE;
bool_ append_name = FALSE;
bool_ show_weapon = FALSE;
bool_ show_armour = FALSE;
- cptr s, u;
- char *t;
-
- char p1 = '(', p2 = ')';
- char b1 = '[', b2 = ']';
- char c1 = '{', c2 = '}';
-
- char tmp_val[160];
- char tmp_val2[90];
-
- s32b power;
- u32b f1, f2, f3, f4, f5, esp;
-
- object_kind *k_ptr = &k_info[o_ptr->k_idx];
-
- cptr str;
+ auto k_ptr = &k_info[o_ptr->k_idx];
/* Extract some flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
-
+ auto const flags = object_flags(o_ptr);
/* See if the object is "aware" */
- if (object_aware_p(o_ptr)) aware = TRUE;
+ bool_ aware = object_aware_p(o_ptr);
/* See if the object is "known" */
- if (object_known_p(o_ptr)) known = TRUE;
+ bool_ known = object_known_p(o_ptr);
/* Hack -- Extract the sub-type "indexx" */
- indexx = o_ptr->sval;
+ auto const indexx = o_ptr->sval;
/* Extract default "base" string */
- basenm = (k_name + k_ptr->name);
+ std::string basenm(k_ptr->name);
/* Assume no "modifier" string */
- modstr = "";
+ std::string modstr;
/* Analyze the object */
switch (o_ptr->tval)
@@ -1371,14 +1086,6 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
break;
}
- /* Trapping Kits */
- case TV_TRAPKIT:
- {
- modstr = basenm;
- basenm = "& # Trap Set~";
- break;
- }
-
/* Armour */
case TV_BOOTS:
case TV_GLOVES:
@@ -1407,12 +1114,15 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
modstr = amulet_adj[indexx];
if (aware) append_name = TRUE;
- if (((plain_descriptions) && (aware)) || o_ptr->ident & IDENT_STOREB)
+ if (aware || o_ptr->ident & IDENT_STOREB)
basenm = "& Amulet~";
else
basenm = aware ? "& # Amulet~" : "& # Amulet~";
- if (known && !o_ptr->art_name && artifact_p(o_ptr)) basenm = k_ptr->name + k_name;
+ if (known && o_ptr->artifact_name.empty() && artifact_p(o_ptr))
+ {
+ basenm = k_ptr->name;
+ }
break;
}
@@ -1424,7 +1134,7 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
modstr = ring_adj[indexx];
if (aware) append_name = TRUE;
- if (((plain_descriptions) && (aware)) || o_ptr->ident & IDENT_STOREB)
+ if (aware || o_ptr->ident & IDENT_STOREB)
basenm = "& Ring~";
else
basenm = aware ? "& # Ring~" : "& # Ring~";
@@ -1432,7 +1142,10 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
/* Hack -- The One Ring */
if (!aware && (o_ptr->sval == SV_RING_POWER)) modstr = "Plain Gold";
- if (known && !o_ptr->art_name && artifact_p(o_ptr)) basenm = k_ptr->name + k_name;
+ if (known && o_ptr->artifact_name.empty() && artifact_p(o_ptr))
+ {
+ basenm = k_ptr->name;
+ }
break;
}
@@ -1442,7 +1155,7 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
/* Color the object */
modstr = staff_adj[o_ptr->pval2 % MAX_WOODS];
if (aware) append_name = TRUE;
- if (((plain_descriptions) && (aware)) || o_ptr->ident & IDENT_STOREB)
+ if (aware || o_ptr->ident & IDENT_STOREB)
basenm = "& Staff~";
else
basenm = "& # Staff~";
@@ -1454,7 +1167,7 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
/* Color the object */
modstr = wand_adj[o_ptr->pval2 % MAX_METALS];
if (aware) append_name = TRUE;
- if (((plain_descriptions) && (aware)) || o_ptr->ident & IDENT_STOREB)
+ if (aware || o_ptr->ident & IDENT_STOREB)
basenm = "& Wand~";
else
basenm = "& # Wand~";
@@ -1466,7 +1179,7 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
/* Color the object */
modstr = rod_adj[indexx];
if (aware) append_name = TRUE;
- if (((plain_descriptions) && (aware)) || o_ptr->ident & IDENT_STOREB)
+ if (aware || o_ptr->ident & IDENT_STOREB)
basenm = "& Rod Tip~";
else
basenm = aware ? "& # Rod Tip~" : "& # Rod Tip~";
@@ -1480,9 +1193,7 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
case TV_ROD_MAIN:
{
- object_kind *tip_ptr = &k_info[lookup_kind(TV_ROD, o_ptr->pval)];
-
- modstr = k_name + tip_ptr->name;
+ modstr = k_info[lookup_kind(TV_ROD, o_ptr->pval)].name;
break;
}
@@ -1491,7 +1202,7 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
/* Color the object */
modstr = scroll_adj[indexx];
if (aware) append_name = TRUE;
- if (((plain_descriptions) && (aware)) || o_ptr->ident & IDENT_STOREB)
+ if (aware || o_ptr->ident & IDENT_STOREB)
basenm = "& Scroll~";
else
basenm = aware ? "& Scroll~ titled \"#\"" : "& Scroll~ titled \"#\"";
@@ -1509,9 +1220,9 @@ 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)
+ if (aware || o_ptr->ident & IDENT_STOREB)
basenm = "& Potion~";
else
basenm = aware ? "& # Potion~" : "& # Potion~";
@@ -1526,7 +1237,7 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
/* Color the object */
modstr = food_adj[indexx];
if (aware) append_name = TRUE;
- if (((plain_descriptions) && (aware)) || o_ptr->ident & IDENT_STOREB)
+ if (aware || o_ptr->ident & IDENT_STOREB)
basenm = "& Mushroom~";
else
basenm = aware ? "& # Mushroom~" : "& # Mushroom~";
@@ -1540,7 +1251,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;
}
@@ -1568,13 +1279,6 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
break;
}
- case TV_BATERIE:
- {
- modstr = basenm;
- basenm = "& Essence~ of #";
- break;
- }
-
case TV_PARCHMENT:
{
modstr = basenm;
@@ -1586,54 +1290,57 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
/* Hack -- Gold/Gems */
case TV_GOLD:
{
- strcpy(buf, basenm);
- return;
+ return basenm;
}
case TV_CORPSE:
{
- monster_race* r_ptr = &r_info[o_ptr->pval2];
+ auto r_ptr = &r_info[o_ptr->pval2];
+
modstr = basenm;
- if (r_ptr->flags1 & RF1_UNIQUE)
- basenm = format("& %s's #~", r_name + r_ptr->name);
+ if (r_ptr->flags & RF_UNIQUE)
+ {
+ basenm = fmt::format("& {}'s #~", r_ptr->name);
+ }
else
- basenm = format("& %s #~", r_name + r_ptr->name);
+ {
+ basenm = fmt::format("& {} #~", r_ptr->name);
+ }
break;
}
case TV_EGG:
{
- monster_race* r_ptr = &r_info[o_ptr->pval2];
- modstr = basenm;
+ auto r_ptr = &r_info[o_ptr->pval2];
- basenm = format("& %s #~", r_name + r_ptr->name);
+ modstr = basenm;
+ basenm = fmt::format("& {} #~", r_ptr->name);
break;
}
case TV_HYPNOS:
{
/* We print hit points further down. --dsb */
- monster_race* r_ptr = &r_info[o_ptr->pval];
+ auto r_ptr = &r_info[o_ptr->pval];
+
modstr = basenm;
- basenm = format("& %s~", r_name + r_ptr->name);
+ basenm = fmt::format("& {}~", r_ptr->name);
break;
}
case TV_TOTEM:
{
- char name[80];
monster_type monster;
-
- monster.sr_ptr = 0;
monster.r_idx = o_ptr->pval;
monster.ego = o_ptr->pval2;
monster.ml = TRUE;
monster.status = MSTATUS_ENEMY;
+ char name[80];
monster_desc(name, &monster, 0x188);
modstr = basenm;
- basenm = format("& #~ of %s", name);
+ basenm = fmt::format("& #~ of {}", name);
break;
}
@@ -1652,83 +1359,57 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
break;
}
- case TV_RUNE2:
- {
- if (o_ptr->sval != RUNE_STONE)
- {
- modstr = basenm;
- basenm = "& Rune~ [#]";
- }
- break;
- }
-
- case TV_RUNE1:
- {
- modstr = basenm;
- basenm = "& Rune~ [#]";
- break;
- }
-
case TV_DAEMON_BOOK:
case TV_BOOK:
{
- basenm = k_name + k_ptr->name;
- if (o_ptr->sval == 255) modstr = school_spells[o_ptr->pval].name;
+ basenm = k_ptr->name;
+ if (o_ptr->sval == 255)
+ {
+ modstr = spell_type_name(spell_at(o_ptr->pval));
+ }
break;
}
/* Used in the "inventory" routine */
default:
- {
- if (process_hooks_ret(HOOK_ITEM_NAME, "ss", "(O,s,s)",
- o_ptr, basenm, modstr))
- {
- basenm = process_hooks_return[0].str;
- modstr = process_hooks_return[1].str;
- break;
- }
- else
- {
- strcpy(buf, "(nothing)");
- return;
- }
- }
+ return "(nothing)";
}
/* Mega Hack */
- if ((!hack_name) && known && (k_ptr->flags5 & TR5_FULL_NAME)) basenm = (k_name + k_ptr->name);
+ if ((!hack_name) && known && (k_ptr->flags & TR_FULL_NAME))
+ {
+ basenm = k_ptr->name;
+ }
+ /* Copy of the base string _without_ a prefix */
+ std::string s;
/* Start dumping the result */
- t = tmp_val;
+ std::string t;
/* The object "expects" a "number" */
- if (basenm[0] == '&')
+ if (starts_with(basenm, "&"))
{
- monster_race* r_ptr;
cptr ego = NULL;
- if (o_ptr->tval == TV_CORPSE) r_ptr = &r_info[o_ptr->pval2];
- else r_ptr = &r_info[o_ptr->pval];
-
/* Grab any ego-item name */
if (known && (o_ptr->name2 || o_ptr->name2b) && (o_ptr->tval != TV_ROD_MAIN))
{
- ego_item_type *e_ptr = &e_info[o_ptr->name2];
- ego_item_type *e2_ptr = &e_info[o_ptr->name2b];
+ auto e_ptr = &e_info[o_ptr->name2];
+ auto e2_ptr = &e_info[o_ptr->name2b];
if (e_ptr->before)
{
- ego = e_ptr->name + e_name;
+ ego = e_ptr->name;
}
else if (e2_ptr->before)
{
- ego = e2_ptr->name + e_name;
+ ego = e2_ptr->name;
}
}
/* Skip the ampersand (and space) */
- s = basenm + 2;
+ s = basenm.substr(2);
/* No prefix */
if (pref <= 0)
@@ -1739,74 +1420,77 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
/* Hack -- None left */
else if (o_ptr->number <= 0)
{
- t = object_desc_str(t, "no more ");
+ t += "no more ";
}
/* Extract the number */
else if (o_ptr->number > 1)
{
- t = object_desc_num(t, o_ptr->number);
- t = object_desc_chr(t, ' ');
+ t += std::to_string(o_ptr->number);
+ t += ' ';
}
- else if ((o_ptr->tval == TV_CORPSE) && (r_ptr->flags1 & RF1_UNIQUE))
- {}
-
+ else if ((o_ptr->tval == TV_CORPSE) && (r_info[o_ptr->pval2].flags & RF_UNIQUE))
+ {
+ /* Nothing */
+ }
- else if ((o_ptr->tval == TV_HYPNOS) && (r_ptr->flags1 & RF1_UNIQUE))
- {}
+ else if ((o_ptr->tval == TV_HYPNOS) && (r_info[o_ptr->pval].flags & RF_UNIQUE))
+ {
+ /* Nothing */
+ }
/* Hack -- The only one of its kind */
- else if (known && (artifact_p(o_ptr) || o_ptr->art_name))
+ else if (known && artifact_p(o_ptr))
{
- t = object_desc_str(t, "The ");
+ t += "The ";
}
else if (ego != NULL)
{
if (is_a_vowel(ego[0]))
{
- t = object_desc_str(t, "an ");
+ t += "an ";
}
else
{
- t = object_desc_str(t, "a ");
+ t += "a ";
}
}
/* A single one, with a vowel in the modifier */
- else if ((*s == '#') && (is_a_vowel(modstr[0])))
+ else if ((s[0] == '#') && (is_a_vowel(modstr[0])))
{
- t = object_desc_str(t, "an ");
+ t += "an ";
}
/* A single one, with a vowel */
- else if (is_a_vowel(*s))
+ else if (is_a_vowel(s[0]))
{
- t = object_desc_str(t, "an ");
+ t += "an ";
}
/* A single one, without a vowel */
else
{
- t = object_desc_str(t, "a ");
+ t += "a ";
}
/* Grab any ego-item name */
if (known && (o_ptr->name2 || o_ptr->name2b) && (o_ptr->tval != TV_ROD_MAIN))
{
- ego_item_type *e_ptr = &e_info[o_ptr->name2];
- ego_item_type *e2_ptr = &e_info[o_ptr->name2b];
+ auto e_ptr = &e_info[o_ptr->name2];
+ auto e2_ptr = &e_info[o_ptr->name2b];
if (e_ptr->before)
{
- t = object_desc_str(t, (e_name + e_ptr->name));
- t = object_desc_chr(t, ' ');
+ t += e_ptr->name;
+ t += ' ';
}
if (e2_ptr->before)
{
- t = object_desc_str(t, (e_name + e2_ptr->name));
- t = object_desc_chr(t, ' ');
+ t += e2_ptr->name;
+ t += ' ';
}
}
@@ -1814,16 +1498,10 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
/* Dagger inscribed {@w0%Smelly} will be named
* Smelly Dagger {@w0} */
- if (o_ptr->note)
+ if (auto str = strchr(o_ptr->inscription.c_str(), '%'))
{
- str = strchr(quark_str(o_ptr->note), '%');
-
- /* Add the false name */
- if (str)
- {
- t = object_desc_str(t, &str[1]);
- t = object_desc_chr(t, ' ');
- }
+ t += &str[1];
+ t += ' ';
}
}
@@ -1843,14 +1521,14 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
/* Hack -- all gone */
else if (o_ptr->number <= 0)
{
- t = object_desc_str(t, "no more ");
+ t += "no more ";
}
/* Prefix a number if required */
else if (o_ptr->number > 1)
{
- t = object_desc_num(t, o_ptr->number);
- t = object_desc_chr(t, ' ');
+ t += std::to_string(o_ptr->number);
+ t += ' ';
}
else if (o_ptr->tval == TV_RANDART)
@@ -1859,9 +1537,9 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
}
/* Hack -- The only one of its kind */
- else if (known && (artifact_p(o_ptr) || o_ptr->art_name))
+ else if (known && artifact_p(o_ptr))
{
- t = object_desc_str(t, "The ");
+ t += "The ";
}
/* Hack -- single items get no prefix */
@@ -1873,100 +1551,92 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
/* Grab any ego-item name */
if (known && (o_ptr->name2 || o_ptr->name2b) && (o_ptr->tval != TV_ROD_MAIN))
{
- ego_item_type *e_ptr = &e_info[o_ptr->name2];
- ego_item_type *e2_ptr = &e_info[o_ptr->name2b];
+ auto e_ptr = &e_info[o_ptr->name2];
+ auto e2_ptr = &e_info[o_ptr->name2b];
if (e_ptr->before)
{
- t = object_desc_str(t, (e_name + e_ptr->name));
- t = object_desc_chr(t, ' ');
+ t += e_ptr->name;
+ t += ' ';
}
if (e2_ptr->before)
{
- t = object_desc_str(t, (e_name + e2_ptr->name));
- t = object_desc_chr(t, ' ');
+ t += e2_ptr->name;
+ t += ' ';
}
}
}
- /* Paranoia -- skip illegal tildes */
- /* while (*s == '~') s++; */
-
/* Copy the string */
- for (; *s; s++)
+ for (auto const c: s)
{
/* Pluralizer */
- if (*s == '~')
+ if (c == '~')
{
/* Add a plural if needed */
if ((o_ptr->number != 1) && (pref >= 0))
{
- char k = t[ -1];
+ assert(t.size() > 0);
+ char k = t[t.size() - 1];
/* XXX XXX XXX Mega-Hack */
/* Hack -- "Cutlass-es" and "Torch-es" */
- if ((k == 's') || (k == 'h')) *t++ = 'e';
+ if ((k == 's') || (k == 'h')) {
+ t += "e";
+ }
/* Add an 's' */
- *t++ = 's';
+ t += "s";
}
}
/* Modifier */
- else if (*s == '#')
+ else if (c == '#')
{
/* Grab any ego-item name */
if (o_ptr->tval == TV_ROD_MAIN)
{
- t = object_desc_chr(t, ' ');
+ t += ' ';
if (known && o_ptr->name2)
{
- ego_item_type *e_ptr = &e_info[o_ptr->name2];
-
- t = object_desc_str(t, (e_name + e_ptr->name));
+ auto e_ptr = &e_info[o_ptr->name2];
+ t += e_ptr->name;
}
}
/* Insert the modifier */
- for (u = modstr; *u; u++) *t++ = *u;
+ t += modstr;
}
/* Normal */
else
{
/* Copy */
- *t++ = *s;
+ t += c;
}
}
- /* Terminate */
- *t = '\0';
-
-
/* Append the "kind name" to the "base name" */
if ((append_name) && (!artifact_p(o_ptr)))
{
- t = object_desc_str(t, " of ");
+ t += " of ";
if (((o_ptr->tval == TV_WAND) || (o_ptr->tval == TV_STAFF)))
{
- t = object_desc_str(t, school_spells[o_ptr->pval2].name);
+ t += spell_type_name(spell_at(o_ptr->pval2));
if (mode >= 1)
{
s32b bonus = o_ptr->pval3 & 0xFFFF;
s32b max = o_ptr->pval3 >> 16;
-
- t = object_desc_chr(t, '[');
- t = object_desc_num(t, bonus);
- t = object_desc_chr(t, '|');
- t = object_desc_num(t, max);
- t = object_desc_chr(t, ']');
+ t += fmt::format("[{:d}|{:d}]", bonus, max);
}
}
else
- t = object_desc_str(t, (k_name + k_ptr->name));
+ {
+ t += k_ptr->name;
+ }
}
/* Hack -- Append "Artifact" or "Special" names */
@@ -1976,100 +1646,77 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
/* -TM- Hack -- Add false-artifact names */
/* Dagger inscribed {@w0#of Smell} will be named
* Dagger of Smell {@w0} */
- if (o_ptr->note)
+ if (auto str = strchr(o_ptr->inscription.c_str(), '#'))
{
- str = strchr(quark_str(o_ptr->note), '#');
-
- /* Add the false name */
- if (str)
- {
- t = object_desc_chr(t, ' ');
- t = object_desc_str(t, &str[1]);
- }
+ t += ' ';
+ t += &str[1];
}
/* Is it a new random artifact ? */
- if (o_ptr->art_name)
+ if (!o_ptr->artifact_name.empty())
{
- t = object_desc_chr(t, ' ');
-
- t = object_desc_str(t, quark_str(o_ptr->art_name));
+ t += ' ';
+ t += o_ptr->artifact_name;
}
/* Grab any artifact name */
else if (o_ptr->name1)
{
- artifact_type *a_ptr = &a_info[o_ptr->name1];
+ auto a_ptr = &a_info[o_ptr->name1];
/* Unique corpses don't require another name */
if (o_ptr->tval != TV_CORPSE)
{
- t = object_desc_chr(t, ' ');
- t = object_desc_str(t, (a_name + a_ptr->name));
+ t += ' ';
+ t += a_ptr->name;
}
}
/* Grab any ego-item name */
else if ((o_ptr->name2 || o_ptr->name2b) && (o_ptr->tval != TV_ROD_MAIN))
{
- ego_item_type *e_ptr = &e_info[o_ptr->name2];
- ego_item_type *e2_ptr = &e_info[o_ptr->name2b];
+ auto e_ptr = &e_info[o_ptr->name2];
+ auto e2_ptr = &e_info[o_ptr->name2b];
if (o_ptr->name2 && !e_ptr->before)
{
- t = object_desc_chr(t, ' ');
- t = object_desc_str(t, (e_name + e_ptr->name));
+ t += ' ';
+ t += e_ptr->name;
}
if (o_ptr->name2b && !e2_ptr->before)
{
- t = object_desc_chr(t, ' ');
- t = object_desc_str(t, (e_name + e2_ptr->name));
+ t += ' ';
+ t += e2_ptr->name;
}
}
}
/* It contains a spell */
- if ((known) && (f5 & TR5_SPELL_CONTAIN) && (o_ptr->pval2 != -1))
+ if (known && (flags & TR_SPELL_CONTAIN) && (o_ptr->pval2 != -1))
{
- t = object_desc_str(t, format(" [%s]", school_spells[o_ptr->pval2].name));
+ t += fmt::format(" [{}]", spell_type_name(spell_at(o_ptr->pval2)));
}
/* Add symbiote hp here, after the "fake-artifact" name. --dsb */
if (o_ptr->tval == TV_HYPNOS)
{
- t = object_desc_str(t, " (");
- t = object_desc_num(t, o_ptr->pval2);
- t = object_desc_str(t, " hp)");
+ t += fmt::format(" ({:d} hp)", o_ptr->pval2);
}
/* No more details wanted */
- if (mode < 1) goto copyback;
-
- /* Hack -- Some objects can have an exp level */
- if ((f4 & TR4_LEVELS) && known)
+ if (mode < 1)
{
- t = object_desc_str(t, " (E:");
- if (exp_need)
- {
- s32b need;
- /* Formula from check_experience_obj(). */
- need = player_exp[o_ptr->elevel - 1] * 5 / 2;
- t = object_desc_num(t, need - o_ptr->exp);
- }
- else
- {
- t = object_desc_num(t, o_ptr->exp);
- }
- t = object_desc_str(t, ", L:");
- t = object_desc_num(t, o_ptr->elevel);
- t = object_desc_chr(t, ')');
+ return t;
}
- if ((f4 & TR4_ART_EXP) && known)
+
+ /* Hack -- Some objects can have an exp level */
+ if ((flags & TR_LEVELS) && known)
{
- t = object_desc_str(t, " (Exp:");
- t = object_desc_num(t, o_ptr->exp);
- t = object_desc_chr(t, ')');
+ auto need_exp = (o_ptr->elevel < PY_MAX_LEVEL)
+ ? std::to_string(calc_object_need_exp(o_ptr) - o_ptr->exp)
+ : "*****";
+ t += fmt::format(" (E:{}, L:{})", need_exp, o_ptr->elevel);
}
/* Hack -- Chests must be described in detail */
@@ -2084,31 +1731,13 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
/* May be "empty" */
else if (!o_ptr->pval)
{
- t = object_desc_str(t, " (empty)");
- }
-
- /* May be "disarmed" */
- else if (o_ptr->pval < 0)
- {
- t = object_desc_str(t, " (disarmed)");
- }
-
- /* Describe the traps, if any */
- else
- {
- /* Describe the traps */
- t = object_desc_str(t, " (");
- if (t_info[o_ptr->pval].ident)
- t = object_desc_str(t, t_name + t_info[o_ptr->pval].name);
- else
- t = object_desc_str(t, "trapped");
- t = object_desc_str(t, ")");
+ t += " (empty)";
}
}
/* Display the item like a weapon */
- if (f3 & (TR3_SHOW_MODS)) show_weapon = TRUE;
+ if (flags & TR_SHOW_MODS) show_weapon = TRUE;
/* Display the item like a weapon */
if (o_ptr->to_h && o_ptr->to_d) show_weapon = TRUE;
@@ -2125,7 +1754,7 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
case TV_ARROW:
/* Exploding arrow? */
if (o_ptr->pval2 != 0)
- t = object_desc_str(t, " (exploding)");
+ t += " (exploding)";
/* No break, we want to continue the description */
case TV_BOOMERANG:
@@ -2139,12 +1768,7 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
break;
/* Append a "damage" string */
- t = object_desc_chr(t, ' ');
- t = object_desc_chr(t, p1);
- t = object_desc_num(t, o_ptr->dd);
- t = object_desc_chr(t, 'd');
- t = object_desc_num(t, o_ptr->ds);
- t = object_desc_chr(t, p2);
+ t += fmt::format(" ({:d}d{:d})", o_ptr->dd, o_ptr->ds);
/* All done */
break;
@@ -2152,19 +1776,14 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
/* Bows get a special "damage string" */
case TV_BOW:
-
/* Mega-Hack -- Extract the "base power" */
- power = (o_ptr->sval % 10);
+ s32b power = (o_ptr->sval % 10);
/* Apply the "Extra Might" flag */
- if (f3 & (TR3_XTRA_MIGHT)) power += o_ptr->pval;
+ if (flags & TR_XTRA_MIGHT) power += o_ptr->pval;
/* Append a special "damage" string */
- t = object_desc_chr(t, ' ');
- t = object_desc_chr(t, p1);
- t = object_desc_chr(t, 'x');
- t = object_desc_num(t, power);
- t = object_desc_chr(t, p2);
+ t += fmt::format(" (x{:d})", power);
/* All done */
break;
@@ -2177,34 +1796,29 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
/* Show the tohit/todam on request */
if (show_weapon)
{
- t = object_desc_chr(t, ' ');
- t = object_desc_chr(t, p1);
- t = object_desc_int(t, o_ptr->to_h);
- t = object_desc_chr(t, ',');
- t = object_desc_int(t, o_ptr->to_d);
- t = object_desc_chr(t, p2);
+ t += fmt::format(" ({:+d},{:+d})", o_ptr->to_h, o_ptr->to_d);
}
/* Show the tohit if needed */
else if (o_ptr->to_h)
{
- t = object_desc_chr(t, ' ');
- t = object_desc_chr(t, p1);
- t = object_desc_int(t, o_ptr->to_h);
- if (!(f3 & (TR3_HIDE_TYPE)) || o_ptr->art_name)
- t = object_desc_str(t, " to accuracy");
- t = object_desc_chr(t, p2);
+ t += fmt::format(" ({:+d}", o_ptr->to_h);
+ if (!(flags & TR_HIDE_TYPE) || (!o_ptr->artifact_name.empty()))
+ {
+ t += " to accuracy";
+ }
+ t += ')';
}
/* Show the todam if needed */
else if (o_ptr->to_d)
{
- t = object_desc_chr(t, ' ');
- t = object_desc_chr(t, p1);
- t = object_desc_int(t, o_ptr->to_d);
- if (!(f3 & (TR3_HIDE_TYPE)) || o_ptr->art_name)
- t = object_desc_str(t, " to damage");
- t = object_desc_chr(t, p2);
+ t += fmt::format(" ({:+d}", o_ptr->to_d);
+ if (!(flags & TR_HIDE_TYPE) || (!o_ptr->artifact_name.empty()))
+ {
+ t += " to damage";
+ }
+ t += ')';
}
}
@@ -2215,63 +1829,37 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
/* Show the armor class info */
if (show_armour)
{
- t = object_desc_chr(t, ' ');
- t = object_desc_chr(t, b1);
- t = object_desc_num(t, o_ptr->ac);
- t = object_desc_chr(t, ',');
- t = object_desc_int(t, o_ptr->to_a);
- t = object_desc_chr(t, b2);
+ t += fmt::format(" [{:d},{:+d}]", o_ptr->ac, o_ptr->to_a);
}
/* No base armor, but does increase armor */
else if (o_ptr->to_a)
{
- t = object_desc_chr(t, ' ');
- t = object_desc_chr(t, b1);
- t = object_desc_int(t, o_ptr->to_a);
- t = object_desc_chr(t, b2);
+ t += fmt::format(" [{:+d}]", o_ptr->to_a);
}
}
/* Hack -- always show base armor */
else if (show_armour)
{
- t = object_desc_chr(t, ' ');
- t = object_desc_chr(t, b1);
- t = object_desc_num(t, o_ptr->ac);
- t = object_desc_chr(t, b2);
+ t += fmt::format(" [{:d}]", o_ptr->ac);
}
- if ((f1 & TR1_MANA) && (known) && (o_ptr->pval > 0))
+ if ((flags & TR_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_str(t, "%)");
+ t += fmt::format("({:d}%)", 100 * o_ptr->pval / 5);
}
- if ((known) && (f2 & TR2_LIFE) ) /* Can disp neg now -- Improv */
+ if (known && (flags & TR_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_str(t, "%)");
+ t += fmt::format("({:d}%)", 100 * o_ptr->pval / 5);
}
/* No more details wanted */
- if (mode < 2) goto copyback;
+ if (mode < 2)
+ {
+ return t;
+ }
/* Hack -- Wands and Staffs have charges */
@@ -2279,13 +1867,8 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
((o_ptr->tval == TV_STAFF) ||
(o_ptr->tval == TV_WAND)))
{
- /* Dump " (N charges)" */
- t = object_desc_chr(t, ' ');
- t = object_desc_chr(t, p1);
- t = object_desc_num(t, o_ptr->pval);
- t = object_desc_str(t, " charge");
- if (o_ptr->pval != 1) t = object_desc_chr(t, 's');
- t = object_desc_chr(t, p2);
+ auto plural = (o_ptr->pval != 1) ? "s" : "";
+ t += fmt::format(" ({:d} charge{})", o_ptr->pval, plural);
}
/*
@@ -2293,12 +1876,7 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
*/
else if (known && (o_ptr->tval == TV_ROD_MAIN))
{
- /* Display prettily. */
- t = object_desc_str(t, " (");
- t = object_desc_num(t, o_ptr->timeout);
- t = object_desc_chr(t, '/');
- t = object_desc_num(t, o_ptr->pval2);
- t = object_desc_chr(t, ')');
+ t += fmt::format(" ({:d}/{:d})", o_ptr->timeout, o_ptr->pval2);
}
/*
@@ -2306,201 +1884,166 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
*/
else if (known && (o_ptr->tval == TV_ROD))
{
- /* Display prettily. */
- t = object_desc_str(t, " (");
- t = object_desc_num(t, o_ptr->pval);
- t = object_desc_str(t, " Mana to cast");
- t = object_desc_chr(t, ')');
+ t += fmt::format(" ({:d} Mana to cast)", o_ptr->pval);
}
/* Hack -- Process Lanterns/Torches */
- else if ((o_ptr->tval == TV_LITE) && (f4 & TR4_FUEL_LITE))
+ else if ((o_ptr->tval == TV_LITE) && (flags & TR_FUEL_LITE))
{
- /* Hack -- Turns of light for normal lites */
- t = object_desc_str(t, " (with ");
- t = object_desc_num(t, o_ptr->timeout);
- t = object_desc_str(t, " turns of light)");
+ t += fmt::format(" (with {:d} turns of light)", o_ptr->timeout);
}
/* Dump "pval" flags for wearable items */
- if (known && ((f1 & (TR1_PVAL_MASK)) || (f5 & (TR5_PVAL_MASK))))
+ if (known && (flags & TR_PVAL_MASK))
{
/* Start the display */
- t = object_desc_chr(t, ' ');
- t = object_desc_chr(t, p1);
-
- /* Dump the "pval" itself */
- t = object_desc_int(t, o_ptr->pval);
+ t += fmt::format(" ({:+d}", o_ptr->pval);
/* Do not display the "pval" flags */
- if (f3 & (TR3_HIDE_TYPE))
+ if (flags & TR_HIDE_TYPE)
{
/* Nothing */
}
/* Speed */
- else if (f1 & (TR1_SPEED))
+ else if (flags & TR_SPEED)
{
- /* Dump " to speed" */
- t = object_desc_str(t, " to speed");
+ t += " to speed";
}
/* Attack speed */
- else if (f1 & (TR1_BLOWS))
+ else if (flags & TR_BLOWS)
{
- /* Add " attack" */
- t = object_desc_str(t, " attack");
-
- /* Add "attacks" */
- if (ABS(o_ptr->pval) != 1) t = object_desc_chr(t, 's');
+ t += " attack";
+ if (ABS(o_ptr->pval) != 1)
+ {
+ t += 's';
+ }
}
/* Critical chance */
- else if (f5 & (TR5_CRIT))
+ else if (flags & TR_CRIT)
{
- /* Add " attack" */
- t = object_desc_str(t, "% of critical hits");
+ t += "% of critical hits";
}
/* Stealth */
- else if (f1 & (TR1_STEALTH))
+ else if (flags & TR_STEALTH)
{
- /* Dump " to stealth" */
- t = object_desc_str(t, " to stealth");
- }
-
- /* Search */
- else if (f1 & (TR1_SEARCH))
- {
- /* Dump " to searching" */
- t = object_desc_str(t, " to searching");
+ t += " to stealth";
}
/* Infravision */
- else if (f1 & (TR1_INFRA))
+ else if (flags & TR_INFRA)
{
- /* Dump " to infravision" */
- t = object_desc_str(t, " to infravision");
+ t += " to infravision";
}
/* Tunneling */
- else if (f1 & (TR1_TUNNEL))
+ else if (flags & TR_TUNNEL)
{
/* Nothing */
}
/* Finish the display */
- t = object_desc_chr(t, p2);
+ t += ')';
}
/* Indicate "charging" artifacts XXX XXX XXX */
- if (known && (f3 & TR3_ACTIVATE) && o_ptr->timeout)
+ if (known && (flags & TR_ACTIVATE) && o_ptr->timeout)
{
- if(o_ptr->tval == TV_EGG)
- /* Hack -- Dump " (stopped)" if relevant */
- t = object_desc_str(t, " (stopped)");
+ if (o_ptr->tval == TV_EGG)
+ {
+ t += " (stopped)";
+ }
else
- /* Hack -- Dump " (charging)" if relevant */
- t = object_desc_str(t, " (charging)");
- }
-
- /* Indicate "charging" Mage Staffs XXX XXX XXX */
- if (known && o_ptr->timeout && (is_ego_p(o_ptr, EGO_MSTAFF_SPELL)))
- {
- /* Hack -- Dump " (charging spell1)" if relevant */
- t = object_desc_str(t, " (charging spell1)");
- }
- if (known && o_ptr->xtra2 && (is_ego_p(o_ptr, EGO_MSTAFF_SPELL)))
- {
- /* Hack -- Dump " (charging spell2)" if relevant */
- t = object_desc_str(t, " (charging spell2)");
+ {
+ t += " (charging)";
+ }
}
/* No more details wanted */
- if (mode < 3) goto copyback;
-
-
- /* No inscription yet */
- tmp_val2[0] = '\0';
-
- /* Sensed stuff */
- if (o_ptr->ident & (IDENT_SENSE))
+ if (mode < 3)
{
- strcpy(tmp_val2, sense_desc[o_ptr->sense]);
+ return t;
}
- /* Hack - Note "cursed" if the item is 'known' and cursed */
- if (cursed_p(o_ptr) && (known) && (!tmp_val2[0]))
- {
- if (tmp_val2[0]) strcat(tmp_val2, ", ");
- strcat(tmp_val2, "cursed");
- }
- /* Use the standard inscription if available */
- if (o_ptr->note)
+ /* Inscribe */
{
- char *u = tmp_val2;
-
- if (tmp_val2[0]) strcat(tmp_val2, ", ");
+ std::vector<std::string> inscrip;
- strcat(tmp_val2, quark_str(o_ptr->note));
-
- for (; *u && (*u != '#') && (*u != '%'); u++);
+ /* Sensed stuff */
+ if ((o_ptr->ident & (IDENT_SENSE)) && sense_desc[o_ptr->sense] && sense_desc[o_ptr->sense][0] != '\0')
+ {
+ inscrip.push_back(sense_desc[o_ptr->sense]);
+ }
- *u = '\0';
- }
+ /* Hack - Note "cursed" if the item is 'known' and cursed */
+ if (cursed_p(o_ptr) && known && inscrip.empty())
+ {
+ inscrip.push_back("cursed");
+ }
- /* Mega-Hack -- note empty wands/staffs */
- if (!known && (o_ptr->ident & (IDENT_EMPTY)))
- {
- if (tmp_val2[0]) strcat(tmp_val2, ", ");
- strcat(tmp_val2, "empty");
- }
+ /* Use the standard inscription if available;
+ Chop at '#' or '%' if present. The suffix of the
+ '%' or '#' is handled elsewhere in this function.
+ */
+ if (auto const pos = o_ptr->inscription.find_first_of("%#") != std::string::npos)
+ {
+ inscrip.push_back(o_ptr->inscription.substr(0, pos));
+ }
- /* Note "tried" if the object has been tested unsuccessfully */
- if (!aware && object_tried_p(o_ptr))
- {
- if (tmp_val2[0]) strcat(tmp_val2, ", ");
- strcpy(tmp_val2, "tried");
- }
+ /* Mega-Hack -- note empty wands/staffs */
+ if (!known && (o_ptr->ident & (IDENT_EMPTY)))
+ {
+ inscrip.push_back("empty");
+ }
- /* Note the discount, if any */
- if ((o_ptr->discount) && (!tmp_val2[0]))
- {
- object_desc_num(tmp_val2, o_ptr->discount);
- strcat(tmp_val2, "% off");
- }
+ /* Note "tried" if the object has been tested unsuccessfully */
+ if (!aware && object_tried_p(o_ptr))
+ {
+ inscrip.push_back("tried");
+ }
- /* Append the inscription, if any */
- if (tmp_val2[0])
- {
- int n;
+ /* Note the discount, if any */
+ if ((o_ptr->discount) && o_ptr->inscription.empty())
+ {
+ inscrip.push_back(fmt::format("{:d}% off", o_ptr->discount));
+ }
- /* Hack -- How much so far */
- n = (t - tmp_val);
+ /* Append the user's inscription */
+ if (!o_ptr->inscription.empty())
+ {
+ inscrip.push_back(o_ptr->inscription);
+ }
- /* Paranoia -- do not be stupid */
- if (n > 75) n = 75;
+ /* Append the inscription, if any */
+ if (!inscrip.empty())
+ {
+ auto inscrip_str = boost::algorithm::join(inscrip, ", ");
- /* Hack -- shrink the inscription */
- tmp_val2[75 - n] = '\0';
+ /* Make sure we don't exceed 75 characters */
+ t.resize(std::min<std::size_t>(t.size(), 75));
- /* Append the inscription */
- t = object_desc_chr(t, ' ');
- t = object_desc_chr(t, c1);
- t = object_desc_str(t, tmp_val2);
- t = object_desc_chr(t, c2);
+ /* Append the inscription */
+ t += fmt::format(" {{{}}}", inscrip_str);
+ }
}
-copyback:
- /* Here's where we dump the built string into buf. */
- tmp_val[79] = '\0';
- t = tmp_val;
- while ((*(buf++) = *(t++))); /* copy the string over */
+
+ return t;
}
+void object_desc(char *buf, object_type const *o_ptr, int pref, int mode)
+{
+ auto s = object_desc_aux(o_ptr, pref, mode);
+ auto n = std::min<std::size_t>(s.size(), 79);
+ s.copy(buf, n);
+ buf[n] = '\0';
+}
/*
* Hack -- describe an item currently in a store's inventory
@@ -2508,6 +2051,8 @@ copyback:
*/
void object_desc_store(char *buf, object_type *o_ptr, int pref, int mode)
{
+ auto &k_info = game->edit_data.k_info;
+
/* Save the "aware" flag */
bool_ hack_aware = k_info[o_ptr->k_idx].aware;
@@ -2540,18 +2085,16 @@ void object_desc_store(char *buf, object_type *o_ptr, int pref, int mode)
* Determine the "Activation" (if any) for an artifact
* Return a string, or NULL for "no activation"
*/
-cptr item_activation(object_type *o_ptr, byte num)
+cptr item_activation(object_type *o_ptr)
{
- u32b f1, f2, f3, f4, f5, esp;
-
- /* Needed hacks */
- static char rspell[2][80];
+ auto const &a_info = game->edit_data.a_info;
+ auto const &e_info = game->edit_data.e_info;
/* Extract the flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ auto const flags = object_flags(o_ptr);
/* Require activation ability */
- if (!(f3 & (TR3_ACTIVATE))) return (NULL);
+ if (!(flags & TR_ACTIVATE)) return (NULL);
/*
@@ -2561,29 +2104,6 @@ cptr item_activation(object_type *o_ptr, byte num)
* for art_name
*/
- if (is_ego_p(o_ptr, EGO_MSTAFF_SPELL))
- {
- int gf, mod, mana;
-
- if (!num)
- {
- gf = o_ptr->pval & 0xFFFF;
- mod = o_ptr->pval3 & 0xFFFF;
- mana = o_ptr->pval2 & 0xFF;
- }
- else
- {
- gf = o_ptr->pval >> 16;
- mod = o_ptr->pval3 >> 16;
- mana = o_ptr->pval2 >> 8;
- }
- sprintf(rspell[num], "runespell(%s, %s, %d) every %d turns",
- k_info[lookup_kind(TV_RUNE1, gf)].name + k_name,
- k_info[lookup_kind(TV_RUNE2, mod)].name + k_name,
- mana, mana * 5);
- return rspell[num];
- }
-
if (o_ptr->tval == TV_EGG)
{
return "stop or resume the egg development";
@@ -2602,14 +2122,11 @@ cptr item_activation(object_type *o_ptr, byte num)
}
}
- if (process_hooks_ret(HOOK_ACTIVATE_DESC, "s", "(O)", o_ptr))
- return (process_hooks_return[0].str);
-
return activation_aux(o_ptr, FALSE, 0);
}
/* Grab the tval desc */
-bool_ grab_tval_desc(int tval)
+static bool_ grab_tval_desc(int tval)
{
int tv = 0;
@@ -2626,8 +2143,16 @@ bool_ grab_tval_desc(int tval)
return TRUE;
}
-#define CHECK_FIRST(txt, first) \
-if ((first)) { (first) = FALSE; text_out((txt)); } else text_out(", ");
+static void check_first(bool_ *first)
+{
+ if (*first) {
+ *first = FALSE;
+ }
+ else
+ {
+ text_out(", ");
+ }
+}
/*
* Display the damage done with a multiplier
@@ -2639,7 +2164,7 @@ void output_dam(object_type *o_ptr, int mult, int mult2, cptr against, cptr agai
dam = (o_ptr->dd + (o_ptr->dd * o_ptr->ds)) * 5 * mult;
dam += (o_ptr->to_d + p_ptr->to_d + p_ptr->to_d_melee) * 10;
dam *= p_ptr->num_blow;
- CHECK_FIRST("", *first);
+ check_first(first);
if (dam > 0)
{
if (dam % 10)
@@ -2656,7 +2181,7 @@ void output_dam(object_type *o_ptr, int mult, int mult2, cptr against, cptr agai
dam = (o_ptr->dd + (o_ptr->dd * o_ptr->ds)) * 5 * mult2;
dam += (o_ptr->to_d + p_ptr->to_d + p_ptr->to_d_melee) * 10;
dam *= p_ptr->num_blow;
- CHECK_FIRST("", *first);
+ check_first(first);
if (dam > 0)
{
if (dam % 10)
@@ -2676,12 +2201,11 @@ void output_dam(object_type *o_ptr, int mult, int mult2, cptr against, cptr agai
void display_weapon_damage(object_type *o_ptr)
{
object_type forge, *old_ptr = &forge;
- u32b f1, f2, f3, f4, f5, esp;
bool_ first = TRUE;
bool_ full = o_ptr->ident & (IDENT_MENTAL);
/* Extract the flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ auto const flags = object_flags(o_ptr);
/* Ok now the hackish stuff, we replace the current weapon with this one */
object_copy(old_ptr, &p_ptr->inventory[INVEN_WIELD]);
@@ -2692,23 +2216,23 @@ void display_weapon_damage(object_type *o_ptr)
text_out_c(TERM_L_GREEN, format("%d ", p_ptr->num_blow));
text_out(format("blow%s and do an average damage per turn of ", (p_ptr->num_blow) ? "s" : ""));
- if (full && (f1 & TR1_SLAY_ANIMAL)) output_dam(o_ptr, 2, 0, "animals", NULL, &first);
- if (full && (f1 & TR1_SLAY_EVIL)) output_dam(o_ptr, 2, 0, "evil creatures", NULL, &first);
- if (full && (f1 & TR1_SLAY_ORC)) output_dam(o_ptr, 3, 0, "orcs", NULL, &first);
- if (full && (f1 & TR1_SLAY_TROLL)) output_dam(o_ptr, 3, 0, "trolls", NULL, &first);
- if (full && (f1 & TR1_SLAY_GIANT)) output_dam(o_ptr, 3, 0, "giants", NULL, &first);
- if (full && (f1 & TR1_KILL_DRAGON)) output_dam(o_ptr, 5, 0, "dragons", NULL, &first);
- else if (full && (f1 & TR1_SLAY_DRAGON)) output_dam(o_ptr, 3, 0, "dragons", NULL, &first);
- if (full && (f5 & TR5_KILL_UNDEAD)) output_dam(o_ptr, 5, 0, "undead", NULL, &first);
- else if (full && (f1 & TR1_SLAY_UNDEAD)) output_dam(o_ptr, 3, 0, "undead", NULL, &first);
- if (full && (f5 & TR5_KILL_DEMON)) output_dam(o_ptr, 5, 0, "demons", NULL, &first);
- else if (full && (f1 & TR1_SLAY_DEMON)) output_dam(o_ptr, 3, 0, "demons", NULL, &first);
-
- if (full && (f1 & TR1_BRAND_FIRE)) output_dam(o_ptr, 3, 6, "non fire resistant creatures", "fire susceptible creatures", &first);
- if (full && (f1 & TR1_BRAND_COLD)) output_dam(o_ptr, 3, 6, "non cold resistant creatures", "cold susceptible creatures", &first);
- if (full && (f1 & TR1_BRAND_ELEC)) output_dam(o_ptr, 3, 6, "non lightning resistant creatures", "lightning susceptible creatures", &first);
- if (full && (f1 & TR1_BRAND_ACID)) output_dam(o_ptr, 3, 6, "non acid resistant creatures", "acid susceptible creatures", &first);
- if (full && (f1 & TR1_BRAND_POIS)) output_dam(o_ptr, 3, 6, "non poison resistant creatures", "poison susceptible creatures", &first);
+ if (full && (flags & TR_SLAY_ANIMAL)) output_dam(o_ptr, 2, 0, "animals", NULL, &first);
+ if (full && (flags & TR_SLAY_EVIL)) output_dam(o_ptr, 2, 0, "evil creatures", NULL, &first);
+ if (full && (flags & TR_SLAY_ORC)) output_dam(o_ptr, 3, 0, "orcs", NULL, &first);
+ if (full && (flags & TR_SLAY_TROLL)) output_dam(o_ptr, 3, 0, "trolls", NULL, &first);
+ if (full && (flags & TR_SLAY_GIANT)) output_dam(o_ptr, 3, 0, "giants", NULL, &first);
+ if (full && (flags & TR_KILL_DRAGON)) output_dam(o_ptr, 5, 0, "dragons", NULL, &first);
+ else if (full && (flags & TR_SLAY_DRAGON)) output_dam(o_ptr, 3, 0, "dragons", NULL, &first);
+ if (full && (flags & TR_KILL_UNDEAD)) output_dam(o_ptr, 5, 0, "undead", NULL, &first);
+ else if (full && (flags & TR_SLAY_UNDEAD)) output_dam(o_ptr, 3, 0, "undead", NULL, &first);
+ if (full && (flags & TR_KILL_DEMON)) output_dam(o_ptr, 5, 0, "demons", NULL, &first);
+ else if (full && (flags & TR_SLAY_DEMON)) output_dam(o_ptr, 3, 0, "demons", NULL, &first);
+
+ if (full && (flags & TR_BRAND_FIRE)) output_dam(o_ptr, 3, 6, "non fire resistant creatures", "fire susceptible creatures", &first);
+ if (full && (flags & TR_BRAND_COLD)) output_dam(o_ptr, 3, 6, "non cold resistant creatures", "cold susceptible creatures", &first);
+ if (full && (flags & TR_BRAND_ELEC)) output_dam(o_ptr, 3, 6, "non lightning resistant creatures", "lightning susceptible creatures", &first);
+ if (full && (flags & TR_BRAND_ACID)) output_dam(o_ptr, 3, 6, "non acid resistant creatures", "acid susceptible creatures", &first);
+ if (full && (flags & TR_BRAND_POIS)) output_dam(o_ptr, 3, 6, "non poison resistant creatures", "poison susceptible creatures", &first);
output_dam(o_ptr, 1, 0, (first) ? "all monsters" : "other monsters", NULL, &first);
@@ -2736,7 +2260,7 @@ void output_ammo_dam(object_type *o_ptr, int mult, int mult2, cptr against, cptr
dam *= tmul;
if (!is_boomerang) dam += (p_ptr->to_d_ranged) * 10;
dam *= mult;
- CHECK_FIRST("", *first);
+ check_first(first);
if (dam > 0)
{
if (dam % 10)
@@ -2756,7 +2280,7 @@ void output_ammo_dam(object_type *o_ptr, int mult, int mult2, cptr against, cptr
dam *= tmul;
if (!is_boomerang) dam += (p_ptr->to_d_ranged) * 10;
dam *= mult2;
- CHECK_FIRST("", *first);
+ check_first(first);
if (dam > 0)
{
if (dam % 10)
@@ -2775,35 +2299,34 @@ void output_ammo_dam(object_type *o_ptr, int mult, int mult2, cptr against, cptr
*/
void display_ammo_damage(object_type *o_ptr)
{
- u32b f1, f2, f3, f4, f5, esp;
bool_ first = TRUE;
int i;
bool_ full = o_ptr->ident & (IDENT_MENTAL);
/* Extract the flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ auto const flags = object_flags(o_ptr);
if (o_ptr->tval == TV_BOOMERANG)
text_out("\nUsing it you would do an average damage per throw of ");
else
text_out("\nUsing it with your current shooter you would do an average damage per shot of ");
- if (full && (f1 & TR1_SLAY_ANIMAL)) output_ammo_dam(o_ptr, 2, 0, "animals", NULL, &first);
- if (full && (f1 & TR1_SLAY_EVIL)) output_ammo_dam(o_ptr, 2, 0, "evil creatures", NULL, &first);
- if (full && (f1 & TR1_SLAY_ORC)) output_ammo_dam(o_ptr, 3, 0, "orcs", NULL, &first);
- if (full && (f1 & TR1_SLAY_TROLL)) output_ammo_dam(o_ptr, 3, 0, "trolls", NULL, &first);
- if (full && (f1 & TR1_SLAY_GIANT)) output_ammo_dam(o_ptr, 3, 0, "giants", NULL, &first);
- if (full && (f1 & TR1_KILL_DRAGON)) output_ammo_dam(o_ptr, 5, 0, "dragons", NULL, &first);
- else if (full && (f1 & TR1_SLAY_DRAGON)) output_ammo_dam(o_ptr, 3, 0, "dragons", NULL, &first);
- if (full && (f5 & TR5_KILL_UNDEAD)) output_ammo_dam(o_ptr, 5, 0, "undeads", NULL, &first);
- else if (full && (f1 & TR1_SLAY_UNDEAD)) output_ammo_dam(o_ptr, 3, 0, "undeads", NULL, &first);
- if (full && (f5 & TR5_KILL_DEMON)) output_ammo_dam(o_ptr, 5, 0, "demons", NULL, &first);
- else if (full && (f1 & TR1_SLAY_DEMON)) output_ammo_dam(o_ptr, 3, 0, "demons", NULL, &first);
-
- if (full && (f1 & TR1_BRAND_FIRE)) output_ammo_dam(o_ptr, 3, 6, "non fire resistant creatures", "fire susceptible creatures", &first);
- if (full && (f1 & TR1_BRAND_COLD)) output_ammo_dam(o_ptr, 3, 6, "non cold resistant creatures", "cold susceptible creatures", &first);
- if (full && (f1 & TR1_BRAND_ELEC)) output_ammo_dam(o_ptr, 3, 6, "non lightning resistant creatures", "lightning susceptible creatures", &first);
- if (full && (f1 & TR1_BRAND_ACID)) output_ammo_dam(o_ptr, 3, 6, "non acid resistant creatures", "acid susceptible creatures", &first);
- if (full && (f1 & TR1_BRAND_POIS)) output_ammo_dam(o_ptr, 3, 6, "non poison resistant creatures", "poison susceptible creatures", &first);
+ if (full && (flags & TR_SLAY_ANIMAL)) output_ammo_dam(o_ptr, 2, 0, "animals", NULL, &first);
+ if (full && (flags & TR_SLAY_EVIL)) output_ammo_dam(o_ptr, 2, 0, "evil creatures", NULL, &first);
+ if (full && (flags & TR_SLAY_ORC)) output_ammo_dam(o_ptr, 3, 0, "orcs", NULL, &first);
+ if (full && (flags & TR_SLAY_TROLL)) output_ammo_dam(o_ptr, 3, 0, "trolls", NULL, &first);
+ if (full && (flags & TR_SLAY_GIANT)) output_ammo_dam(o_ptr, 3, 0, "giants", NULL, &first);
+ if (full && (flags & TR_KILL_DRAGON)) output_ammo_dam(o_ptr, 5, 0, "dragons", NULL, &first);
+ else if (full && (flags & TR_SLAY_DRAGON)) output_ammo_dam(o_ptr, 3, 0, "dragons", NULL, &first);
+ if (full && (flags & TR_KILL_UNDEAD)) output_ammo_dam(o_ptr, 5, 0, "undeads", NULL, &first);
+ else if (full && (flags & TR_SLAY_UNDEAD)) output_ammo_dam(o_ptr, 3, 0, "undeads", NULL, &first);
+ if (full && (flags & TR_KILL_DEMON)) output_ammo_dam(o_ptr, 5, 0, "demons", NULL, &first);
+ else if (full && (flags & TR_SLAY_DEMON)) output_ammo_dam(o_ptr, 3, 0, "demons", NULL, &first);
+
+ if (full && (flags & TR_BRAND_FIRE)) output_ammo_dam(o_ptr, 3, 6, "non fire resistant creatures", "fire susceptible creatures", &first);
+ if (full && (flags & TR_BRAND_COLD)) output_ammo_dam(o_ptr, 3, 6, "non cold resistant creatures", "cold susceptible creatures", &first);
+ if (full && (flags & TR_BRAND_ELEC)) output_ammo_dam(o_ptr, 3, 6, "non lightning resistant creatures", "lightning susceptible creatures", &first);
+ if (full && (flags & TR_BRAND_ACID)) output_ammo_dam(o_ptr, 3, 6, "non acid resistant creatures", "acid susceptible creatures", &first);
+ if (full && (flags & TR_BRAND_POIS)) output_ammo_dam(o_ptr, 3, 6, "non poison resistant creatures", "poison susceptible creatures", &first);
output_ammo_dam(o_ptr, 1, 0, (first) ? "all monsters" : "other monsters", NULL, &first);
text_out(". ");
@@ -2826,28 +2349,39 @@ void display_ammo_damage(object_type *o_ptr)
/*
* Describe a magic stick powers
*/
-void describe_device(object_type *o_ptr)
+static 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))
{
/* Enter device mode */
set_stick_mode(o_ptr);
- text_out("\nSpell description:");
- exec_lua(format("print_device_desc(%d)", o_ptr->pval2));
+ // Spell reference
+ auto spell = spell_at(o_ptr->pval2);
+
+ text_out("\nSpell description:\n");
+ spell_type_description_foreach(spell,
+ [] (std::string const &text) -> void {
+ text_out("\n");
+ text_out(text.c_str());
+ });
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));
+ 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)));
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_device(spell));
+ text_out_c(TERM_GREEN, buf);
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, spell_type_info(spell));
/* Leave device mode */
unset_stick_mode();
@@ -2865,18 +2399,31 @@ void describe_device(object_type *o_ptr)
*/
static cptr object_out_desc_where_found(s16b level, s16b dungeon)
{
+ auto const &d_info = game->edit_data.d_info;
+ auto const &wf_info = game->edit_data.wf_info;
+
static char str[80];
if (dungeon == DUNGEON_WILDERNESS)
+ {
/* Taking care of older objects */
if (level == 0)
+ {
sprintf(str, "in the wilderness or in a town");
+ }
else if (wf_info[level].terrain_idx == TERRAIN_TOWN)
- sprintf(str, "in the town of %s", wf_info[level].name + wf_name);
+ {
+ sprintf(str, "in the town of %s", wf_info[level].name);
+ }
else
- sprintf(str, "in %s", wf_info[level].text + wf_text);
+ {
+ sprintf(str, "in %s", wf_info[level].text);
+ }
+ }
else
- sprintf(str, "on level %d of %s", level, d_info[dungeon].name + d_name);
+ {
+ sprintf(str, "on level %d of %s", level, d_info[dungeon].name.c_str());
+ }
return str;
}
@@ -2886,29 +2433,25 @@ static cptr object_out_desc_where_found(s16b level, s16b dungeon)
*/
bool_ object_out_desc(object_type *o_ptr, FILE *fff, bool_ trim_down, bool_ wait_for_it)
{
- u32b f1, f2, f3, f4, f5, esp;
-
- char *txt;
+ auto const &set_info = game->edit_data.set_info;
+ auto const &st_info = game->edit_data.st_info;
+ auto const &k_info = game->edit_data.k_info;
+ auto const &a_info = game->edit_data.a_info;
cptr vp[64];
byte vc[64];
int vn;
- bool_ first = TRUE;
+ object_flag_set flags;
/* Extract the flags */
if ((!(o_ptr->ident & (IDENT_MENTAL))) && (!fff))
{
- f1 = o_ptr->art_oflags1;
- f2 = o_ptr->art_oflags2;
- f3 = o_ptr->art_oflags3;
- f4 = o_ptr->art_oflags4;
- f5 = o_ptr->art_oflags5;
- esp = o_ptr->art_oesp;
+ flags = o_ptr->art_oflags;
}
else
{
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ flags = object_flags(o_ptr);
}
if (fff)
@@ -2938,51 +2481,46 @@ bool_ object_out_desc(object_type *o_ptr, FILE *fff, bool_ trim_down, bool_ wait
{
if (o_ptr->k_idx && (!trim_down))
{
- object_kind *k_ptr = &k_info[o_ptr->k_idx];
+ auto k_ptr = &k_info[o_ptr->k_idx];
- text_out_c(TERM_ORANGE, k_text + k_ptr->text);
+ text_out_c(TERM_ORANGE, k_ptr->text);
text_out("\n");
}
if (o_ptr->name1 && (!trim_down))
{
- artifact_type *a_ptr = &a_info[o_ptr->name1];
+ auto a_ptr = &a_info[o_ptr->name1];
- text_out_c(TERM_YELLOW, a_text + a_ptr->text);
+ text_out_c(TERM_YELLOW, a_ptr->text);
text_out("\n");
if (a_ptr->set != -1)
{
- set_type *set_ptr = &set_info[a_ptr->set];
-
- text_out_c(TERM_GREEN, set_text + set_ptr->desc);
+ text_out_c(TERM_GREEN, set_info[a_ptr->set].desc.c_str());
text_out("\n");
}
}
- if ((f4 & TR4_LEVELS) && (!trim_down))
+ if ((flags & TR_LEVELS) && (!trim_down))
{
- int j = 0;
-
- if (count_bits(o_ptr->pval3) == 0) text_out("It is sentient");
+ if (o_ptr->pval3 == 0) text_out("It is sentient");
else if (count_bits(o_ptr->pval3) > 1) text_out("It is sentient and can have access to the realms of ");
else text_out("It is sentient and can have access to the realm of ");
- first = TRUE;
- txt = "";
- for (j = 0; j < MAX_FLAG_GROUP; j++)
+ bool_ first = TRUE;
+ for (std::size_t j = 0; j < flags_groups().size(); j++)
{
if (BIT(j) & o_ptr->pval3)
{
- CHECK_FIRST(txt, first);
- text_out_c(flags_groups[j].color, flags_groups[j].name);
+ check_first(&first);
+ text_out_c(flags_groups()[j].color, flags_groups()[j].name);
}
}
text_out(". ");
}
- if (f4 & TR4_ULTIMATE)
+ if (flags & TR_ULTIMATE)
{
if ((wield_slot(o_ptr) == INVEN_WIELD) ||
(wield_slot(o_ptr) == INVEN_BOW))
@@ -2991,24 +2529,17 @@ bool_ object_out_desc(object_type *o_ptr, FILE *fff, bool_ trim_down, bool_ wait
text_out_c(TERM_VIOLET, "It is the ultimate armor. ");
}
- if (f4 & TR4_COULD2H) text_out("It can be wielded two-handed. ");
- if (f4 & TR4_MUST2H) text_out("It must be wielded two-handed. ");
+ if (flags & TR_COULD2H) text_out("It can be wielded two-handed. ");
+ if (flags & TR_MUST2H) text_out("It must be wielded two-handed. ");
/* Mega-Hack -- describe activation */
- if (f3 & (TR3_ACTIVATE))
+ if (flags & TR_ACTIVATE)
{
text_out("It can be activated for ");
- if (is_ego_p(o_ptr, EGO_MSTAFF_SPELL))
- {
- text_out(item_activation(o_ptr, 0));
- text_out(" and ");
- text_out(item_activation(o_ptr, 1));
- }
- else
- text_out(item_activation(o_ptr, 0));
+ text_out(item_activation(o_ptr));
/* Mega-hack -- get rid of useless line for e.g. randarts */
- if (f5 & (TR5_ACTIVATE_NO_WIELD))
+ if (flags & TR_ACTIVATE_NO_WIELD)
text_out(". ");
else
text_out(" if it is being worn. ");
@@ -3021,23 +2552,25 @@ bool_ object_out_desc(object_type *o_ptr, FILE *fff, bool_ trim_down, bool_ wait
text_out(" if it is being worn. ");
}
- /* Hack -- describe lites */
- if ((o_ptr->tval == TV_LITE) || (f3 & TR3_LITE1) || (f4 & TR4_LITE2) || (f4 & TR4_LITE3))
+ /* Describe light sources */
{
int radius = 0;
- if (f3 & TR3_LITE1) radius++;
- if (f4 & TR4_LITE2) radius += 2;
- if (f4 & TR4_LITE3) radius += 3;
+ if (flags & TR_LITE1) radius += 1;
+ if (flags & TR_LITE2) radius += 2;
+ if (flags & TR_LITE3) radius += 3;
if (radius > 5) radius = 5;
- if (f4 & TR4_FUEL_LITE)
- {
- text_out(format("It provides light (radius %d) when fueled. ", radius));
- }
- else
+ if (radius > 0)
{
- text_out(format("It provides light (radius %d) forever. ", radius));
+ if (flags & TR_FUEL_LITE)
+ {
+ text_out(format("It provides light (radius %d) when fueled. ", radius));
+ }
+ else
+ {
+ text_out(format("It provides light (radius %d). ", radius));
+ }
}
}
@@ -3047,12 +2580,12 @@ bool_ object_out_desc(object_type *o_ptr, FILE *fff, bool_ trim_down, bool_ wait
text_out("It prevents the space-time continuum from being disrupted. ");
}
- if ((f4 & (TR4_ANTIMAGIC_50)) || (f4 & (TR4_ANTIMAGIC_30)) || (f4 & (TR4_ANTIMAGIC_20)) || (f4 & (TR4_ANTIMAGIC_10)))
+ if (flags & TR_ANTIMAGIC_50)
{
text_out("It generates an antimagic field. ");
}
- if (f5 & TR5_SPELL_CONTAIN)
+ if (flags & TR_SPELL_CONTAIN)
{
if (o_ptr->pval2 == -1)
text_out("It can be used to store a spell. ");
@@ -3062,21 +2595,19 @@ bool_ object_out_desc(object_type *o_ptr, FILE *fff, bool_ trim_down, bool_ wait
/* Pick up stat bonuses */
vn = 0;
- if (f1 & (TR1_STR)) vp[vn++] = "strength";
- if (f1 & (TR1_INT)) vp[vn++] = "intelligence";
- if (f1 & (TR1_WIS)) vp[vn++] = "wisdom";
- if (f1 & (TR1_DEX)) vp[vn++] = "dexterity";
- if (f1 & (TR1_CON)) vp[vn++] = "constitution";
- if (f1 & (TR1_CHR)) vp[vn++] = "charisma";
- if ((o_ptr->tval != TV_TRAPKIT) && (f1 & (TR1_STEALTH))) vp[vn++] = "stealth";
- if (f1 & (TR1_SEARCH)) vp[vn++] = "searching";
- if (f1 & (TR1_INFRA)) vp[vn++] = "infravision";
- if (f1 & (TR1_TUNNEL)) vp[vn++] = "ability to tunnel";
- if (f1 & (TR1_SPEED)) vp[vn++] = "speed";
- if (f1 & (TR1_BLOWS)) vp[vn++] = "attack speed";
- if (f5 & (TR5_CRIT)) vp[vn++] = "ability to score critical hits";
- if (f5 & (TR5_LUCK)) vp[vn++] = "luck";
- if (f1 & (TR1_SPELL)) vp[vn++] = "spell power";
+ if (flags & TR_STR) vp[vn++] = "strength";
+ if (flags & TR_INT) vp[vn++] = "intelligence";
+ if (flags & TR_WIS) vp[vn++] = "wisdom";
+ if (flags & TR_DEX) vp[vn++] = "dexterity";
+ if (flags & TR_CON) vp[vn++] = "constitution";
+ if (flags & TR_CHR) vp[vn++] = "charisma";
+ if (flags & TR_INFRA) vp[vn++] = "infravision";
+ if (flags & TR_TUNNEL) vp[vn++] = "ability to tunnel";
+ if (flags & TR_SPEED) vp[vn++] = "speed";
+ if (flags & TR_BLOWS) vp[vn++] = "attack speed";
+ if (flags & TR_CRIT) vp[vn++] = "ability to score critical hits";
+ if (flags & TR_LUCK) vp[vn++] = "luck";
+ if (flags & TR_SPELL) vp[vn++] = "spell power";
/* Describe */
if (vn)
@@ -3112,8 +2643,8 @@ bool_ object_out_desc(object_type *o_ptr, FILE *fff, bool_ trim_down, bool_ wait
vn = 0;
- if (f1 & (TR1_MANA)) vp[vn++] = "mana capacity";
- if (f2 & (TR2_LIFE)) vp[vn++] = "hit points";
+ if (flags & TR_MANA) vp[vn++] = "mana capacity";
+ if (flags & TR_LIFE) vp[vn++] = "hit points";
/* Describe with percentuals */
if (vn)
@@ -3135,7 +2666,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)
@@ -3145,28 +2676,23 @@ bool_ object_out_desc(object_type *o_ptr, FILE *fff, bool_ trim_down, bool_ wait
text_out(". ");
}
- if ((o_ptr->tval == TV_TRAPKIT) && (f1 & (TR1_STEALTH)))
- {
- text_out("It is well-hidden. ");
- }
-
vn = 0;
- if (f1 & (TR1_BRAND_ACID))
+ if (flags & TR_BRAND_ACID)
{
vc[vn] = TERM_GREEN;
vp[vn++] = "acid";
}
- if (f1 & (TR1_BRAND_ELEC))
+ if (flags & TR_BRAND_ELEC)
{
vc[vn] = TERM_L_BLUE;
vp[vn++] = "electricity";
}
- if (f1 & (TR1_BRAND_FIRE))
+ if (flags & TR_BRAND_FIRE)
{
vc[vn] = TERM_RED;
vp[vn++] = "fire";
}
- if (f1 & (TR1_BRAND_COLD))
+ if (flags & TR_BRAND_COLD)
{
vc[vn] = TERM_L_WHITE;
vp[vn++] = "frost";
@@ -3194,296 +2720,261 @@ bool_ object_out_desc(object_type *o_ptr, FILE *fff, bool_ trim_down, bool_ wait
}
- if (f1 & (TR1_BRAND_POIS))
+ if (flags & TR_BRAND_POIS)
{
text_out("It ");
text_out_c(TERM_L_GREEN, "poisons your foes");
text_out(". ");
}
- if (f1 & (TR1_CHAOTIC))
+ if (flags & TR_CHAOTIC)
{
text_out("It produces chaotic effects. ");
}
- if (f1 & (TR1_VAMPIRIC))
+ if (flags & TR_VAMPIRIC)
{
text_out("It drains life from your foes. ");
}
- if (f1 & (TR1_IMPACT))
+ if (flags & TR_IMPACT)
{
text_out("It can cause earthquakes. ");
}
- if (f1 & (TR1_VORPAL))
+ if (flags & TR_VORPAL)
{
text_out("It is very sharp and can cut your foes. ");
}
- if (f5 & (TR5_WOUNDING))
+ if (flags & TR_WOUNDING)
{
text_out("It is very sharp and can make your foes bleed. ");
}
- if (f1 & (TR1_KILL_DRAGON))
+ if (flags & TR_KILL_DRAGON)
{
text_out("It is a great bane of dragons. ");
}
- else if (f1 & (TR1_SLAY_DRAGON))
+ else if (flags & TR_SLAY_DRAGON)
{
text_out("It is especially deadly against dragons. ");
}
- if (f1 & (TR1_SLAY_ORC))
+
+ if (flags & TR_SLAY_ORC)
{
text_out("It is especially deadly against orcs. ");
}
- if (f1 & (TR1_SLAY_TROLL))
+
+ if (flags & TR_SLAY_TROLL)
{
text_out("It is especially deadly against trolls. ");
}
- if (f1 & (TR1_SLAY_GIANT))
+
+ if (flags & TR_SLAY_GIANT)
{
text_out("It is especially deadly against giants. ");
}
- if (f5 & (TR5_KILL_DEMON))
+
+ if (flags & TR_KILL_DEMON)
{
text_out("It is a great bane of demons. ");
}
- else if (f1 & (TR1_SLAY_DEMON))
+ else if (flags & TR_SLAY_DEMON)
{
text_out("It strikes at demons with holy wrath. ");
}
- if (f5 & (TR5_KILL_UNDEAD))
+
+ if (flags & TR_KILL_UNDEAD)
{
text_out("It is a great bane of undead. ");
}
- else if (f1 & (TR1_SLAY_UNDEAD))
+ else if (flags & TR_SLAY_UNDEAD)
{
text_out("It strikes at undead with holy wrath. ");
}
- if (f1 & (TR1_SLAY_EVIL))
+
+ if (flags & TR_SLAY_EVIL)
{
text_out("It fights against evil with holy fury. ");
}
- if (f1 & (TR1_SLAY_ANIMAL))
+
+ if (flags & TR_SLAY_ANIMAL)
{
text_out("It is especially deadly against natural creatures. ");
}
- if (f2 & (TR2_INVIS))
+ if (flags & TR_INVIS)
{
text_out("It makes you invisible. ");
}
- if (o_ptr->tval != TV_TRAPKIT)
+ vn = 0;
+ if (flags & TR_SUST_STR)
{
- vn = 0;
- if (f2 & (TR2_SUST_STR))
- {
- vp[vn++] = "strength";
- }
- if (f2 & (TR2_SUST_INT))
- {
- vp[vn++] = "intelligence";
- }
- if (f2 & (TR2_SUST_WIS))
- {
- vp[vn++] = "wisdom";
- }
- if (f2 & (TR2_SUST_DEX))
- {
- vp[vn++] = "dexterity";
- }
- if (f2 & (TR2_SUST_CON))
- {
- vp[vn++] = "constitution";
- }
- if (f2 & (TR2_SUST_CHR))
- {
- vp[vn++] = "charisma";
- }
- /* Describe */
- if (vn)
- {
- int i;
-
- /* Intro */
- text_out("It sustains ");
-
- /* List */
- for (i = 0; i < vn; i++)
- {
- /* Connectives */
- if (i == 0) text_out("your ");
- else if (i < (vn - 1)) text_out(", ");
- else text_out(" and ");
+ vp[vn++] = "strength";
+ }
+ if (flags & TR_SUST_INT)
+ {
+ vp[vn++] = "intelligence";
+ }
+ if (flags & TR_SUST_WIS)
+ {
+ vp[vn++] = "wisdom";
+ }
+ if (flags & TR_SUST_DEX)
+ {
+ vp[vn++] = "dexterity";
+ }
+ if (flags & TR_SUST_CON)
+ {
+ vp[vn++] = "constitution";
+ }
+ if (flags & TR_SUST_CHR)
+ {
+ vp[vn++] = "charisma";
+ }
+ /* Describe */
+ if (vn)
+ {
+ int i;
- /* Dump the stat */
- text_out(vp[i]);
- }
- text_out(". ");
- }
+ /* Intro */
+ text_out("It sustains ");
- vn = 0;
- if (f2 & (TR2_IM_ACID))
- {
- vc[vn] = TERM_GREEN;
- vp[vn++] = "acid";
- }
- if (f2 & (TR2_IM_ELEC))
- {
- vc[vn] = TERM_L_BLUE;
- vp[vn++] = "electricity";
- }
- if (f2 & (TR2_IM_FIRE))
- {
- vc[vn] = TERM_RED;
- vp[vn++] = "fire";
- }
- if (f2 & (TR2_IM_COLD))
- {
- vc[vn] = TERM_L_WHITE;
- vp[vn++] = "cold";
- }
- if (f4 & (TR4_IM_NETHER))
- {
- vc[vn] = TERM_L_GREEN;
- vp[vn++] = "nether";
- }
- /* Describe */
- if (vn)
+ /* List */
+ for (i = 0; i < vn; i++)
{
- int i;
-
- /* Intro */
- text_out("It provides immunity ");
-
- /* List */
- for (i = 0; i < vn; i++)
- {
- /* Connectives */
- if (i == 0) text_out("to ");
- else if (i < (vn - 1)) text_out(", ");
- else text_out(" and ");
+ /* Connectives */
+ if (i == 0) text_out("your ");
+ else if (i < (vn - 1)) text_out(", ");
+ else text_out(" and ");
- /* Dump the stat */
- text_out_c(vc[i], vp[i]);
- }
- text_out(". ");
+ /* Dump the stat */
+ text_out(vp[i]);
}
+ text_out(". ");
}
- else
+
+ vn = 0;
+ if (flags & TR_IM_ACID)
{
- if (f2 & (TRAP2_AUTOMATIC_5))
- {
- text_out("It can rearm itself. ");
- }
- if (f2 & (TRAP2_AUTOMATIC_99))
- {
- text_out("It rearms itself. ");
- }
- if (f2 & (TRAP2_KILL_GHOST))
- {
- text_out("It is effective against Ghosts. ");
- }
- if (f2 & (TRAP2_TELEPORT_TO))
- {
- text_out("It can teleport monsters to you. ");
- }
- if (f2 & (TRAP2_ONLY_DRAGON))
- {
- text_out("It can only be set off by dragons. ");
- }
- if (f2 & (TRAP2_ONLY_DEMON))
- {
- text_out("It can only be set off by demons. ");
- }
- if (f2 & (TRAP2_ONLY_UNDEAD))
- {
- text_out("It can only be set off by undead. ");
- }
- if (f2 & (TRAP2_ONLY_ANIMAL))
- {
- text_out("It can only be set off by animals. ");
- }
- if (f2 & (TRAP2_ONLY_EVIL))
+ vc[vn] = TERM_GREEN;
+ vp[vn++] = "acid";
+ }
+ if (flags & TR_IM_ELEC)
+ {
+ vc[vn] = TERM_L_BLUE;
+ vp[vn++] = "electricity";
+ }
+ if (flags & TR_IM_FIRE)
+ {
+ vc[vn] = TERM_RED;
+ vp[vn++] = "fire";
+ }
+ if (flags & TR_IM_COLD)
+ {
+ vc[vn] = TERM_L_WHITE;
+ vp[vn++] = "cold";
+ }
+ if (flags & TR_IM_NETHER)
+ {
+ vc[vn] = TERM_L_GREEN;
+ vp[vn++] = "nether";
+ }
+ /* Describe */
+ if (vn)
+ {
+ int i;
+
+ /* Intro */
+ text_out("It provides immunity ");
+
+ /* List */
+ for (i = 0; i < vn; i++)
{
- text_out("It can only be set off by evil creatures. ");
+ /* Connectives */
+ if (i == 0) text_out("to ");
+ else if (i < (vn - 1)) text_out(", ");
+ else text_out(" and ");
+
+ /* Dump the stat */
+ text_out_c(vc[i], vp[i]);
}
+ text_out(". ");
}
- if (f2 & (TR2_FREE_ACT))
+ if (flags & TR_FREE_ACT)
{
text_out("It provides immunity to paralysis. ");
}
- if (f2 & (TR2_RES_FEAR))
+ if (flags & TR_RES_FEAR)
{
text_out("It makes you completely fearless. ");
}
vn = 0;
- if (f2 & (TR2_HOLD_LIFE))
+ if (flags & TR_HOLD_LIFE)
{
vp[vn++] = "life draining";
}
- if ((f2 & (TR2_RES_ACID)) && !(f2 & (TR2_IM_ACID)))
+ if ((flags & TR_RES_ACID) && !(flags & TR_IM_ACID))
{
vp[vn++] = "acid";
}
- if ((f2 & (TR2_RES_ELEC)) && !(f2 & (TR2_IM_ELEC)))
+ if ((flags & TR_RES_ELEC) && !(flags & TR_IM_ELEC))
{
vp[vn++] = "electricity";
}
- if ((f2 & (TR2_RES_FIRE)) && !(f2 & (TR2_IM_FIRE)))
+ if ((flags & TR_RES_FIRE) && !(flags & TR_IM_FIRE))
{
vp[vn++] = "fire";
}
- if ((f2 & (TR2_RES_COLD)) && !(f2 & (TR2_IM_COLD)))
+ if ((flags & TR_RES_COLD) && !(flags & TR_IM_COLD))
{
vp[vn++] = "cold";
}
- if (f2 & (TR2_RES_POIS))
+ if (flags & TR_RES_POIS)
{
vp[vn++] = "poison";
}
- if (f2 & (TR2_RES_LITE))
+ if (flags & TR_RES_LITE)
{
vp[vn++] = "light";
}
- if (f2 & (TR2_RES_DARK))
+ if (flags & TR_RES_DARK)
{
vp[vn++] = "dark";
}
- if (f2 & (TR2_RES_BLIND))
+ if (flags & TR_RES_BLIND)
{
vp[vn++] = "blindness";
}
- if (f2 & (TR2_RES_CONF))
+ if (flags & TR_RES_CONF)
{
vp[vn++] = "confusion";
}
- if (f2 & (TR2_RES_SOUND))
+ if (flags & TR_RES_SOUND)
{
vp[vn++] = "sound";
}
- if (f2 & (TR2_RES_SHARDS))
+ if (flags & TR_RES_SHARDS)
{
vp[vn++] = "shards";
}
- if ((f2 & (TR2_RES_NETHER)) && !(f4 & (TR4_IM_NETHER)))
+ if ((flags & TR_RES_NETHER) && !(flags & TR_IM_NETHER))
{
vp[vn++] = "nether";
}
- if (f2 & (TR2_RES_NEXUS))
+ if (flags & TR_RES_NEXUS)
{
vp[vn++] = "nexus";
}
- if (f2 & (TR2_RES_CHAOS))
+ if (flags & TR_RES_CHAOS)
{
vp[vn++] = "chaos";
}
- if (f2 & (TR2_RES_DISEN))
+ if (flags & TR_RES_DISEN)
{
vp[vn++] = "disenchantment";
}
@@ -3509,61 +3000,65 @@ bool_ object_out_desc(object_type *o_ptr, FILE *fff, bool_ trim_down, bool_ wait
text_out(". ");
}
- if (f2 & (TR2_SENS_FIRE))
+ if (flags & TR_SENS_FIRE)
{
text_out("It renders you especially vulnerable to fire. ");
}
- if (f3 & (TR3_WRAITH))
+ if (flags & TR_WRAITH)
{
text_out("It renders you incorporeal. ");
}
- if (f5 & (TR5_WATER_BREATH))
+ if (flags & TR_WATER_BREATH)
{
text_out("It allows you to breathe underwater. ");
}
- if (f5 & (TR5_MAGIC_BREATH))
+ if (flags & TR_MAGIC_BREATH)
{
text_out("It allows you to breathe without air. ");
}
- if (f3 & (TR3_FEATHER))
+ if (flags & TR_FEATHER)
{
text_out("It allows you to levitate. ");
}
- if (f4 & (TR4_FLY))
+ if (flags & TR_FLY)
{
text_out("It allows you to fly. ");
}
- if (f4 & (TR4_CLIMB))
+ if (flags & TR_CLIMB)
{
text_out("It allows you to climb mountains. ");
}
- if (f5 & (TR5_IMMOVABLE))
+ if (flags & TR_IMMOVABLE)
{
text_out("It renders you immovable. ");
}
- if (f3 & (TR3_SEE_INVIS))
+ if (flags & TR_SEE_INVIS)
{
text_out("It allows you to see invisible monsters. ");
}
- if (esp)
+
+ // ESP_*
{
- if (esp & ESP_ALL) text_out("It gives telepathic powers. ");
+ if (flags & ESP_ALL)
+ {
+ text_out("It gives telepathic powers. ");
+ }
else
{
vn = 0;
- if (esp & ESP_ORC) vp[vn++] = "orcs";
- if (esp & ESP_TROLL) vp[vn++] = "trolls";
- if (esp & ESP_DRAGON) vp[vn++] = "dragons";
- if (esp & ESP_SPIDER) vp[vn++] = "spiders";
- if (esp & ESP_GIANT) vp[vn++] = "giants";
- if (esp & ESP_DEMON) vp[vn++] = "demons";
- if (esp & ESP_UNDEAD) vp[vn++] = "undead";
- if (esp & ESP_EVIL) vp[vn++] = "evil beings";
- if (esp & ESP_ANIMAL) vp[vn++] = "animals";
- if (esp & ESP_THUNDERLORD) vp[vn++] = "thunderlords";
- if (esp & ESP_GOOD) vp[vn++] = "good beings";
- if (esp & ESP_NONLIVING) vp[vn++] = "non-living things";
- if (esp & ESP_UNIQUE) vp[vn++] = "unique beings";
+ if (flags & ESP_ORC) vp[vn++] = "orcs";
+ if (flags & ESP_TROLL) vp[vn++] = "trolls";
+ if (flags & ESP_DRAGON) vp[vn++] = "dragons";
+ if (flags & ESP_SPIDER) vp[vn++] = "spiders";
+ if (flags & ESP_GIANT) vp[vn++] = "giants";
+ if (flags & ESP_DEMON) vp[vn++] = "demons";
+ if (flags & ESP_UNDEAD) vp[vn++] = "undead";
+ if (flags & ESP_EVIL) vp[vn++] = "evil beings";
+ if (flags & ESP_ANIMAL) vp[vn++] = "animals";
+ if (flags & ESP_THUNDERLORD) vp[vn++] = "thunderlords";
+ if (flags & ESP_GOOD) vp[vn++] = "good beings";
+ if (flags & ESP_NONLIVING) vp[vn++] = "non-living things";
+ if (flags & ESP_UNIQUE) vp[vn++] = "unique beings";
/* Describe */
if (vn)
{
@@ -3588,55 +3083,55 @@ bool_ object_out_desc(object_type *o_ptr, FILE *fff, bool_ trim_down, bool_ wait
}
}
- if (f3 & (TR3_SLOW_DIGEST))
+ if (flags & TR_SLOW_DIGEST)
{
text_out("It slows your metabolism. ");
}
- if (f3 & (TR3_REGEN))
+ if (flags & TR_REGEN)
{
text_out("It speeds your regenerative powers. ");
}
- if (f2 & (TR2_REFLECT))
+ if (flags & TR_REFLECT)
{
text_out("It reflects bolts and arrows. ");
}
- if (f3 & (TR3_SH_FIRE))
+ if (flags & TR_SH_FIRE)
{
text_out("It produces a fiery sheath. ");
}
- if (f3 & (TR3_SH_ELEC))
+ if (flags & TR_SH_ELEC)
{
text_out("It produces an electric sheath. ");
}
- if (f3 & (TR3_NO_MAGIC))
+ if (flags & TR_NO_MAGIC)
{
text_out("It produces an anti-magic shell. ");
}
- if (f3 & (TR3_NO_TELE))
+ if (flags & TR_NO_TELE)
{
text_out("It prevents teleportation. ");
}
- if (f3 & (TR3_XTRA_MIGHT))
+ if (flags & TR_XTRA_MIGHT)
{
text_out("It fires missiles with extra might. ");
}
- if (f3 & (TR3_XTRA_SHOTS))
+ if (flags & TR_XTRA_SHOTS)
{
text_out("It fires missiles excessively fast. ");
}
vn = 0;
- if (f5 & (TR5_DRAIN_MANA))
+ if (flags & TR_DRAIN_MANA)
{
vc[vn] = TERM_BLUE;
vp[vn++] = "mana";
}
- if (f5 & (TR5_DRAIN_HP))
+ if (flags & TR_DRAIN_HP)
{
vc[vn] = TERM_RED;
vp[vn++] = "life";
}
- if (f3 & (TR3_DRAIN_EXP))
+ if (flags & TR_DRAIN_EXP)
{
vc[vn] = TERM_L_DARK;
vp[vn++] = "experience";
@@ -3663,38 +3158,38 @@ bool_ object_out_desc(object_type *o_ptr, FILE *fff, bool_ trim_down, bool_ wait
text_out(". ");
}
- if (f3 & (TR3_BLESSED))
+ if (flags & TR_BLESSED)
{
text_out("It has been blessed by the gods. ");
}
- if (f4 & (TR4_AUTO_ID))
+ if (flags & TR_AUTO_ID)
{
text_out("It identifies all items for you. ");
}
- if (f3 & (TR3_TELEPORT))
+ if (flags & TR_TELEPORT)
{
text_out("It induces random teleportation. ");
}
- if (f3 & (TR3_AGGRAVATE))
+ if (flags & TR_AGGRAVATE)
{
text_out("It aggravates nearby creatures. ");
}
- if (f4 & (TR4_NEVER_BLOW))
+ if (flags & TR_NEVER_BLOW)
{
text_out("It can't attack. ");
}
- if (f4 & (TR4_BLACK_BREATH))
+ if (flags & TR_BLACK_BREATH)
{
text_out("It fills you with the Black Breath. ");
}
if (cursed_p(o_ptr))
{
- if (f3 & (TR3_PERMA_CURSE))
+ if (flags & TR_PERMA_CURSE)
{
text_out("It is permanently cursed. ");
}
- else if (f3 & (TR3_HEAVY_CURSE))
+ else if (flags & TR_HEAVY_CURSE)
{
text_out("It is heavily cursed. ");
}
@@ -3703,68 +3198,68 @@ bool_ object_out_desc(object_type *o_ptr, FILE *fff, bool_ trim_down, bool_ wait
text_out("It is cursed. ");
}
}
- if (f3 & (TR3_TY_CURSE))
+ if (flags & TR_TY_CURSE)
{
text_out("It carries an ancient foul curse. ");
}
- if (f4 & (TR4_DG_CURSE))
+ if (flags & TR_DG_CURSE)
{
text_out("It carries an ancient Morgothian curse. ");
}
- if (f4 & (TR4_CLONE))
+ if (flags & TR_CLONE)
{
text_out("It can clone monsters. ");
}
- if (f4 & (TR4_CURSE_NO_DROP))
+ if (flags & TR_CURSE_NO_DROP)
{
text_out("It cannot be dropped while cursed. ");
}
- if (f3 & (TR3_AUTO_CURSE))
+ if (flags & TR_AUTO_CURSE)
{
text_out("It can re-curse itself. ");
}
- if (f4 & (TR4_CAPACITY))
+ if (flags & TR_CAPACITY)
{
text_out("It can hold more mana. ");
}
- if (f4 & (TR4_CHEAPNESS))
+ if (flags & TR_CHEAPNESS)
{
text_out("It can cast spells for a lesser mana cost. ");
}
- if (f4 & (TR4_FAST_CAST))
+ if (flags & TR_FAST_CAST)
{
text_out("It can cast spells faster. ");
}
- if (f4 & (TR4_CHARGING))
+ if (flags & TR_CHARGING)
{
text_out("It regenerates its mana faster. ");
}
- if (f5 & (TR5_RES_MORGUL))
+ if (flags & TR_RES_MORGUL)
{
text_out("It can resist being shattered by morgul beings. ");
}
- if ((f3 & (TR3_IGNORE_ACID)) && (f3 & (TR3_IGNORE_FIRE)) && (f3 & (TR3_IGNORE_COLD)) && (f3 & (TR3_IGNORE_ELEC)))
+ if ((flags & TR_IGNORE_ACID) && (flags & TR_IGNORE_FIRE) && (flags & TR_IGNORE_COLD) && (flags & TR_IGNORE_ELEC))
{
text_out("It cannot be harmed by acid, cold, lightning or fire. ");
}
else
{
- if (f3 & (TR3_IGNORE_ACID))
+ if (flags & TR_IGNORE_ACID)
{
text_out("It cannot be harmed by acid. ");
}
- if (f3 & (TR3_IGNORE_ELEC))
+ if (flags & TR_IGNORE_ELEC)
{
text_out("It cannot be harmed by electricity. ");
}
- if (f3 & (TR3_IGNORE_FIRE))
+ if (flags & TR_IGNORE_FIRE)
{
text_out("It cannot be harmed by fire. ");
}
- if (f3 & (TR3_IGNORE_COLD))
+ if (flags & TR_IGNORE_COLD)
{
text_out("It cannot be harmed by cold. ");
}
@@ -3828,7 +3323,7 @@ bool_ object_out_desc(object_type *o_ptr, FILE *fff, bool_ trim_down, bool_ wait
/* Copying how others seem to do it. -- neil */
if (o_ptr->tval == TV_RING || o_ptr->tval == TV_AMULET ||
- !trim_down || (ego_item_p(o_ptr)) || (artifact_p(o_ptr)))
+ !trim_down || ego_item_p(o_ptr) || artifact_p(o_ptr))
{
/* Where did we found it ? */
if (o_ptr->found == OBJ_FOUND_MONSTER)
@@ -3864,12 +3359,12 @@ bool_ object_out_desc(object_type *o_ptr, FILE *fff, bool_ trim_down, bool_ wait
else if (o_ptr->found == OBJ_FOUND_STORE)
{
text_out(format("\nYou bought it from the %s.",
- st_info[o_ptr->found_aux1].name + st_name));
+ st_info[o_ptr->found_aux1].name.c_str()));
}
else if (o_ptr->found == OBJ_FOUND_STOLEN)
{
text_out(format("\nYou stole it from the %s.",
- st_info[o_ptr->found_aux1].name + st_name));
+ st_info[o_ptr->found_aux1].name.c_str()));
}
else if (o_ptr->found == OBJ_FOUND_SELFMADE)
{
@@ -3929,7 +3424,7 @@ char index_to_label(int i)
* Convert a label into the index of an item in the "inven"
* Return "-1" if the label does not indicate a real item
*/
-s16b label_to_inven(int c)
+static s16b label_to_inven(int c)
{
int i;
@@ -3951,7 +3446,7 @@ s16b label_to_inven(int c)
* Convert a label into the index of a item in the "equip"
* Return "-1" if the label does not indicate a real item
*/
-s16b label_to_equip(int c)
+static s16b label_to_equip(int c)
{
int i;
@@ -3972,7 +3467,7 @@ s16b label_to_equip(int c)
* Returns the next free slot of the given "type", return the first
* if all are used
*/
-int get_slot(int slot)
+static int get_slot(int slot)
{
int i = 0;
@@ -4002,12 +3497,8 @@ int get_slot(int slot)
* Determine which equipment slot (if any) an item likes, ignoring the player's
* current body and stuff if ideal == TRUE
*/
-s16b wield_slot_ideal(object_type *o_ptr, bool_ ideal)
+s16b wield_slot_ideal(object_type const *o_ptr, bool_ ideal)
{
- /* Try for a script first */
- if (process_hooks_ret(HOOK_WIELD_SLOT, "d", "(O,d)", o_ptr, ideal))
- return process_hooks_return[0].num;
-
/* Slot for equipment */
switch (o_ptr->tval)
{
@@ -4145,6 +3636,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 */
@@ -4155,7 +3665,7 @@ s16b wield_slot_ideal(object_type *o_ptr, bool_ ideal)
* Determine which equipment slot (if any) an item likes for the player's
* current body and stuff
*/
-s16b wield_slot(object_type *o_ptr)
+s16b wield_slot(object_type const *o_ptr)
{
return wield_slot_ideal(o_ptr, FALSE);
}
@@ -4163,7 +3673,7 @@ s16b wield_slot(object_type *o_ptr)
/*
* Return a string mentioning how a given item is carried
*/
-cptr mention_use(int i)
+static cptr mention_use(int i)
{
cptr p;
@@ -4268,7 +3778,7 @@ cptr mention_use(int i)
*/
cptr describe_use(int i)
{
- cptr p;
+ cptr p = nullptr;
switch (i)
{
@@ -4366,45 +3876,42 @@ cptr describe_use(int i)
/*
* Check an item against the item tester info
*/
-bool_ item_tester_okay(object_type *o_ptr)
+static bool item_tester_okay(object_type const *o_ptr, object_filter_t const &filter)
{
/* Hack -- allow listing empty slots */
- if (item_tester_full) return (TRUE);
+ if (item_tester_full)
+ {
+ return true;
+ }
/* Require an item */
- if (!o_ptr->k_idx) return (FALSE);
-
- /* Hack -- ignore "gold" */
- if (o_ptr->tval == TV_GOLD) return (FALSE);
-
- /* Check the tval */
- if (item_tester_tval)
+ if (!o_ptr->k_idx)
{
- if (!(item_tester_tval == o_ptr->tval)) return (FALSE);
+ return false;
}
- /* Check the hook */
- if (item_tester_hook)
+ /* Hack -- ignore "gold" */
+ if (o_ptr->tval == TV_GOLD)
{
- if (!(*item_tester_hook)(o_ptr)) return (FALSE);
+ return false;
}
- /* Assume okay */
- return (TRUE);
+ /* Check against the filter */
+ return filter(o_ptr);
}
-void show_equip_aux(bool_ mirror, bool_ everything);
-void show_inven_aux(bool_ mirror, bool_ everything);
+static void show_equip_aux(bool_ mirror, object_filter_t const &filter);
+static void show_inven_aux(bool_ mirror, object_filter_t const &filter);
/*
* Choice window "shadow" of the "show_inven()" function
*/
-void display_inven(void)
+void display_inven()
{
- show_inven_aux(TRUE, inventory_no_move);
+ show_inven_aux(TRUE, object_filter::True());
}
@@ -4412,16 +3919,18 @@ void display_inven(void)
/*
* Choice window "shadow" of the "show_equip()" function
*/
-void display_equip(void)
+void display_equip()
{
- show_equip_aux(TRUE, inventory_no_move);
+ show_equip_aux(TRUE, object_filter::True());
}
/* Get the color of the letter idx */
-byte get_item_letter_color(object_type *o_ptr)
+byte get_item_letter_color(object_type const *o_ptr)
{
+ auto const &a_info = game->edit_data.a_info;
+
byte color = TERM_WHITE;
/* Must have knowlegde */
@@ -4430,7 +3939,7 @@ byte get_item_letter_color(object_type *o_ptr)
if (ego_item_p(o_ptr)) color = TERM_L_BLUE;
if (artifact_p(o_ptr)) color = TERM_YELLOW;
if (o_ptr->name1 && ( -1 != a_info[o_ptr->name1].set)) color = TERM_GREEN;
- if (o_ptr->name1 && (a_info[o_ptr->name1].flags4 & TR4_ULTIMATE) && (o_ptr->ident & (IDENT_MENTAL))) color = TERM_VIOLET;
+ if (o_ptr->name1 && (a_info[o_ptr->name1].flags & TR_ULTIMATE) && (o_ptr->ident & (IDENT_MENTAL))) color = TERM_VIOLET;
return (color);
}
@@ -4441,7 +3950,7 @@ byte get_item_letter_color(object_type *o_ptr)
*
* Hack -- do not display "trailing" empty slots
*/
-void show_inven_aux(bool_ mirror, bool_ everything)
+void show_inven_aux(bool_ mirror, const object_filter_t &filter)
{
int i, j, k, l, z = 0;
int row, col, len, lim;
@@ -4469,11 +3978,11 @@ 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;
+ /* Space for icon */
+ lim -= 2;
/* Find the "final" slot */
for (i = 0; i < INVEN_PACK; i++)
@@ -4493,18 +4002,15 @@ void show_inven_aux(bool_ mirror, bool_ everything)
o_ptr = &p_ptr->inventory[i];
/* Is this item acceptable? */
- if (!item_tester_okay(o_ptr))
+ if (!item_tester_okay(o_ptr, filter))
{
- if ( !everything )
- continue;
- out_index[k] = -i - 1;
- }
- else
- {
- /* Save the object index */
- out_index[k] = i + 1;
+ /* Skip to next slot */
+ continue;
}
+ /* Save the object index */
+ out_index[k] = i + 1;
+
/* Describe the object */
object_desc(o_name, o_ptr, TRUE, 3);
@@ -4513,16 +4019,16 @@ void show_inven_aux(bool_ mirror, bool_ everything)
/* Save the object color, and description */
out_color[k] = tval_to_attr[o_ptr->tval % 128];
- (void)strcpy(out_desc[k], o_name);
+ strcpy(out_desc[k], o_name);
/* Find the predicted "line length" */
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;
+ /* Account for icon */
+ l += 2;
/* Maintain the maximum length */
if (l > len) len = l;
@@ -4557,8 +4063,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);
@@ -4568,16 +4073,14 @@ 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 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);
}
}
@@ -4585,8 +4088,10 @@ void show_inven_aux(bool_ mirror, bool_ everything)
/* Shadow windows */
if (mirror)
{
+ int hgt;
+ Term_get_size(nullptr, &hgt);
/* Erase the rest of the window */
- for (j = row + k; j < Term->hgt; j++)
+ for (j = row + k; j < hgt; j++)
{
/* Erase the line */
Term_erase(0, j, 255);
@@ -4602,20 +4107,34 @@ void show_inven_aux(bool_ mirror, bool_ everything)
}
-void show_inven()
+static void show_inven(object_filter_t const &filter)
+{
+ show_inven_aux(FALSE, filter);
+}
+
+void show_inven_full()
{
- show_inven_aux(FALSE, FALSE);
+ item_tester_full = true;
+ show_inven(object_filter::True());
+ item_tester_full = false;
}
-void show_equip()
+static void show_equip(object_filter_t const &filter)
{
- show_equip_aux(FALSE, FALSE);
+ show_equip_aux(FALSE, filter);
+}
+
+void show_equip_full()
+{
+ item_tester_full = true;
+ show_equip(object_filter::True());
+ item_tester_full = false;
}
/*
* Display the equipment.
*/
-void show_equip_aux(bool_ mirror, bool_ everything)
+void show_equip_aux(bool_ mirror, object_filter_t const &filter)
{
int i, j, k, l;
int row, col, len, lim, idx;
@@ -4644,13 +4163,14 @@ 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 (if needed) */
- if (show_weights) lim -= 9;
+ /* Require space for weight */
+ lim -= 9;
- if (show_equip_graph) lim -= 2;
+ /* Require space for icon */
+ lim -= 2;
/* Scan the equipment list */
idx = 0;
@@ -4669,7 +4189,6 @@ void show_equip_aux(bool_ mirror, bool_ everything)
!o_ptr->k_idx &&
p_ptr->inventory[i - INVEN_ARM + INVEN_WIELD].k_idx)
{
- u32b f1, f2, f3, f4, f5, esp;
object_type *q_ptr = &p_ptr->inventory[i - INVEN_ARM + INVEN_WIELD];
char q_name[80];
@@ -4677,9 +4196,9 @@ void show_equip_aux(bool_ mirror, bool_ everything)
object_desc(q_name, q_ptr, TRUE, 3);
/* Get weapon flags */
- object_flags(q_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ auto const flags = object_flags(q_ptr);
- if (f4 & TR4_MUST2H)
+ if (flags & TR_MUST2H)
{
sprintf(o_name, "(two handed) %s", q_name);
@@ -4693,7 +4212,7 @@ void show_equip_aux(bool_ mirror, bool_ everything)
/* Save the color */
out_color[k] = TERM_L_RED;
- (void)strcpy(out_desc[k], o_name);
+ strcpy(out_desc[k], o_name);
continue;
}
}
@@ -4701,7 +4220,7 @@ void show_equip_aux(bool_ mirror, bool_ everything)
if ((p_ptr->body_parts[i - INVEN_WIELD] == INVEN_WIELD) &&
!o_ptr->k_idx)
{
- sprintf(o_name, "(%s)", melee_names[get_melee_skill()]);
+ sprintf(o_name, "(%s)", get_melee_name());
/* Truncate the description */
o_name[lim] = 0;
@@ -4713,7 +4232,7 @@ void show_equip_aux(bool_ mirror, bool_ everything)
/* Save the color */
out_color[k] = TERM_L_BLUE;
- (void)strcpy(out_desc[k], o_name);
+ strcpy(out_desc[k], o_name);
}
else
{
@@ -4724,34 +4243,34 @@ void show_equip_aux(bool_ mirror, bool_ everything)
/* Truncate the description */
o_name[lim] = 0;
+
/* Is this item acceptable? */
- if (!item_tester_okay(o_ptr))
+ if (!item_tester_okay(o_ptr, filter))
{
- if (!everything) continue;
- out_index[k] = -1;
- }
- else
- {
- /* Save the index */
- out_index[k] = idx;
+ /* Skip to next slot */
+ continue;
}
+
+ /* Save the index */
+ out_index[k] = idx;
out_rindex[k] = i;
/* Save the color */
out_color[k] = tval_to_attr[o_ptr->tval % 128];
- (void)strcpy(out_desc[k], o_name);
+ strcpy(out_desc[k], o_name);
}
/* Extract the maximal length (see below) */
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 (if needed) */
- if (show_weights) l += 9;
+ /* Increase length for weight */
+ l += 9;
- if (show_equip_graph) l += 2;
+ /* Icon */
+ l += 2;
/* Maintain the max-length */
if (l > len) len = l;
@@ -4787,7 +4306,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);
@@ -4798,28 +4317,19 @@ 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]));
- put_str(tmp_val, row + j, show_equip_graph ? col + 5 : col + 3);
+ sprintf(tmp_val, "%-14s: ", mention_use(out_rindex[j]));
+ 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);
}
- /* 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 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);
}
}
@@ -4828,8 +4338,10 @@ void show_equip_aux(bool_ mirror, bool_ everything)
/* Shadow windows */
if (mirror)
{
+ int hgt;
+ Term_get_size(nullptr, &hgt);
/* Erase the rest of the window */
- for (j = row + k; j < Term->hgt; j++)
+ for (j = row + k; j < hgt; j++)
{
/* Erase the line */
Term_erase(0, j, 255);
@@ -4850,12 +4362,12 @@ void show_equip_aux(bool_ mirror, bool_ everything)
/*
* Flip "inven" and "equip" in any sub-windows
*/
-void toggle_inven_equip(void)
+void toggle_inven_equip()
{
int j;
/* Scan windows */
- for (j = 0; j < 8; j++)
+ for (j = 0; j < ANGBAND_TERM_MAX; j++)
{
/* Unused */
if (!angband_term[j]) continue;
@@ -4906,7 +4418,7 @@ bool_ verify(cptr prompt, int item)
object_desc(o_name, o_ptr, TRUE, 3);
/* Prompt */
- (void)sprintf(out_val, "%s %s? ", prompt, o_name);
+ sprintf(out_val, "%s %s? ", prompt, o_name);
/* Query */
return (get_check(out_val));
@@ -4920,18 +4432,17 @@ bool_ verify(cptr prompt, int item)
*/
static bool_ get_item_allow(int item)
{
- cptr s;
-
- object_type *o_ptr;
-
/* Get object */
- o_ptr = get_object(item);
+ auto o_ptr = get_object(item);
/* No inscription */
- if (!o_ptr->note) return (TRUE);
+ if (o_ptr->inscription.empty())
+ {
+ return TRUE;
+ }
/* Find a '!' */
- s = strchr(quark_str(o_ptr->note), '!');
+ auto s = strchr(o_ptr->inscription.c_str(), '!');
/* Process preventions */
while (s)
@@ -4956,16 +4467,16 @@ static bool_ get_item_allow(int item)
/*
* Auxiliary function for "get_item()" -- test an index
*/
-static bool_ get_item_okay(int i)
+static bool get_item_okay(int i, object_filter_t const &filter)
{
/* Illegal items */
- if ((i < 0) || (i >= INVEN_TOTAL)) return (FALSE);
+ if ((i < 0) || (i >= INVEN_TOTAL))
+ {
+ return (FALSE);
+ }
/* Verify the item */
- if (!item_tester_okay(&p_ptr->inventory[i])) return (FALSE);
-
- /* Assume okay */
- return (TRUE);
+ return item_tester_okay(&p_ptr->inventory[i], filter);
}
@@ -4981,23 +4492,25 @@ static bool_ get_item_okay(int i)
*/
static int get_tag(int *cp, char tag)
{
- int i;
- cptr s;
-
-
/* Check every object */
- for (i = 0; i < INVEN_TOTAL; ++i)
+ for (int i = 0; i < INVEN_TOTAL; ++i)
{
object_type *o_ptr = &p_ptr->inventory[i];
/* Skip non-objects */
- if (!o_ptr->k_idx) continue;
+ if (!o_ptr->k_idx)
+ {
+ continue;
+ }
/* Skip empty inscriptions */
- if (!o_ptr->note) continue;
+ if (o_ptr->inscription.empty())
+ {
+ continue;
+ }
/* Find a '@' */
- s = strchr(quark_str(o_ptr->note), '@');
+ auto s = strchr(o_ptr->inscription.c_str(), '@');
/* Process all tags */
while (s)
@@ -5035,61 +4548,45 @@ static int get_tag(int *cp, char tag)
* scan_floor --
*
* Return a list of o_list[] indexes of items at the given cave
- * location. Valid flags are:
- *
- * mode & 0x01 -- Item tester
- * mode & 0x02 -- Marked items only
- * mode & 0x04 -- Stop after first
+ * location.
*/
-bool_ scan_floor(int *items, int *item_num, int y, int x, int mode)
+static std::vector<int> scan_floor(int y, int x, object_filter_t const &filter)
{
- int this_o_idx, next_o_idx;
-
- int num = 0;
-
- (*item_num) = 0;
+ std::vector<int> items;
/* Sanity */
- if (!in_bounds(y, x)) return (FALSE);
+ if (!in_bounds(y, x))
+ {
+ return items;
+ }
/* Scan all objects in the grid */
- for (this_o_idx = cave[y][x].o_idx; this_o_idx; this_o_idx = next_o_idx)
+ for (auto const this_o_idx: cave[y][x].o_idxs)
{
- object_type * o_ptr;
-
/* Acquire object */
- o_ptr = &o_list[this_o_idx];
-
- /* Acquire next object */
- next_o_idx = o_ptr->next_o_idx;
+ object_type * o_ptr = &o_list[this_o_idx];
/* Item tester */
- if ((mode & 0x01) && !item_tester_okay(o_ptr)) continue;
-
- /* Marked */
- if ((mode & 0x02) && !o_ptr->marked) continue;
+ if (!item_tester_okay(o_ptr, filter))
+ {
+ continue;
+ }
/* Accept this item */
- items[num++] = this_o_idx;
-
- /* Only one */
- if (mode & 0x04) break;
+ items.push_back(this_o_idx);
/* XXX Hack -- Enforce limit */
- if (num == 23) break;
+ if (items.size() == 23) break;
}
- /* Number of items */
- (*item_num) = num;
-
/* Result */
- return (num != 0);
+ return items;
}
/*
* Display a list of the items on the floor at the given location.
*/
-void show_floor(int y, int x)
+static void show_floor(int y, int x, object_filter_t const &filter)
{
int i, j, k, l;
int col, len, lim;
@@ -5104,19 +4601,19 @@ void show_floor(int y, int x)
byte out_color[23];
char out_desc[23][80];
- int floor_list[23], floor_num;
-
/* Default length */
len = 79 - 50;
/* 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);
+ auto const floor_list = scan_floor(y, x, filter);
+ assert(floor_list.size() <= 23);
+ int const floor_num = floor_list.size(); // "int" for warning avoidance
/* Display the inventory */
for (k = 0, i = 0; i < floor_num; i++)
@@ -5141,8 +4638,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;
@@ -5176,7 +4673,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);
@@ -5192,8 +4688,7 @@ void show_floor(int y, int x)
* This version of get_item() is called by get_item() when
* the easy_floor is on.
*/
-bool_ (*get_item_extra_hook)(int *cp);
-bool_ get_item_floor(int *cp, cptr pmt, cptr str, int mode)
+static bool_ get_item_floor(int *cp, cptr pmt, cptr str, int mode, object_filter_t const &filter, select_by_name_t const &select_by_name)
{
char n1 = 0, n2 = 0, which = ' ';
@@ -5206,7 +4701,6 @@ bool_ get_item_floor(int *cp, cptr pmt, cptr str, int mode)
bool_ equip = FALSE;
bool_ inven = FALSE;
bool_ floor = FALSE;
- bool_ extra = FALSE;
bool_ automat = FALSE;
bool_ allow_equip = FALSE;
@@ -5218,7 +4712,7 @@ bool_ get_item_floor(int *cp, cptr pmt, cptr str, int mode)
char tmp_val[160];
char out_val[160];
- int floor_num, floor_list[23], floor_top = 0;
+ int floor_top = 0;
k = 0;
@@ -5237,28 +4731,16 @@ bool_ get_item_floor(int *cp, cptr pmt, cptr str, int mode)
o_ptr = &o_list[k];
/* Validate the item */
- if (item_tester_okay(o_ptr))
+ if (item_tester_okay(o_ptr, filter))
{
- /* Forget the item_tester_tval restriction */
- item_tester_tval = 0;
-
- /* Forget the item_tester_hook restriction */
- item_tester_hook = NULL;
-
/* Success */
return (TRUE);
}
}
/* Verify the item */
- else if (get_item_okay(*cp))
+ else if (get_item_okay(*cp, filter))
{
- /* Forget the item_tester_tval restriction */
- item_tester_tval = 0;
-
- /* Forget the item_tester_hook restriction */
- item_tester_hook = NULL;
-
/* Success */
return (TRUE);
}
@@ -5269,7 +4751,6 @@ bool_ get_item_floor(int *cp, cptr pmt, cptr str, int mode)
if (mode & (USE_EQUIP)) equip = TRUE;
if (mode & (USE_INVEN)) inven = TRUE;
if (mode & (USE_FLOOR)) floor = TRUE;
- if (mode & (USE_EXTRA)) extra = TRUE;
if (mode & (USE_AUTO)) automat = TRUE;
@@ -5292,8 +4773,8 @@ bool_ get_item_floor(int *cp, cptr pmt, cptr str, int mode)
if (!inven) i2 = -1;
/* Restrict inventory indexes */
- while ((i1 <= i2) && (!get_item_okay(i1))) i1++;
- while ((i1 <= i2) && (!get_item_okay(i2))) i2--;
+ while ((i1 <= i2) && (!get_item_okay(i1, filter))) i1++;
+ while ((i1 <= i2) && (!get_item_okay(i2, filter))) i2--;
/* Full equipment */
@@ -5304,19 +4785,16 @@ bool_ get_item_floor(int *cp, cptr pmt, cptr str, int mode)
if (!equip) e2 = -1;
/* Restrict equipment indexes */
- while ((e1 <= e2) && (!get_item_okay(e1))) e1++;
- while ((e1 <= e2) && (!get_item_okay(e2))) e2--;
+ while ((e1 <= e2) && (!get_item_okay(e1, filter))) e1++;
+ while ((e1 <= e2) && (!get_item_okay(e2, filter))) e2--;
- /* Count "okay" floor items */
- floor_num = 0;
-
- /* Restrict floor usage */
- if (floor)
- {
- /* Scan all objects in the grid */
- (void) scan_floor(floor_list, &floor_num, p_ptr->py, p_ptr->px, 0x01);
- }
+ /* Floor items? */
+ auto const floor_list =
+ floor ? scan_floor(p_ptr->py, p_ptr->px, filter)
+ : std::vector<int>();
+ assert(floor_list.size() <= 23);
+ int const floor_num = floor_list.size(); // "int" for warning avoidance
/* Accept inventory */
if (i1 <= i2) allow_inven = TRUE;
@@ -5325,7 +4803,7 @@ bool_ get_item_floor(int *cp, cptr pmt, cptr str, int mode)
if (e1 <= e2) allow_equip = TRUE;
/* Accept floor */
- if (floor_num) allow_floor = TRUE;
+ if (!floor_list.empty()) allow_floor = TRUE;
/* Require at least one legal choice */
if (!allow_inven && !allow_equip && !allow_floor)
@@ -5372,13 +4850,12 @@ 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;
/* Scan windows */
- for (j = 0; j < 8; j++)
+ for (j = 0; j < ANGBAND_TERM_MAX; j++)
{
/* Unused */
if (!angband_term[j]) continue;
@@ -5416,7 +4893,7 @@ bool_ get_item_floor(int *cp, cptr pmt, cptr str, int mode)
n2 = I2A(i2);
/* Redraw */
- show_inven();
+ show_inven(filter);
}
/* Equipment screen */
@@ -5427,7 +4904,7 @@ bool_ get_item_floor(int *cp, cptr pmt, cptr str, int mode)
n2 = I2A(e2 - INVEN_WIELD);
/* Redraw */
- show_equip();
+ show_equip(filter);
}
/* Floor screen */
@@ -5441,7 +4918,7 @@ bool_ get_item_floor(int *cp, cptr pmt, cptr str, int mode)
n2 = I2A(k - floor_top);
/* Redraw */
- show_floor(p_ptr->py, p_ptr->px);
+ show_floor(p_ptr->py, p_ptr->px, filter);
}
/* Viewing inventory */
@@ -5507,8 +4984,8 @@ bool_ get_item_floor(int *cp, cptr pmt, cptr str, int mode)
}
}
- /* Extra? */
- if (extra)
+ /* Do we allow selection by name? */
+ if (select_by_name)
{
strcat(out_val, " @ for extra selection,");
}
@@ -5661,7 +5138,7 @@ bool_ get_item_floor(int *cp, cptr pmt, cptr str, int mode)
}
/* Validate the item */
- if (!get_item_okay(k))
+ if (!get_item_okay(k, filter))
{
bell();
break;
@@ -5720,7 +5197,7 @@ bool_ get_item_floor(int *cp, cptr pmt, cptr str, int mode)
}
/* Validate the item */
- if (!get_item_okay(k))
+ if (!get_item_okay(k, filter))
{
bell();
break;
@@ -5742,11 +5219,15 @@ bool_ get_item_floor(int *cp, cptr pmt, cptr str, int mode)
case '@':
{
- int i;
-
- if (extra && get_item_extra_hook(&i))
+ // Ignore if not "enabled"
+ if (!select_by_name)
{
- (*cp) = i;
+ break;
+ }
+ // Find by name
+ if (auto i = select_by_name(filter))
+ {
+ (*cp) = *i;
item = TRUE;
done = TRUE;
}
@@ -5803,7 +5284,7 @@ bool_ get_item_floor(int *cp, cptr pmt, cptr str, int mode)
}
/* Validate the item */
- if ((k >= 0) && !get_item_okay(k))
+ if ((k >= 0) && !get_item_okay(k, filter))
{
bell();
break;
@@ -5835,12 +5316,6 @@ bool_ get_item_floor(int *cp, cptr pmt, cptr str, int mode)
/* Fix the screen */
screen_load();
- /* Forget the item_tester_tval restriction */
- item_tester_tval = 0;
-
- /* Forget the item_tester_hook restriction */
- item_tester_hook = NULL;
-
/* Track */
if (item && done)
{
@@ -5855,7 +5330,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();
@@ -5929,17 +5403,16 @@ bool_ get_item_floor(int *cp, cptr pmt, cptr str, int mode)
* We always erase the prompt when we are done, leaving a blank line,
* or a warning message, if appropriate, if no items are available.
*/
-bool_ get_item(int *cp, cptr pmt, cptr str, int mode)
+bool_ get_item(int *cp, cptr pmt, cptr str, int mode, object_filter_t const &filter, select_by_name_t const &select_by_name)
{
automatizer_create = FALSE;
-
- return get_item_floor(cp, pmt, str, mode);
+ return get_item_floor(cp, pmt, str, mode, filter, select_by_name);
}
/*
* Hook to determine if an object is getable
*/
-static bool_ item_tester_hook_getable(object_type *o_ptr)
+static bool item_tester_hook_getable(object_type const *o_ptr)
{
if (!inven_carry_okay(o_ptr)) return (FALSE);
@@ -6011,7 +5484,7 @@ int wear_ammo(object_type *o_ptr)
p_ptr->update |= (PU_MANA);
/* Redraw monster hitpoint */
- p_ptr->redraw |= (PR_MH);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
@@ -6025,21 +5498,19 @@ int wear_ammo(object_type *o_ptr)
*/
void pickup_ammo()
{
- s16b this_o_idx, next_o_idx = 0, slot;
- char o_name[80];
+ /* Copy list of objects since we're manipulating the list */
+ auto const object_idxs(cave[p_ptr->py][p_ptr->px].o_idxs);
/* 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)
+ for (auto const this_o_idx: object_idxs)
{
- object_type * o_ptr;
-
/* Acquire object */
- o_ptr = &o_list[this_o_idx];
+ object_type *o_ptr = &o_list[this_o_idx];
if (object_similar(o_ptr, &p_ptr->inventory[INVEN_AMMO]))
{
msg_print("You add the ammo to your quiver.");
- slot = wear_ammo(o_ptr);
+ s16b slot = wear_ammo(o_ptr);
if (slot != -1)
{
@@ -6047,6 +5518,7 @@ void pickup_ammo()
o_ptr = &p_ptr->inventory[slot];
/* Describe the object */
+ char o_name[80];
object_desc(o_name, o_ptr, TRUE, 3);
/* Message */
@@ -6056,51 +5528,35 @@ void pickup_ammo()
delete_object_idx(this_o_idx);
}
}
-
- /* Acquire next object */
- next_o_idx = o_ptr->next_o_idx;
}
}
-/*
- * Make the player carry everything in a grid
- *
- * If "pickup" is FALSE then only gold will be picked up
- *
- * This is called by py_pickup() when easy_floor is TRUE.
+/**
+ * Check for encumberance if player were to pick up
+ * given item.
*/
-bool_ can_carry_heavy(object_type *o_ptr)
+static bool can_carry_heavy(object_type const *o_ptr)
{
- /* Query if object is heavy */
- if (prompt_pickup_heavy)
- {
- int i, j;
- int old_enc = 0;
- int new_enc = 0;
+ /* Extract the "weight limit" (in tenth pounds) */
+ int i = weight_limit();
- /* Extract the "weight limit" (in tenth pounds) */
- i = weight_limit();
+ /* Calculate current encumbarance */
+ int j = calc_total_weight();
- /* Calculate current encumbarance */
- j = calc_total_weight();
+ /* Apply encumbarance from weight */
+ int old_enc = 0;
+ if (j > i / 2) old_enc = ((j - (i / 2)) / (i / 10));
- /* Apply encumbarance from weight */
- if (j > i / 2) old_enc = ((j - (i / 2)) / (i / 10));
+ /* Increase the weight, recalculate encumbarance */
+ j += (o_ptr->number * o_ptr->weight);
- /* Increase the weight, recalculate encumbarance */
- j += (o_ptr->number * o_ptr->weight);
+ /* Apply encumbarance from weight */
+ int new_enc = 0;
+ if (j > i / 2) new_enc = ((j - (i / 2)) / (i / 10));
- /* Apply encumbarance from weight */
- if (j > i / 2) new_enc = ((j - (i / 2)) / (i / 10));
-
- /* Should we query? */
- if (new_enc > old_enc)
- {
- return (FALSE);
- }
- }
- return (TRUE);
+ /* If the encumberance is the same, then we pick up without prompt */
+ return (new_enc <= old_enc);
}
/* Do the actuall picking up */
@@ -6131,9 +5587,14 @@ void object_pickup(int this_o_idx)
/* Pick up object */
else
{
- /* Tell the scripts */
- 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];
@@ -6172,60 +5633,19 @@ void object_pickup(int this_o_idx)
}
-void py_pickup_floor(int pickup)
+static void absorb_gold(cave_type const *c_ptr)
{
- s16b this_o_idx, next_o_idx = 0;
-
- char o_name[80] = "";
- object_type *o_ptr = 0;
-
- int floor_num = 0, floor_o_idx = 0;
-
- bool_ do_pickup = TRUE;
-
- bool_ do_ask = TRUE;
-
- /* Hack -- ignore monster traps */
- if (cave[p_ptr->py][p_ptr->px].feat == FEAT_MON_TRAP) return;
-
- /* Try to grab ammo */
- pickup_ammo();
-
- /* Mega Hack -- If we have auto-Id, do an ID sweep *before* squleching,
- * so that we don't have to walk over things twice to get them
- * squelched. --dsb */
- if (p_ptr->auto_id)
- {
- this_o_idx = cave[p_ptr->py][p_ptr->px].o_idx;
-
- for (; this_o_idx; this_o_idx = next_o_idx)
- {
- /* Aquire the object */
- o_ptr = &o_list[this_o_idx];
-
- /* Acquire the next object index */
- next_o_idx = o_ptr->next_o_idx;
-
- /* Identify Object */
- object_aware(o_ptr);
- object_known(o_ptr);
- }
- }
+ /* Copy list of objects since we're going to manipulate the list itself */
+ auto const object_idxs(c_ptr->o_idxs);
- /* Squeltch the floor */
- squeltch_grid();
-
- /* 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)
+ /* Go through everything */
+ for (auto const this_o_idx: object_idxs)
{
/* Acquire object */
- o_ptr = &o_list[this_o_idx];
-
- /* Acquire next object */
- next_o_idx = o_ptr->next_o_idx;
+ object_type *o_ptr = &o_list[this_o_idx];
/* Hack -- disturb */
- disturb(0, 0);
+ disturb();
/* Pick up gold */
if (o_ptr->tval == TV_GOLD)
@@ -6234,152 +5654,181 @@ void py_pickup_floor(int pickup)
object_desc(goldname, o_ptr, TRUE, 3);
/* Message */
msg_format("You have found %ld gold pieces worth of %s.",
- (long)o_ptr->pval, goldname);
+ (long)o_ptr->pval, goldname);
/* Collect the gold */
p_ptr->au += o_ptr->pval;
/* Redraw gold */
- p_ptr->redraw |= (PR_GOLD);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
/* Delete the gold */
delete_object_idx(this_o_idx);
-
- continue;
}
+ }
+}
+static void sense_floor(cave_type const *c_ptr)
+{
+ /* Build a list of the floor objects. */
+ std::vector<int> floor_object_idxs;
+ {
+ /* Reserve the correct number of slots */
+ floor_object_idxs.reserve(c_ptr->o_idxs.size());
+ /* Fill in the indexes */
+ for (auto const this_o_idx: c_ptr->o_idxs)
{
- char testdesc[80];
+ // Note the "-"! We need it for get_object()
+ // lookups to function correctly.
+ floor_object_idxs.push_back(0 - this_o_idx);
+ }
+ }
- object_desc(testdesc, o_ptr, TRUE, 3);
- if (0 != strncmp(testdesc, "(nothing)", 80))
- {
- strncpy(o_name, testdesc, 80);
- }
+ /* Mega Hack -- If we have auto-Id, do an ID sweep *before* squleching,
+ * so that we don't have to walk over things twice to get them
+ * squelched. --dsb */
+ if (p_ptr->auto_id)
+ {
+ for (auto const o_idx: floor_object_idxs)
+ {
+ object_type *o_ptr = get_object(o_idx);
+ object_aware(o_ptr);
+ object_known(o_ptr);
}
+ }
- /* Count non-gold */
- floor_num++;
+ /* Sense floor tile */
+ sense_objects(floor_object_idxs);
+}
- /* Remember this index */
- floor_o_idx = this_o_idx;
- }
+void py_pickup_floor(int pickup)
+{
+ /* Get the tile */
+ auto c_ptr = &cave[p_ptr->py][p_ptr->px];
+
+ /* Try to grab ammo */
+ pickup_ammo();
+
+ /* Auto-ID and pseudo-ID */
+ sense_floor(c_ptr);
+
+ /* Squeltch the floor */
+ squeltch_grid();
- /* There were no non-gold items */
- if (!floor_num) return;
+ /* Absorb gold on the tile */
+ absorb_gold(&cave[p_ptr->py][p_ptr->px]);
- /* Mention number of items */
- if (!pickup)
+ /* We handle 0, 1, or "many" items cases separately */
+ if (c_ptr->o_idxs.empty())
+ {
+ /* Nothing to do */
+ }
+ else if (c_ptr->o_idxs.size() == 1)
{
- /* One item */
- if (floor_num == 1)
+ /* Acquire object */
+ auto floor_o_idx = c_ptr->o_idxs.front();
+ auto o_ptr = &o_list[floor_o_idx];
+
+ /* Describe or pick up? */
+ if (!pickup)
{
- /* Acquire object */
- o_ptr = &o_list[floor_o_idx];
+ /* Describe */
+ char o_name[80] = "";
+ object_desc(o_name, o_ptr, TRUE, 3);
/* Message */
msg_format("You see %s.", o_name);
}
-
- /* Multiple items */
else
{
- /* Message */
- msg_format("You see a pile of %d items.", floor_num);
- }
+ /* Are we actually going to pick up? */
+ bool_ do_pickup = TRUE;
- /* Done */
- return;
- }
-
- /* One item */
- if (floor_num == 1)
- {
- /* Hack -- query every item */
- if (carry_query_flag || (!can_carry_heavy(&o_list[floor_o_idx])))
- {
- if (!inven_carry_okay(o_ptr) && !object_similar(o_ptr, &p_ptr->inventory[INVEN_AMMO]))
+ /* Hack -- query every item */
+ if (options->carry_query_flag || !can_carry_heavy(&o_list[floor_o_idx]))
{
+ char o_name[80] = "";
object_desc(o_name, o_ptr, TRUE, 3);
- msg_format("You have no room for %s.", o_name);
- do_pickup = FALSE;
+
+ if (!inven_carry_okay(o_ptr) && !object_similar(o_ptr, &p_ptr->inventory[INVEN_AMMO]))
+ {
+ msg_format("You have no room for %s.", o_name);
+ return; /* Done */
+ }
+ else
+ {
+ char out_val[160];
+ sprintf(out_val, "Pick up %s? ", o_name);
+ do_pickup = get_check(out_val);
+ }
}
- else
+
+ /* Just pick it up; unless it's a symbiote and we don't have Symbiosis */
+ if (do_pickup && ((o_list[floor_o_idx].tval != TV_HYPNOS) || (get_skill(SKILL_SYMBIOTIC))))
{
- char out_val[160];
- sprintf(out_val, "Pick up %s? ", o_name);
- do_pickup = get_check(out_val);
+ object_pickup(floor_o_idx);
}
}
-
- /* Don't ask */
- do_ask = FALSE;
-
- if ((o_list[floor_o_idx].tval == TV_HYPNOS) && (!get_skill(SKILL_SYMBIOTIC)))
- do_pickup = FALSE;
- else
- this_o_idx = floor_o_idx;
}
-
- /* Ask */
- if (do_ask)
+ else
{
- cptr q, s;
-
- int item;
-
- /* Get an item */
-
- item_tester_hook = item_tester_hook_getable;
-
- q = "Get which item? ";
- s = "You have no room in your pack for any of the items here.";
- if (get_item(&item, q, s, (USE_FLOOR)))
+ /* Describe or pick up? */
+ if (!pickup)
{
- this_o_idx = 0 - item;
-
- if (!can_carry_heavy(&o_list[this_o_idx]))
+ /* Message */
+ msg_format("You see a pile of %d items.", c_ptr->o_idxs.size());
+ }
+ else
+ {
+ /* Prompt for the item to pick up */
+ cptr q = "Get which item? ";
+ cptr s = "You have no room in your pack for any of the items here.";
+ int item;
+ if (get_item(&item, q, s, (USE_FLOOR), item_tester_hook_getable))
{
- char out_val[160];
+ s16b this_o_idx = 0 - item;
- /* Describe the object */
- object_desc(o_name, &o_list[this_o_idx], TRUE, 3);
+ bool_ do_pickup = TRUE;
+ if (!can_carry_heavy(&o_list[this_o_idx]))
+ {
+ /* Describe the object */
+ char o_name[80] = "";
+ object_desc(o_name, &o_list[this_o_idx], TRUE, 3);
+
+ /* Prompt */
+ char out_val[160];
+ sprintf(out_val, "Pick up %s? ", o_name);
+ do_pickup = get_check(out_val);
+ }
- sprintf(out_val, "Pick up %s? ", o_name);
- do_pickup = get_check(out_val);
+ /* Pick up the item */
+ if (do_pickup)
+ {
+ object_pickup(this_o_idx);
+ }
}
}
- else
- {
- do_pickup = FALSE;
- }
- }
-
- /* Pick up the item */
- if (do_pickup)
- {
- object_pickup(this_o_idx);
}
}
/* Add a flags group */
-void gain_flag_group(object_type *o_ptr, bool_ silent)
+static void gain_flag_group(object_type *o_ptr)
{
int grp = 0;
int tries = 1000;
while (tries--)
{
- grp = rand_int(MAX_FLAG_GROUP);
+ grp = rand_int(flags_groups().size());
/* If we already got this group continue */
if (o_ptr->pval3 & BIT(grp)) continue;
/* Not enough points ? */
- if (flags_groups[grp].price > o_ptr->pval2) continue;
+ if (flags_groups()[grp].price > o_ptr->pval2) continue;
/* Ok, enough points and not already got it */
break;
@@ -6388,132 +5837,91 @@ void gain_flag_group(object_type *o_ptr, bool_ silent)
/* Ack, nothing found */
if (tries <= 1) return;
- o_ptr->pval2 -= flags_groups[grp].price;
+ o_ptr->pval2 -= flags_groups()[grp].price;
o_ptr->pval3 |= BIT(grp);
- if (!silent)
+ /* Message */
{
char o_name[80];
object_desc(o_name, o_ptr, FALSE, 0);
- msg_format("%s gains access to the %s realm.", o_name, flags_groups[grp].name);
+ msg_format("%s gains access to the %s realm.", o_name, flags_groups()[grp].name);
}
}
-u32b get_flag(object_type *o_ptr, int grp, int k)
+static object_flag_set get_flag(object_type *o_ptr, int grp)
{
- u32b f = 0, flag_set = 0;
int tries = 1000;
- u32b f1, f2, f3, f4, f5, esp, flag_test;
-
- /* Extract some flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
/* get the corresponding flag set of the group */
- switch (k)
- {
- case 0:
- flag_set = flags_groups[grp].flags1;
- flag_test = f1;
- break;
- case 1:
- flag_set = flags_groups[grp].flags2;
- flag_test = f2;
- break;
- case 2:
- flag_set = flags_groups[grp].flags3;
- flag_test = f3;
- break;
- case 3:
- flag_set = flags_groups[grp].flags4;
- flag_test = f4;
- break;
- case 4:
- flag_set = flags_groups[grp].esp;
- flag_test = esp;
- break;
- default:
- flag_set = flags_groups[grp].flags1;
- flag_test = f1;
- break;
- }
+ auto const flag_set = flags_groups()[grp].flags;
+ auto const flag_test = object_flags(o_ptr);
/* If no flags, no need to look */
- if (!count_bits(flag_set)) return 0;
+ if (flag_set.empty())
+ {
+ return object_flag_set();
+ }
while (tries--)
{
- /* get a random flag */
- f = BIT(rand_int(32));
+ // Choose a random flag
+ auto const f = object_flag_set::make_bit(rand_int(object_flag_set::nbits));
- /* is it part of the group */
- if (!(f & flag_set)) continue;
+ // Ignore if not part of the group
+ if (!(f & flag_set))
+ {
+ continue;
+ }
- /* Already got it */
- if (f & flag_test) continue;
+ // Ignore if already present
+ if (f & flag_test)
+ {
+ continue;
+ }
- /* Ok one */
- break;
+ // Got a match!
+ return f;
}
- if (tries <= 1) return (0);
- else return (f);
+ // Exhausted the number of tries
+ return object_flag_set();
}
/* Add a flags from a flag group */
-void gain_flag_group_flag(object_type *o_ptr, bool_ silent)
+static void gain_flag_group_flag(object_type *o_ptr)
{
- int grp = 0, k = 0;
- u32b f = 0;
- int tries = 20000;
-
- if (!count_bits(o_ptr->pval3)) return;
-
- while (tries--)
+ // Try a "few" times to see if we can't find a flag.
+ for (int tries = 20000; tries > 0; tries--)
{
- /* Get a flag set */
- k = rand_int(5);
-
- /* get a flag group */
- grp = rand_int(MAX_FLAG_GROUP);
-
- if (!(BIT(grp) & o_ptr->pval3)) continue;
+ // Choose a random flag group
+ auto grp = rand_int(flags_groups().size());
- /* Return a flag from the group/set */
- f = get_flag(o_ptr, grp, k);
+ // If that group isn't available to the object, then choose a new one.
+ if (!(BIT(grp) & o_ptr->pval3))
+ {
+ continue;
+ }
- if (!f) continue;
+ // Get an as-yet unused flag from the group, if possible.
+ auto const f = get_flag(o_ptr, grp);
- break;
- }
-
- if (tries <= 1) return;
+ // If we couldn't find a flag, then we try again.
+ if (f.empty())
+ {
+ continue;
+ }
- switch (k)
- {
- case 0:
- o_ptr->art_flags1 |= f;
- break;
- case 1:
- o_ptr->art_flags2 |= f;
- break;
- case 2:
- o_ptr->art_flags3 |= f;
- break;
- case 3:
- o_ptr->art_flags4 |= f;
- break;
- case 4:
- o_ptr->art_esp |= f;
- break;
- }
+ // Got a flag; mix it into the object.
+ o_ptr->art_flags |= f;
- if (!silent)
- {
+ // Describe what happened
char o_name[80];
-
object_desc(o_name, o_ptr, FALSE, 0);
- msg_format("%s gains a new power from the %s realm.", o_name, flags_groups[grp].name);
+ msg_format("%s gains a new power from the %s realm.", o_name, flags_groups()[grp].name);
+
+ // We're done.
+ return;
}
}
@@ -6522,11 +5930,6 @@ void gain_flag_group_flag(object_type *o_ptr, bool_ silent)
*/
void object_gain_level(object_type *o_ptr)
{
- u32b f1, f2, f3, f4, f5, esp;
-
- /* Extract some flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
-
/* First it can gain some tohit and todam */
if ((o_ptr->tval == TV_AXE) || (o_ptr->tval == TV_SWORD) || (o_ptr->tval == TV_POLEARM) ||
(o_ptr->tval == TV_HAFTED) || (o_ptr->tval == TV_MSTAFF))
@@ -6545,20 +5948,35 @@ void object_gain_level(object_type *o_ptr)
o_ptr->to_h += 1;
o_ptr->pval2++;
- if (magik(NEW_GROUP_CHANCE)) gain_flag_group(o_ptr, FALSE);
+ if (magik(NEW_GROUP_CHANCE)) gain_flag_group(o_ptr);
}
else
{
- if (!o_ptr->pval3) gain_flag_group(o_ptr, FALSE);
+ // Gain a group if none are available.
+ if (!o_ptr->pval3)
+ {
+ gain_flag_group(o_ptr);
+ }
- gain_flag_group_flag(o_ptr, FALSE);
+ // Gain a flag
+ gain_flag_group_flag(o_ptr);
- if (!o_ptr->pval) o_ptr->pval = 1;
+ // Increase/grant PVAL
+ if (!o_ptr->pval)
+ {
+ o_ptr->pval = 1;
+ }
else
{
- while (magik(20 - (o_ptr->pval * 2))) o_ptr->pval++;
+ while (magik(20 - (o_ptr->pval * 2)))
+ {
+ o_ptr->pval++;
+ }
- if (o_ptr->pval > 5) o_ptr->pval = 5;
+ if (o_ptr->pval > 5)
+ {
+ o_ptr->pval = 5;
+ }
}
}
}
@@ -6570,78 +5988,121 @@ void object_gain_level(object_type *o_ptr)
*/
bool_ wield_set(s16b a_idx, s16b set_idx, bool_ silent)
{
- set_type *s_ptr = &set_info[set_idx];
- int i;
+ auto &set_info = game->edit_data.set_info;
+ auto const &a_info = game->edit_data.a_info;
if ( -1 == a_info[a_idx].set) return (FALSE);
+
+ auto s_ptr = &set_info[set_idx];
+
+ int i;
for (i = 0; i < s_ptr->num; i++)
- if (a_idx == s_ptr->arts[i].a_idx) break;
+ {
+ if (a_idx == s_ptr->arts[i].a_idx)
+ {
+ break;
+ }
+ }
+
if (!s_ptr->arts[i].present)
{
s_ptr->num_use++;
s_ptr->arts[i].present = TRUE;
- if (s_ptr->num_use > s_ptr->num) msg_print("ERROR!! s_ptr->num_use > s_ptr->use");
- else if ((s_ptr->num_use == s_ptr->num) && (!silent)) cmsg_format(TERM_GREEN, "%s item set completed.", s_ptr->name + set_name);
+ if (s_ptr->num_use > s_ptr->num)
+ {
+ msg_print("ERROR!! s_ptr->num_use > s_ptr->use");
+ }
+ else if ((s_ptr->num_use == s_ptr->num) && (!silent))
+ {
+ cmsg_format(TERM_GREEN, "%s item set completed.", s_ptr->name.c_str());
+ }
return (TRUE);
}
+
return (FALSE);
}
bool_ takeoff_set(s16b a_idx, s16b set_idx)
{
- set_type *s_ptr = &set_info[set_idx];
- int i;
+ auto &set_info = game->edit_data.set_info;
+ auto const &a_info = game->edit_data.a_info;
if ( -1 == a_info[a_idx].set) return (FALSE);
+
+ auto s_ptr = &set_info[set_idx];
+
+ int i;
for (i = 0; i < s_ptr->num; i++)
- if (a_idx == s_ptr->arts[i].a_idx) break;
+ {
+ if (a_idx == s_ptr->arts[i].a_idx)
+ {
+ break;
+ }
+ }
if (s_ptr->arts[i].present)
{
s_ptr->arts[i].present = FALSE;
+
+ assert(s_ptr->num_use > 0);
s_ptr->num_use--;
- if (s_ptr->num_use == 255) msg_print("ERROR!! s_ptr->num_use < 0");
- if (s_ptr->num_use == s_ptr->num - 1) cmsg_format(TERM_GREEN, "%s item set not complete anymore.", s_ptr->name + set_name);
+ if (s_ptr->num_use == s_ptr->num - 1)
+ {
+ cmsg_format(TERM_GREEN, "%s item set not complete anymore.", s_ptr->name.c_str());
+ }
+
return (TRUE);
}
+
return (FALSE);
}
-bool_ apply_set(s16b a_idx, s16b set_idx)
+void apply_set(s16b a_idx, s16b set_idx)
{
- set_type *s_ptr = &set_info[set_idx];
- int i, j;
+ auto const &set_info = game->edit_data.set_info;
+ auto const &a_info = game->edit_data.a_info;
- if ( -1 == a_info[a_idx].set) return (FALSE);
+ if ( -1 == a_info[a_idx].set)
+ {
+ return;
+ }
+
+ auto s_ptr = &set_info[set_idx];
+
+ int i;
for (i = 0; i < s_ptr->num; i++)
- if (a_idx == s_ptr->arts[i].a_idx) break;
+ {
+ if (a_idx == s_ptr->arts[i].a_idx)
+ {
+ break;
+ }
+ }
+
if (s_ptr->arts[i].present)
{
- for (j = 0; j < s_ptr->num_use; j++)
+ for (int j = 0; j < s_ptr->num_use; j++)
{
- apply_flags(s_ptr->arts[i].flags1[j],
- s_ptr->arts[i].flags2[j],
- s_ptr->arts[i].flags3[j],
- s_ptr->arts[i].flags4[j],
- s_ptr->arts[i].flags5[j],
- s_ptr->arts[i].esp[j],
+ apply_flags(s_ptr->arts[i].flags[j],
s_ptr->arts[i].pval[j],
0, 0, 0, 0);
}
- return (TRUE);
}
- return (FALSE);
}
-bool_ apply_flags_set(s16b a_idx, s16b set_idx,
- u32b *f1, u32b *f2, u32b *f3, u32b *f4, u32b *f5, u32b *esp)
+static void apply_flags_set(s16b a_idx, s16b set_idx, object_flag_set *f)
{
- set_type *s_ptr = &set_info[set_idx];
- int i, j;
+ auto const &set_info = game->edit_data.set_info;
+ auto const &a_info = game->edit_data.a_info;
- if ( -1 == a_info[a_idx].set) return (FALSE);
+ if ( -1 == a_info[a_idx].set)
+ {
+ return;
+ }
+ auto s_ptr = &set_info[set_idx];
+
+ int i;
for (i = 0; i < s_ptr->num; i++)
{
if (a_idx == s_ptr->arts[i].a_idx) break;
@@ -6649,21 +6110,125 @@ bool_ apply_flags_set(s16b a_idx, s16b set_idx,
if (s_ptr->arts[i].present)
{
- for (j = 0; j < s_ptr->num_use; j++)
+ for (int j = 0; j < s_ptr->num_use; j++)
{
- (*f1) |= s_ptr->arts[i].flags1[j];
- (*f2) |= s_ptr->arts[i].flags2[j];
- (*f3) |= s_ptr->arts[i].flags3[j];
- (*f4) |= s_ptr->arts[i].flags4[j];
- (*f5) |= s_ptr->arts[i].flags5[j];
- (*esp) |= s_ptr->arts[i].esp[j];
+ (*f) |= s_ptr->arts[i].flags[j];
}
- return (TRUE);
}
- return (FALSE);
}
+/*
+ * Return the "attr" for a given item.
+ * Use "flavor" if available.
+ * Default to user definitions.
+ */
+
+byte object_attr(object_type const *o_ptr)
+{
+ auto const &k_info = game->edit_data.k_info;
+ auto const &random_artifacts = game->random_artifacts;
+
+ if (o_ptr->tval == TV_RANDART)
+ {
+ return random_artifacts[o_ptr->sval].attr;
+ }
+ else if (k_info[o_ptr->k_idx].flavor)
+ {
+ return misc_to_attr[k_info[o_ptr->k_idx].flavor];
+ }
+ else
+ {
+ return k_info[o_ptr->k_idx].x_attr;
+ }
+}
+
+byte object_attr_default(object_type *o_ptr)
+{
+ auto const &k_info = game->edit_data.k_info;
+ auto const &random_artifacts = game->random_artifacts;
+
+ if (o_ptr->tval == TV_RANDART)
+ {
+ return random_artifacts[o_ptr->sval].attr;
+ }
+ else if (k_info[o_ptr->k_idx].flavor)
+ {
+ return misc_to_attr[k_info[o_ptr->k_idx].flavor];
+ }
+ else
+ {
+ return k_info[o_ptr->k_idx].d_attr;
+ }
+}
+
+/*
+ * Return the "char" for a given item.
+ * Use "flavor" if available.
+ * Default to user definitions.
+ */
+
+char object_char(object_type const *o_ptr)
+{
+ auto const &k_info = game->edit_data.k_info;
+
+ if (k_info[o_ptr->k_idx].flavor)
+ {
+ return misc_to_char[k_info[o_ptr->k_idx].flavor];
+ }
+ else
+ {
+ return k_info[o_ptr->k_idx].x_char;
+ }
+}
+
+char object_char_default(object_type const *o_ptr)
+{
+ auto const &k_info = game->edit_data.k_info;
+
+ if (k_info[o_ptr->k_idx].flavor)
+ {
+ return misc_to_char[k_info[o_ptr->k_idx].flavor];
+ }
+ else
+ {
+ return k_info[o_ptr->k_idx].d_char;
+ }
+}
+
+/**
+ * Is the given object an artifact?
+ */
+bool artifact_p(object_type const *o_ptr)
+{
+ auto const &k_info = game->edit_data.k_info;
+ return
+ (o_ptr->tval == TV_RANDART) ||
+ (o_ptr->name1 ? true : false) ||
+ (!o_ptr->artifact_name.empty()) ||
+ ((k_info[o_ptr->k_idx].flags & TR_NORM_ART) ? true : false);
+}
+/**
+ * Is the given object an ego item?
+ */
+bool ego_item_p(object_type const *o_ptr)
+{
+ return o_ptr->name2 || (o_ptr->name2b ? TRUE : FALSE);
+}
+/*
+ * Is the given object an ego item of the given type?
+ */
+bool is_ego_p(object_type const *o_ptr, s16b ego)
+{
+ return (o_ptr->name2 == ego) || (o_ptr->name2b == ego);
+}
+/**
+ * Is the given object identified as cursed?
+ */
+bool cursed_p(object_type const *o_ptr)
+{
+ return o_ptr->ident & (IDENT_CURSED);
+}
diff --git a/src/object1.hpp b/src/object1.hpp
new file mode 100644
index 00000000..8b9d6dc9
--- /dev/null
+++ b/src/object1.hpp
@@ -0,0 +1,49 @@
+#pragma once
+
+#include "h-basic.h"
+#include "object_filter.hpp"
+#include "object_flag_set.hpp"
+
+#include <boost/optional.hpp>
+#include <functional>
+
+typedef std::function<boost::optional<int>(object_filter_t const &filter)> select_by_name_t;
+
+byte get_item_letter_color(object_type const *o_ptr);
+void object_pickup(int this_o_idx);
+void apply_set(s16b a_idx, s16b set_idx);
+bool_ takeoff_set(s16b a_idx, s16b set_idx);
+bool_ wield_set(s16b a_idx, s16b set_idx, bool_ silent);
+bool_ verify(cptr prompt, int item);
+void flavor_init();
+void reset_visuals();
+int object_power(object_type *o_ptr);
+extern bool_ object_flags_no_set;
+object_flag_set object_flags(object_type const *o_ptr);
+object_flag_set object_flags_known(object_type const *o_ptr);
+
+s32b calc_object_need_exp(object_type const *o_ptr);
+void object_desc(char *buf, object_type const *o_ptr, int pref, int mode);
+void object_desc_store(char *buf, object_type *o_ptr, int pref, int mode);
+bool_ object_out_desc(object_type *o_ptr, FILE *fff, bool_ trim_down, bool_ wait_for_it);
+char index_to_label(int i);
+s16b wield_slot_ideal(object_type const *o_ptr, bool_ ideal);
+s16b wield_slot(object_type const *o_ptr);
+cptr describe_use(int i);
+void display_inven();
+void display_equip();
+void show_inven_full();
+void show_equip_full();
+void toggle_inven_equip();
+bool_ get_item(int *cp, cptr pmt, cptr str, int mode, object_filter_t const &filter = object_filter::True(), select_by_name_t const &select_by_name = select_by_name_t());
+cptr item_activation(object_type *o_ptr);
+void py_pickup_floor(int pickup);
+void object_gain_level(object_type *o_ptr);
+byte object_attr(object_type const *o_ptr);
+byte object_attr_default(object_type *o_ptr);
+char object_char(object_type const *o_ptr);
+char object_char_default(object_type const *o_ptr);
+bool artifact_p(object_type const *o_ptr);
+bool ego_item_p(object_type const *o_ptr);
+bool is_ego_p(object_type const *o_ptr, s16b ego);
+bool cursed_p(object_type const *o_ptr);
diff --git a/src/object2.c b/src/object2.cc
index 98afb815..2d6ea672 100644
--- a/src/object2.c
+++ b/src/object2.cc
@@ -1,7 +1,3 @@
-/* File: object2.c */
-
-/* Purpose: Object code, part 2 */
-
/*
* Copyright (c) 1989 James E. Wilson, Robert A. Koeneke
*
@@ -10,12 +6,55 @@
* included in all such copies.
*/
-#include "angband.h"
+#include "object2.hpp"
+
+#include "alloc_entry.hpp"
+#include "artifact_type.hpp"
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "spell_type.hpp"
+#include "device_allocation.hpp"
+#include "dungeon_info_type.hpp"
+#include "ego_flag.hpp"
+#include "ego_item_type.hpp"
+#include "feature_flag.hpp"
+#include "feature_type.hpp"
+#include "game.hpp"
+#include "hooks.hpp"
+#include "mimic.hpp"
+#include "monster2.hpp"
+#include "monster_race.hpp"
+#include "monster_race_flag.hpp"
+#include "monster_type.hpp"
+#include "object1.hpp"
+#include "object_flag.hpp"
+#include "object_flag_meta.hpp"
+#include "object_kind.hpp"
+#include "object_type.hpp"
+#include "options.hpp"
+#include "player_type.hpp"
+#include "randart.hpp"
+#include "randart_part_type.hpp"
+#include "skills.hpp"
+#include "spells2.hpp"
+#include "spells3.hpp"
+#include "spells5.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+#include "wilderness_map.hpp"
+#include "xtra1.hpp"
+#include "z-rand.hpp"
+
+#include <algorithm>
+#include <cassert>
+#include <type_traits>
+#include <vector>
/*
* Calculate the player's total inventory weight.
*/
-s32b calc_total_weight(void)
+s32b calc_total_weight()
{
int i;
s32b total;
@@ -33,123 +72,36 @@ s32b calc_total_weight(void)
*/
void excise_object_idx(int o_idx)
{
- object_type *j_ptr;
-
- s16b this_o_idx, next_o_idx = 0;
-
- s16b prev_o_idx = 0;
-
+ /* Function to remove from list */
+ auto remove_it = [o_idx](std::vector<s16b> *v) -> void {
+ v->erase(
+ std::remove(
+ v->begin(),
+ v->end(),
+ o_idx),
+ v->end());
+ };
/* Object */
- j_ptr = &o_list[o_idx];
+ object_type *o_ptr = &o_list[o_idx];
/* Monster */
- if (j_ptr->held_m_idx)
+ if (o_ptr->held_m_idx)
{
- monster_type *m_ptr;
-
/* Monster */
- m_ptr = &m_list[j_ptr->held_m_idx];
-
- /* Scan all objects in the grid */
- 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;
-
- /* Done */
- if (this_o_idx == o_idx)
- {
- /* No previous */
- if (prev_o_idx == 0)
- {
- /* Remove from list */
- m_ptr->hold_o_idx = next_o_idx;
- }
-
- /* Real previous */
- else
- {
- object_type *k_ptr;
-
- /* Previous object */
- k_ptr = &o_list[prev_o_idx];
-
- /* Remove from list */
- k_ptr->next_o_idx = next_o_idx;
- }
+ monster_type *m_ptr = &m_list[o_ptr->held_m_idx];
- /* Forget next pointer */
- o_ptr->next_o_idx = 0;
-
- /* Done */
- break;
- }
-
- /* Save prev_o_idx */
- prev_o_idx = this_o_idx;
- }
+ /* Remove object from list of held objects, if present. */
+ remove_it(&m_ptr->hold_o_idxs);
}
-
/* Dungeon */
else
{
- cave_type *c_ptr;
-
- int y = j_ptr->iy;
- int x = j_ptr->ix;
-
/* Grid */
- c_ptr = &cave[y][x];
-
- /* 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;
-
- /* Done */
- if (this_o_idx == o_idx)
- {
- /* No previous */
- if (prev_o_idx == 0)
- {
- /* Remove from list */
- c_ptr->o_idx = next_o_idx;
- }
-
- /* Real previous */
- else
- {
- object_type *k_ptr;
-
- /* Previous object */
- k_ptr = &o_list[prev_o_idx];
-
- /* Remove from list */
- k_ptr->next_o_idx = next_o_idx;
- }
-
- /* Forget next pointer */
- o_ptr->next_o_idx = 0;
-
- /* Done */
- break;
- }
+ cave_type *c_ptr = &cave[o_ptr->iy][o_ptr->ix];
- /* Save prev_o_idx */
- prev_o_idx = this_o_idx;
- }
+ /* Remove object from list of objects in the grid, if present. */
+ remove_it(&c_ptr->o_idxs);
}
}
@@ -195,28 +147,17 @@ void delete_object_idx(int o_idx)
*/
void delete_object(int y, int x)
{
- cave_type *c_ptr;
-
- s16b this_o_idx, next_o_idx = 0;
-
-
/* Refuse "illegal" locations */
if (!in_bounds(y, x)) return;
-
/* Grid */
- c_ptr = &cave[y][x];
+ cave_type *c_ptr = &cave[y][x];
/* Scan all objects in the grid */
- for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
+ for (auto const this_o_idx: c_ptr->o_idxs)
{
- object_type * o_ptr;
-
/* Acquire object */
- o_ptr = &o_list[this_o_idx];
-
- /* Acquire next object */
- next_o_idx = o_ptr->next_o_idx;
+ object_type *o_ptr = &o_list[this_o_idx];
/* Wipe the object */
object_wipe(o_ptr);
@@ -226,7 +167,7 @@ void delete_object(int y, int x)
}
/* Objects are gone */
- c_ptr->o_idx = 0;
+ c_ptr->o_idxs.clear();
/* Visual update */
lite_spot(y, x);
@@ -238,76 +179,44 @@ void delete_object(int y, int x)
*/
static void compact_objects_aux(int i1, int i2)
{
- int i;
-
- cave_type *c_ptr;
-
- object_type *o_ptr;
-
-
/* Do nothing */
if (i1 == i2) return;
-
- /* Repair objects */
- for (i = 1; i < o_max; i++)
- {
- /* Acquire object */
- o_ptr = &o_list[i];
-
- /* Skip "dead" objects */
- if (!o_ptr->k_idx) continue;
-
- /* Repair "next" pointers */
- if (o_ptr->next_o_idx == i1)
- {
- /* Repair */
- o_ptr->next_o_idx = i2;
- }
- }
-
-
/* Acquire object */
- o_ptr = &o_list[i1];
-
+ object_type *o_ptr = &o_list[i1];
/* Monster */
if (o_ptr->held_m_idx)
{
- monster_type *m_ptr;
-
/* Acquire monster */
- m_ptr = &m_list[o_ptr->held_m_idx];
+ monster_type *m_ptr = &m_list[o_ptr->held_m_idx];
/* Repair monster */
- if (m_ptr->hold_o_idx == i1)
+ for (auto &hold_o_idx: m_ptr->hold_o_idxs)
{
- /* Repair */
- m_ptr->hold_o_idx = i2;
+ if (hold_o_idx == i1)
+ {
+ hold_o_idx = i2;
+ }
}
}
/* Dungeon */
else
{
- int y, x;
-
- /* Acquire location */
- y = o_ptr->iy;
- x = o_ptr->ix;
-
/* Acquire grid */
- c_ptr = &cave[y][x];
+ cave_type *c_ptr = &cave[o_ptr->iy][o_ptr->ix];
/* Repair grid */
- if (c_ptr->o_idx == i1)
+ for (auto &o_idx: c_ptr->o_idxs)
{
- /* Repair */
- c_ptr->o_idx = i2;
+ if (o_idx == i1)
+ {
+ o_idx = i2;
+ }
}
}
-
/* Structure copy */
o_list[i2] = o_list[i1];
@@ -330,6 +239,8 @@ static void compact_objects_aux(int i1, int i2)
*/
void compact_objects(int size)
{
+ auto const &k_info = game->edit_data.k_info;
+
int i, y, x, num;
int cur_lev, cur_dis, chance;
@@ -359,7 +270,7 @@ void compact_objects(int size)
{
object_type *o_ptr = &o_list[i];
- object_kind *k_ptr = &k_info[o_ptr->k_idx];
+ auto k_ptr = &k_info[o_ptr->k_idx];
/* Skip dead objects */
if (!o_ptr->k_idx) continue;
@@ -402,7 +313,7 @@ void compact_objects(int size)
chance = chance - cur_lev / 2;
/* Artifacts */
- if ( artifact_p(o_ptr) || o_ptr->art_name )
+ if (artifact_p(o_ptr))
{
/* Artifacts are "immune if the level is lower */
/* than 300 + artifact level */
@@ -410,7 +321,7 @@ void compact_objects(int size)
continue;
/* That's 400 + level for fixed artifacts */
- if ( (k_ptr->flags3 & TR3_NORM_ART) && cur_lev < 400 + k_ptr->level )
+ if ( (k_ptr->flags & TR_NORM_ART) && cur_lev < 400 + k_ptr->level )
continue;
/* Never protect if level is high enough; so we don't wipe a better artifact */
@@ -465,8 +376,11 @@ void compact_objects(int size)
* clear those fields for grids/monsters containing objects,
* and we clear it once for every such object.
*/
-void wipe_o_list(void)
+void wipe_o_list()
{
+ auto &k_info = game->edit_data.k_info;
+ auto &a_info = game->edit_data.a_info;
+
int i;
/* Delete the existing objects */
@@ -478,7 +392,7 @@ void wipe_o_list(void)
if (!o_ptr->k_idx) continue;
/* Mega-Hack -- preserve artifacts */
- if (!character_dungeon || p_ptr->preserve)
+ if (!character_dungeon || options->preserve)
{
/* Hack -- Preserve unknown artifacts */
if (artifact_p(o_ptr) && !object_known_p(o_ptr))
@@ -486,9 +400,9 @@ void wipe_o_list(void)
/* Mega-Hack -- Preserve the artifact */
if (o_ptr->tval == TV_RANDART)
{
- random_artifacts[o_ptr->sval].generated = FALSE;
+ game->random_artifacts[o_ptr->sval].generated = FALSE;
}
- else if (k_info[o_ptr->k_idx].flags3 & TR3_NORM_ART)
+ else if (k_info[o_ptr->k_idx].flags & TR_NORM_ART)
{
k_info[o_ptr->k_idx].artifact = FALSE;
}
@@ -502,13 +416,11 @@ void wipe_o_list(void)
/* Monster */
if (o_ptr->held_m_idx)
{
- monster_type *m_ptr;
-
/* Monster */
- m_ptr = &m_list[o_ptr->held_m_idx];
+ monster_type *m_ptr = &m_list[o_ptr->held_m_idx];
/* Hack -- see above */
- m_ptr->hold_o_idx = 0;
+ m_ptr->hold_o_idxs.clear();
}
/* Dungeon */
@@ -524,11 +436,11 @@ void wipe_o_list(void)
c_ptr = &cave[y][x];
/* Hack -- see above */
- c_ptr->o_idx = 0;
+ c_ptr->o_idxs.clear();
}
/* Wipe the object */
- o_ptr = WIPE(o_ptr, object_type);
+ object_wipe(o_ptr);
}
/* Reset "o_max" */
@@ -545,7 +457,7 @@ void wipe_o_list(void)
* This routine should almost never fail, but in case it does,
* we must be sure to handle "failure" of this routine.
*/
-s16b o_pop(void)
+s16b o_pop()
{
int i;
@@ -598,28 +510,25 @@ s16b o_pop(void)
/*
* Apply a "object restriction function" to the "object allocation table"
*/
-errr get_obj_num_prep(void)
+errr get_obj_num_prep()
{
- int i;
-
- /* Get the entry */
- alloc_entry *table = alloc_kind_table;
+ auto &alloc = game->alloc;
/* Scan the allocation table */
- for (i = 0; i < alloc_kind_size; i++)
+ for (auto &&entry: alloc.kind_table)
{
/* Accept objects which pass the restriction, if any */
- if (!get_obj_num_hook || (*get_obj_num_hook)(table[i].index))
+ if (!get_obj_num_hook || (*get_obj_num_hook)(entry.index))
{
/* Accept this object */
- table[i].prob2 = table[i].prob1;
+ entry.prob2 = entry.prob1;
}
/* Do not use this object */
else
{
/* Decline this object */
- table[i].prob2 = 0;
+ entry.prob2 = 0;
}
}
@@ -646,11 +555,13 @@ errr get_obj_num_prep(void)
*/
s16b get_obj_num(int level)
{
- int i, j, p;
+ auto const &k_info = game->edit_data.k_info;
+ auto &alloc = game->alloc;
+
+ std::size_t i, j;
+ int p;
int k_idx;
long value, total;
- object_kind *k_ptr;
- alloc_entry *table = alloc_kind_table;
/* Boost level */
@@ -669,51 +580,56 @@ s16b get_obj_num(int level)
total = 0L;
/* Process probabilities */
- for (i = 0; i < alloc_kind_size; i++)
+ for (i = 0; i < alloc.kind_table.size(); i++)
{
+ auto &entry = alloc.kind_table[i];
+
/* Objects are sorted by depth */
- if (table[i].level > level) break;
+ if (entry.level > level) break;
/* Default */
- table[i].prob3 = 0;
+ entry.prob3 = 0;
/* Access the index */
- k_idx = table[i].index;
+ k_idx = entry.index;
/* Access the actual kind */
- k_ptr = &k_info[k_idx];
+ auto k_ptr = &k_info[k_idx];
/* Hack -- prevent embedded chests */
if (opening_chest && (k_ptr->tval == TV_CHEST)) continue;
/* Accept */
- table[i].prob3 = table[i].prob2;
+ entry.prob3 = entry.prob2;
/* Total */
- total += table[i].prob3;
+ total += entry.prob3;
}
/* No legal objects */
if (total <= 0) return (0);
-
/* Pick an object */
value = rand_int(total);
/* Find the object */
- for (i = 0; i < alloc_kind_size; i++)
+ for (i = 0; i < alloc.kind_table.size(); i++)
{
+ auto &entry = alloc.kind_table[i];
+
/* Found the entry */
- if (value < table[i].prob3) break;
+ if (value < entry.prob3) break;
/* Decrement */
- value = value - table[i].prob3;
+ value = value - entry.prob3;
}
-
/* Power boost */
p = rand_int(100);
+ /* Shorthand */
+ auto &table = alloc.kind_table;
+
/* Try for a "better" object once (50%) or twice (10%) */
if (p < 60)
{
@@ -724,8 +640,9 @@ s16b get_obj_num(int level)
value = rand_int(total);
/* Find the monster */
- for (i = 0; i < alloc_kind_size; i++)
+ for (i = 0; i < table.size(); i++)
{
+
/* Found the entry */
if (value < table[i].prob3) break;
@@ -747,7 +664,7 @@ s16b get_obj_num(int level)
value = rand_int(total);
/* Find the object */
- for (i = 0; i < alloc_kind_size; i++)
+ for (i = 0; i < table.size(); i++)
{
/* Found the entry */
if (value < table[i].prob3) break;
@@ -805,6 +722,19 @@ void object_known(object_type *o_ptr)
+/*
+ * Determine if a given inventory item is "known"
+ * Test One -- Check for special "known" tag
+ * Test Two -- Check for "Easy Know" + "Aware"
+ */
+bool object_known_p(object_type const *o_ptr)
+{
+ auto const &k_info = game->edit_data.k_info;
+
+ return ((o_ptr->ident & (IDENT_KNOWN)) ||
+ (k_info[o_ptr->k_idx].easy_know && k_info[o_ptr->k_idx].aware));
+}
+
/*
@@ -812,10 +742,21 @@ void object_known(object_type *o_ptr)
*/
void object_aware(object_type *o_ptr)
{
+ auto &k_info = game->edit_data.k_info;
+
/* Fully aware of the effects */
k_info[o_ptr->k_idx].aware = TRUE;
}
+/**
+ * Is the player aware of the effects of the given object?
+ */
+bool object_aware_p(object_type const *o_ptr)
+{
+ auto const &k_info = game->edit_data.k_info;
+
+ return k_info[o_ptr->k_idx].aware;
+}
/*
@@ -823,19 +764,34 @@ void object_aware(object_type *o_ptr)
*/
void object_tried(object_type *o_ptr)
{
+ auto &k_info = game->edit_data.k_info;
+
/* Mark it as tried (even if "aware") */
k_info[o_ptr->k_idx].tried = TRUE;
}
+/**
+ * Has the given object been "tried"?
+ */
+bool object_tried_p(object_type const *o_ptr)
+{
+ auto const &k_info = game->edit_data.k_info;
+
+ return k_info[o_ptr->k_idx].tried;
+}
+
/*
* Return the "value" of an "unknown" item
* Make a guess at the value of non-aware items
*/
-static s32b object_value_base(object_type *o_ptr)
+static s32b object_value_base(object_type const *o_ptr)
{
- object_kind *k_ptr = &k_info[o_ptr->k_idx];
+ auto const &r_info = game->edit_data.r_info;
+ auto const &k_info = game->edit_data.k_info;
+
+ auto k_ptr = &k_info[o_ptr->k_idx];
/* Aware item -- use template cost */
if ((object_aware_p(o_ptr)) && (o_ptr->tval != TV_EGG)) return (k_ptr->cost);
@@ -882,7 +838,7 @@ static s32b object_value_base(object_type *o_ptr)
/* Eggs */
case TV_EGG:
{
- monster_race *r_ptr = &r_info[o_ptr->pval2];
+ auto r_ptr = &r_info[o_ptr->pval2];
/* Pay the monster level */
return (r_ptr->level * 100) + 100;
@@ -897,139 +853,139 @@ static s32b object_value_base(object_type *o_ptr)
}
/* Return the value of the flags the object has... */
-s32b flag_cost(object_type * o_ptr, int plusses)
+s32b flag_cost(object_type const *o_ptr, int plusses)
{
- s32b total = 0;
- u32b f1, f2, f3, f4, f5, esp;
-
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ auto const flags = object_flags(o_ptr);
- if (f5 & TR5_TEMPORARY)
+ if (flags & TR_TEMPORARY)
{
return 0;
}
- if (f4 & TR4_CURSE_NO_DROP)
+
+ if (flags & TR_CURSE_NO_DROP)
{
return 0;
}
- if (f1 & TR1_STR) total += (1000 * plusses);
- if (f1 & TR1_INT) total += (1000 * plusses);
- if (f1 & TR1_WIS) total += (1000 * plusses);
- if (f1 & TR1_DEX) total += (1000 * plusses);
- if (f1 & TR1_CON) total += (1000 * plusses);
- if (f1 & TR1_CHR) total += (250 * plusses);
- if (f1 & TR1_CHAOTIC) total += 10000;
- if (f1 & TR1_VAMPIRIC) total += 13000;
- if (f1 & TR1_STEALTH) total += (250 * plusses);
- if (f1 & TR1_SEARCH) total += (100 * plusses);
- if (f1 & TR1_INFRA) total += (150 * plusses);
- if (f1 & TR1_TUNNEL) total += (175 * plusses);
- if ((f1 & TR1_SPEED) && (plusses > 0))
+
+ s32b total = 0;
+
+ if (flags & TR_STR) total += (1000 * plusses);
+ if (flags & TR_INT) total += (1000 * plusses);
+ if (flags & TR_WIS) total += (1000 * plusses);
+ if (flags & TR_DEX) total += (1000 * plusses);
+ if (flags & TR_CON) total += (1000 * plusses);
+ if (flags & TR_CHR) total += (250 * plusses);
+ if (flags & TR_CHAOTIC) total += 10000;
+ if (flags & TR_VAMPIRIC) total += 13000;
+ if (flags & TR_STEALTH) total += (250 * plusses);
+ if (flags & TR_INFRA) total += (150 * plusses);
+ if (flags & TR_TUNNEL) total += (175 * plusses);
+ if ((flags & TR_SPEED) && (plusses > 0))
total += (10000 + (2500 * plusses));
- if ((f1 & TR1_BLOWS) && (plusses > 0))
+ if ((flags & TR_BLOWS) && (plusses > 0))
total += (10000 + (2500 * plusses));
- if (f1 & TR1_MANA) total += (1000 * plusses);
- if (f1 & TR1_SPELL) total += (2000 * plusses);
- if (f1 & TR1_SLAY_ANIMAL) total += 3500;
- if (f1 & TR1_SLAY_EVIL) total += 4500;
- if (f1 & TR1_SLAY_UNDEAD) total += 3500;
- if (f1 & TR1_SLAY_DEMON) total += 3500;
- if (f1 & TR1_SLAY_ORC) total += 3000;
- if (f1 & TR1_SLAY_TROLL) total += 3500;
- if (f1 & TR1_SLAY_GIANT) total += 3500;
- if (f1 & TR1_SLAY_DRAGON) total += 3500;
- if (f5 & TR5_KILL_DEMON) total += 5500;
- if (f5 & TR5_KILL_UNDEAD) total += 5500;
- if (f1 & TR1_KILL_DRAGON) total += 5500;
- if (f1 & TR1_VORPAL) total += 5000;
- if (f1 & TR1_IMPACT) total += 5000;
- if (f1 & TR1_BRAND_POIS) total += 7500;
- if (f1 & TR1_BRAND_ACID) total += 7500;
- if (f1 & TR1_BRAND_ELEC) total += 7500;
- if (f1 & TR1_BRAND_FIRE) total += 5000;
- if (f1 & TR1_BRAND_COLD) total += 5000;
- if (f2 & TR2_SUST_STR) total += 850;
- if (f2 & TR2_SUST_INT) total += 850;
- if (f2 & TR2_SUST_WIS) total += 850;
- if (f2 & TR2_SUST_DEX) total += 850;
- if (f2 & TR2_SUST_CON) total += 850;
- if (f2 & TR2_SUST_CHR) total += 250;
- if (f2 & TR2_INVIS) total += 3000;
- if (f2 & TR2_LIFE) total += (5000 * plusses);
- if (f2 & TR2_IM_ACID) total += 10000;
- if (f2 & TR2_IM_ELEC) total += 10000;
- if (f2 & TR2_IM_FIRE) total += 10000;
- if (f2 & TR2_IM_COLD) total += 10000;
- if (f2 & TR2_SENS_FIRE) total -= 100;
- if (f2 & TR2_REFLECT) total += 10000;
- if (f2 & TR2_FREE_ACT) total += 4500;
- if (f2 & TR2_HOLD_LIFE) total += 8500;
- if (f2 & TR2_RES_ACID) total += 1250;
- if (f2 & TR2_RES_ELEC) total += 1250;
- if (f2 & TR2_RES_FIRE) total += 1250;
- if (f2 & TR2_RES_COLD) total += 1250;
- if (f2 & TR2_RES_POIS) total += 2500;
- if (f2 & TR2_RES_FEAR) total += 2500;
- if (f2 & TR2_RES_LITE) total += 1750;
- if (f2 & TR2_RES_DARK) total += 1750;
- if (f2 & TR2_RES_BLIND) total += 2000;
- if (f2 & TR2_RES_CONF) total += 2000;
- if (f2 & TR2_RES_SOUND) total += 2000;
- if (f2 & TR2_RES_SHARDS) total += 2000;
- if (f2 & TR2_RES_NETHER) total += 2000;
- if (f2 & TR2_RES_NEXUS) total += 2000;
- if (f2 & TR2_RES_CHAOS) total += 2000;
- if (f2 & TR2_RES_DISEN) total += 10000;
- if (f3 & TR3_SH_FIRE) total += 5000;
- if (f3 & TR3_SH_ELEC) total += 5000;
- if (f3 & TR3_DECAY) total += 0;
- if (f3 & TR3_NO_TELE) total += 2500;
- if (f3 & TR3_NO_MAGIC) total += 2500;
- if (f3 & TR3_WRAITH) total += 250000;
- if (f3 & TR3_TY_CURSE) total -= 15000;
- if (f3 & TR3_EASY_KNOW) total += 0;
- if (f3 & TR3_HIDE_TYPE) total += 0;
- if (f3 & TR3_SHOW_MODS) total += 0;
- if (f3 & TR3_INSTA_ART) total += 0;
- if (f3 & TR3_LITE1) total += 750;
- if (f4 & TR4_LITE2) total += 1250;
- if (f4 & TR4_LITE3) total += 2750;
- if (f3 & TR3_SEE_INVIS) total += 2000;
- if (esp) total += (12500 * count_bits(esp));
- if (f3 & TR3_SLOW_DIGEST) total += 750;
- if (f3 & TR3_REGEN) total += 2500;
- if (f3 & TR3_XTRA_MIGHT) total += 2250;
- if (f3 & TR3_XTRA_SHOTS) total += 10000;
- if (f3 & TR3_IGNORE_ACID) total += 100;
- if (f3 & TR3_IGNORE_ELEC) total += 100;
- if (f3 & TR3_IGNORE_FIRE) total += 100;
- if (f3 & TR3_IGNORE_COLD) total += 100;
- if (f3 & TR3_ACTIVATE) total += 100;
- if (f3 & TR3_DRAIN_EXP) total -= 12500;
- if (f3 & TR3_TELEPORT)
+ if (flags & TR_MANA) total += (1000 * plusses);
+ if (flags & TR_SPELL) total += (2000 * plusses);
+ if (flags & TR_SLAY_ANIMAL) total += 3500;
+ if (flags & TR_SLAY_EVIL) total += 4500;
+ if (flags & TR_SLAY_UNDEAD) total += 3500;
+ if (flags & TR_SLAY_DEMON) total += 3500;
+ if (flags & TR_SLAY_ORC) total += 3000;
+ if (flags & TR_SLAY_TROLL) total += 3500;
+ if (flags & TR_SLAY_GIANT) total += 3500;
+ if (flags & TR_SLAY_DRAGON) total += 3500;
+ if (flags & TR_KILL_DEMON) total += 5500;
+ if (flags & TR_KILL_UNDEAD) total += 5500;
+ if (flags & TR_KILL_DRAGON) total += 5500;
+ if (flags & TR_VORPAL) total += 5000;
+ if (flags & TR_IMPACT) total += 5000;
+ if (flags & TR_BRAND_POIS) total += 7500;
+ if (flags & TR_BRAND_ACID) total += 7500;
+ if (flags & TR_BRAND_ELEC) total += 7500;
+ if (flags & TR_BRAND_FIRE) total += 5000;
+ if (flags & TR_BRAND_COLD) total += 5000;
+ if (flags & TR_SUST_STR) total += 850;
+ if (flags & TR_SUST_INT) total += 850;
+ if (flags & TR_SUST_WIS) total += 850;
+ if (flags & TR_SUST_DEX) total += 850;
+ if (flags & TR_SUST_CON) total += 850;
+ if (flags & TR_SUST_CHR) total += 250;
+ if (flags & TR_INVIS) total += 3000;
+ if (flags & TR_LIFE) total += (5000 * plusses);
+ if (flags & TR_IM_ACID) total += 10000;
+ if (flags & TR_IM_ELEC) total += 10000;
+ if (flags & TR_IM_FIRE) total += 10000;
+ if (flags & TR_IM_COLD) total += 10000;
+ if (flags & TR_SENS_FIRE) total -= 100;
+ if (flags & TR_REFLECT) total += 10000;
+ if (flags & TR_FREE_ACT) total += 4500;
+ if (flags & TR_HOLD_LIFE) total += 8500;
+ if (flags & TR_RES_ACID) total += 1250;
+ if (flags & TR_RES_ELEC) total += 1250;
+ if (flags & TR_RES_FIRE) total += 1250;
+ if (flags & TR_RES_COLD) total += 1250;
+ if (flags & TR_RES_POIS) total += 2500;
+ if (flags & TR_RES_FEAR) total += 2500;
+ if (flags & TR_RES_LITE) total += 1750;
+ if (flags & TR_RES_DARK) total += 1750;
+ if (flags & TR_RES_BLIND) total += 2000;
+ if (flags & TR_RES_CONF) total += 2000;
+ if (flags & TR_RES_SOUND) total += 2000;
+ if (flags & TR_RES_SHARDS) total += 2000;
+ if (flags & TR_RES_NETHER) total += 2000;
+ if (flags & TR_RES_NEXUS) total += 2000;
+ if (flags & TR_RES_CHAOS) total += 2000;
+ if (flags & TR_RES_DISEN) total += 10000;
+ if (flags & TR_SH_FIRE) total += 5000;
+ if (flags & TR_SH_ELEC) total += 5000;
+ if (flags & TR_DECAY) total += 0;
+ if (flags & TR_NO_TELE) total += 2500;
+ if (flags & TR_NO_MAGIC) total += 2500;
+ if (flags & TR_WRAITH) total += 250000;
+ if (flags & TR_TY_CURSE) total -= 15000;
+ if (flags & TR_EASY_KNOW) total += 0;
+ if (flags & TR_HIDE_TYPE) total += 0;
+ if (flags & TR_SHOW_MODS) total += 0;
+ if (flags & TR_INSTA_ART) total += 0;
+ if (flags & TR_LITE1) total += 750;
+ if (flags & TR_LITE2) total += 1250;
+ if (flags & TR_LITE3) total += 2750;
+ if (flags & TR_SEE_INVIS) total += 2000;
+ total += 12500 * ((flags & object_flags_esp()).count());
+ if (flags & TR_SLOW_DIGEST) total += 750;
+ if (flags & TR_REGEN) total += 2500;
+ if (flags & TR_XTRA_MIGHT) total += 2250;
+ if (flags & TR_XTRA_SHOTS) total += 10000;
+ if (flags & TR_IGNORE_ACID) total += 100;
+ if (flags & TR_IGNORE_ELEC) total += 100;
+ if (flags & TR_IGNORE_FIRE) total += 100;
+ if (flags & TR_IGNORE_COLD) total += 100;
+ if (flags & TR_ACTIVATE) total += 100;
+ if (flags & TR_DRAIN_EXP) total -= 12500;
+ if (flags & TR_TELEPORT)
{
if (o_ptr->ident & IDENT_CURSED)
total -= 7500;
else
total += 250;
}
- if (f3 & TR3_AGGRAVATE) total -= 10000;
- if (f3 & TR3_BLESSED) total += 750;
- if ((f3 & TR3_CURSED) && (o_ptr->ident & IDENT_CURSED)) total -= 5000;
- if ((f3 & TR3_HEAVY_CURSE) && (o_ptr->ident & IDENT_CURSED)) total -= 12500;
- if (f3 & TR3_PERMA_CURSE) total -= 15000;
- if (f3 & TR3_FEATHER) total += 1250;
- if (f4 & TR4_FLY) total += 10000;
- if (f4 & TR4_NEVER_BLOW) total -= 15000;
- if (f4 & TR4_PRECOGNITION) total += 250000;
- if (f4 & TR4_BLACK_BREATH) total -= 12500;
- if (f4 & TR4_DG_CURSE) total -= 25000;
- if (f4 & TR4_CLONE) total -= 10000;
- if (f4 & TR4_LEVELS) total += o_ptr->elevel * 2000;
+ if (flags & TR_AGGRAVATE) total -= 10000;
+ if (flags & TR_BLESSED) total += 750;
+ if ((flags & TR_CURSED) && (o_ptr->ident & IDENT_CURSED)) total -= 5000;
+ if ((flags & TR_HEAVY_CURSE) && (o_ptr->ident & IDENT_CURSED)) total -= 12500;
+ if (flags & TR_PERMA_CURSE) total -= 15000;
+ if (flags & TR_FEATHER) total += 1250;
+ if (flags & TR_FLY) total += 10000;
+ if (flags & TR_NEVER_BLOW) total -= 15000;
+ if (flags & TR_PRECOGNITION) total += 250000;
+ if (flags & TR_BLACK_BREATH) total -= 12500;
+ if (flags & TR_DG_CURSE) total -= 25000;
+ if (flags & TR_CLONE) total -= 10000;
+ if (flags & TR_LEVELS) total += o_ptr->elevel * 2000;
/* Also, give some extra for activatable powers... */
- if ((o_ptr->art_name) && (o_ptr->art_flags3 & (TR3_ACTIVATE)))
+ if ((!o_ptr->artifact_name.empty()) && (o_ptr->art_flags & TR_ACTIVATE))
{
int type = o_ptr->xtra2;
@@ -1133,17 +1089,20 @@ s32b flag_cost(object_type * o_ptr, int plusses)
*
* Every wearable item with a "pval" bonus is worth extra (see below).
*/
-s32b object_value_real(object_type *o_ptr)
+s32b object_value_real(object_type const *o_ptr)
{
- s32b value;
+ auto const &r_info = game->edit_data.r_info;
+ auto const &k_info = game->edit_data.k_info;
+ auto const &a_info = game->edit_data.a_info;
+ auto const &e_info = game->edit_data.e_info;
- u32b f1, f2, f3, f4, f5, esp;
+ s32b value;
- object_kind *k_ptr = &k_info[o_ptr->k_idx];
+ auto k_ptr = &k_info[o_ptr->k_idx];
if (o_ptr->tval == TV_RANDART)
{
- return random_artifacts[o_ptr->sval].cost;
+ return game->random_artifacts[o_ptr->sval].cost;
}
/* Hack -- "worthless" items */
@@ -1153,18 +1112,18 @@ s32b object_value_real(object_type *o_ptr)
value = k_ptr->cost;
/* Extract some flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ auto const flags = object_flags(o_ptr);
- if (f5 & TR5_TEMPORARY) return (0L);
+ if (flags & TR_TEMPORARY) return (0L);
- if (o_ptr->art_flags1 || o_ptr->art_flags2 || o_ptr->art_flags3)
+ if (o_ptr->art_flags)
{
value += flag_cost (o_ptr, o_ptr->pval);
}
/* Artifact */
else if (o_ptr->name1)
{
- artifact_type *a_ptr = &a_info[o_ptr->name1];
+ auto a_ptr = &a_info[o_ptr->name1];
/* Hack -- "worthless" artifacts */
if (!a_ptr->cost) return (0L);
@@ -1176,7 +1135,7 @@ s32b object_value_real(object_type *o_ptr)
/* Ego-Item */
else if (o_ptr->name2)
{
- ego_item_type *e_ptr = &e_info[o_ptr->name2];
+ auto e_ptr = &e_info[o_ptr->name2];
/* Hack -- "worthless" ego-items */
if (!e_ptr->cost) return (0L);
@@ -1186,7 +1145,7 @@ s32b object_value_real(object_type *o_ptr)
if (o_ptr->name2b)
{
- ego_item_type *e_ptr = &e_info[o_ptr->name2b];
+ auto e_ptr = &e_info[o_ptr->name2b];
/* Hack -- "worthless" ego-items */
if (!e_ptr->cost) return (0L);
@@ -1197,10 +1156,10 @@ s32b object_value_real(object_type *o_ptr)
}
/* Pay the spell */
- if (f5 & TR5_SPELL_CONTAIN)
+ if (flags & TR_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;
}
@@ -1228,35 +1187,33 @@ s32b object_value_real(object_type *o_ptr)
case TV_AMULET:
case TV_RING:
case TV_MSTAFF:
- case TV_TRAPKIT:
case TV_INSTRUMENT:
{
/* No pval */
if (!o_ptr->pval) break;
/* Give credit for stat bonuses */
- if (f1 & (TR1_STR)) value += (o_ptr->pval * 200L);
- if (f1 & (TR1_INT)) value += (o_ptr->pval * 200L);
- if (f1 & (TR1_WIS)) value += (o_ptr->pval * 200L);
- if (f1 & (TR1_DEX)) value += (o_ptr->pval * 200L);
- if (f1 & (TR1_CON)) value += (o_ptr->pval * 200L);
- if (f1 & (TR1_CHR)) value += (o_ptr->pval * 200L);
+ if (flags & TR_STR) value += (o_ptr->pval * 200L);
+ if (flags & TR_INT) value += (o_ptr->pval * 200L);
+ if (flags & TR_WIS) value += (o_ptr->pval * 200L);
+ if (flags & TR_DEX) value += (o_ptr->pval * 200L);
+ if (flags & TR_CON) value += (o_ptr->pval * 200L);
+ if (flags & TR_CHR) value += (o_ptr->pval * 200L);
- if (f5 & (TR5_CRIT)) value += (o_ptr->pval * 500L);
+ if (flags & TR_CRIT) value += (o_ptr->pval * 500L);
/* Give credit for stealth and searching */
- if (f1 & (TR1_STEALTH)) value += (o_ptr->pval * 100L);
- if (f1 & (TR1_SEARCH)) value += (o_ptr->pval * 100L);
+ if (flags & TR_STEALTH) value += (o_ptr->pval * 100L);
/* Give credit for infra-vision and tunneling */
- if (f1 & (TR1_INFRA)) value += (o_ptr->pval * 50L);
- if (f1 & (TR1_TUNNEL)) value += (o_ptr->pval * 50L);
+ if (flags & TR_INFRA) value += (o_ptr->pval * 50L);
+ if (flags & TR_TUNNEL) value += (o_ptr->pval * 50L);
/* Give credit for extra attacks */
- if (f1 & (TR1_BLOWS)) value += (o_ptr->pval * 2000L);
+ if (flags & TR_BLOWS) value += (o_ptr->pval * 2000L);
/* Give credit for speed bonus */
- if (f1 & (TR1_SPEED)) value += (o_ptr->pval * 30000L);
+ if (flags & TR_SPEED) value += (o_ptr->pval * 30000L);
break;
}
@@ -1269,7 +1226,7 @@ s32b object_value_real(object_type *o_ptr)
/* Eggs */
case TV_EGG:
{
- monster_race *r_ptr = &r_info[o_ptr->pval2];
+ auto r_ptr = &r_info[o_ptr->pval2];
/* Pay the monster level */
value += r_ptr->level * 100;
@@ -1282,7 +1239,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 +1254,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 +1271,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;
@@ -1388,7 +1345,6 @@ s32b object_value_real(object_type *o_ptr)
case TV_DAEMON_BOOK:
case TV_AXE:
case TV_POLEARM:
- case TV_TRAPKIT:
{
/* Hack -- negative hit/damage bonuses */
if (o_ptr->to_h + o_ptr->to_d < 0 && !value) return (0L);
@@ -1447,7 +1403,7 @@ s32b object_value_real(object_type *o_ptr)
* Note that discounted items stay discounted forever, even if
* the discount is "forgotten" by the player via memory loss.
*/
-s32b object_value(object_type *o_ptr)
+s32b object_value(object_type const *o_ptr)
{
s32b value;
@@ -1503,20 +1459,18 @@ s32b object_value(object_type *o_ptr)
*
* Chests, and activatable items, never stack (for various reasons).
*/
-bool_ object_similar(object_type *o_ptr, object_type *j_ptr)
+bool_ object_similar(object_type const *o_ptr, object_type const *j_ptr)
{
int total = o_ptr->number + j_ptr->number;
- u32b f1, f2, f3, f4, f5, esp, f11, f12, f13, f14, esp1, f15;
/* Extract the flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
- object_flags(j_ptr, &f11, &f12, &f13, &f14, &f15, &esp1);
-
+ auto const o_flags = object_flags(o_ptr);
+ auto const j_flags = object_flags(j_ptr);
/* Require identical object types */
if (o_ptr->k_idx != j_ptr->k_idx) return (0);
- if ((f5 & TR5_SPELL_CONTAIN) || (f15 & TR5_SPELL_CONTAIN))
+ if ((o_flags & TR_SPELL_CONTAIN) || (j_flags & TR_SPELL_CONTAIN))
return FALSE;
/* Analyze the items */
@@ -1555,17 +1509,6 @@ bool_ object_similar(object_type *o_ptr, object_type *j_ptr)
return FALSE;
}
- case TV_RUNE1:
- {
- return TRUE;
- }
-
- case TV_RUNE2:
- {
- if ((o_ptr->sval == RUNE_STONE) || (j_ptr->sval == RUNE_STONE)) return FALSE;
- else return TRUE;
- }
-
case TV_INSTRUMENT:
{
return FALSE;
@@ -1620,7 +1563,7 @@ bool_ object_similar(object_type *o_ptr, object_type *j_ptr)
if (o_ptr->pval != j_ptr->pval) return (0);
/* Do not combine recharged ones with non recharged ones. */
- if ((f4 & TR4_RECHARGED) != (f14 & TR4_RECHARGED)) return (0);
+ if ((o_flags & TR_RECHARGED) != (j_flags & TR_RECHARGED)) return (0);
/* Do not combine different spells */
if (o_ptr->pval2 != j_ptr->pval2) return (0);
@@ -1655,7 +1598,7 @@ bool_ object_similar(object_type *o_ptr, object_type *j_ptr)
if (o_ptr->name1 != j_ptr->name1) return (0);
/* Do not combine recharged ones with non recharged ones. */
- if ((f4 & TR4_RECHARGED) != (f14 & TR4_RECHARGED)) return (0);
+ if ((o_flags & TR_RECHARGED) != (j_flags & TR_RECHARGED)) return (0);
/* Do not combine different spells */
if (o_ptr->pval2 != j_ptr->pval2) return (0);
@@ -1705,12 +1648,8 @@ bool_ object_similar(object_type *o_ptr, object_type *j_ptr)
case TV_SOFT_ARMOR:
case TV_HARD_ARMOR:
case TV_DRAG_ARMOR:
- case TV_TRAPKIT:
case TV_DAEMON_BOOK:
{
- /* Require permission */
- if (!stack_allow_items) return (0);
-
/* Fall through */
}
@@ -1785,13 +1724,6 @@ bool_ object_similar(object_type *o_ptr, object_type *j_ptr)
break;
}
- /* UHH ugly hack for the fireproof quest, sorry */
- case TV_BATERIE:
- {
- if (o_ptr->pval2 != j_ptr->pval2) return (FALSE);
- break;
- }
-
/* Various */
default:
{
@@ -1805,23 +1737,19 @@ bool_ object_similar(object_type *o_ptr, object_type *j_ptr)
/* Hack -- Identical art_flags! */
- if ((o_ptr->art_flags1 != j_ptr->art_flags1) ||
- (o_ptr->art_flags2 != j_ptr->art_flags2) ||
- (o_ptr->art_flags3 != j_ptr->art_flags3))
+ if (o_ptr->art_flags != j_ptr->art_flags)
+ {
return (0);
+ }
/* Hack -- Require identical "cursed" status */
if ((o_ptr->ident & (IDENT_CURSED)) != (j_ptr->ident & (IDENT_CURSED))) return (0);
/* Hack -- require semi-matching "inscriptions" */
- if (o_ptr->note && j_ptr->note && (o_ptr->note != j_ptr->note)) return (0);
-
- /* Hack -- normally require matching "inscriptions" */
- if (!stack_force_notes && (o_ptr->note != j_ptr->note)) return (0);
-
- /* Hack -- normally require matching "discounts" */
- if (!stack_force_costs && (o_ptr->discount != j_ptr->discount)) return (0);
-
+ if ((!o_ptr->inscription.empty()) && (!j_ptr->inscription.empty()) && (o_ptr->inscription != j_ptr->inscription))
+ {
+ return (0);
+ }
/* Maximal "stacking" limit */
if (total >= MAX_STACK_SIZE) return (0);
@@ -1857,7 +1785,10 @@ void object_absorb(object_type *o_ptr, object_type *j_ptr)
if (j_ptr->ident & (IDENT_MENTAL)) o_ptr->ident |= (IDENT_MENTAL);
/* Hack -- blend "inscriptions" */
- if (j_ptr->note) o_ptr->note = j_ptr->note;
+ if (!j_ptr->inscription.empty())
+ {
+ o_ptr->inscription = j_ptr->inscription;
+ }
/* Hack -- could average discounts XXX XXX XXX */
/* Hack -- save largest discount XXX XXX XXX */
@@ -1877,22 +1808,22 @@ void object_absorb(object_type *o_ptr, object_type *j_ptr)
*/
s16b lookup_kind(int tval, int sval)
{
- int k;
+ auto const &k_info = game->edit_data.k_info;
- /* Look for it */
- for (k = 1; k < max_k_idx; k++)
+ for (std::size_t k = 1; k < k_info.size(); k++)
{
- object_kind *k_ptr = &k_info[k];
-
- /* Found a match */
- if ((k_ptr->tval == tval) && (k_ptr->sval == sval)) return (k);
+ auto k_ptr = &k_info[k];
+ if ((k_ptr->tval == tval) && (k_ptr->sval == sval))
+ {
+ return k;
+ }
}
/* Oops */
if (wizard) msg_format("No object (%d,%d)", tval, sval);
/* Oops */
- return (0);
+ return 0;
}
@@ -1902,7 +1833,7 @@ s16b lookup_kind(int tval, int sval)
void object_wipe(object_type *o_ptr)
{
/* Wipe the structure */
- o_ptr = WIPE(o_ptr, object_type);
+ *o_ptr = object_type();
}
@@ -1912,7 +1843,18 @@ void object_wipe(object_type *o_ptr)
void object_copy(object_type *o_ptr, object_type *j_ptr)
{
/* Copy the structure */
- COPY(o_ptr, j_ptr, object_type);
+ *o_ptr = *j_ptr;
+}
+
+
+/*
+ * Initialize the experience of an object which is a
+ * "sentient" object.
+ */
+static void init_obj_exp(object_type *o_ptr, object_kind const *k_ptr)
+{
+ o_ptr->elevel = (k_ptr->level / 10) + 1;
+ o_ptr->exp = player_exp[o_ptr->elevel - 1];
}
@@ -1921,10 +1863,12 @@ void object_copy(object_type *o_ptr, object_type *j_ptr)
*/
void object_prep(object_type *o_ptr, int k_idx)
{
- object_kind *k_ptr = &k_info[k_idx];
+ auto const &k_info = game->edit_data.k_info;
+
+ auto k_ptr = &k_info[k_idx];
/* Clear the record */
- o_ptr = WIPE(o_ptr, object_type);
+ object_wipe(o_ptr);
/* Save the kind index */
o_ptr->k_idx = k_idx;
@@ -1954,13 +1898,15 @@ void object_prep(object_type *o_ptr, int k_idx)
o_ptr->ds = k_ptr->ds;
/* Hack -- cursed items are always "cursed" */
- if (k_ptr->flags3 & (TR3_CURSED)) o_ptr->ident |= (IDENT_CURSED);
+ if (k_ptr->flags & TR_CURSED)
+ {
+ o_ptr->ident |= (IDENT_CURSED);
+ }
/* Hack give a basic exp/exp level to an object that needs it */
- if (k_ptr->flags4 & TR4_LEVELS)
+ if (k_ptr->flags & TR_LEVELS)
{
- o_ptr->elevel = (k_ptr->level / 10) + 1;
- o_ptr->exp = player_exp[o_ptr->elevel - 1];
+ init_obj_exp(o_ptr, k_ptr);
o_ptr->pval2 = 1; /* Start with one point */
o_ptr->pval3 = 0; /* No flags groups */
}
@@ -2056,24 +2002,21 @@ s16b m_bonus(int max, int level)
*/
static void finalize_randart(object_type* o_ptr, int lev)
{
- int r;
- int i = 0;
- int foo = lev + randnor(0, 5);
- bool_ flag = TRUE;
+ auto &random_artifacts = game->random_artifacts;
/* Paranoia */
- if (o_ptr->tval != TV_RANDART) return;
-
- if (foo < 1) foo = 1;
- if (foo > 100) foo = 100;
+ if (o_ptr->tval != TV_RANDART)
+ {
+ return;
+ }
- while (flag)
+ for (int i = 0; ; i++)
{
- r = rand_int(MAX_RANDARTS);
+ auto const r = rand_int(MAX_RANDARTS);
if (!(random_artifacts[r].generated) || i > 2000)
{
- random_artifact* ra_ptr = &random_artifacts[r];
+ auto ra_ptr = &random_artifacts[r];
o_ptr->sval = r;
o_ptr->pval2 = ra_ptr->activation;
@@ -2081,10 +2024,8 @@ static void finalize_randart(object_type* o_ptr, int lev)
ra_ptr->level = lev;
ra_ptr->generated = TRUE;
- flag = FALSE;
+ return;
}
-
- i++;
}
}
@@ -2108,7 +2049,7 @@ static void object_mention(object_type *o_ptr)
}
/* Random Artifact */
- else if (o_ptr->art_name)
+ else if (!o_ptr->artifact_name.empty())
{
msg_print("Random artifact");
}
@@ -2128,86 +2069,106 @@ static void object_mention(object_type *o_ptr)
}
}
-
-void random_artifact_resistance(object_type * o_ptr)
+static void random_artifact_power(object_type *o_ptr)
{
- bool_ give_resistance = FALSE, give_power = FALSE;
-
- switch (o_ptr->name1)
- {
- case ART_CELEBORN:
- case ART_ARVEDUI:
- case ART_CASPANION:
- case ART_TRON:
- case ART_ROHIRRIM:
- case ART_CELEGORM:
- case ART_ANARION:
- case ART_THRANDUIL:
- case ART_LUTHIEN:
- case ART_THROR:
- case ART_THORIN:
- case ART_NIMTHANC:
- case ART_DETHANC:
- case ART_NARTHANC:
- case ART_STING:
- case ART_TURMIL:
- case ART_THALKETTOTH:
- {
- /* Give a resistance */
- give_resistance = TRUE;
+ // Shorthand
+ auto flags = &o_ptr->art_flags;
+
+ // Choose ability
+ auto try_choose = [&o_ptr, &flags](int choice) {
+ switch (choice)
+ {
+ case 0:
+ (*flags) |= (TR_FEATHER);
+ break;
+ case 1:
+ (*flags) |= (TR_LITE1);
+ break;
+ case 2:
+ (*flags) |= (TR_SEE_INVIS);
+ break;
+ case 3:
+ (*flags) |= (ESP_ALL);
+ break;
+ case 4:
+ (*flags) |= (TR_SLOW_DIGEST);
+ break;
+ case 5:
+ (*flags) |= (TR_REGEN);
+ break;
+ case 6:
+ (*flags) |= (TR_FREE_ACT);
+ break;
+ case 7:
+ (*flags) |= (TR_HOLD_LIFE);
+ break;
}
- break;
- case ART_MAEDHROS:
- case ART_GLAMDRING:
- case ART_ORCRIST:
- case ART_ANDURIL:
- case ART_ZARCUTHRA:
- case ART_GURTHANG:
- case ART_HARADEKKET:
- case ART_CUBRAGOL:
- case ART_DAWN:
- {
- /* Give a resistance OR a power */
- if (randint(2) == 1) give_resistance = TRUE;
- else give_power = TRUE;
+ };
+
+ // Save old values for comparison
+ auto const old_flags = *flags;
+
+ // Choose an ability; make sure we choose one that isn't already chosen
+ for (int tries = 0; tries < 1000; tries++)
+ {
+ // Tentative choice
+ int choice = rand_int(8);
+ try_choose(choice);
+
+ // If there's any difference, then we've chosen a non-overlapping power.
+ if (*flags != old_flags)
+ {
+ break;
}
- break;
- case ART_NENYA:
- case ART_VILYA:
- case ART_BERUTHIEL:
- case ART_FINGOLFIN:
- case ART_THINGOL:
- case ART_ULMO:
- case ART_OLORIN:
+ }
+}
+
+void random_artifact_resistance(object_type * o_ptr)
+{
+ auto const &a_info = game->edit_data.a_info;
+
+ auto const art_flags = a_info[o_ptr->name1].flags;
+
+ // Check flags of the 'protype' artifact
+ auto give_resistance = bool(art_flags & TR_RANDOM_RESIST);
+ auto give_power = bool(art_flags & TR_RANDOM_POWER);
+ if (art_flags & TR_RANDOM_RES_OR_POWER)
+ {
+ if (randint(2) == 1)
{
- /* Give a power */
- give_power = TRUE;
+ give_resistance = true;
}
- break;
- case ART_POWER:
- case ART_GONDOR:
- case ART_AULE:
+ else
{
- /* Give both */
- give_power = TRUE;
- give_resistance = TRUE;
+ give_power = true;
}
- break;
}
+ // Grant a power?
if (give_power)
{
- o_ptr->xtra1 = EGO_XTRA_ABILITY;
-
- /* Randomize the "xtra" power */
- if (o_ptr->xtra1) o_ptr->xtra2 = randint(256);
+ random_artifact_power(o_ptr);
}
artifact_bias = 0;
if (give_resistance)
{
- random_resistance(o_ptr, FALSE, ((randint(22)) + 16));
+ // Save the *combined* pre-existing flags on the object;
+ // including any power we may have granted above.
+ auto const flags_before = art_flags | o_ptr->art_flags;
+
+ // We'll be a little generous here and make sure that the object
+ // gets a resistance that it doesn't actually already have.
+ for (int tries = 0; tries < 1000; tries++)
+ {
+ random_resistance(o_ptr, randint(22) + 16);
+ // Picked up new resistance?
+ if (flags_before != (art_flags | o_ptr->art_flags))
+ {
+ break;
+ }
+ }
}
}
@@ -2222,17 +2183,16 @@ void random_artifact_resistance(object_type * o_ptr)
*/
static bool_ make_artifact_special(object_type *o_ptr)
{
- int i;
- int k_idx = 0;
- u32b f1, f2, f3, f4, f5, esp;
+ auto const &k_info = game->edit_data.k_info;
+ auto const &a_info = game->edit_data.a_info;
/* No artifacts in the town */
if (!dun_level) return (FALSE);
/* Check the artifact list (just the "specials") */
- for (i = 0; i < max_a_idx; i++)
+ for (std::size_t i = 0; i < a_info.size(); i++)
{
- artifact_type *a_ptr = &a_info[i];
+ auto a_ptr = &a_info[i];
/* Skip "empty" artifacts */
if (!a_ptr->name) continue;
@@ -2241,10 +2201,10 @@ static bool_ make_artifact_special(object_type *o_ptr)
if (a_ptr->cur_num) continue;
/* Cannot generate non special ones */
- if (!(a_ptr->flags3 & TR3_INSTA_ART)) continue;
+ if (!(a_ptr->flags & TR_INSTA_ART)) continue;
/* Cannot generate some artifacts because they can only exists in special dungeons/quests/... */
- if ((a_ptr->flags4 & TR4_SPECIAL_GENE) && (!a_allow_special[i])) continue;
+ if ((a_ptr->flags & TR_SPECIAL_GENE) && (!a_allow_special[i])) continue;
/* XXX XXX Enforce minimum "depth" (loosely) */
if (a_ptr->level > dun_level)
@@ -2260,7 +2220,7 @@ static bool_ make_artifact_special(object_type *o_ptr)
if (rand_int(a_ptr->rarity - luck( -(a_ptr->rarity / 2), a_ptr->rarity / 2)) != 0) continue;
/* Find the base object */
- k_idx = lookup_kind(a_ptr->tval, a_ptr->sval);
+ int k_idx = lookup_kind(a_ptr->tval, a_ptr->sval);
/* XXX XXX Enforce minimum "object" level (loosely) */
if (k_info[k_idx].level > object_level)
@@ -2279,13 +2239,12 @@ static bool_ make_artifact_special(object_type *o_ptr)
o_ptr->name1 = i;
/* Extract some flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ auto const flags = object_flags(o_ptr);
/* Hack give a basic exp/exp level to an object that needs it */
- if (f4 & TR4_LEVELS)
+ if (flags & TR_LEVELS)
{
- o_ptr->elevel = (k_info[k_idx].level / 10) + 1;
- o_ptr->exp = player_exp[o_ptr->elevel - 1];
+ init_obj_exp(o_ptr, &k_info[k_idx]);
}
/* Success */
@@ -2306,9 +2265,8 @@ static bool_ make_artifact_special(object_type *o_ptr)
*/
static bool_ make_artifact(object_type *o_ptr)
{
- int i;
- u32b f1, f2, f3, f4, f5, esp;
- object_kind *k_ptr = &k_info[o_ptr->k_idx];
+ auto const &a_info = game->edit_data.a_info;
+ auto const &k_info = game->edit_data.k_info;
/* No artifacts in the town */
if (!dun_level) return (FALSE);
@@ -2317,9 +2275,9 @@ static bool_ make_artifact(object_type *o_ptr)
if (o_ptr->number != 1) return (FALSE);
/* Check the artifact list (skip the "specials") */
- for (i = 0; i < max_a_idx; i++)
+ for (std::size_t i = 0; i < a_info.size(); i++)
{
- artifact_type *a_ptr = &a_info[i];
+ auto a_ptr = &a_info[i];
/* Skip "empty" items */
if (!a_ptr->name) continue;
@@ -2328,10 +2286,10 @@ static bool_ make_artifact(object_type *o_ptr)
if (a_ptr->cur_num) continue;
/* Cannot generate special ones */
- if (a_ptr->flags3 & TR3_INSTA_ART) continue;
+ if (a_ptr->flags & TR_INSTA_ART) continue;
/* Cannot generate some artifacts because they can only exists in special dungeons/quests/... */
- if ((a_ptr->flags4 & TR4_SPECIAL_GENE) && (!a_allow_special[i])) continue;
+ if ((a_ptr->flags & TR_SPECIAL_GENE) && (!a_allow_special[i])) continue;
/* Must have the correct fields */
if (a_ptr->tval != o_ptr->tval) continue;
@@ -2357,13 +2315,12 @@ static bool_ make_artifact(object_type *o_ptr)
random_artifact_resistance(o_ptr);
/* Extract some flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ auto const flags = object_flags(o_ptr);
/* Hack give a basic exp/exp level to an object that needs it */
- if (f4 & TR4_LEVELS)
+ if (flags & TR_LEVELS)
{
- o_ptr->elevel = (k_ptr->level / 10) + 1;
- o_ptr->exp = player_exp[o_ptr->elevel - 1];
+ init_obj_exp(o_ptr, &k_info[o_ptr->k_idx]);
}
/* Success */
@@ -2381,26 +2338,27 @@ static bool_ make_artifact(object_type *o_ptr)
*/
static bool_ make_ego_item(object_type *o_ptr, bool_ good)
{
- int i = 0, j;
- int *ok_ego, ok_num = 0;
+ auto const &k_info = game->edit_data.k_info;
+ auto const &e_info = game->edit_data.e_info;
+
bool_ ret = FALSE;
- object_kind *k_ptr = &k_info[o_ptr->k_idx];
+ auto k_ptr = &k_info[o_ptr->k_idx];
if (artifact_p(o_ptr) || o_ptr->name2) return (FALSE);
- C_MAKE(ok_ego, max_e_idx, int);
+ std::vector<size_t> ok_ego;
/* Grab the ok ego */
- for (i = 0; i < max_e_idx; i++)
+ for (size_t i = 0; i < e_info.size(); i++)
{
- ego_item_type *e_ptr = &e_info[i];
+ auto e_ptr = &e_info[i];
bool_ ok = FALSE;
/* Skip "empty" items */
if (!e_ptr->name) continue;
/* Must have the correct fields */
- for (j = 0; j < 6; j++)
+ for (size_t j = 0; j < 6; j++)
{
if (e_ptr->tval[j] == o_ptr->tval)
{
@@ -2420,32 +2378,20 @@ static bool_ make_ego_item(object_type *o_ptr, bool_ good)
if ((!good) && e_ptr->cost) continue;
/* Must posses the good flags */
- if (((k_ptr->flags1 & e_ptr->need_flags1) != e_ptr->need_flags1) ||
- ((k_ptr->flags2 & e_ptr->need_flags2) != e_ptr->need_flags2) ||
- ((k_ptr->flags3 & e_ptr->need_flags3) != e_ptr->need_flags3) ||
- ((k_ptr->flags4 & e_ptr->need_flags4) != e_ptr->need_flags4) ||
- ((k_ptr->flags5 & e_ptr->need_flags5) != e_ptr->need_flags5) ||
- ((k_ptr->esp & e_ptr->need_esp) != e_ptr->need_esp))
+ if ((k_ptr->flags & e_ptr->need_flags) != e_ptr->need_flags)
continue;
- if ((k_ptr->flags1 & e_ptr->forbid_flags1) ||
- (k_ptr->flags2 & e_ptr->forbid_flags2) ||
- (k_ptr->flags3 & e_ptr->forbid_flags3) ||
- (k_ptr->flags4 & e_ptr->forbid_flags4) ||
- (k_ptr->flags5 & e_ptr->forbid_flags5) ||
- (k_ptr->esp & e_ptr->forbid_esp))
+ if (k_ptr->flags & e_ptr->forbid_flags)
continue;
/* ok */
- ok_ego[ok_num++] = i;
+ ok_ego.push_back(i);
}
/* Now test them a few times */
- for (i = 0; i < ok_num * 10; i++)
+ for (size_t i = 0; i < ok_ego.size() * 10; i++)
{
- ego_item_type *e_ptr;
-
- int j = ok_ego[rand_int(ok_num)];
- e_ptr = &e_info[j];
+ size_t j = ok_ego[rand_int(ok_ego.size())];
+ auto e_ptr = &e_info[j];
/* XXX XXX Enforce minimum "depth" (loosely) */
if (e_ptr->level > dun_level)
@@ -2481,12 +2427,10 @@ static bool_ make_ego_item(object_type *o_ptr, bool_ good)
if (magik(7 + luck( -7, 7)) && (!o_ptr->name2b))
{
/* Now test them a few times */
- for (i = 0; i < ok_num * 10; i++)
+ for (size_t i = 0; i < ok_ego.size() * 10; i++)
{
- ego_item_type *e_ptr;
-
- int j = ok_ego[rand_int(ok_num)];
- e_ptr = &e_info[j];
+ int j = ok_ego[rand_int(ok_ego.size())]; // Explicit int conversion to avoid warning
+ auto e_ptr = &e_info[j];
/* Cannot be a double ego of the same ego type */
if (j == o_ptr->name2) continue;
@@ -2523,8 +2467,6 @@ static bool_ make_ego_item(object_type *o_ptr, bool_ good)
}
}
- C_FREE(ok_ego, max_e_idx, int);
-
/* Return */
return (ret);
}
@@ -2535,7 +2477,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 = spell_type_roll_charges(spell);
}
/*
@@ -2559,7 +2502,7 @@ static void a_m_aux_1(object_type *o_ptr, int level, int power)
if (power > 1)
{
/* Make ego item */
- if ((rand_int(RANDART_WEAPON) == 1) && (o_ptr->tval != TV_TRAPKIT)) create_artifact(o_ptr, FALSE, TRUE);
+ if (rand_int(RANDART_WEAPON) == 1) create_artifact(o_ptr, FALSE, TRUE);
else make_ego_item(o_ptr, TRUE);
}
else if (power < -1)
@@ -2604,49 +2547,11 @@ static void a_m_aux_1(object_type *o_ptr, int level, int power)
}
/* Some special cases */
- if (process_hooks(HOOK_APPLY_MAGIC, "(O,d,d)", o_ptr, level, power))
- return;
switch (o_ptr->tval)
{
- case TV_TRAPKIT:
- {
- /* Good */
- if (power > 0) o_ptr->to_a += randint(5);
-
- /* Very good */
- if (power > 1) o_ptr->to_a += randint(5);
-
- /* Bad */
- if (power < 0) o_ptr->to_a -= randint(5);
-
- /* Very bad */
- if (power < -1) o_ptr->to_a -= randint(5);
-
- break;
- }
case TV_MSTAFF:
{
- if (is_ego_p(o_ptr, EGO_MSTAFF_SPELL))
- {
- int gf[2], i;
-
- for (i = 0; i < 2; i++)
- {
- int k = 0;
-
- gf[i] = 0;
- while (!k)
- {
- k = lookup_kind(TV_RUNE1, (gf[i] = rand_int(MAX_GF)));
- }
- }
-
- o_ptr->pval = gf[0] + (gf[1] << 16);
- o_ptr->pval3 = rand_int(RUNE_MOD_MAX) + (rand_int(RUNE_MOD_MAX) << 16);
- o_ptr->pval2 = randint(70) + (randint(70) << 8);
- }
- else
- o_ptr->art_flags5 |= (TR5_SPELL_CONTAIN | TR5_WIELD_CAST);
+ o_ptr->art_flags |= (TR_SPELL_CONTAIN | TR_WIELD_CAST);
break;
}
case TV_BOLT:
@@ -2684,9 +2589,9 @@ static void dragon_resist(object_type * o_ptr)
artifact_bias = 0;
if (randint(4) == 1)
- random_resistance(o_ptr, FALSE, ((randint(14)) + 4));
+ random_resistance(o_ptr, randint(14) + 4);
else
- random_resistance(o_ptr, FALSE, ((randint(22)) + 16));
+ random_resistance(o_ptr, randint(22) + 16);
}
while (randint(2) == 1);
}
@@ -2751,19 +2656,17 @@ static void a_m_aux_2(object_type *o_ptr, int level, int power)
}
/* Analyze type */
- if (process_hooks(HOOK_APPLY_MAGIC, "(O,d,d)", o_ptr, level, power))
- return;
switch (o_ptr->tval)
{
case TV_CLOAK:
{
if (o_ptr->sval == SV_ELVEN_CLOAK)
+ {
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;
@@ -2774,7 +2677,10 @@ static void a_m_aux_2(object_type *o_ptr, int level, int power)
rating += 30;
/* Mention the item */
- if ((cheat_peek) || (p_ptr->precognition)) object_mention(o_ptr);
+ if (options->cheat_peek || p_ptr->precognition)
+ {
+ object_mention(o_ptr);
+ }
break;
}
@@ -2786,7 +2692,10 @@ static void a_m_aux_2(object_type *o_ptr, int level, int power)
rating += 5;
/* Mention the item */
- if ((cheat_peek) || (p_ptr->precognition)) object_mention(o_ptr);
+ if (options->cheat_peek || p_ptr->precognition)
+ {
+ object_mention(o_ptr);
+ }
dragon_resist(o_ptr);
}
break;
@@ -2799,7 +2708,10 @@ static void a_m_aux_2(object_type *o_ptr, int level, int power)
rating += 5;
/* Mention the item */
- if ((cheat_peek) || (p_ptr->precognition)) object_mention(o_ptr);
+ if (options->cheat_peek || p_ptr->precognition)
+ {
+ object_mention(o_ptr);
+ }
dragon_resist(o_ptr);
}
break;
@@ -2836,8 +2748,6 @@ static void a_m_aux_3(object_type *o_ptr, int level, int power)
}
/* Apply magic (good or bad) according to type */
- if (process_hooks(HOOK_APPLY_MAGIC, "(O,d,d)", o_ptr, level, power))
- return;
switch (o_ptr->tval)
{
case TV_RING:
@@ -2932,7 +2842,10 @@ static void a_m_aux_3(object_type *o_ptr, int level, int power)
rating += 25;
/* Mention the item */
- if ((cheat_peek) || (p_ptr->precognition)) object_mention(o_ptr);
+ if (options->cheat_peek || p_ptr->precognition)
+ {
+ object_mention(o_ptr);
+ }
break;
}
@@ -2941,7 +2854,7 @@ static void a_m_aux_3(object_type *o_ptr, int level, int power)
{
do
{
- random_resistance(o_ptr, FALSE, ((randint(20)) + 18));
+ random_resistance(o_ptr, randint(20) + 18);
}
while (randint(4) == 1);
@@ -2951,25 +2864,6 @@ static void a_m_aux_3(object_type *o_ptr, int level, int power)
}
break;
- /* Searching */
- case SV_RING_SEARCHING:
- {
- /* Bonus to searching */
- o_ptr->pval = 1 + m_bonus(5, level);
-
- /* Cursed */
- if (power < 0)
- {
- /* Cursed */
- o_ptr->ident |= (IDENT_CURSED);
-
- /* Reverse pval */
- o_ptr->pval = 0 - (o_ptr->pval);
- }
-
- break;
- }
-
/* Flames, Acid, Ice */
case SV_RING_FLAMES:
case SV_RING_ACID:
@@ -3100,7 +2994,10 @@ static void a_m_aux_3(object_type *o_ptr, int level, int power)
o_ptr->pval = 1 + m_bonus(3, level);
/* Mention the item */
- if ((cheat_peek) || (p_ptr->precognition)) object_mention(o_ptr);
+ if (options->cheat_peek || p_ptr->precognition)
+ {
+ object_mention(o_ptr);
+ }
break;
}
@@ -3112,7 +3009,10 @@ static void a_m_aux_3(object_type *o_ptr, int level, int power)
o_ptr->to_d = 1 + m_bonus(5, level);
/* Mention the item */
- if ((cheat_peek) || (p_ptr->precognition)) object_mention(o_ptr);
+ if (options->cheat_peek || p_ptr->precognition)
+ {
+ object_mention(o_ptr);
+ }
break;
}
@@ -3168,41 +3068,26 @@ static void a_m_aux_3(object_type *o_ptr, int level, int power)
case SV_AMULET_RESISTANCE:
{
- if (randint(3) == 1) random_resistance(o_ptr, FALSE, ((randint(34)) + 4));
- if (randint(5) == 1) o_ptr->art_flags2 |= TR2_RES_POIS;
+ if (randint(3) == 1) random_resistance(o_ptr, randint(34) + 4);
+ if (randint(5) == 1) o_ptr->art_flags |= TR_RES_POIS;
}
break;
- /* Amulet of searching */
- case SV_AMULET_SEARCHING:
- {
- o_ptr->pval = randint(5) + m_bonus(5, level);
-
- /* Cursed */
- if (power < 0)
- {
- /* Cursed */
- o_ptr->ident |= (IDENT_CURSED);
-
- /* Reverse bonuses */
- o_ptr->pval = 0 - (o_ptr->pval);
- }
-
- break;
- }
-
/* Amulet of the Magi -- never cursed */
case SV_AMULET_THE_MAGI:
{
o_ptr->pval = 1 + m_bonus(3, level);
- if (randint(3) == 1) o_ptr->art_flags3 |= TR3_SLOW_DIGEST;
+ if (randint(3) == 1) o_ptr->art_flags |= TR_SLOW_DIGEST;
/* Boost the rating */
rating += 25;
/* Mention the item */
- if ((cheat_peek) || (p_ptr->precognition)) object_mention(o_ptr);
+ if (options->cheat_peek || p_ptr->precognition)
+ {
+ object_mention(o_ptr);
+ }
break;
}
@@ -3226,6 +3111,49 @@ static void a_m_aux_3(object_type *o_ptr, int level, int power)
}
}
+/*
+ * 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 = spell_type_device_allocation(spell, tval);
+ assert(device_allocation != NULL);
+ 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 = spell_type_device_allocation(spell, tval);
+ assert(device_allocation != NULL);
+ return randomized_level_in_range(&device_allocation->max_level, level);
+}
+
/*
* Apply magic to an item known to be "boring"
@@ -3234,9 +3162,11 @@ static void a_m_aux_3(object_type *o_ptr, int level, int power)
*/
static void a_m_aux_4(object_type *o_ptr, int level, int power)
{
- u32b f1, f2, f3, f4, f5, esp;
+ auto const &r_info = game->edit_data.r_info;
+ auto const &k_info = game->edit_data.k_info;
+
s32b bonus_lvl, max_lvl;
- object_kind *k_ptr = &k_info[o_ptr->k_idx];
+ auto k_ptr = &k_info[o_ptr->k_idx];
/* Very good */
if (power > 1)
@@ -3252,8 +3182,6 @@ static void a_m_aux_4(object_type *o_ptr, int level, int power)
}
/* Apply magic (good or bad) according to type */
- if (process_hooks(HOOK_APPLY_MAGIC, "(O,d,d)", o_ptr, level, power))
- return;
switch (o_ptr->tval)
{
case TV_BOOK:
@@ -3265,9 +3193,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)
@@ -3281,12 +3213,15 @@ static void a_m_aux_4(object_type *o_ptr, int level, int power)
case TV_LITE:
{
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ auto const flags = object_flags(o_ptr);
/* Hack -- random fuel */
- if (f4 & TR4_FUEL_LITE)
+ if (flags & TR_FUEL_LITE)
{
- if (k_info[o_ptr->k_idx].pval2 > 0) o_ptr->timeout = randint(k_info[o_ptr->k_idx].pval2);
+ if (k_info[o_ptr->k_idx].pval2 > 0)
+ {
+ o_ptr->timeout = randint(k_info[o_ptr->k_idx].pval2);
+ }
}
break;
@@ -3295,14 +3230,18 @@ static void a_m_aux_4(object_type *o_ptr, int level, int power)
case TV_CORPSE:
{
/* Hack -- choose a monster */
- monster_race* r_ptr;
int r_idx = get_mon_num(dun_level);
- r_ptr = &r_info[r_idx];
+ auto r_ptr = &r_info[r_idx];
- if (!(r_ptr->flags1 & RF1_UNIQUE))
+ if (!(r_ptr->flags & RF_UNIQUE))
+ {
o_ptr->pval2 = r_idx;
+ }
else
+ {
o_ptr->pval2 = 2;
+ }
+
o_ptr->pval3 = 0;
break;
}
@@ -3310,25 +3249,28 @@ static void a_m_aux_4(object_type *o_ptr, int level, int power)
case TV_EGG:
{
/* Hack -- choose a monster */
- monster_race* r_ptr;
int r_idx, count = 0;
bool_ OK = FALSE;
while ((!OK) && (count < 1000))
{
r_idx = get_mon_num(dun_level);
- r_ptr = &r_info[r_idx];
+ auto r_ptr = &r_info[r_idx];
- if (r_ptr->flags9 & RF9_HAS_EGG)
+ if (r_ptr->flags & RF_HAS_EGG)
{
o_ptr->pval2 = r_idx;
OK = TRUE;
}
count++;
}
- if (count == 1000) o_ptr->pval2 = 940; /* Blue fire-lizard */
- r_ptr = &r_info[o_ptr->pval2];
+ if (count == 1000)
+ {
+ o_ptr->pval2 = 940; /* Blue fire-lizard */
+ }
+
+ auto r_ptr = &r_info[o_ptr->pval2];
o_ptr->weight = (r_ptr->weight + rand_int(r_ptr->weight) / 100) + 1;
o_ptr->pval = r_ptr->weight * 3 + rand_int(r_ptr->weight) + 1;
break;
@@ -3337,11 +3279,10 @@ static void a_m_aux_4(object_type *o_ptr, int level, int power)
case TV_HYPNOS:
{
/* Hack -- choose a monster */
- monster_race* r_ptr;
int r_idx = get_mon_num(dun_level);
- r_ptr = &r_info[r_idx];
+ auto r_ptr = &r_info[r_idx];
- if (!(r_ptr->flags1 & RF1_NEVER_MOVE))
+ if (!(r_ptr->flags & RF_NEVER_MOVE))
o_ptr->pval = r_idx;
else
o_ptr->pval = 20;
@@ -3361,9 +3302,11 @@ 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)");
-
- if (spl == -1) spl = exec_lua("return find_spell('Manathrust')");
+ auto spl = get_random_stick(TV_WAND, dun_level);
+ if (spl == -1)
+ {
+ spl = MANATHRUST;
+ }
o_ptr->pval2 = spl;
}
@@ -3374,8 +3317,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 */
@@ -3389,9 +3332,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;
}
@@ -3402,8 +3348,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 */
@@ -3417,9 +3363,6 @@ static void a_m_aux_4(object_type *o_ptr, int level, int power)
/* Hack -- skip ruined chests */
if (k_info[o_ptr->k_idx].level <= 0) break;
- /* Pick a trap */
- place_trap_object(o_ptr);
-
/* Hack - set pval2 to the number of objects in it */
if (o_ptr->pval)
o_ptr->pval2 = (o_ptr->sval % SV_CHEST_MIN_LARGE) * 2;
@@ -3431,15 +3374,16 @@ static void a_m_aux_4(object_type *o_ptr, int level, int power)
/* Rating boost */
rating += 25;
/* Mention the item */
- if ((cheat_peek) || (p_ptr->precognition)) object_mention(o_ptr);
+ if (options->cheat_peek || p_ptr->precognition)
+ {
+ object_mention(o_ptr);
+ }
}
break;
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;
@@ -3481,153 +3425,137 @@ static void a_m_aux_4(object_type *o_ptr, int level, int power)
}
}
-void trap_hack(object_type *o_ptr)
-{
- if (o_ptr->tval != TV_TRAPKIT) return;
-
- switch (o_ptr->sval)
- {
- case SV_TRAPKIT_POTION:
- case SV_TRAPKIT_SCROLL:
- case SV_TRAPKIT_DEVICE:
- o_ptr->to_h = 0;
- o_ptr->to_d = 0;
- default:
- return;
- }
-}
-
/* Add a random glag to the ego item */
-void add_random_ego_flag(object_type *o_ptr, int fego, bool_ *limit_blows)
+void add_random_ego_flag(object_type *o_ptr, ego_flag_set const &fego, bool_ *limit_blows)
{
- if (fego & ETR4_SUSTAIN)
+ if (fego & ETR_SUSTAIN)
{
/* Make a random sustain */
switch (randint(6))
{
case 1:
- o_ptr->art_flags2 |= TR2_SUST_STR;
+ o_ptr->art_flags |= TR_SUST_STR;
break;
case 2:
- o_ptr->art_flags2 |= TR2_SUST_INT;
+ o_ptr->art_flags |= TR_SUST_INT;
break;
case 3:
- o_ptr->art_flags2 |= TR2_SUST_WIS;
+ o_ptr->art_flags |= TR_SUST_WIS;
break;
case 4:
- o_ptr->art_flags2 |= TR2_SUST_DEX;
+ o_ptr->art_flags |= TR_SUST_DEX;
break;
case 5:
- o_ptr->art_flags2 |= TR2_SUST_CON;
+ o_ptr->art_flags |= TR_SUST_CON;
break;
case 6:
- o_ptr->art_flags2 |= TR2_SUST_CHR;
+ o_ptr->art_flags |= TR_SUST_CHR;
break;
}
}
- if (fego & ETR4_OLD_RESIST)
+ if (fego & ETR_OLD_RESIST)
{
/* Make a random resist, equal probabilities */
switch (randint(11))
{
case 1:
- o_ptr->art_flags2 |= (TR2_RES_BLIND);
+ o_ptr->art_flags |= TR_RES_BLIND;
break;
case 2:
- o_ptr->art_flags2 |= (TR2_RES_CONF);
+ o_ptr->art_flags |= TR_RES_CONF;
break;
case 3:
- o_ptr->art_flags2 |= (TR2_RES_SOUND);
+ o_ptr->art_flags |= TR_RES_SOUND;
break;
case 4:
- o_ptr->art_flags2 |= (TR2_RES_SHARDS);
+ o_ptr->art_flags |= TR_RES_SHARDS;
break;
case 5:
- o_ptr->art_flags2 |= (TR2_RES_NETHER);
+ o_ptr->art_flags |= TR_RES_NETHER;
break;
case 6:
- o_ptr->art_flags2 |= (TR2_RES_NEXUS);
+ o_ptr->art_flags |= TR_RES_NEXUS;
break;
case 7:
- o_ptr->art_flags2 |= (TR2_RES_CHAOS);
+ o_ptr->art_flags |= TR_RES_CHAOS;
break;
case 8:
- o_ptr->art_flags2 |= (TR2_RES_DISEN);
+ o_ptr->art_flags |= TR_RES_DISEN;
break;
case 9:
- o_ptr->art_flags2 |= (TR2_RES_POIS);
+ o_ptr->art_flags |= TR_RES_POIS;
break;
case 10:
- o_ptr->art_flags2 |= (TR2_RES_DARK);
+ o_ptr->art_flags |= TR_RES_DARK;
break;
case 11:
- o_ptr->art_flags2 |= (TR2_RES_LITE);
+ o_ptr->art_flags |= TR_RES_LITE;
break;
}
}
- if (fego & ETR4_ABILITY)
+ if (fego & ETR_ABILITY)
{
/* Choose an ability */
switch (randint(8))
{
case 1:
- o_ptr->art_flags3 |= (TR3_FEATHER);
+ o_ptr->art_flags |= TR_FEATHER;
break;
case 2:
- o_ptr->art_flags3 |= (TR3_LITE1);
+ o_ptr->art_flags |= TR_LITE1;
break;
case 3:
- o_ptr->art_flags3 |= (TR3_SEE_INVIS);
+ o_ptr->art_flags |= TR_SEE_INVIS;
break;
case 4:
- o_ptr->art_esp |= (ESP_ALL);
+ o_ptr->art_flags |= ESP_ALL;
break;
case 5:
- o_ptr->art_flags3 |= (TR3_SLOW_DIGEST);
+ o_ptr->art_flags |= TR_SLOW_DIGEST;
break;
case 6:
- o_ptr->art_flags3 |= (TR3_REGEN);
+ o_ptr->art_flags |= TR_REGEN;
break;
case 7:
- o_ptr->art_flags2 |= (TR2_FREE_ACT);
+ o_ptr->art_flags |= TR_FREE_ACT;
break;
case 8:
- o_ptr->art_flags2 |= (TR2_HOLD_LIFE);
+ o_ptr->art_flags |= TR_HOLD_LIFE;
break;
}
}
- if (fego & ETR4_R_ELEM)
+ if (fego & ETR_R_ELEM)
{
/* Make an acid/elec/fire/cold/poison resist */
- random_resistance(o_ptr, FALSE, randint(14) + 4);
+ random_resistance(o_ptr, randint(14) + 4);
}
- if (fego & ETR4_R_LOW)
+ if (fego & ETR_R_LOW)
{
/* Make an acid/elec/fire/cold resist */
- random_resistance(o_ptr, FALSE, randint(12) + 4);
+ random_resistance(o_ptr, randint(12) + 4);
}
- if (fego & ETR4_R_HIGH)
+ if (fego & ETR_R_HIGH)
{
/* Make a high resist */
- random_resistance(o_ptr, FALSE, randint(22) + 16);
+ random_resistance(o_ptr, randint(22) + 16);
}
- if (fego & ETR4_R_ANY)
+ if (fego & ETR_R_ANY)
{
/* Make any resist */
- random_resistance(o_ptr, FALSE, randint(34) + 4);
+ random_resistance(o_ptr, randint(34) + 4);
}
- if (fego & ETR4_R_DRAGON)
+ if (fego & ETR_R_DRAGON)
{
/* Make "dragon resist" */
dragon_resist(o_ptr);
}
- if (fego & ETR4_SLAY_WEAP)
+ if (fego & ETR_SLAY_WEAP)
{
/* Make a Weapon of Slaying */
@@ -3648,254 +3576,251 @@ void add_random_ego_flag(object_type *o_ptr, int fego, bool_ *limit_blows)
}
if (randint(5) == 1)
{
- o_ptr->art_flags1 |= TR1_BRAND_POIS;
+ o_ptr->art_flags |= TR_BRAND_POIS;
}
if (o_ptr->tval == TV_SWORD && (randint(3) == 1))
{
- o_ptr->art_flags1 |= TR1_VORPAL;
+ o_ptr->art_flags |= TR_VORPAL;
}
}
- if (fego & ETR4_DAM_DIE)
+ if (fego & ETR_DAM_DIE)
{
/* Increase damage dice */
o_ptr->dd++;
}
- if (fego & ETR4_DAM_SIZE)
+ if (fego & ETR_DAM_SIZE)
{
/* Increase damage dice size */
o_ptr->ds++;
}
- if (fego & ETR4_LIMIT_BLOWS)
+ if (fego & ETR_LIMIT_BLOWS)
{
/* Swap this flag */
*limit_blows = !(*limit_blows);
}
- if (fego & ETR4_PVAL_M1)
+ if (fego & ETR_PVAL_M1)
{
/* Increase pval */
o_ptr->pval++;
}
- if (fego & ETR4_PVAL_M2)
+ if (fego & ETR_PVAL_M2)
{
/* Increase pval */
o_ptr->pval += m_bonus(2, dun_level);
}
- if (fego & ETR4_PVAL_M3)
+ if (fego & ETR_PVAL_M3)
{
/* Increase pval */
o_ptr->pval += m_bonus(3, dun_level);
}
- if (fego & ETR4_PVAL_M5)
+ if (fego & ETR_PVAL_M5)
{
/* Increase pval */
o_ptr->pval += m_bonus(5, dun_level);
}
- if (fego & ETR4_AC_M1)
+ if (fego & ETR_AC_M1)
{
/* Increase ac */
o_ptr->to_a++;
}
- if (fego & ETR4_AC_M2)
+ if (fego & ETR_AC_M2)
{
/* Increase ac */
o_ptr->to_a += m_bonus(2, dun_level);
}
- if (fego & ETR4_AC_M3)
+ if (fego & ETR_AC_M3)
{
/* Increase ac */
o_ptr->to_a += m_bonus(3, dun_level);
}
- if (fego & ETR4_AC_M5)
+ if (fego & ETR_AC_M5)
{
/* Increase ac */
o_ptr->to_a += m_bonus(5, dun_level);
}
- if (fego & ETR4_TH_M1)
+ if (fego & ETR_TH_M1)
{
/* Increase to hit */
o_ptr->to_h++;
}
- if (fego & ETR4_TH_M2)
+ if (fego & ETR_TH_M2)
{
/* Increase to hit */
o_ptr->to_h += m_bonus(2, dun_level);
}
- if (fego & ETR4_TH_M3)
+ if (fego & ETR_TH_M3)
{
/* Increase to hit */
o_ptr->to_h += m_bonus(3, dun_level);
}
- if (fego & ETR4_TH_M5)
+ if (fego & ETR_TH_M5)
{
/* Increase to hit */
o_ptr->to_h += m_bonus(5, dun_level);
}
- if (fego & ETR4_TD_M1)
+ if (fego & ETR_TD_M1)
{
/* Increase to dam */
o_ptr->to_d++;
}
- if (fego & ETR4_TD_M2)
+ if (fego & ETR_TD_M2)
{
/* Increase to dam */
o_ptr->to_d += m_bonus(2, dun_level);
}
- if (fego & ETR4_TD_M3)
+ if (fego & ETR_TD_M3)
{
/* Increase to dam */
o_ptr->to_d += m_bonus(3, dun_level);
}
- if (fego & ETR4_TD_M5)
+ if (fego & ETR_TD_M5)
{
/* Increase to dam */
o_ptr->to_d += m_bonus(5, dun_level);
}
- if (fego & ETR4_R_P_ABILITY)
+ if (fego & ETR_R_P_ABILITY)
{
/* Add a random pval-affected ability */
/* This might cause boots with + to blows */
- switch (randint(6))
+ switch (randint(5))
{
case 1:
- o_ptr->art_flags1 |= TR1_STEALTH;
+ o_ptr->art_flags |= TR_STEALTH;
break;
case 2:
- o_ptr->art_flags1 |= TR1_SEARCH;
+ o_ptr->art_flags |= TR_INFRA;
break;
case 3:
- o_ptr->art_flags1 |= TR1_INFRA;
+ o_ptr->art_flags |= TR_TUNNEL;
break;
case 4:
- o_ptr->art_flags1 |= TR1_TUNNEL;
+ o_ptr->art_flags |= TR_SPEED;
break;
case 5:
- o_ptr->art_flags1 |= TR1_SPEED;
- break;
- case 6:
- o_ptr->art_flags1 |= TR1_BLOWS;
+ o_ptr->art_flags |= TR_BLOWS;
break;
}
}
- if (fego & ETR4_R_STAT)
+ if (fego & ETR_R_STAT)
{
/* Add a random stat */
switch (randint(6))
{
case 1:
- o_ptr->art_flags1 |= TR1_STR;
+ o_ptr->art_flags |= TR_STR;
break;
case 2:
- o_ptr->art_flags1 |= TR1_INT;
+ o_ptr->art_flags |= TR_INT;
break;
case 3:
- o_ptr->art_flags1 |= TR1_WIS;
+ o_ptr->art_flags |= TR_WIS;
break;
case 4:
- o_ptr->art_flags1 |= TR1_DEX;
+ o_ptr->art_flags |= TR_DEX;
break;
case 5:
- o_ptr->art_flags1 |= TR1_CON;
+ o_ptr->art_flags |= TR_CON;
break;
case 6:
- o_ptr->art_flags1 |= TR1_CHR;
+ o_ptr->art_flags |= TR_CHR;
break;
}
}
- if (fego & ETR4_R_STAT_SUST)
+ if (fego & ETR_R_STAT_SUST)
{
/* Add a random stat and sustain it */
switch (randint(6))
{
case 1:
{
- o_ptr->art_flags1 |= TR1_STR;
- o_ptr->art_flags2 |= TR2_SUST_STR;
+ o_ptr->art_flags |= TR_STR;
+ o_ptr->art_flags |= TR_SUST_STR;
break;
}
case 2:
{
- o_ptr->art_flags1 |= TR1_INT;
- o_ptr->art_flags2 |= TR2_SUST_INT;
+ o_ptr->art_flags |= TR_INT;
+ o_ptr->art_flags |= TR_SUST_INT;
break;
}
case 3:
{
- o_ptr->art_flags1 |= TR1_WIS;
- o_ptr->art_flags2 |= TR2_SUST_WIS;
+ o_ptr->art_flags |= TR_WIS;
+ o_ptr->art_flags |= TR_SUST_WIS;
break;
}
case 4:
{
- o_ptr->art_flags1 |= TR1_DEX;
- o_ptr->art_flags2 |= TR2_SUST_DEX;
+ o_ptr->art_flags |= TR_DEX;
+ o_ptr->art_flags |= TR_SUST_DEX;
break;
}
case 5:
{
- o_ptr->art_flags1 |= TR1_CON;
- o_ptr->art_flags2 |= TR2_SUST_CON;
+ o_ptr->art_flags |= TR_CON;
+ o_ptr->art_flags |= TR_SUST_CON;
break;
}
case 6:
{
- o_ptr->art_flags1 |= TR1_CHR;
- o_ptr->art_flags2 |= TR2_SUST_CHR;
+ o_ptr->art_flags |= TR_CHR;
+ o_ptr->art_flags |= TR_SUST_CHR;
break;
}
}
}
- if (fego & ETR4_R_IMMUNITY)
+ if (fego & ETR_R_IMMUNITY)
{
/* Give a random immunity */
switch (randint(4))
{
case 1:
{
- o_ptr->art_flags2 |= TR2_IM_FIRE;
- o_ptr->art_flags3 |= TR3_IGNORE_FIRE;
+ o_ptr->art_flags |= TR_IM_FIRE;
+ o_ptr->art_flags |= TR_IGNORE_FIRE;
break;
}
case 2:
{
- o_ptr->art_flags2 |= TR2_IM_ACID;
- o_ptr->art_flags3 |= TR3_IGNORE_ACID;
+ o_ptr->art_flags |= TR_IM_ACID;
+ o_ptr->art_flags |= TR_IGNORE_ACID;
break;
}
case 3:
{
- o_ptr->art_flags2 |= TR2_IM_ELEC;
- o_ptr->art_flags3 |= TR3_IGNORE_ELEC;
+ o_ptr->art_flags |= TR_IM_ELEC;
+ o_ptr->art_flags |= TR_IGNORE_ELEC;
break;
}
case 4:
{
- o_ptr->art_flags2 |= TR2_IM_COLD;
- o_ptr->art_flags3 |= TR3_IGNORE_COLD;
+ o_ptr->art_flags |= TR_IM_COLD;
+ o_ptr->art_flags |= TR_IGNORE_COLD;
break;
}
}
@@ -3933,33 +3858,31 @@ void add_random_ego_flag(object_type *o_ptr, int fego, bool_ *limit_blows)
* "good" and "great" arguments are false. As a total hack, if "great" is
* true, then the item gets 3 extra "attempts" to become an artifact.
*/
-int hack_apply_magic_power = 0;
-void apply_magic(object_type *o_ptr, int lev, bool_ okay, bool_ good, bool_ great)
+void apply_magic(object_type *o_ptr, int lev, bool_ okay, bool_ good, bool_ great, boost::optional<int> force_power)
{
- int i, rolls, f1, f2, power;
- object_kind *k_ptr = &k_info[o_ptr->k_idx];
+ auto &k_info = game->edit_data.k_info;
+ auto &a_info = game->edit_data.a_info;
+ auto const &e_info = game->edit_data.e_info;
+
+ int i, rolls;
+ auto k_ptr = &k_info[o_ptr->k_idx];
/* Aply luck */
lev += luck( -7, 7);
- /* Spell in it ? no ! */
- if (k_ptr->flags5 & TR5_SPELL_CONTAIN)
+ /* Spell in it? No! */
+ if (k_ptr->flags & TR_SPELL_CONTAIN)
o_ptr->pval2 = -1;
/* Important to do before all else, be sure to have the basic obvious flags set */
- o_ptr->art_oflags1 = k_ptr->oflags1;
- o_ptr->art_oflags2 = k_ptr->oflags2;
- o_ptr->art_oflags3 = k_ptr->oflags3;
- o_ptr->art_oflags4 = k_ptr->oflags4;
- o_ptr->art_oflags5 = k_ptr->oflags5;
- o_ptr->art_oesp = k_ptr->oesp;
+ o_ptr->art_oflags = k_ptr->oflags;
/* No need to touch normal artifacts */
- if (k_ptr->flags3 & TR3_NORM_ART)
+ if (k_ptr->flags & TR_NORM_ART)
{
/* Ahah! we tried to trick us !! */
if (k_ptr->artifact ||
- ((k_ptr->flags4 & TR4_SPECIAL_GENE) &&
+ ((k_ptr->flags & TR_SPECIAL_GENE) &&
(!k_allow_special[o_ptr->k_idx])))
{
object_prep(o_ptr, lookup_kind(k_ptr->btval, k_ptr->bsval));
@@ -3979,8 +3902,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 */
@@ -3989,7 +3912,10 @@ void apply_magic(object_type *o_ptr, int lev, bool_ okay, bool_ good, bool_ grea
k_ptr->artifact = TRUE;
- if (cheat_peek || p_ptr->precognition) object_mention(o_ptr);
+ if (options->cheat_peek || p_ptr->precognition)
+ {
+ object_mention(o_ptr);
+ }
}
return;
@@ -3998,52 +3924,50 @@ void apply_magic(object_type *o_ptr, int lev, bool_ okay, bool_ good, bool_ grea
/* Maximum "level" for various things */
if (lev > MAX_DEPTH - 1) lev = MAX_DEPTH - 1;
+ /* Roll for power */
+ int power = 0;
+ {
+ /* Base chance of being "good" */
+ int f1 = lev + 10 + luck( -15, 15);
- /* Base chance of being "good" */
- f1 = lev + 10 + luck( -15, 15);
-
- /* Maximal chance of being "good" */
- if (f1 > 75) f1 = 75;
-
- /* Base chance of being "great" */
- f2 = f1 / 2;
+ /* Maximal chance of being "good" */
+ if (f1 > 75) f1 = 75;
- /* Maximal chance of being "great" */
- if (f2 > 20) f2 = 20;
+ /* Base chance of being "great" */
+ int f2 = f1 / 2;
+ /* Maximal chance of being "great" */
+ if (f2 > 20) f2 = 20;
- /* Assume normal */
- power = 0;
+ /* Assume normal */
+ power = 0;
- /* Roll for "good" */
- if (good || magik(f1))
- {
- /* Assume "good" */
- power = 1;
+ /* Roll for "good" */
+ if (good || magik(f1))
+ {
+ /* Assume "good" */
+ power = 1;
- /* Roll for "great" */
- if (great || magik(f2)) power = 2;
- }
+ /* Roll for "great" */
+ if (great || magik(f2)) power = 2;
+ }
- /* Roll for "cursed" */
- else if (magik(f1))
- {
- /* Assume "cursed" */
- power = -1;
+ /* Roll for "cursed" */
+ else if (magik(f1))
+ {
+ /* Assume "cursed" */
+ power = -1;
- /* Roll for "broken" */
- if (magik(f2)) power = -2;
- }
+ /* Roll for "broken" */
+ if (magik(f2)) power = -2;
+ }
- /* Mega hack */
- if (hack_apply_magic_power)
- {
- if (hack_apply_magic_power == -99)
- power = 0;
- else
- power = hack_apply_magic_power;
+ /* Override power with parameter? */
+ if (auto power_override = force_power)
+ {
+ power = *power_override;
+ }
}
- hack_apply_magic_power = 0;
/* Assume no rolls */
rolls = 0;
@@ -4077,7 +4001,7 @@ void apply_magic(object_type *o_ptr, int lev, bool_ okay, bool_ good, bool_ grea
/* Hack -- analyze artifacts */
if (o_ptr->name1)
{
- artifact_type *a_ptr = &a_info[o_ptr->name1];
+ auto a_ptr = &a_info[o_ptr->name1];
/* Hack -- Mark the artifact as "created" */
a_ptr->cur_num = 1;
@@ -4094,7 +4018,7 @@ void apply_magic(object_type *o_ptr, int lev, bool_ okay, bool_ good, bool_ grea
o_ptr->number = 1;
/* Hack -- extract the "cursed" flag */
- if (a_ptr->flags3 & (TR3_CURSED)) o_ptr->ident |= (IDENT_CURSED);
+ if (a_ptr->flags & TR_CURSED) o_ptr->ident |= (IDENT_CURSED);
/* Mega-Hack -- increase the rating */
rating += 10;
@@ -4106,17 +4030,19 @@ void apply_magic(object_type *o_ptr, int lev, bool_ okay, bool_ good, bool_ grea
good_item_flag = TRUE;
/* Cheat -- peek at the item */
- if ((cheat_peek) || (p_ptr->precognition)) object_mention(o_ptr);
+ if (options->cheat_peek || p_ptr->precognition)
+ {
+ object_mention(o_ptr);
+ }
- /* Spell in it ? no ! */
- if (a_ptr->flags5 & TR5_SPELL_CONTAIN)
+ /* Spell in it? No! */
+ if (a_ptr->flags & TR_SPELL_CONTAIN)
o_ptr->pval2 = -1;
/* Give a basic exp/exp level to an artifact that needs it */
- if (a_ptr->flags4 & TR4_LEVELS)
+ if (a_ptr->flags & TR_LEVELS)
{
- o_ptr->elevel = (k_ptr->level / 10) + 1;
- o_ptr->exp = player_exp[o_ptr->elevel - 1];
+ init_obj_exp(o_ptr, k_ptr);
}
/* Done */
@@ -4142,7 +4068,6 @@ void apply_magic(object_type *o_ptr, int lev, bool_ okay, bool_ good, bool_ grea
case TV_SHOT:
case TV_ARROW:
case TV_BOLT:
- case TV_TRAPKIT:
{
if (power) a_m_aux_1(o_ptr, lev, power);
break;
@@ -4191,58 +4116,47 @@ void apply_magic(object_type *o_ptr, int lev, bool_ okay, bool_ good, bool_ grea
}
}
- if (o_ptr->art_name) rating += 40;
+ if (!o_ptr->artifact_name.empty())
+ {
+ rating += 40;
+ }
/* Hack -- analyze ego-items */
else if (o_ptr->name2)
{
- ego_item_type *e_ptr;
int j;
bool_ limit_blows = FALSE;
- u32b f1, f2, f3, f4, f5, esp;
s16b e_idx;
e_idx = o_ptr->name2;
/* Ok now, THAT is truly ugly */
try_an_other_ego:
- e_ptr = &e_info[e_idx];
+ auto e_ptr = &e_info[e_idx];
/* Hack -- extra powers */
- for (j = 0; j < 5; j++)
+ for (j = 0; j < FLAG_RARITY_MAX; j++)
{
/* Rarity check */
if (magik(e_ptr->rar[j]))
{
- o_ptr->art_flags1 |= e_ptr->flags1[j];
- o_ptr->art_flags2 |= e_ptr->flags2[j];
- o_ptr->art_flags3 |= e_ptr->flags3[j];
- o_ptr->art_flags4 |= e_ptr->flags4[j];
- o_ptr->art_flags5 |= e_ptr->flags5[j];
- o_ptr->art_esp |= e_ptr->esp[j];
-
- o_ptr->art_oflags1 |= e_ptr->oflags1[j];
- o_ptr->art_oflags2 |= e_ptr->oflags2[j];
- o_ptr->art_oflags3 |= e_ptr->oflags3[j];
- o_ptr->art_oflags4 |= e_ptr->oflags4[j];
- o_ptr->art_oflags5 |= e_ptr->oflags5[j];
- o_ptr->art_oesp |= e_ptr->oesp[j];
-
+ o_ptr->art_flags |= e_ptr->flags[j];
+ o_ptr->art_oflags |= e_ptr->oflags[j];
add_random_ego_flag(o_ptr, e_ptr->fego[j], &limit_blows);
}
}
/* No insane number of blows */
- if (limit_blows && (o_ptr->art_flags1 & TR1_BLOWS))
+ if (limit_blows && (o_ptr->art_flags & TR_BLOWS))
{
if (o_ptr->pval > 2) o_ptr->pval = randint(2);
}
/* get flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ auto const flags = object_flags(o_ptr);
/* Hack -- acquire "cursed" flag */
- if (f3 & TR3_CURSED) o_ptr->ident |= (IDENT_CURSED);
+ if (flags & TR_CURSED) o_ptr->ident |= (IDENT_CURSED);
/* Hack -- obtain bonuses */
if (e_ptr->max_to_h > 0) o_ptr->to_h += randint(e_ptr->max_to_h);
@@ -4265,53 +4179,41 @@ try_an_other_ego:
goto try_an_other_ego;
}
- /* Spell in it ? no ! */
- if (f5 & TR5_SPELL_CONTAIN)
+ /* Spell in it ? No! */
+ if (flags & TR_SPELL_CONTAIN)
{
- /* Mega hack, mage staves of spell cannot SPELL_CONTAIN */
- if (is_ego_p(o_ptr, EGO_MSTAFF_SPELL))
- {
- o_ptr->art_flags5 &= ~TR5_SPELL_CONTAIN;
- }
- else
- o_ptr->pval2 = -1;
+ o_ptr->pval2 = -1;
}
/* Cheat -- describe the item */
- if ((cheat_peek) || (p_ptr->precognition)) object_mention(o_ptr);
+ if (options->cheat_peek || p_ptr->precognition)
+ {
+ object_mention(o_ptr);
+ }
}
/* Examine real objects */
if (o_ptr->k_idx)
{
- u32b f1, f2, f3, f4, f5, esp;
-
object_kind *k_ptr = &k_info[o_ptr->k_idx];
/* Hack -- acquire "cursed" flag */
- if (k_ptr->flags3 & (TR3_CURSED)) o_ptr->ident |= (IDENT_CURSED);
+ if (k_ptr->flags & TR_CURSED) o_ptr->ident |= (IDENT_CURSED);
/* Extract some flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ auto const flags = object_flags(o_ptr);
/* Hack give a basic exp/exp level to an object that needs it */
- if (f4 & TR4_LEVELS)
+ if (flags & TR_LEVELS)
{
- o_ptr->elevel = (k_ptr->level / 10) + 1;
- o_ptr->exp = player_exp[o_ptr->elevel - 1];
+ init_obj_exp(o_ptr, k_ptr);
}
- /* Spell in it ? no ! */
- if (f5 & TR5_SPELL_CONTAIN)
+ /* Spell in it ? No! */
+ if (flags & TR_SPELL_CONTAIN)
{
- /* Mega hack, mage staves of spell cannot SPELL_CONTAIN */
- if (is_ego_p(o_ptr, EGO_MSTAFF_SPELL))
- {
- o_ptr->art_flags5 &= ~TR5_SPELL_CONTAIN;
- }
- else
- o_ptr->pval2 = -1;
+ o_ptr->pval2 = -1;
}
/* Hacccccccckkkkk attack ! :) -- To prevent som ugly crashs */
@@ -4324,64 +4226,62 @@ try_an_other_ego:
if (o_ptr->tval == TV_ROD_MAIN)
{
/* Set the max mana and the current mana */
- o_ptr->pval2 = (f4 & TR4_CAPACITY) ? o_ptr->sval * 2 : o_ptr->sval;
+ o_ptr->pval2 = (flags & TR_CAPACITY) ? o_ptr->sval * 2 : o_ptr->sval;
o_ptr->timeout = o_ptr->pval2;
}
-
- /* Remove some unnecessary stuff hack */
- if (o_ptr->tval == TV_TRAPKIT) trap_hack(o_ptr);
}
}
/* The themed objects to use */
-static obj_theme match_theme;
+static obj_theme *match_theme = nullptr;
/*
* XXX XXX XXX It relies on the fact that obj_theme is a four byte structure
* for its efficient operation. A horrendous hack, I'd say.
*/
-void init_match_theme(obj_theme theme)
+bool init_match_theme(obj_theme const &theme)
{
- /* Save the theme */
- match_theme = theme;
+ if (match_theme == nullptr)
+ {
+ match_theme = new obj_theme(theme);
+ return true;
+ }
+ else if (*match_theme != theme)
+ {
+ *match_theme = theme;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
}
/*
- * Ditto XXX XXX XXX
+ * Maga-Hack -- match certain types of object only.
*/
-static bool_ theme_changed(obj_theme theme)
+static bool kind_is_theme(obj_theme const *theme, int k_idx)
{
- /* Any of the themes has been changed */
- if (theme.treasure != match_theme.treasure) return (TRUE);
- if (theme.combat != match_theme.combat) return (TRUE);
- if (theme.magic != match_theme.magic) return (TRUE);
- if (theme.tools != match_theme.tools) return (TRUE);
-
- /* No changes */
- return (FALSE);
-}
+ auto const &k_info = game->edit_data.k_info;
+ assert(theme != nullptr);
-/*
- * Maga-Hack -- match certain types of object only.
- */
-bool_ kind_is_theme(int k_idx)
-{
- object_kind *k_ptr = &k_info[k_idx];
+ auto k_ptr = &k_info[k_idx];
s32b prob = 0;
-
/*
* Paranoia -- Prevent accidental "(Nothing)"
* that are results of uninitialised theme structs.
*
* Caution: Junks go into the allocation table.
*/
- if (match_theme.treasure + match_theme.combat +
- match_theme.magic + match_theme.tools == 0) return (TRUE);
+ if (theme->treasure + theme->combat + theme->magic + theme->tools == 0)
+ {
+ return TRUE;
+ }
/* Pick probability to use */
@@ -4400,153 +4300,141 @@ bool_ kind_is_theme(int k_idx)
* larger than theme components, or we would see
* unexpected, well, junks.
*/
- prob = 100 - (match_theme.treasure + match_theme.combat +
- match_theme.magic + match_theme.tools);
+ prob = 100 - (theme->treasure + theme->combat +
+ theme->magic + theme->tools);
break;
}
case TV_CHEST:
- prob = match_theme.treasure;
+ prob = theme->treasure;
break;
case TV_CROWN:
- prob = match_theme.treasure;
+ prob = theme->treasure;
break;
case TV_DRAG_ARMOR:
- prob = match_theme.treasure;
+ prob = theme->treasure;
break;
case TV_AMULET:
- prob = match_theme.treasure;
+ prob = theme->treasure;
break;
case TV_RING:
- prob = match_theme.treasure;
+ prob = theme->treasure;
break;
case TV_SHOT:
- prob = match_theme.combat;
+ prob = theme->combat;
break;
case TV_ARROW:
- prob = match_theme.combat;
+ prob = theme->combat;
break;
case TV_BOLT:
- prob = match_theme.combat;
+ prob = theme->combat;
break;
case TV_BOOMERANG:
- prob = match_theme.combat;
+ prob = theme->combat;
break;
case TV_BOW:
- prob = match_theme.combat;
+ prob = theme->combat;
break;
case TV_HAFTED:
- prob = match_theme.combat;
+ prob = theme->combat;
break;
case TV_POLEARM:
- prob = match_theme.combat;
+ prob = theme->combat;
break;
case TV_SWORD:
- prob = match_theme.combat;
+ prob = theme->combat;
break;
case TV_AXE:
- prob = match_theme.combat;
+ prob = theme->combat;
break;
case TV_GLOVES:
- prob = match_theme.combat;
+ prob = theme->combat;
break;
case TV_HELM:
- prob = match_theme.combat;
+ prob = theme->combat;
break;
case TV_SHIELD:
- prob = match_theme.combat;
+ prob = theme->combat;
break;
case TV_SOFT_ARMOR:
- prob = match_theme.combat;
+ prob = theme->combat;
break;
case TV_HARD_ARMOR:
- prob = match_theme.combat;
+ prob = theme->combat;
break;
case TV_MSTAFF:
- prob = match_theme.magic;
+ prob = theme->magic;
break;
case TV_STAFF:
- prob = match_theme.magic;
+ prob = theme->magic;
break;
case TV_WAND:
- prob = match_theme.magic;
+ prob = theme->magic;
break;
case TV_ROD:
- prob = match_theme.magic;
+ prob = theme->magic;
break;
case TV_ROD_MAIN:
- prob = match_theme.magic;
+ prob = theme->magic;
break;
case TV_SCROLL:
- prob = match_theme.magic;
+ prob = theme->magic;
break;
case TV_PARCHMENT:
- prob = match_theme.magic;
+ prob = theme->magic;
break;
case TV_POTION:
- prob = match_theme.magic;
+ prob = theme->magic;
break;
case TV_POTION2:
- prob = match_theme.magic;
- break;
- case TV_BATERIE:
- prob = match_theme.magic;
+ prob = theme->magic;
break;
case TV_RANDART:
- prob = match_theme.magic;
- break;
- case TV_RUNE1:
- prob = match_theme.magic;
- break;
- case TV_RUNE2:
- prob = match_theme.magic;
+ prob = theme->magic;
break;
case TV_BOOK:
- prob = match_theme.magic;
+ prob = theme->magic;
break;
case TV_SYMBIOTIC_BOOK:
- prob = match_theme.magic;
+ prob = theme->magic;
break;
case TV_MUSIC_BOOK:
- prob = match_theme.magic;
+ prob = theme->magic;
break;
case TV_DRUID_BOOK:
- prob = match_theme.magic;
+ prob = theme->magic;
break;
case TV_DAEMON_BOOK:
- prob = match_theme.magic;
+ prob = theme->magic;
break;
case TV_LITE:
- prob = match_theme.tools;
+ prob = theme->tools;
break;
case TV_CLOAK:
- prob = match_theme.tools;
+ prob = theme->tools;
break;
case TV_BOOTS:
- prob = match_theme.tools;
+ prob = theme->tools;
break;
case TV_SPIKE:
- prob = match_theme.tools;
+ prob = theme->tools;
break;
case TV_DIGGING:
- prob = match_theme.tools;
+ prob = theme->tools;
break;
case TV_FLASK:
- prob = match_theme.tools;
+ prob = theme->tools;
break;
case TV_FOOD:
- prob = match_theme.tools;
+ prob = theme->tools;
break;
case TV_TOOL:
- prob = match_theme.tools;
+ prob = theme->tools;
break;
case TV_INSTRUMENT:
- prob = match_theme.tools;
- break;
- case TV_TRAPKIT:
- prob = match_theme.tools;
+ prob = theme->tools;
break;
}
@@ -4560,21 +4448,22 @@ bool_ kind_is_theme(int k_idx)
/*
* Determine if an object must not be generated.
*/
-int kind_is_legal_special = -1;
bool_ kind_is_legal(int k_idx)
{
- object_kind *k_ptr = &k_info[k_idx];
+ auto const &k_info = game->edit_data.k_info;
+
+ auto k_ptr = &k_info[k_idx];
- if (!kind_is_theme(k_idx)) return FALSE;
+ if (!kind_is_theme(match_theme, k_idx)) return FALSE;
- if (k_ptr->flags4 & TR4_SPECIAL_GENE)
+ if (k_ptr->flags & TR_SPECIAL_GENE)
{
if (k_allow_special[k_idx]) return TRUE;
else return FALSE;
}
/* No 2 times the same normal artifact */
- if ((k_ptr->flags3 & TR3_NORM_ART) && (k_ptr->artifact))
+ if ((k_ptr->flags & TR_NORM_ART) && (k_ptr->artifact))
{
return FALSE;
}
@@ -4597,9 +4486,6 @@ bool_ kind_is_legal(int k_idx)
/* Used only for the Nazgul rings */
if ((k_ptr->tval == TV_RING) && (k_ptr->sval == SV_RING_SPECIAL)) return FALSE;
- /* Are we forced to one tval ? */
- if ((kind_is_legal_special != -1) && (kind_is_legal_special != k_ptr->tval)) return (FALSE);
-
/* Assume legal */
return TRUE;
}
@@ -4608,9 +4494,11 @@ bool_ kind_is_legal(int k_idx)
/*
* Hack -- determine if a template is "good"
*/
-bool_ kind_is_good(int k_idx)
+static bool_ kind_is_good(int k_idx)
{
- object_kind *k_ptr = &k_info[k_idx];
+ auto const &k_info = game->edit_data.k_info;
+
+ auto k_ptr = &k_info[k_idx];
if (!kind_is_legal(k_idx)) return FALSE;
@@ -4639,7 +4527,6 @@ bool_ kind_is_good(int k_idx)
case TV_HAFTED:
case TV_POLEARM:
case TV_DIGGING:
- case TV_TRAPKIT:
case TV_MSTAFF:
case TV_BOOMERANG:
{
@@ -4665,7 +4552,6 @@ bool_ kind_is_good(int k_idx)
/* Expensive rod tips are good */
case TV_ROD:
{
- /* Probing is not good, but Recall is*/
if (k_ptr->cost >= 4500) return TRUE;
return FALSE;
}
@@ -4707,23 +4593,21 @@ bool_ kind_is_good(int k_idx)
*/
bool_ kind_is_artifactable(int k_idx)
{
- int i, j;
- object_kind *k_ptr = &k_info[k_idx];
+ auto const &ra_info = game->edit_data.ra_info;
+ auto const &k_info = game->edit_data.k_info;
+ auto k_ptr = &k_info[k_idx];
if (kind_is_good(k_idx))
{
- /* We consider the item artifactable if there is at least one
- * randart power in ra_info that could be added to this item. */
- for (i = 0; i < max_ra_idx; i++)
+ // Consider the item artifactable if there is at least one
+ // randart power which could be added to the item.
+ for (auto const &ra_ref: ra_info)
{
- randart_part_type *ra_ptr = &ra_info[i];
-
- for (j = 0; j < 20; j++)
+ for (auto const &filter: ra_ref.kind_filter)
{
- if (ra_ptr->tval[j] != k_ptr->tval) continue;
- if (ra_ptr->min_sval[j] > k_ptr->sval) continue;
- if (ra_ptr->max_sval[j] < k_ptr->sval) continue;
- /* Winner */
+ if (filter.tval != k_ptr->tval) continue;
+ if (filter.min_sval > k_ptr->sval) continue;
+ if (filter.max_sval < k_ptr->sval) continue;
return TRUE;
}
}
@@ -4748,8 +4632,11 @@ bool_ kind_is_artifactable(int k_idx)
* through the forge--object_prep()--apply_magic() sequence and
* get_obj_num() should never be called for that purpose XXX XXX XXX
*/
-bool_ make_object(object_type *j_ptr, bool_ good, bool_ great, obj_theme theme)
+bool_ make_object(object_type *j_ptr, bool_ good, bool_ great, obj_theme const &theme)
{
+ auto const &k_info = game->edit_data.k_info;
+ auto &alloc = game->alloc;
+
int invprob, base;
@@ -4763,16 +4650,11 @@ bool_ make_object(object_type *j_ptr, bool_ good, bool_ great, obj_theme theme)
/* Generate a special object, or a normal object */
if ((rand_int(invprob) != 0) || !make_artifact_special(j_ptr))
{
- int k_idx;
-
- /* See if the theme has been changed XXX XXX XXX */
- if (theme_changed(theme))
+ /* See if the theme has been changed */
+ if (init_match_theme(theme))
{
- /* Select items based on "theme" */
- init_match_theme(theme);
-
/* Invalidate the cached allocation table */
- alloc_kind_table_valid = FALSE;
+ alloc.kind_table_valid = false;
}
/* Good objects */
@@ -4786,7 +4668,7 @@ bool_ make_object(object_type *j_ptr, bool_ good, bool_ great, obj_theme theme)
}
/* Normal objects -- only when the cache is invalidated */
- else if (!alloc_kind_table_valid)
+ else if (!alloc.kind_table_valid)
{
/* Activate normal restriction */
get_obj_num_hook = kind_is_legal;
@@ -4795,11 +4677,11 @@ bool_ make_object(object_type *j_ptr, bool_ good, bool_ great, obj_theme theme)
get_obj_num_prep();
/* The table is synchronised */
- alloc_kind_table_valid = TRUE;
+ alloc.kind_table_valid = true;
}
/* Pick a random object */
- k_idx = get_obj_num(base);
+ int k_idx = get_obj_num(base);
/* Good objects */
if (good)
@@ -4811,7 +4693,7 @@ bool_ make_object(object_type *j_ptr, bool_ good, bool_ great, obj_theme theme)
get_obj_num_prep();
/* The table is synchronised */
- alloc_kind_table_valid = TRUE;
+ alloc.kind_table_valid = true;
}
/* Handle failure */
@@ -4847,7 +4729,10 @@ bool_ make_object(object_type *j_ptr, bool_ good, bool_ great, obj_theme theme)
rating += (k_info[j_ptr->k_idx].level - dun_level);
/* Cheat -- peek at items */
- if ((cheat_peek) || (p_ptr->precognition)) object_mention(j_ptr);
+ if (options->cheat_peek || p_ptr->precognition)
+ {
+ object_mention(j_ptr);
+ }
}
/* Success */
@@ -4867,6 +4752,11 @@ bool_ make_object(object_type *j_ptr, bool_ good, bool_ great, obj_theme theme)
*/
void place_object(int y, int x, bool_ good, bool_ great, int where)
{
+ auto const &d_info = game->edit_data.d_info;
+ auto &k_info = game->edit_data.k_info;
+ auto &a_info = game->edit_data.a_info;
+ auto &random_artifacts = game->random_artifacts;
+
s16b o_idx;
cave_type *c_ptr;
@@ -4918,10 +4808,8 @@ void place_object(int y, int x, bool_ good, bool_ great, int where)
/* Success */
if (o_idx)
{
- object_type *o_ptr;
-
/* Acquire object */
- o_ptr = &o_list[o_idx];
+ object_type *o_ptr = &o_list[o_idx];
/* Structure Copy */
object_copy(o_ptr, q_ptr);
@@ -4933,11 +4821,8 @@ void place_object(int y, int x, bool_ good, bool_ great, int where)
/* Acquire grid */
c_ptr = &cave[y][x];
- /* Build a stack */
- o_ptr->next_o_idx = c_ptr->o_idx;
-
/* Place the object */
- c_ptr->o_idx = o_idx;
+ c_ptr->o_idxs.push_back(o_idx);
/* Notice */
note_spot(y, x);
@@ -4954,7 +4839,7 @@ void place_object(int y, int x, bool_ good, bool_ great, int where)
{
a_info[q_ptr->name1].cur_num = 0;
}
- else if (k_info[q_ptr->k_idx].flags3 & TR3_NORM_ART)
+ else if (k_info[q_ptr->k_idx].flags & TR_NORM_ART)
{
k_info[q_ptr->k_idx].artifact = 0;
}
@@ -4979,6 +4864,8 @@ void place_object(int y, int x, bool_ good, bool_ great, int where)
*/
bool_ make_gold(object_type *j_ptr)
{
+ auto const &k_info = game->edit_data.k_info;
+
int i;
s32b base;
@@ -5007,6 +4894,12 @@ bool_ make_gold(object_type *j_ptr)
/* Determine how much the treasure is "worth" */
j_ptr->pval = (base + (8L * randint(base)) + randint(8));
+
+ /* Multiply value by 5 if selling is disabled */
+ if (options->no_selling)
+ {
+ j_ptr->pval *= 5;
+ }
/* Success */
return (TRUE);
@@ -5066,11 +4959,8 @@ void place_gold(int y, int x)
/* Acquire grid */
c_ptr = &cave[y][x];
- /* Build a stack */
- o_ptr->next_o_idx = c_ptr->o_idx;
-
/* Place the object */
- c_ptr->o_idx = o_idx;
+ c_ptr->o_idxs.push_back(o_idx);
/* Notice */
note_spot(y, x);
@@ -5099,6 +4989,11 @@ void place_gold(int y, int x)
*/
s16b drop_near(object_type *j_ptr, int chance, int y, int x)
{
+ auto const &f_info = game->edit_data.f_info;
+ auto &k_info = game->edit_data.k_info;
+ auto &a_info = game->edit_data.a_info;
+ auto &random_artifacts = game->random_artifacts;
+
int i, k, d, s;
int bs, bn;
@@ -5106,10 +5001,6 @@ s16b drop_near(object_type *j_ptr, int chance, int y, int x)
int dy, dx;
int ty, tx;
- s16b o_idx = 0;
-
- s16b this_o_idx, next_o_idx = 0;
-
cave_type *c_ptr;
char o_name[80];
@@ -5128,7 +5019,7 @@ s16b drop_near(object_type *j_ptr, int chance, int y, int x)
/* Handle normal "breakage" */
- if (!(j_ptr->art_name || artifact_p(j_ptr)) && (rand_int(100) < chance))
+ if ((!artifact_p(j_ptr)) && (rand_int(100) < chance))
{
/* Message */
msg_format("The %s disappear%s.",
@@ -5180,24 +5071,16 @@ s16b drop_near(object_type *j_ptr, int chance, int y, int x)
c_ptr = &cave[ty][tx];
/* Require floor space (or shallow terrain) -KMW- */
- if (!(f_info[c_ptr->feat].flags1 & FF1_FLOOR)) continue;
-
- /* No traps */
- if (c_ptr->t_idx) continue;
+ if (!(f_info[c_ptr->feat].flags & FF_FLOOR)) continue;
/* No objects */
k = 0;
/* Scan objects in that grid */
- for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
+ for (auto const this_o_idx: c_ptr->o_idxs)
{
- object_type * o_ptr;
-
/* Acquire object */
- o_ptr = &o_list[this_o_idx];
-
- /* Acquire next object */
- next_o_idx = o_ptr->next_o_idx;
+ object_type *o_ptr = &o_list[this_o_idx];
/* Check for possible combination */
if (object_similar(o_ptr, j_ptr)) comb = TRUE;
@@ -5209,9 +5092,6 @@ s16b drop_near(object_type *j_ptr, int chance, int y, int x)
/* Add new object */
if (!comb) k++;
- /* No stacking (allow combining) */
- if (!testing_stack && (k > 1)) continue;
-
/* Paranoia */
if (k > 23) continue;
@@ -5241,7 +5121,7 @@ s16b drop_near(object_type *j_ptr, int chance, int y, int x)
/* Handle lack of space */
- if (!flag && !(artifact_p(j_ptr) || j_ptr->art_name))
+ if (!flag && (!artifact_p(j_ptr)))
{
/* Message */
msg_format("The %s disappear%s.",
@@ -5298,15 +5178,10 @@ s16b drop_near(object_type *j_ptr, int chance, int y, int x)
c_ptr = &cave[by][bx];
/* Scan objects in that grid for combination */
- for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
+ for (auto const this_o_idx: c_ptr->o_idxs)
{
- object_type * o_ptr;
-
/* Acquire object */
- o_ptr = &o_list[this_o_idx];
-
- /* Acquire next object */
- next_o_idx = o_ptr->next_o_idx;
+ object_type *o_ptr = &o_list[this_o_idx];
/* Check for combination */
if (object_similar(o_ptr, j_ptr))
@@ -5323,6 +5198,7 @@ s16b drop_near(object_type *j_ptr, int chance, int y, int x)
}
/* Get new object */
+ s16b o_idx = 0;
if (!done) o_idx = o_pop();
/* Failure */
@@ -5340,7 +5216,7 @@ s16b drop_near(object_type *j_ptr, int chance, int y, int x)
{
a_info[j_ptr->name1].cur_num = 0;
}
- else if (k_info[j_ptr->k_idx].flags3 & TR3_NORM_ART)
+ else if (k_info[j_ptr->k_idx].flags & TR_NORM_ART)
{
k_info[j_ptr->k_idx].artifact = 0;
}
@@ -5369,11 +5245,8 @@ s16b drop_near(object_type *j_ptr, int chance, int y, int x)
/* No monster */
j_ptr->held_m_idx = 0;
- /* Build a stack */
- j_ptr->next_o_idx = c_ptr->o_idx;
-
/* Place the object */
- c_ptr->o_idx = o_idx;
+ c_ptr->o_idxs.push_back(o_idx);
/* Success */
done = TRUE;
@@ -5390,8 +5263,6 @@ s16b drop_near(object_type *j_ptr, int chance, int y, int x)
if (chance && (by == p_ptr->py) && (bx == p_ptr->px))
{
msg_print("You feel something roll beneath your feet.");
- /* Sound */
- sound(SOUND_DROP);
}
/* XXX XXX XXX */
@@ -5408,6 +5279,8 @@ s16b drop_near(object_type *j_ptr, int chance, int y, int x)
*/
void acquirement(int y1, int x1, int num, bool_ great, bool_ known)
{
+ auto const &d_info = game->edit_data.d_info;
+
object_type *i_ptr;
object_type object_type_body;
@@ -5435,30 +5308,6 @@ void acquirement(int y1, int x1, int num, bool_ great, bool_ known)
}
-
-/*
- * Hack -- instantiate a trap
- *
- * XXX XXX XXX This routine should be redone to reflect trap "level".
- * That is, it does not make sense to have spiked pits at 50 feet.
- * Actually, it is not this routine, but the "trap instantiation"
- * code, which should also check for "trap doors" on quest levels.
- */
-void pick_trap(int y, int x)
-{
- cave_type *c_ptr = &cave[y][x];
-
- /* Paranoia */
- if ((c_ptr->t_idx == 0) || (c_ptr->info & CAVE_TRDT)) return;
-
- /* Activate the trap */
- c_ptr->info |= (CAVE_TRDT);
-
- /* Notice and redraw */
- note_spot(y, x);
- lite_spot(y, x);
-}
-
/*
* Describe the charges on an item in the inventory.
*/
@@ -5547,6 +5396,8 @@ void inven_item_increase(int item, int num)
*/
bool_ inven_item_optimize(int item)
{
+ auto const &a_info = game->edit_data.a_info;
+
object_type *o_ptr = &p_ptr->inventory[item];
/* Only optimize real items */
@@ -5740,7 +5591,7 @@ void inc_stack_size_ex(int item, int delta, optimize_flag opt, describe_flag des
/*
* Check if we have space for an item in the pack without overflow
*/
-bool_ inven_carry_okay(object_type *o_ptr)
+bool_ inven_carry_okay(object_type const *o_ptr)
{
int j;
@@ -5913,7 +5764,6 @@ s16b inven_carry(object_type *o_ptr, bool_ final)
/* Clean out unused fields */
o_ptr->iy = o_ptr->ix = 0;
- o_ptr->next_o_idx = 0;
o_ptr->held_m_idx = 0;
/* Count the items */
@@ -6129,7 +5979,7 @@ void inven_drop(int item, int amt, int dy, int dx, bool_ silent)
*
* Note special handling of the "overflow" slot
*/
-void combine_pack(void)
+void combine_pack()
{
int i, j, k;
object_type *o_ptr;
@@ -6196,7 +6046,7 @@ void combine_pack(void)
*
* Note special handling of the "overflow" slot
*/
-void reorder_pack(void)
+void reorder_pack()
{
int i, j, k;
s32b o_value;
@@ -6297,72 +6147,17 @@ void reorder_pack(void)
if (flag) msg_print("You reorder some items in your pack.");
}
-/*
- * Hack -- display an object kind in the current window
- *
- * Include list of usable spells for readible books
- */
-void display_koff(int k_idx)
-{
- int y;
-
- object_type forge;
- object_type *q_ptr;
-
- char o_name[80];
-
-
- /* Erase the window */
- for (y = 0; y < Term->hgt; y++)
- {
- /* Erase the line */
- Term_erase(0, y, 255);
- }
-
- /* No info */
- if (!k_idx) return;
-
-
- /* Get local object */
- q_ptr = &forge;
-
- /* Prepare the object */
- object_wipe(q_ptr);
-
- /* Prepare the object */
- object_prep(q_ptr, k_idx);
-
-
- /* Describe */
- object_desc_store(o_name, q_ptr, FALSE, 0);
-
- /* Mention the object name */
- Term_putstr(0, 0, -1, TERM_WHITE, o_name);
-}
-
/*
* Let the floor carry an object
*/
s16b floor_carry(int y, int x, object_type *j_ptr)
{
- int n = 0;
-
- s16b o_idx;
-
- s16b this_o_idx, next_o_idx = 0;
-
-
/* Scan objects in that grid for combination */
- for (this_o_idx = cave[y][x].o_idx; this_o_idx; this_o_idx = next_o_idx)
+ for (auto const this_o_idx: cave[y][x].o_idxs)
{
- object_type * o_ptr;
-
/* Acquire object */
- o_ptr = &o_list[this_o_idx];
-
- /* Acquire next object */
- next_o_idx = o_ptr->next_o_idx;
+ object_type *o_ptr = &o_list[this_o_idx];
/* Check for combination */
if (object_similar(o_ptr, j_ptr))
@@ -6370,27 +6165,25 @@ s16b floor_carry(int y, int x, object_type *j_ptr)
/* Combine the items */
object_absorb(o_ptr, j_ptr);
- /* Result */
- return (this_o_idx);
+ /* Done */
+ return this_o_idx;
}
-
- /* Count objects */
- n++;
}
/* The stack is already too large */
- if (n > 23) return (0);
+ if (cave[y][x].o_idxs.size() > 23)
+ {
+ return (0);
+ }
/* Make an object */
- o_idx = o_pop();
+ s16b o_idx = o_pop();
/* Success */
if (o_idx)
{
- object_type *o_ptr;
-
/* Acquire object */
- o_ptr = &o_list[o_idx];
+ object_type *o_ptr = &o_list[o_idx];
/* Structure Copy */
object_copy(o_ptr, j_ptr);
@@ -6402,11 +6195,8 @@ s16b floor_carry(int y, int x, object_type *j_ptr)
/* Forget monster */
o_ptr->held_m_idx = 0;
- /* Build a stack */
- o_ptr->next_o_idx = cave[y][x].o_idx;
-
/* Place the object */
- cave[y][x].o_idx = o_idx;
+ cave[y][x].o_idxs.push_back(o_idx);
/* Notice */
note_spot(y, x);
@@ -6424,9 +6214,11 @@ s16b floor_carry(int y, int x, object_type *j_ptr)
*/
void pack_decay(int item)
{
+ auto const &r_info = game->edit_data.r_info;
+
object_type *o_ptr = &p_ptr->inventory[item];
- monster_race *r_ptr = &r_info[o_ptr->pval2];
+ auto r_ptr = &r_info[o_ptr->pval2];
object_type *i_ptr;
object_type object_type_body;
@@ -6475,7 +6267,7 @@ void pack_decay(int item)
}
/* Monster must have a skeleton for its corpse to become one */
- if ((i_ptr->sval == SV_CORPSE_CORPSE) && (r_ptr->flags3 & RF9_DROP_SKELETON))
+ if ((i_ptr->sval == SV_CORPSE_CORPSE) && (r_ptr->flags & RF_DROP_SKELETON))
{
/* Replace the corpse with a skeleton */
object_prep(i_ptr, lookup_kind(TV_CORPSE, SV_CORPSE_SKELETON));
@@ -6509,9 +6301,11 @@ void pack_decay(int item)
*/
void floor_decay(int item)
{
+ auto const &r_info = game->edit_data.r_info;
+
object_type *o_ptr = &o_list[item];
- monster_race *r_ptr = &r_info[o_ptr->pval2];
+ auto r_ptr = &r_info[o_ptr->pval2];
object_type *i_ptr;
object_type object_type_body;
@@ -6570,7 +6364,7 @@ void floor_decay(int item)
}
/* Monster must have a skeleton for its corpse to become one */
- if ((i_ptr->sval == SV_CORPSE_CORPSE) && (r_ptr->flags3 & RF9_DROP_SKELETON))
+ if ((i_ptr->sval == SV_CORPSE_CORPSE) && (r_ptr->flags & RF_DROP_SKELETON))
{
/* Replace the corpse with a skeleton */
object_prep(i_ptr, lookup_kind(TV_CORPSE, SV_CORPSE_SKELETON));
@@ -6602,13 +6396,11 @@ void floor_decay(int item)
/* Return the item be it on the floor or in inven */
object_type *get_object(int item)
{
- /* Get the item (in the pack) */
if (item >= 0)
{
+ assert(item < INVEN_TOTAL);
return &p_ptr->inventory[item];
}
-
- /* Get the item (on the floor) */
else
{
return &o_list[0 - item];
diff --git a/src/object2.hpp b/src/object2.hpp
new file mode 100644
index 00000000..a91631aa
--- /dev/null
+++ b/src/object2.hpp
@@ -0,0 +1,69 @@
+#pragma once
+
+#include "ego_flag_set.hpp"
+#include "h-basic.h"
+#include "object_type_fwd.hpp"
+#include "obj_theme_fwd.hpp"
+
+#include <boost/optional.hpp>
+
+typedef enum { OPTIMIZE, NO_OPTIMIZE } optimize_flag;
+typedef enum { DESCRIBE, NO_DESCRIBE } describe_flag;
+
+void inc_stack_size(int item, int delta);
+void inc_stack_size_ex(int item, int delta, optimize_flag opt, describe_flag desc);
+object_type *get_object(int item);
+s32b calc_total_weight();
+void add_random_ego_flag(object_type *o_ptr, ego_flag_set const &fego, bool_ *limit_blows);
+bool init_match_theme(obj_theme const &theme);
+bool_ kind_is_artifactable(int k_idx);
+bool_ kind_is_legal(int k_idx);
+void inven_item_charges(int item);
+void inven_item_describe(int item);
+void inven_item_increase(int item, int num);
+bool_ inven_item_optimize(int item);
+void floor_item_charges(int item);
+void floor_item_describe(int item);
+void floor_item_increase(int item, int num);
+void floor_item_optimize(int item);
+bool_ inven_carry_okay(object_type const *o_ptr);
+s16b inven_carry(object_type *o_ptr, bool_ final);
+s16b inven_takeoff(int item, int amt, bool_ force_drop);
+void inven_drop(int item, int amt, int dy, int dx, bool_ silent);
+void excise_object_idx(int o_idx);
+void delete_object_idx(int o_idx);
+void delete_object(int y, int x);
+void compact_objects(int size);
+void wipe_o_list();
+s16b o_pop();
+errr get_obj_num_prep();
+s16b get_obj_num(int level);
+void object_known(object_type *o_ptr);
+bool object_known_p(object_type const *o_ptr);
+void object_aware(object_type *o_ptr);
+bool object_aware_p(object_type const *o_ptr);
+void object_tried(object_type *o_ptr);
+bool object_tried_p(object_type const *o_ptr);
+s32b object_value(object_type const *o_ptr);
+s32b object_value_real(object_type const *o_ptr);
+bool_ object_similar(object_type const *o_ptr, object_type const *j_ptr);
+void object_absorb(object_type *o_ptr, object_type *j_ptr);
+s16b lookup_kind(int tval, int sval);
+void object_wipe(object_type *o_ptr);
+void object_prep(object_type *o_ptr, int k_idx);
+void object_copy(object_type *o_ptr, object_type *j_ptr);
+void apply_magic(object_type *o_ptr, int lev, bool_ okay, bool_ good, bool_ great, boost::optional<int> force_power = boost::none);
+bool_ make_object(object_type *j_ptr, bool_ good, bool_ great, obj_theme const &theme);
+void place_object(int y, int x, bool_ good, bool_ great, int where);
+bool_ make_gold(object_type *j_ptr);
+void place_gold(int y, int x);
+s16b drop_near(object_type *o_ptr, int chance, int y, int x);
+void acquirement(int y1, int x1, int num, bool_ great, bool_ known);
+void combine_pack();
+void reorder_pack();
+void random_artifact_resistance(object_type * o_ptr);
+s16b floor_carry(int y, int x, object_type *j_ptr);
+void pack_decay(int item);
+void floor_decay(int item);
+s16b m_bonus(int max, int level);
+s32b flag_cost(object_type const *o_ptr, int plusses);
diff --git a/src/object_filter.cc b/src/object_filter.cc
new file mode 100644
index 00000000..936eef7d
--- /dev/null
+++ b/src/object_filter.cc
@@ -0,0 +1,75 @@
+#include "object_filter.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_type.hpp"
+
+namespace object_filter {
+
+object_filter_t TVal(byte tval) {
+ return [=](object_type const *o_ptr) -> bool {
+ return o_ptr->tval == tval;
+ };
+}
+
+object_filter_t SVal(byte sval) {
+ return [=](object_type const *o_ptr) -> bool {
+ return o_ptr->sval == sval;
+ };
+}
+
+object_filter_t HasFlags(object_flag_set const &mask) {
+ return [=](object_type const *o_ptr) -> bool {
+ auto const flags = object_flags(o_ptr);
+ return bool(flags & mask);
+ };
+}
+
+object_filter_t IsArtifact() {
+ return [](object_type const *o_ptr) -> bool {
+ return o_ptr->name1 > 0;
+ };
+}
+
+object_filter_t IsArtifactP() {
+ return [](object_type const *o_ptr) -> bool {
+ return artifact_p(o_ptr);
+ };
+}
+
+object_filter_t IsEgo() {
+ return [](object_type const *o_ptr) -> bool {
+ return ego_item_p(o_ptr);
+ };
+}
+
+object_filter_t IsKnown() {
+ return [](object_type const *o_ptr) -> bool {
+ return object_known_p(o_ptr);
+ };
+}
+
+object_filter_t True() {
+ return [](object_type const *o_ptr) -> bool {
+ return true;
+ };
+}
+
+object_filter_t Not(object_filter_t p) {
+ return [=](object_type const *o_ptr) -> bool {
+ return !p(o_ptr);
+ };
+}
+
+object_filter_t And() {
+ return [](object_type const *) -> bool {
+ return true;
+ };
+}
+
+object_filter_t Or() {
+ return [](object_type const *) -> bool {
+ return false;
+ };
+}
+
+}
diff --git a/src/object_filter.hpp b/src/object_filter.hpp
new file mode 100644
index 00000000..d18e13ee
--- /dev/null
+++ b/src/object_filter.hpp
@@ -0,0 +1,90 @@
+#pragma once
+
+#include "h-basic.h"
+#include "object_flag_set.hpp"
+#include "object_type_fwd.hpp"
+
+#include <functional>
+#include <initializer_list>
+
+typedef std::function<bool (object_type const *)> object_filter_t;
+
+namespace object_filter {
+
+/**
+ * Is TVal equal to the given value?
+ */
+object_filter_t TVal(byte tval);
+
+/**
+ * Is SVal equal to the given value?
+ */
+object_filter_t SVal(byte sval);
+
+/**
+ * Has given set of flags set.
+ */
+object_filter_t HasFlags(object_flag_set const &);
+
+/**
+ * Is the object an artifact?
+ */
+object_filter_t IsArtifact();
+
+/**
+ * Is the object an artifact as determined by artifact_p?
+ */
+object_filter_t IsArtifactP();
+
+/**
+ * Is the object an ego item?
+ */
+object_filter_t IsEgo();
+
+/**
+ * Is the object "known"?
+ */
+object_filter_t IsKnown();
+
+/**
+ * True always accepts all items.
+ */
+object_filter_t True();
+
+/**
+ * Invert an object filter.
+ */
+object_filter_t Not(object_filter_t p);
+
+/**
+ * Logical conjunction (AND)
+ */
+object_filter_t And();
+
+/**
+ * Logical conjunction (AND)
+ */
+template<typename Arg0, typename... Args> object_filter_t And(Arg0&& arg0, Args&&... args) {
+ auto argsFilter = And(args...);
+ return [=](object_type const *o_ptr) -> bool {
+ return arg0(o_ptr) && argsFilter(o_ptr);
+ };
+}
+
+/**
+ * Logical disjunction (OR)
+ */
+object_filter_t Or();
+
+/**
+ * Logical disjunction (OR)
+ */
+template<typename Arg0, typename... Args> object_filter_t Or(Arg0&& arg0, Args&&... args) {
+ auto argsFilter = Or(args...);
+ return [=](object_type const *o_ptr) -> bool {
+ auto x = arg0(o_ptr) || argsFilter(o_ptr);
+ return x;
+ };
+}
+
+}
diff --git a/src/object_flag.hpp b/src/object_flag.hpp
new file mode 100644
index 00000000..d5ec2fef
--- /dev/null
+++ b/src/object_flag.hpp
@@ -0,0 +1,12 @@
+#pragma once
+
+#include "object_flag_set.hpp"
+#include <boost/preprocessor/cat.hpp>
+
+//
+// Define flag set for each flag.
+//
+#define TR(tier, index, name, e_name, c_name, c_page, c_col, c_row, c_type, c_prio, is_pval, is_esp) \
+ DECLARE_FLAG(object_flag_set, name, tier, index)
+#include "object_flag_list.hpp"
+#undef TR
diff --git a/src/object_flag_list.hpp b/src/object_flag_list.hpp
new file mode 100644
index 00000000..a7aef7d4
--- /dev/null
+++ b/src/object_flag_list.hpp
@@ -0,0 +1,185 @@
+/**
+ * X-macro list of all the object flags.
+ *
+ * Parameters:
+ *
+ * - e_name: name of the flag in the edit files.
+ * - c_name: name of the flag on the character sheet
+ * (10 characters max). If nullptrptr the
+ * flag doesn't appear and the other c_*
+ * values are ignored.
+ * - c_page: page on the character sheet (0-3).
+ * - c_col: column number on the character sheet (0-1).
+ * - c_row: row number on the character sheet (0-15).
+ * - c_type: type of the character sheet; either
+ * NUMERIC, BINARY or TERNARY(n).
+ * - c_prio: priority if the flag overlaps another flag
+ * on the character sheet. 0 is lowes priority.
+ * - is_pval: true iff the flag _description_ depends on PVAL.
+ * - is_esp: true iff the flag affects ESP.
+ */
+
+/* TR(<tier>, <index>, <name>, <e_name>, <c_name>, <c_page>, <c_col>, <c_row>, <c_type>, <c_prio>, <is_pval>, <is_esp>) */
+
+TR(1, 0, TR_STR , STR , "Add Str" , 0, 0, 0, NUMERIC , 0, true , false)
+TR(1, 1, TR_INT , INT , "Add Int" , 0, 0, 1, NUMERIC , 0, true , false)
+TR(1, 2, TR_WIS , WIS , "Add Wis" , 0, 0, 2, NUMERIC , 0, true , false)
+TR(1, 3, TR_DEX , DEX , "Add Dex" , 0, 0, 3, NUMERIC , 0, true , false)
+TR(1, 4, TR_CON , CON , "Add Con" , 0, 0, 4, NUMERIC , 0, true , false)
+TR(1, 5, TR_CHR , CHR , "Add Chr" , 0, 0, 5, NUMERIC , 0, true , false)
+TR(1, 6, TR_MANA , MANA , "Mul Mana" , 0, 0, 6, BINARY , 0, false, false)
+TR(1, 7, TR_SPELL , SPELL , "Mul SPower", 0, 0, 7, BINARY , 0, true , false)
+TR(1, 8, TR_STEALTH , STEALTH , "Add Stea." , 0, 0, 8, NUMERIC , 0, true , false)
+TR(1, 10, TR_INFRA , INFRA , "Add Infra" , 0, 0, 9, NUMERIC , 0, true , false)
+TR(1, 11, TR_TUNNEL , TUNNEL , "Add Tun.." , 0, 0, 10, NUMERIC , 0, true , false)
+TR(1, 12, TR_SPEED , SPEED , "Add Speed" , 0, 0, 11, NUMERIC , 0, true , false)
+TR(1, 13, TR_BLOWS , BLOWS , "Add Blows" , 0, 0, 12, NUMERIC , 0, true , false)
+TR(1, 14, TR_CHAOTIC , CHAOTIC , "Chaotic" , 0, 0, 13, BINARY , 0, false, false)
+TR(1, 15, TR_VAMPIRIC , VAMPIRIC , "Vampiric" , 0, 0, 14, BINARY , 0, false, false)
+TR(1, 16, TR_SLAY_ANIMAL , SLAY_ANIMAL , "Slay Anim.", 0, 1, 0, BINARY , 0, false, false)
+TR(1, 17, TR_SLAY_EVIL , SLAY_EVIL , "Slay Evil" , 0, 1, 1, BINARY , 0, false, false)
+TR(1, 18, TR_SLAY_UNDEAD , SLAY_UNDEAD , "Slay Und." , 0, 1, 2, BINARY , 0, false, false)
+TR(1, 19, TR_SLAY_DEMON , SLAY_DEMON , "Slay Demon", 0, 1, 3, BINARY , 0, false, false)
+TR(1, 20, TR_SLAY_ORC , SLAY_ORC , "Slay Orc" , 0, 1, 4, BINARY , 0, false, false)
+TR(1, 21, TR_SLAY_TROLL , SLAY_TROLL , "Slay Troll", 0, 1, 5, BINARY , 0, false, false)
+TR(1, 22, TR_SLAY_GIANT , SLAY_GIANT , "Slay Giant", 0, 1, 6, BINARY , 0, false, false)
+TR(1, 23, TR_SLAY_DRAGON , SLAY_DRAGON , "Slay Drag.", 0, 1, 7, BINARY , 0, false, false)
+TR(1, 24, TR_KILL_DRAGON , KILL_DRAGON , "Kill Drag.", 0, 1, 8, BINARY , 0, false, false)
+TR(1, 25, TR_VORPAL , VORPAL , "Sharpness" , 0, 1, 9, BINARY , 0, false, false)
+TR(1, 26, TR_IMPACT , IMPACT , "Impact" , 0, 1, 10, BINARY , 0, false, false)
+TR(1, 27, TR_BRAND_POIS , BRAND_POIS , "Poison Brd", 0, 1, 11, BINARY , 0, false, false)
+TR(1, 28, TR_BRAND_ACID , BRAND_ACID , "Acid Brand", 0, 1, 12, BINARY , 0, false, false)
+TR(1, 29, TR_BRAND_ELEC , BRAND_ELEC , "Elec Brand", 0, 1, 13, BINARY , 0, false, false)
+TR(1, 30, TR_BRAND_FIRE , BRAND_FIRE , "Fire Brand", 0, 1, 14, BINARY , 0, false, false)
+TR(1, 31, TR_BRAND_COLD , BRAND_COLD , "Cold Brand", 0, 1, 15, BINARY , 0, false, false)
+
+TR(2, 0, TR_SUST_STR , SUST_STR , "Sust Str" , 1, 0, 0, BINARY , 0, false, false)
+TR(2, 1, TR_SUST_INT , SUST_INT , "Sust Int" , 1, 0, 1, BINARY , 0, false, false)
+TR(2, 2, TR_SUST_WIS , SUST_WIS , "Sust Wis" , 1, 0, 2, BINARY , 0, false, false)
+TR(2, 3, TR_SUST_DEX , SUST_DEX , "Sust Dex" , 1, 0, 3, BINARY , 0, false, false)
+TR(2, 4, TR_SUST_CON , SUST_CON , "Sust Con" , 1, 0, 4, BINARY , 0, false, false)
+TR(2, 5, TR_SUST_CHR , SUST_CHR , "Sust Chr" , 1, 0, 5, BINARY , 0, false, false)
+TR(2, 6, TR_INVIS , INVIS , "Invisible" , 1, 0, 6, BINARY , 0, false, false)
+TR(2, 7, TR_LIFE , LIFE , "Mul life" , 1, 0, 7, BINARY , 0, false, false)
+TR(2, 8, TR_IM_ACID , IM_ACID , "Imm Acid" , 1, 1, 0, TERNARY(2), 1, false, false)
+TR(2, 9, TR_IM_ELEC , IM_ELEC , "Imm Elec" , 1, 1, 1, TERNARY(2), 1, false, false)
+TR(2, 10, TR_IM_FIRE , IM_FIRE , "Imm Fire" , 1, 1, 2, TERNARY(2), 1, false, false)
+TR(2, 11, TR_IM_COLD , IM_COLD , "Imm Cold" , 1, 1, 3, TERNARY(2), 1, false, false)
+TR(2, 12, TR_SENS_FIRE , SENS_FIRE , "Sens Fire" , 1, 0, 12, BINARY , 0, false, false)
+TR(2, 13, TR_REFLECT , REFLECT , "Reflect" , 1, 0, 13, BINARY , 0, false, false)
+TR(2, 14, TR_FREE_ACT , FREE_ACT , "Free Act" , 1, 0, 14, BINARY , 0, false, false)
+TR(2, 15, TR_HOLD_LIFE , HOLD_LIFE , "Hold Life" , 1, 0, 15, BINARY , 0, false, false)
+TR(2, 16, TR_RES_ACID , RES_ACID , "Res Acid" , 1, 1, 0, TERNARY(1), 0, false, false)
+TR(2, 17, TR_RES_ELEC , RES_ELEC , "Res Elec" , 1, 1, 1, TERNARY(1), 0, false, false)
+TR(2, 18, TR_RES_FIRE , RES_FIRE , "Res Fire" , 1, 1, 2, TERNARY(1), 0, false, false)
+TR(2, 19, TR_RES_COLD , RES_COLD , "Res Cold" , 1, 1, 3, TERNARY(1), 0, false, false)
+TR(2, 20, TR_RES_POIS , RES_POIS , "Res Pois" , 1, 1, 4, BINARY , 0, false, false)
+TR(2, 21, TR_RES_FEAR , RES_FEAR , "Res Fear" , 1, 1, 5, BINARY , 0, false, false)
+TR(2, 22, TR_RES_LITE , RES_LITE , "Res Light" , 1, 1, 6, BINARY , 0, false, false)
+TR(2, 23, TR_RES_DARK , RES_DARK , "Res Dark" , 1, 1, 7, BINARY , 0, false, false)
+TR(2, 24, TR_RES_BLIND , RES_BLIND , "Res Blind" , 1, 1, 8, BINARY , 0, false, false)
+TR(2, 25, TR_RES_CONF , RES_CONF , "Res Conf" , 1, 1, 9, BINARY , 0, false, false)
+TR(2, 26, TR_RES_SOUND , RES_SOUND , "Res Sound" , 1, 1, 10, BINARY , 0, false, false)
+TR(2, 27, TR_RES_SHARDS , RES_SHARDS , "Res Shard" , 1, 1, 11, BINARY , 0, false, false)
+TR(2, 28, TR_RES_NETHER , RES_NETHER , "Res Neth" , 1, 1, 12, TERNARY(1), 0, false, false)
+TR(2, 29, TR_RES_NEXUS , RES_NEXUS , "Res Nexus" , 1, 1, 13, BINARY , 0, false, false)
+TR(2, 30, TR_RES_CHAOS , RES_CHAOS , "Res Chaos" , 1, 1, 14, BINARY , 0, false, false)
+TR(2, 31, TR_RES_DISEN , RES_DISEN , "Res Disen" , 1, 1, 15, BINARY , 0, false, false)
+
+TR(3, 0, TR_SH_FIRE , SH_FIRE , "Aura Fire" , 2, 0, 0, BINARY , 0, false, false)
+TR(3, 1, TR_SH_ELEC , SH_ELEC , "Aura Elec" , 2, 0, 1, BINARY , 0, false, false)
+TR(3, 2, TR_AUTO_CURSE , AUTO_CURSE , "Auto Curse", 2, 0, 2, BINARY , 0, false, false)
+TR(3, 3, TR_DECAY , DECAY , nullptr , -1, -1, -1, BINARY , 0, false, false)
+TR(3, 4, TR_NO_TELE , NO_TELE , "NoTeleport", 2, 0, 4, BINARY , 0, false, false)
+TR(3, 5, TR_NO_MAGIC , NO_MAGIC , "AntiMagic" , 2, 0, 5, BINARY , 0, false, false)
+TR(3, 6, TR_WRAITH , WRAITH , "WraithForm", 2, 0, 6, BINARY , 0, false, false)
+TR(3, 7, TR_TY_CURSE , TY_CURSE , "EvilCurse" , 2, 0, 7, BINARY , 0, false, false)
+TR(3, 8, TR_EASY_KNOW , EASY_KNOW , nullptr , -1, -1, -1, BINARY , 0, false, false)
+TR(3, 9, TR_HIDE_TYPE , HIDE_TYPE , nullptr , -1, -1, -1, BINARY , 0, false, false)
+TR(3, 10, TR_SHOW_MODS , SHOW_MODS , nullptr , -1, -1, -1, BINARY , 0, false, false)
+TR(3, 11, TR_INSTA_ART , INSTA_ART , nullptr , -1, -1, -1, BINARY , 0, false, false)
+TR(3, 12, TR_FEATHER , FEATHER , "Levitate" , 2, 0, 12, BINARY , 0, false, false)
+TR(3, 13, TR_LITE1 , LITE1 , "Lite" , 2, 0, 13, FIXED(1) , 0, false, false)
+TR(3, 14, TR_SEE_INVIS , SEE_INVIS , "See Invis" , 2, 0, 14, BINARY , 0, false, false)
+TR(3, 15, TR_NORM_ART , NORM_ART , nullptr , -1, -1, -1, BINARY , 0, false, false)
+TR(3, 16, TR_SLOW_DIGEST , SLOW_DIGEST , "Digestion" , 2, 1, 0, BINARY , 0, false, false)
+TR(3, 17, TR_REGEN , REGEN , "Regen" , 2, 1, 1, BINARY , 0, false, false)
+TR(3, 18, TR_XTRA_MIGHT , XTRA_MIGHT , "Xtra Might", 2, 1, 2, BINARY , 0, false, false)
+TR(3, 19, TR_XTRA_SHOTS , XTRA_SHOTS , "Xtra Shots", 2, 1, 3, BINARY , 0, false, false)
+TR(3, 20, TR_IGNORE_ACID , IGNORE_ACID , nullptr , -1, -1, -1, BINARY , 0, false, false)
+TR(3, 21, TR_IGNORE_ELEC , IGNORE_ELEC , nullptr , -1, -1, -1, BINARY , 0, false, false)
+TR(3, 22, TR_IGNORE_FIRE , IGNORE_FIRE , nullptr , -1, -1, -1, BINARY , 0, false, false)
+TR(3, 23, TR_IGNORE_COLD , IGNORE_COLD , nullptr , -1, -1, -1, BINARY , 0, false, false)
+TR(3, 24, TR_ACTIVATE , ACTIVATE , "Activate" , 2, 1, 8, BINARY , 0, false, false)
+TR(3, 25, TR_DRAIN_EXP , DRAIN_EXP , "Drain Exp" , 2, 1, 9, BINARY , 0, false, false)
+TR(3, 26, TR_TELEPORT , TELEPORT , "Teleport" , 2, 1, 10, BINARY , 0, false, false)
+TR(3, 27, TR_AGGRAVATE , AGGRAVATE , "Aggravate" , 2, 1, 11, BINARY , 0, false, false)
+TR(3, 28, TR_BLESSED , BLESSED , "Blessed" , 2, 1, 12, BINARY , 0, false, false)
+TR(3, 29, TR_CURSED , CURSED , "Cursed" , 2, 1, 13, BINARY , 0, false, false)
+TR(3, 30, TR_HEAVY_CURSE , HEAVY_CURSE , "Hvy Curse" , 2, 1, 14, BINARY , 0, false, false)
+TR(3, 31, TR_PERMA_CURSE , PERMA_CURSE , "Prm Curse" , 2, 1, 15, BINARY , 0, false, false)
+
+TR(4, 0, TR_NEVER_BLOW , NEVER_BLOW , "No blows" , 3, 0, 0, BINARY , 0, false, false)
+TR(4, 1, TR_PRECOGNITION , PRECOGNITION , "Precogn." , 3, 0, 1, BINARY , 0, false, false)
+TR(4, 2, TR_BLACK_BREATH , BLACK_BREATH , "B.Breath" , 3, 0, 2, BINARY , 0, false, false)
+TR(4, 3, TR_RECHARGE , RECHARGE , "Recharge" , 3, 0, 3, BINARY , 0, false, false)
+TR(4, 4, TR_FLY , FLY , "Fly" , 3, 0, 4, BINARY , 0, false, false)
+TR(4, 5, TR_DG_CURSE , DG_CURSE , "Mrg.Curse" , 3, 0, 5, BINARY , 0, false, false)
+TR(4, 6, TR_COULD2H , COULD2H , nullptr , -1, -1, -1, BINARY , 0, false, false)
+TR(4, 7, TR_MUST2H , MUST2H , nullptr , -1, -1, -1, BINARY , 0, false, false)
+TR(4, 8, TR_LEVELS , LEVELS , "Sentient" , 3, 0, 8, BINARY , 0, false, false)
+TR(4, 9, TR_CLONE , CLONE , "Clone" , 3, 0, 9, BINARY , 0, false, false)
+TR(4, 10, TR_SPECIAL_GENE , SPECIAL_GENE , nullptr , 3, 0, 10, BINARY , 0, false, false)
+TR(4, 11, TR_CLIMB , CLIMB , "Climb" , 3, 0, 11, BINARY , 0, false, false)
+TR(4, 12, TR_FAST_CAST , FAST_CAST , nullptr , -1, -1, -1, BINARY , 0, false, false)
+TR(4, 13, TR_CAPACITY , CAPACITY , nullptr , -1, -1, -1, BINARY , 0, false, false)
+TR(4, 14, TR_CHARGING , CHARGING , nullptr , -1, -1, -1, BINARY , 0, false, false)
+TR(4, 15, TR_CHEAPNESS , CHEAPNESS , nullptr , -1, -1, -1, BINARY , 0, false, false)
+TR(4, 16, TR_FOUNTAIN , FOUNTAIN , nullptr , -1, -1, -1, BINARY , 0, false, false)
+TR(4, 17, TR_ANTIMAGIC_50 , ANTIMAGIC_50 , nullptr , -1, -1, -1, BINARY , 0, false, false)
+TR(4, 21, TR_EASY_USE , EASY_USE , nullptr , -1, -1, -1, BINARY , 0, false, false)
+TR(4, 22, TR_IM_NETHER , IM_NETHER , "Imm Neth" , 1, 1, 12, TERNARY(2), 1, false, false)
+TR(4, 23, TR_RECHARGED , RECHARGED , nullptr , -1, -1, -1, BINARY , 0, false, false)
+TR(4, 24, TR_ULTIMATE , ULTIMATE , nullptr , -1, -1, -1, BINARY , 0, false, false)
+TR(4, 25, TR_AUTO_ID , AUTO_ID , nullptr , -1, -1, -1, BINARY , 0, false, false)
+TR(4, 26, TR_LITE2 , LITE2 , "Lite" , 2, 0, 13, FIXED(2) , 0, false, false)
+TR(4, 27, TR_LITE3 , LITE3 , "Lite" , 2, 0, 13, FIXED(3) , 0, false, false)
+TR(4, 28, TR_FUEL_LITE , FUEL_LITE , nullptr , -1, -1, -1, BINARY , 0, false, false)
+TR(4, 30, TR_CURSE_NO_DROP , CURSE_NO_DROP , nullptr , -1, -1, -1, BINARY , 0, false, false)
+TR(4, 31, TR_NO_RECHARGE , NO_RECHARGE , nullptr , -1, -1, -1, BINARY , 0, false, false)
+
+TR(5, 0, TR_TEMPORARY , TEMPORARY , nullptr , -1, -1, -1, BINARY , 0, false, false)
+TR(5, 1, TR_DRAIN_MANA , DRAIN_MANA , nullptr , -1, -1, -1, BINARY , 0, false, false)
+TR(5, 2, TR_DRAIN_HP , DRAIN_HP , nullptr , -1, -1, -1, BINARY , 0, false, false)
+TR(5, 3, TR_KILL_DEMON , KILL_DEMON , nullptr , -1, -1, -1, BINARY , 0, false, false)
+TR(5, 4, TR_KILL_UNDEAD , KILL_UNDEAD , nullptr , -1, -1, -1, BINARY , 0, false, false)
+TR(5, 5, TR_CRIT , CRIT , nullptr , -1, -1, -1, BINARY , 0, true , false)
+TR(5, 6, TR_ATTR_MULTI , ATTR_MULTI , nullptr , -1, -1, -1, BINARY , 0, false, false)
+TR(5, 7, TR_WOUNDING , WOUNDING , nullptr , -1, -1, -1, BINARY , 0, false, false)
+TR(5, 8, TR_FULL_NAME , FULL_NAME , nullptr , -1, -1, -1, BINARY , 0, false, false)
+TR(5, 9, TR_LUCK , LUCK , nullptr , -1, -1, -1, BINARY , 0, true , false)
+TR(5, 10, TR_IMMOVABLE , IMMOVABLE , nullptr , -1, -1, -1, BINARY , 0, false, false)
+TR(5, 11, TR_SPELL_CONTAIN , SPELL_CONTAIN , nullptr , -1, -1, -1, BINARY , 0, false, false)
+TR(5, 12, TR_RES_MORGUL , RES_MORGUL , nullptr , -1, -1, -1, BINARY , 0, false, false)
+TR(5, 13, TR_ACTIVATE_NO_WIELD , ACTIVATE_NO_WIELD , nullptr , -1, -1, -1, BINARY , 0, false, false)
+TR(5, 14, TR_MAGIC_BREATH , MAGIC_BREATH , nullptr , -1, -1, -1, BINARY , 0, false, false)
+TR(5, 15, TR_WATER_BREATH , WATER_BREATH , nullptr , -1, -1, -1, BINARY , 0, false, false)
+TR(5, 16, TR_WIELD_CAST , WIELD_CAST , nullptr , -1, -1, -1, BINARY , 0, false, false)
+TR(5, 17, TR_RANDOM_RESIST , RANDOM_RESIST , nullptr , -1, -1, -1, BINARY , 0, false, false)
+TR(5, 18, TR_RANDOM_POWER , RANDOM_POWER , nullptr , -1, -1, -1, BINARY , 0, false, false)
+TR(5, 19, TR_RANDOM_RES_OR_POWER, RANDOM_RES_OR_POWER, nullptr , -1, -1, -1, BINARY , 0, false, false)
+
+TR(6, 0, ESP_ORC , ESP_ORC , "Orc.ESP" , 3, 1, 0, BINARY , 0, false, true )
+TR(6, 1, ESP_TROLL , ESP_TROLL , "Troll.ESP" , 3, 1, 1, BINARY , 0, false, true )
+TR(6, 2, ESP_DRAGON , ESP_DRAGON , "Dragon.ESP", 3, 1, 2, BINARY , 0, false, true )
+TR(6, 3, ESP_GIANT , ESP_GIANT , "Giant.ESP" , 3, 1, 3, BINARY , 0, false, true )
+TR(6, 4, ESP_DEMON , ESP_DEMON , "Demon.ESP" , 3, 1, 4, BINARY , 0, false, true )
+TR(6, 5, ESP_UNDEAD , ESP_UNDEAD , "Undead.ESP", 3, 1, 5, BINARY , 0, false, true )
+TR(6, 6, ESP_EVIL , ESP_EVIL , "Evil.ESP" , 3, 1, 6, BINARY , 0, false, true )
+TR(6, 7, ESP_ANIMAL , ESP_ANIMAL , "Animal.ESP", 3, 1, 7, BINARY , 0, false, true )
+TR(6, 8, ESP_THUNDERLORD , ESP_THUNDERLORD , "TLord.ESP" , 3, 1, 8, BINARY , 0, false, true )
+TR(6, 9, ESP_GOOD , ESP_GOOD , "Good.ESP" , 3, 1, 9, BINARY , 0, false, true )
+TR(6, 10, ESP_NONLIVING , ESP_NONLIVING , "Nlive.ESP" , 3, 1, 10, BINARY , 0, false, true )
+TR(6, 11, ESP_UNIQUE , ESP_UNIQUE , "Unique.ESP", 3, 1, 11, BINARY , 0, false, true )
+TR(6, 12, ESP_SPIDER , ESP_SPIDER , "Spider ESP", 3, 1, 12, BINARY , 0, false, true )
+TR(6, 31, ESP_ALL , ESP_ALL , "Full ESP" , 3, 1, 15, BINARY , 0, false, true )
diff --git a/src/object_flag_meta.cc b/src/object_flag_meta.cc
new file mode 100644
index 00000000..89b91fea
--- /dev/null
+++ b/src/object_flag_meta.cc
@@ -0,0 +1,59 @@
+#include "object_flag_meta.hpp"
+
+#include "object_flag.hpp"
+
+std::vector<object_flag_meta const *> const &object_flags_meta()
+{
+ static std::vector<object_flag_meta const *> instance;
+
+ if (instance.empty())
+ {
+#define NUMERIC 'n'
+#define BINARY 'b'
+#define TERNARY(n) ((n == 1) ? '+' : ((n == 2) ? '*' : '?'))
+#define FIXED(n) ((n == 1) ? '1' : ((n == 2) ? '2' : ((n == 3) ? '3' : '?')))
+#define TR(tier, index, name, e_name, c_name, c_page, c_col, c_row, c_type, c_prio, is_pval, is_esp) \
+ instance.emplace_back(new object_flag_meta { \
+ name, \
+ #name, \
+ #e_name, \
+ c_name, \
+ c_page, \
+ c_col, \
+ c_row, \
+ c_type, \
+ c_prio, \
+ is_pval, \
+ is_esp \
+ });
+#include "object_flag_list.hpp"
+#undef TR
+#undef FIXED
+#undef TERNARY
+#undef BINARY
+#undef NUMERIC
+ };
+
+ return instance;
+}
+
+object_flag_set const &object_flags_esp()
+{
+ static object_flag_set instance;
+ static bool initialized = false;
+
+ if (!initialized)
+ {
+ for (auto const object_flag_meta: object_flags_meta())
+ {
+ if (object_flag_meta->is_esp)
+ {
+ instance |= object_flag_meta->flag_set;
+ }
+ }
+
+ initialized = true;
+ }
+
+ return instance;
+}
diff --git a/src/object_flag_meta.hpp b/src/object_flag_meta.hpp
new file mode 100644
index 00000000..d488c0d5
--- /dev/null
+++ b/src/object_flag_meta.hpp
@@ -0,0 +1,75 @@
+#pragma once
+
+#include "object_flag_set.hpp"
+
+#include <vector>
+
+struct object_flag_meta {
+
+ /**
+ * Flag set representation of the object flag.
+ */
+ const object_flag_set flag_set;
+
+ /**
+ * Name of the object flag.
+ */
+ const char *name;
+
+ /**
+ * Edit file name of the object flag.
+ */
+ const char *e_name;
+
+ /**
+ * Character sheet name of the object flag.
+ */
+ const char *c_name;
+
+ /**
+ * Character sheet page.
+ */
+ const int c_page;
+
+ /**
+ * Character sheet column.
+ */
+ const int c_column;
+
+ /**
+ * Character sheet row.
+ */
+ const int c_row;
+
+ /**
+ * Character sheet type.
+ */
+ char c_type;
+
+ /**
+ * Priority wrt. other flags in the same position
+ * on the character sheet.
+ */
+ int c_priority;
+
+ /**
+ * Is this flag *described* using PVAL?
+ */
+ bool is_pval;
+
+ /**
+ * Is this a flag which affects ESP?
+ */
+ bool is_esp;
+
+};
+
+/**
+ * Get a vector of all the object flags.
+ */
+std::vector<object_flag_meta const *> const &object_flags_meta();
+
+/**
+ * Get a flag representing all ESP flags.
+ */
+object_flag_set const &object_flags_esp();
diff --git a/src/object_flag_set.hpp b/src/object_flag_set.hpp
new file mode 100644
index 00000000..a4e8f874
--- /dev/null
+++ b/src/object_flag_set.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "flag_set.hpp"
+
+constexpr std::size_t TR_MAX_TIERS = 6;
+
+typedef flag_set<TR_MAX_TIERS> object_flag_set;
diff --git a/src/object_kind.hpp b/src/object_kind.hpp
new file mode 100644
index 00000000..2f347f3f
--- /dev/null
+++ b/src/object_kind.hpp
@@ -0,0 +1,73 @@
+#pragma once
+
+#include "h-basic.h"
+#include "object_flag_set.hpp"
+
+/**
+ * Size of allocation table for objects
+ */
+constexpr int ALLOCATION_MAX = 8;
+
+/**
+ * Object "kind" descriptor. Includes player knowledge.
+ *
+ * Only "aware" and "tried" are saved in the savefile
+ */
+struct object_kind
+{
+ const char *name = nullptr; /* Name */
+ char *text = nullptr; /* Text */
+
+ byte tval = 0; /* Object type */
+ byte sval = 0; /* Object sub type */
+
+ s32b pval = 0; /* Object extra info */
+ s32b pval2 = 0; /* Object extra info */
+
+ s16b to_h = 0; /* Bonus to hit */
+ s16b to_d = 0; /* Bonus to damage */
+ s16b to_a = 0; /* Bonus to armor */
+
+ s16b activate = 0; /* Activation number */
+
+ s16b ac = 0; /* Base armor */
+
+ byte dd = 0; /* Damage dice */
+ byte ds = 0; /* Damage sides */
+
+ s32b weight = 0; /* Weight */
+
+ s32b cost = 0; /* Object "base cost" */
+
+ object_flag_set flags;
+
+ object_flag_set oflags;
+
+ byte locale[ALLOCATION_MAX] = { 0 }; /* Allocation level(s) */
+ byte chance[ALLOCATION_MAX] = { 0 }; /* Allocation chance(s) */
+
+ byte level = 0; /* Level */
+
+
+ byte d_attr = 0; /* Default object attribute */
+ char d_char = 0; /* Default object character */
+
+
+ byte x_attr = 0; /* Desired object attribute */
+ char x_char = 0; /* Desired object character */
+
+
+ byte flavor = 0; /* Special object flavor (or zero) */
+
+ bool_ easy_know = 0; /* This object is always known (if aware) */
+
+ bool_ aware = 0; /* The player is "aware" of the item's effects */
+
+ bool_ tried = 0; /* The player has "tried" one of the items */
+
+ byte btval = 0; /* Become Object type */
+ byte bsval = 0; /* Become Object sub type */
+ bool_ artifact = 0; /* Is it a normal artifact(already generated) */
+
+ s16b power = 0; /* Power granted(if any) */
+};
diff --git a/src/object_proto.hpp b/src/object_proto.hpp
new file mode 100644
index 00000000..faa0b2e8
--- /dev/null
+++ b/src/object_proto.hpp
@@ -0,0 +1,12 @@
+#pragma once
+
+#include "h-basic.h"
+
+struct object_proto
+{
+ s16b tval = 0;
+ s16b sval = 0;
+ s16b pval = 0;
+ s16b dd = 0;
+ s16b ds = 0;
+};
diff --git a/src/object_type.hpp b/src/object_type.hpp
new file mode 100644
index 00000000..3a34d181
--- /dev/null
+++ b/src/object_type.hpp
@@ -0,0 +1,96 @@
+#pragma once
+
+#include "h-basic.h"
+#include "object_flag_set.hpp"
+
+#include <string>
+
+/**
+ * Object information for a specific object.
+ *
+ * Note that a "discount" on an item is permanent and never goes away.
+ *
+ * Note that inscriptions are now handled via the "quark_str()" function
+ * applied to the "note" field, which will return NULL if "note" is zero.
+ *
+ * Note that "object" records are "copied" on a fairly regular basis,
+ * and care must be taken when handling such objects.
+ *
+ * Note that "object flags" must now be derived from the object kind,
+ * the artifact and ego-item indexes, and the two "xtra" fields.
+ *
+ * Each cave grid points to one (or zero) objects via the "o_idx"
+ * field (above). Each object then points to one (or zero) objects
+ * via the "next_o_idx" field, forming a singly linked list, which
+ * in game terms, represents a "stack" of objects in the same grid.
+ *
+ * Each monster points to one (or zero) objects via the "hold_o_idx"
+ * field (below). Each object then points to one (or zero) objects
+ * via the "next_o_idx" field, forming a singly linked list, which
+ * in game terms, represents a pile of objects held by the monster.
+ *
+ * The "held_m_idx" field is used to indicate which monster, if any,
+ * is holding the object. Objects being held have "ix=0" and "iy=0".
+ */
+struct object_type
+{
+ s16b k_idx = 0; /* Kind index (zero if "dead") */
+
+ byte iy = 0; /* Y-position on map, or zero */
+ byte ix = 0; /* X-position on map, or zero */
+
+ byte tval = 0; /* Item type (from kind) */
+ byte sval = 0; /* Item sub-type (from kind) */
+
+ s32b pval = 0; /* Item extra-parameter */
+ s16b pval2 = 0; /* Item extra-parameter for some special items */
+ s32b pval3 = 0; /* Item extra-parameter for some special items */
+
+ byte discount = 0; /* Discount (if any) */
+
+ byte number = 0; /* Number of items */
+
+ s32b weight = 0; /* Item weight */
+
+ byte elevel = 0; /* Item exp level */
+ s32b exp = 0; /* Item exp */
+
+ byte name1 = 0; /* Artifact type, if any */
+ s16b name2 = 0; /* Ego-Item type, if any */
+ s16b name2b = 0; /* Second Ego-Item type, if any */
+
+ byte xtra1 = 0; /* Extra info type */
+ s16b xtra2 = 0; /* Extra info index */
+
+ s16b to_h = 0; /* Plusses to hit */
+ s16b to_d = 0; /* Plusses to damage */
+ s16b to_a = 0; /* Plusses to AC */
+
+ s16b ac = 0; /* Normal AC */
+
+ byte dd = 0; /* Damage dice/sides */
+ byte ds = 0; /* Damage dice/sides */
+
+ s16b timeout = 0; /* Timeout Counter */
+
+ byte ident = 0; /* Special flags */
+
+ byte marked = 0; /* Object is marked */
+
+ std::string inscription; /* Inscription index */
+
+ std::string artifact_name; /* Artifact name */
+
+ object_flag_set art_flags; /* Flags */
+ object_flag_set art_oflags; /* Obvious flags */
+
+ s16b held_m_idx = 0; /* Monster holding the object; if any */
+
+ byte sense = 0; /* Pseudo-id status */
+
+ byte found = 0; /* How did we find it */
+ s16b found_aux1 = 0; /* Stores info for found */
+ s16b found_aux2 = 0; /* Stores info for found */
+ s16b found_aux3 = 0; /* Stores info for found */
+ s16b found_aux4 = 0; /* Stores info for found */
+};
diff --git a/src/object_type_fwd.hpp b/src/object_type_fwd.hpp
new file mode 100644
index 00000000..d99e60a6
--- /dev/null
+++ b/src/object_type_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct object_type;
diff --git a/src/option_type.hpp b/src/option_type.hpp
new file mode 100644
index 00000000..4d8a7a51
--- /dev/null
+++ b/src/option_type.hpp
@@ -0,0 +1,34 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * Option descriptor.
+ */
+struct option_type
+{
+ /**
+ * Address of actual option variable.
+ */
+ bool_ *o_var;
+
+ /**
+ * Option page number.
+ */
+ byte o_page;
+
+ /**
+ * Savefile bit in the page-specific list of options.
+ */
+ byte o_bit;
+
+ /**
+ * Textual name.
+ */
+ cptr o_text;
+
+ /**
+ * Textual description
+ */
+ cptr o_desc;
+};
diff --git a/src/options.cc b/src/options.cc
new file mode 100644
index 00000000..ea2f3172
--- /dev/null
+++ b/src/options.cc
@@ -0,0 +1,10 @@
+#include "options.hpp"
+
+void options::reset_cheat_options()
+{
+ cheat_peek = FALSE;
+ cheat_hear = FALSE;
+ cheat_room = FALSE;
+ cheat_xtra = FALSE;
+ cheat_live = FALSE;
+}
diff --git a/src/options.hpp b/src/options.hpp
new file mode 100644
index 00000000..c1ac35a9
--- /dev/null
+++ b/src/options.hpp
@@ -0,0 +1,215 @@
+#pragma once
+
+#include "h-basic.h"
+#include "option_type.hpp"
+
+#include <vector>
+
+/**
+ * Game options accessible via the '=' menu.
+ */
+struct options {
+
+ //
+ // Option Set 1 -- User Interface
+ //
+ bool_ rogue_like_commands = FALSE; /* Rogue-like commands */
+ bool_ quick_messages = TRUE; /* Activate quick messages */
+ bool_ carry_query_flag = FALSE; /* Prompt before picking things up */
+ bool_ use_old_target = FALSE; /* Use old target by default */
+ bool_ always_pickup = FALSE; /* Pick things up by default */
+ bool_ always_repeat = TRUE; /* Repeat obvious commands */
+ bool_ ring_bell = FALSE; /* Ring the bell (on errors, etc) */
+
+ //
+ // Option Set 2 -- Disturbance
+ //
+ bool_ find_ignore_stairs = FALSE; /* Run past stairs */
+ bool_ find_ignore_doors = TRUE; /* Run through open doors */
+ bool_ find_cut = FALSE; /* Run past known corners */
+ bool_ find_examine = TRUE; /* Run into potential corners */
+ bool_ disturb_move = FALSE; /* Disturb whenever any monster moves */
+ bool_ disturb_near = TRUE; /* Disturb whenever viewable monster moves */
+ bool_ disturb_panel = TRUE; /* Disturb whenever map panel changes */
+ bool_ disturb_state = TRUE; /* Disturn whenever player state changes */
+ bool_ disturb_minor = TRUE; /* Disturb whenever boring things happen */
+ bool_ disturb_other = FALSE; /* Disturb whenever various things happen */
+ bool_ last_words = TRUE; /* Get last words upon dying */
+ bool_ wear_confirm = TRUE; /* Confirm before putting on known cursed items */
+ bool_ confirm_stairs = FALSE; /* Prompt before staircases... */
+ bool_ disturb_pets = FALSE; /* Pets moving nearby disturb us */
+
+ //
+ // Option Set 3 -- Game-Play
+ //
+ bool_ auto_scum = TRUE; /* Auto-scum for good levels */
+ bool_ view_perma_grids = TRUE; /* Map remembers all perma-lit grids */
+ bool_ view_torch_grids = FALSE; /* Map remembers all torch-lit grids */
+ bool_ dungeon_align = TRUE; /* Generate dungeons with aligned rooms */
+ bool_ dungeon_stair = TRUE; /* Generate dungeons with connected stairs */
+ bool_ flow_by_sound = FALSE; /* Monsters track new player location */
+ bool_ smart_learn = FALSE; /* Monsters learn from their mistakes */
+ bool_ small_levels = TRUE; /* Allow unusually small dungeon levels */
+ bool_ empty_levels = TRUE; /* Allow empty 'arena' levels */
+
+ //
+ // Option Set 4 -- Efficiency
+ //
+ bool_ view_reduce_lite = FALSE; /* Reduce lite-radius when running */
+ bool_ avoid_abort = FALSE; /* Avoid checking for user abort */
+ bool_ avoid_shimmer = FALSE; /* Avoid processing extra shimmering */
+ bool_ avoid_other = FALSE; /* Avoid processing special colors */
+ bool_ flush_failure = TRUE; /* Flush input on any failure */
+ bool_ flush_disturb = FALSE; /* Flush input on disturbance */
+ bool_ flush_command = FALSE; /* Flush input before every command */
+ bool_ fresh_before = TRUE; /* Flush output before normal commands */
+ bool_ fresh_after = FALSE; /* Flush output after normal commands */
+ bool_ fresh_message = FALSE; /* Flush output after all messages */
+ bool_ hilite_player = FALSE; /* Hilite the player with the cursor */
+ bool_ view_yellow_lite = FALSE; /* Use special colors for torch-lit grids */
+ bool_ view_bright_lite = FALSE; /* Use special colors for 'viewable' grids */
+ bool_ view_granite_lite = FALSE; /* Use special colors for wall grids (slow) */
+ bool_ view_special_lite = FALSE; /* Use special colors for floor grids (slow) */
+ bool_ center_player = FALSE; /* Center view on player */
+
+ //
+ // Option Set 5 - ToME options
+ //
+ bool_ ingame_help = TRUE; /* In-game contextual help? */
+ bool_ auto_more = FALSE; /* Auto more */
+ bool_ player_char_health = TRUE; /* Display the player as a special symbol when in bad health ? */
+ bool_ linear_stats = TRUE;
+
+ //
+ // Option Set 6 - Birth options
+ //
+ bool_ preserve = TRUE; /* Preserve artifacts */
+ bool_ autoroll = TRUE; /* Specify 'minimal' stats to roll */
+ bool_ point_based = FALSE; /* Generate character using a point system */
+ bool_ ironman_rooms = FALSE; /* Always generate very unusual rooms */
+ bool_ joke_monsters = FALSE; /* Allow 'joke' monsters */
+ bool_ always_small_level = FALSE; /* Force small levels */
+ bool_ fate_option = TRUE; /* Player can receive fates */
+ bool_ no_selling = FALSE; /* Player cannot sell items */
+
+ //
+ // Other options
+ //
+
+ bool_ cheat_peek = FALSE; /* Peek into object creation */
+ bool_ cheat_hear = FALSE; /* Peek into monster creation */
+ bool_ cheat_room = FALSE; /* Peek into dungeon creation */
+ bool_ cheat_xtra = FALSE; /* Peek into something else */
+ bool_ cheat_live = FALSE; /* Allow player to avoid death */
+
+ byte hitpoint_warn = 0; /* Hitpoint warning (0 to 9) */
+
+ byte delay_factor = 0; /* Delay factor (0 to 9) */
+
+ s16b autosave_freq = 100; /* Autosave frequency */
+ bool_ autosave_t = FALSE; /* Timed autosave */
+ bool_ autosave_l = FALSE; /* Autosave before entering new levels */
+
+ /**
+ * Option groups
+ */
+ std::vector<option_type> standard_options = {
+ // User-Interface
+ { &rogue_like_commands, 1, 0, "rogue_like_commands", "Rogue-like commands" },
+ { &quick_messages , 1, 1, "quick_messages" , "Activate quick messages" },
+ { &carry_query_flag , 1, 3, "carry_query_flag" , "Prompt before picking things up" },
+ { &use_old_target , 1, 4, "use_old_target" , "Use old target by default" },
+ { &always_pickup , 1, 5, "always_pickup" , "Pick things up by default" },
+ { &always_repeat , 1, 7, "always_repeat" , "Repeat obvious commands" },
+ { &ring_bell , 1, 18, "ring_bell" , "Audible bell (on errors, etc)" },
+ // Disturbance
+ { &find_ignore_stairs , 2, 0, "find_ignore_stairs" , "Run past stairs" },
+ { &find_ignore_doors , 2, 1, "find_ignore_doors" , "Run through open doors" },
+ { &find_cut , 2, 2, "find_cut" , "Run past known corners" },
+ { &find_examine , 2, 3, "find_examine" , "Run into potential corners" },
+ { &disturb_move , 2, 4, "disturb_move" , "Disturb whenever any monster moves" },
+ { &disturb_near , 2, 5, "disturb_near" , "Disturb whenever viewable monster moves" },
+ { &disturb_panel , 2, 6, "disturb_panel" , "Disturb whenever map panel changes" },
+ { &disturb_state , 2, 7, "disturb_state" , "Disturb whenever player state changes" },
+ { &disturb_minor , 2, 8, "disturb_minor" , "Disturb whenever boring things happen" },
+ { &disturb_other , 2, 9, "disturb_other" , "Disturb whenever random things happen" },
+ { &last_words , 2, 12, "last_words" , "Get last words when the character dies" },
+ { &wear_confirm , 2, 15, "confirm_wear" , "Confirm to wear/wield known cursed items" },
+ { &confirm_stairs , 2, 16, "confirm_stairs" , "Prompt before exiting a dungeon level" },
+ { &disturb_pets , 2, 17, "disturb_pets" , "Disturb when visible pets move" },
+ // Game-Play
+ { &auto_scum , 3, 1, "auto_scum" , "Auto-scum for good levels" },
+ { &view_perma_grids , 3, 6, "view_perma_grids" , "Map remembers all perma-lit grids" },
+ { &view_torch_grids , 3, 7, "view_torch_grids" , "Map remembers all torch-lit grids" },
+ { &dungeon_align , 3, 8, "dungeon_align" , "Generate dungeons with aligned rooms" },
+ { &dungeon_stair , 3, 9, "dungeon_stair" , "Generate dungeons with connected stairs" },
+ { &flow_by_sound , 3, 10, "flow_by_sound" , "Monsters chase current location (v.slow)" },
+ { &smart_learn , 3, 14, "smart_learn" , "Monsters learn from their mistakes" },
+ { &small_levels , 3, 17, "small_levels" , "Allow unusually small dungeon levels" },
+ { &empty_levels , 3, 18, "empty_levels" , "Allow empty 'arena' levels" },
+ // Efficiency
+ { &view_reduce_lite , 4, 0, "view_reduce_lite" , "Reduce lite-radius when running" },
+ { &avoid_abort , 4, 2, "avoid_abort" , "Avoid checking for user abort" },
+ { &avoid_shimmer , 4, 17, "avoid_shimmer" , "Avoid extra shimmering (fast)" },
+ { &avoid_other , 4, 3, "avoid_other" , "Avoid processing special colors (fast)" },
+ { &flush_failure , 4, 4, "flush_failure" , "Flush input on various failures" },
+ { &flush_disturb , 4, 5, "flush_disturb" , "Flush input whenever disturbed" },
+ { &flush_command , 4, 6, "flush_command" , "Flush input before every command" },
+ { &fresh_before , 4, 7, "fresh_before" , "Flush output before every command" },
+ { &fresh_after , 4, 8, "fresh_after" , "Flush output after every command" },
+ { &fresh_message , 4, 9, "fresh_message" , "Flush output after every message" },
+ { &hilite_player , 4, 11, "hilite_player" , "Hilite the player with the cursor" },
+ { &view_yellow_lite , 4, 12, "view_yellow_lite" , "Use special colors for torch-lit grids" },
+ { &view_bright_lite , 4, 13, "view_bright_lite" , "Use special colors for 'viewable' grids" },
+ { &view_granite_lite , 4, 14, "view_granite_lite" , "Use special colors for wall grids (slow)" },
+ { &view_special_lite , 4, 15, "view_special_lite" , "Use special colors for floor grids (slow)" },
+ { &center_player , 4, 16, "center_player" , "Center the view on the player (very slow)" },
+ // ToME options
+ { &ingame_help , 5, 1, "ingame_help" , "Ingame contextual help" },
+ { &auto_more , 5, 4, "auto_more" , "Automatically clear '-more-' prompts" },
+ { &player_char_health , 5, 6, "player_char_health" , "Player char represent his/her health" },
+ { &linear_stats , 5, 7, "linear_stats" , "Stats are represented in a linear way" },
+ // Birth Options
+ { &preserve , 6, 2, "preserve" , "Preserve artifacts" },
+ { &autoroll , 6, 3, "autoroll" , "Specify 'minimal' stats" },
+ { &point_based , 6, 17, "point_based" , "Generate character using a point system" },
+ { &ironman_rooms , 6, 6, "ironman_rooms" , "Always generate very unusual rooms" },
+ { &joke_monsters , 6, 14, "joke_monsters" , "Allow use of some 'joke' monsters" },
+ { &always_small_level , 6, 16, "always_small_level" , "Always make small levels" },
+ { &fate_option , 6, 18, "fate_option" , "You can receive fates, good or bad" },
+ { &no_selling , 6, 20, "no_selling" , "Items always sell for 0 gold" },
+ };
+
+ /*
+ * Cheating options
+ */
+ std::vector<option_type> cheat_options = {
+ { &cheat_peek, 0, 0, "cheat_peek", "Peek into object creation" },
+ { &cheat_hear, 0, 1, "cheat_hear", "Peek into monster creation" },
+ { &cheat_room, 0, 2, "cheat_room", "Peek into dungeon creation" },
+ { &cheat_xtra, 0, 3, "cheat_xtra", "Peek into something else" },
+ { &cheat_live, 0, 5, "cheat_live", "Allow player to avoid death" },
+ };
+
+ /**
+ * Autosave boolean options
+ */
+ std::vector<option_type> autosave_options {
+ { &autosave_l, 0, 6, "autosave_l", "Autosave when entering new levels" },
+ { &autosave_t, 0, 7, "autosave_t", "Timed autosave" }
+ };
+
+ /*
+ * Reset cheat options
+ */
+ void reset_cheat_options();
+
+ /**
+ * Convert delay_factor to milliseconds
+ */
+ int delay_factor_ms() const
+ {
+ return delay_factor * delay_factor * delay_factor;
+ }
+
+};
diff --git a/src/owner_type.hpp b/src/owner_type.hpp
new file mode 100644
index 00000000..4c47dc48
--- /dev/null
+++ b/src/owner_type.hpp
@@ -0,0 +1,41 @@
+#pragma once
+
+#include <string>
+
+#include "h-basic.h"
+
+/*
+ * Store owner descriptor.
+ */
+struct owner_type
+{
+ /**
+ * Name
+ */
+ std::string name;
+
+ /**
+ * Purse limit
+ */
+ s16b max_cost = 0;
+
+ /**
+ * Inflation
+ */
+ s16b inflation = 0;
+
+ /**
+ * Liked/hated races.
+ */
+ u32b races[2][2] { };
+
+ /**
+ * Liked/hated classes
+ */
+ u32b classes[2][2] { };
+
+ /**
+ * Costs for liked people
+ */
+ s16b costs[3] { };
+};
diff --git a/src/player.pkg b/src/player.pkg
deleted file mode 100644
index dfdced26..00000000
--- a/src/player.pkg
+++ /dev/null
@@ -1,3519 +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
-/** @} */
-
-/** @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 */
-#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_INIT]
- * @brief Boolean
- * @note Intrinsinc powers
- */
- bool powers_mod[POWER_MAX_INIT];
- /** @structvar powers[power_max]
- * @brief Boolean
- */
- 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 */
- /** @structvar corruptions_aux;
- * @brief Boolean
- */
- bool corruptions[max_corruptions] @ corruptions_aux;
-
- /* 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;
-};
-
-/** @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
-/** @} */
-
-
-/** @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
-/** @} */
-
-
-/** @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);
-
-/** @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
- * @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
-/** @} */
-
-/* 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();
-
-/** @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
- * @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);
- * @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/player_class.hpp b/src/player_class.hpp
new file mode 100644
index 00000000..02d0fc11
--- /dev/null
+++ b/src/player_class.hpp
@@ -0,0 +1,49 @@
+#pragma once
+
+#include "body.hpp"
+#include "h-basic.h"
+#include "object_flag_set.hpp"
+#include "object_proto.hpp"
+#include "player_defs.hpp"
+#include "player_level_flag.hpp"
+#include "player_race_flag_set.hpp"
+#include "player_shared.hpp"
+#include "player_spec.hpp"
+#include "skill_modifiers.hpp"
+
+/**
+ * Player descriptor and runtime data.
+ */
+struct player_class
+{
+ std::string title; /* Type of class */
+ std::string desc; /* Small desc of the class */
+ const char *titles[PY_MAX_LEVEL / 5] { }; /* Titles */
+
+ int display_order_idx; /* Display order index; lowest first */
+
+ player_shared ps;
+
+ player_race_flag_set flags;
+
+ s16b mana = 0;
+ s16b blow_num = 0;
+ s16b blow_wgt = 0;
+ s16b blow_mul = 0;
+ s16b extra_blows = 0;
+
+ std::vector<object_proto> object_protos;
+
+ char body_parts[BODY_MAX] { }; /* To help to decide what to use when body changing */
+
+ std::array<player_level_flag, PY_MAX_LEVEL+1> lflags;
+
+ struct skill_modifiers skill_modifiers;
+
+ u32b gods = 0;
+
+ std::vector<player_spec> spec;
+
+ std::vector<player_race_ability_type> abilities; /* Abilities to be gained by level; ignores prereqs */
+};
+
diff --git a/src/player_class_fwd.hpp b/src/player_class_fwd.hpp
new file mode 100644
index 00000000..2402934d
--- /dev/null
+++ b/src/player_class_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct player_class;
diff --git a/src/player_defs.hpp b/src/player_defs.hpp
new file mode 100644
index 00000000..2f57409c
--- /dev/null
+++ b/src/player_defs.hpp
@@ -0,0 +1,6 @@
+#pragma once
+
+/**
+ * Maximum player level
+ */
+#define PY_MAX_LEVEL 50
diff --git a/src/player_level_flag.hpp b/src/player_level_flag.hpp
new file mode 100644
index 00000000..fe4c862c
--- /dev/null
+++ b/src/player_level_flag.hpp
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "h-basic.h"
+#include "object_flag_set.hpp"
+#include "player_defs.hpp"
+
+struct player_level_flag {
+
+ object_flag_set oflags;
+
+ s16b pval = 0;
+
+};
diff --git a/src/player_race.hpp b/src/player_race.hpp
new file mode 100644
index 00000000..e0b236db
--- /dev/null
+++ b/src/player_race.hpp
@@ -0,0 +1,46 @@
+#pragma once
+
+#include "h-basic.h"
+#include "body.hpp"
+#include "object_flag_set.hpp"
+#include "object_proto.hpp"
+#include "player_defs.hpp"
+#include "player_level_flag.hpp"
+#include "player_race_ability_type.hpp"
+#include "player_race_flag_set.hpp"
+#include "player_shared.hpp"
+#include "skill_modifiers.hpp"
+
+#include <array>
+#include <string>
+#include <vector>
+
+
+/**
+ * Player racial descriptior.
+ */
+struct player_race
+{
+ std::string title; /* Type of race */
+ std::string desc;
+
+ char luck = '\0'; /* Luck */
+
+ player_shared ps;
+
+ byte infra = 0; /* Infra-vision range */
+
+ u32b choice[2] { }; /* Legal class choices */
+
+ byte body_parts[BODY_MAX] { }; /* To help to decide what to use when body changing */
+
+ player_race_flag_set flags;
+
+ std::array<player_level_flag, PY_MAX_LEVEL+1> lflags;
+
+ struct skill_modifiers skill_modifiers;
+
+ std::vector<object_proto> object_protos;
+
+ std::vector<player_race_ability_type> abilities; /* Abilities to be gained by level; ignores prereqs */
+};
diff --git a/src/player_race_ability_type.hpp b/src/player_race_ability_type.hpp
new file mode 100644
index 00000000..5f520052
--- /dev/null
+++ b/src/player_race_ability_type.hpp
@@ -0,0 +1,9 @@
+#pragma once
+
+#include "h-basic.h"
+
+struct player_race_ability_type
+{
+ s16b ability = 0;
+ s16b level = 0;
+};
diff --git a/src/player_race_flag.hpp b/src/player_race_flag.hpp
new file mode 100644
index 00000000..1268c3c0
--- /dev/null
+++ b/src/player_race_flag.hpp
@@ -0,0 +1,12 @@
+#pragma once
+
+#include "player_race_flag_set.hpp"
+#include <boost/preprocessor/cat.hpp>
+
+//
+// Define flag set for each flag.
+//
+#define PR(tier, index, name) \
+ DECLARE_FLAG(player_race_flag_set, BOOST_PP_CAT(PR_,name), tier, index)
+#include "player_race_flag_list.hpp"
+#undef PR
diff --git a/src/player_race_flag_list.hpp b/src/player_race_flag_list.hpp
new file mode 100644
index 00000000..5116ad87
--- /dev/null
+++ b/src/player_race_flag_list.hpp
@@ -0,0 +1,26 @@
+/**
+ * X-macro list of all the player race flags
+ */
+
+/* PR(<tier>, <index>, <name>) */
+
+PR(1, 0, EXPERIMENTAL) /* Experimental */
+PR(1, 1, RESIST_BLACK_BREATH) /* Resists black breath */
+PR(1, 2, NO_STUN) /* Cannot be stunned */
+PR(1, 3, XTRA_MIGHT_BOW) /* Xtra might with bows */
+PR(1, 4, XTRA_MIGHT_XBOW) /* Xtra might with x-bows */
+PR(1, 5, XTRA_MIGHT_SLING) /* Xtra might with slings */
+PR(1, 6, AC_LEVEL) /* AC increases with levels */
+PR(1, 7, HURT_LITE) /* Hurt by light */
+PR(1, 8, VAMPIRE) /* Vampire */
+PR(1, 9, UNDEAD) /* Undead */
+PR(1, 10, NO_CUT) /* No cuts */
+PR(1, 11, CORRUPT) /* Corrupted; automatically gains corruptions */
+PR(1, 12, NO_FOOD) /* Little gain from food */
+PR(1, 13, NO_GOD) /* Cannot worship any gods */
+PR(1, 14, ELF) /* Is an elf */
+PR(1, 15, SEMI_WRAITH) /* Allows walking through walls; taking damage */
+PR(1, 16, NO_SUBRACE_CHANGE) /* Impossible to change subrace */
+PR(1, 17, GOD_FRIEND) /* Better grace */
+PR(1, 18, EASE_STEAL) /* Gain XP by stealing */
+PR(1, 19, ASTRAL) /* Astral being from the halls of Mandos */
diff --git a/src/player_race_flag_set.hpp b/src/player_race_flag_set.hpp
new file mode 100644
index 00000000..4dd8dd9f
--- /dev/null
+++ b/src/player_race_flag_set.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "flag_set.hpp"
+
+constexpr std::size_t PR_MAX_TIERS = 1;
+
+typedef flag_set<PR_MAX_TIERS> player_race_flag_set;
diff --git a/src/player_race_fwd.hpp b/src/player_race_fwd.hpp
new file mode 100644
index 00000000..c3c3350b
--- /dev/null
+++ b/src/player_race_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct player_race;
diff --git a/src/player_race_mod.hpp b/src/player_race_mod.hpp
new file mode 100644
index 00000000..8eb984b7
--- /dev/null
+++ b/src/player_race_mod.hpp
@@ -0,0 +1,52 @@
+#pragma once
+
+#include "body.hpp"
+#include "h-basic.h"
+#include "object_flag_set.hpp"
+#include "object_proto.hpp"
+#include "player_defs.hpp"
+#include "player_level_flag.hpp"
+#include "player_race_ability_type.hpp"
+#include "player_race_flag_set.hpp"
+#include "player_shared.hpp"
+#include "skill_modifiers.hpp"
+#include "skills_defs.hpp"
+
+#include <array>
+#include <string>
+#include <vector>
+
+struct player_race_mod
+{
+ std::string title;
+ std::string description;
+
+ bool_ place = FALSE; /* TRUE = race race modifier, FALSE = Race modifier race */
+
+ char luck = '\0'; /* Luck */
+ s16b mana = 0; /* Mana % */
+
+ player_shared ps;
+
+ char infra = '\0'; /* (+) Infra-vision range */
+
+ u32b choice[2] { }; /* Legal race choices */
+
+ u32b pclass[2] { }; /* Classes allowed */
+ u32b mclass[2] { }; /* Classes restricted */
+
+ char body_parts[BODY_MAX] { }; /* To help to decide what to use when body changing */
+
+ player_race_flag_set flags;
+
+ std::array<player_level_flag, PY_MAX_LEVEL+1> lflags;
+
+ byte g_attr = 0; /* Overlay graphic attribute */
+ char g_char = '\0'; /* Overlay graphic character */
+
+ struct skill_modifiers skill_modifiers;
+
+ std::vector<object_proto> object_protos;
+
+ std::vector<player_race_ability_type> abilities; /* Abilities to be gained by level; ignores prereqs */
+};
diff --git a/src/player_race_mod_fwd.hpp b/src/player_race_mod_fwd.hpp
new file mode 100644
index 00000000..12eb468a
--- /dev/null
+++ b/src/player_race_mod_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct player_race_mod;
diff --git a/src/player_shared.hpp b/src/player_shared.hpp
new file mode 100644
index 00000000..1ae7b9a7
--- /dev/null
+++ b/src/player_shared.hpp
@@ -0,0 +1,16 @@
+#pragma once
+
+#include "h-basic.h"
+#include "skills_defs.hpp"
+#include <array>
+#include <vector>
+
+struct player_shared
+{
+ std::array<s16b, 6> adj { }; /* Stat modifiers */
+
+ s16b mhp = 0; /* Hit-dice adjustment */
+ s16b exp = 0; /* Experience factor */
+
+ std::vector<s16b> powers; /* Powers */
+};
diff --git a/src/player_spec.hpp b/src/player_spec.hpp
new file mode 100644
index 00000000..574425f6
--- /dev/null
+++ b/src/player_spec.hpp
@@ -0,0 +1,29 @@
+#pragma once
+
+#include "h-basic.h"
+#include "object_proto.hpp"
+#include "player_race_ability_type.hpp"
+#include "player_race_flag_set.hpp"
+#include "skill_modifiers.hpp"
+
+#include <array>
+#include <vector>
+
+/**
+ * Player class descriptor.
+ */
+struct player_spec
+{
+ const char *title = nullptr; /* Type of class spec */
+ char *desc = nullptr; /* Small desc of the class spec */
+
+ struct skill_modifiers skill_modifiers;
+
+ std::vector<object_proto> object_protos;
+
+ u32b gods = 0;
+
+ player_race_flag_set flags;
+
+ std::vector<player_race_ability_type> abilities; /* Abilities to be gained by level; ignores prereqs */
+};
diff --git a/src/player_spec_fwd.hpp b/src/player_spec_fwd.hpp
new file mode 100644
index 00000000..9083acd0
--- /dev/null
+++ b/src/player_spec_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct player_spec;
diff --git a/src/player_type.cc b/src/player_type.cc
new file mode 100644
index 00000000..0cc66de7
--- /dev/null
+++ b/src/player_type.cc
@@ -0,0 +1,28 @@
+#include "player_type.hpp"
+
+#include <algorithm>
+
+bool player_type::has_ability(u16b ability_idx) const
+{
+ return std::find(
+ abilities.begin(),
+ abilities.end(),
+ ability_idx) != abilities.end();
+}
+
+void player_type::gain_ability(u16b ability_idx)
+{
+ // Duplicates don't really matter, so let's just
+ // accept whatever value we get without checking
+ // anything.
+ abilities.push_back(ability_idx);
+}
+
+void player_type::lose_ability(u16b ability_idx)
+{
+ abilities.erase(
+ std::remove(
+ abilities.begin(),
+ abilities.end(),
+ ability_idx));
+}
diff --git a/src/player_type.hpp b/src/player_type.hpp
new file mode 100644
index 00000000..9b7ac21d
--- /dev/null
+++ b/src/player_type.hpp
@@ -0,0 +1,428 @@
+#pragma once
+
+#include "corrupt.hpp"
+#include "defines.h"
+#include "h-basic.h"
+#include "help_info.hpp"
+#include "inventory.hpp"
+#include "object_type.hpp"
+#include "powers.hpp"
+#include "random_spell.hpp"
+#include "spellbinder.hpp"
+
+#include <array>
+
+/*
+ * Most of the "player" information goes here.
+ *
+ * This stucture gives us a large collection of player variables.
+ *
+ * This structure contains several "blocks" of information.
+ * (1) the "permanent" info
+ * (2) the "variable" info
+ * (3) the "transient" info
+ *
+ * All of the "permanent" info, and most of the "variable" info,
+ * is saved in the savefile. The "transient" info is recomputed
+ * whenever anything important changes.
+ */
+
+struct player_type
+{
+ s32b lives = 0; /* How many times we resurected */
+
+ s16b oldpy = 0; /* Previous player location */
+ s16b oldpx = 0; /* Previous player location */
+
+ s16b py = 0; /* Player location */
+ s16b px = 0; /* Player location */
+
+ byte prace = 0; /* Race index */
+ byte pracem = 0; /* Race Mod index */
+ byte pclass = 0; /* Class index */
+ byte pspec = 0; /* Class spec index */
+ byte mimic_form = 0; /* Actualy transformation */
+ s16b mimic_level = 0; /* Level of the mimic effect */
+
+ std::array<object_type, INVEN_TOTAL> inventory { }; /* Player inventory */
+
+ byte hitdie = 0; /* Hit dice (sides) */
+ u16b expfact = 0; /* Experience factor */
+
+ byte allow_one_death = 0; /* Blood of life */
+
+ s32b au = 0; /* Current Gold */
+
+ s32b max_exp = 0; /* Max experience */
+ s32b exp = 0; /* Cur experience */
+ u16b exp_frac = 0; /* Cur exp frac (times 2^16) */
+
+ s16b lev = 0; /* Level */
+
+ s16b town_num = 0; /* Current town number */
+ s16b inside_quest = 0; /* Inside quest level */
+
+ s32b wilderness_x = 0; /* Coordinates in the wilderness */
+ s32b wilderness_y = 0;
+ bool_ wild_mode = FALSE; /* TRUE = Small map, FLASE = Big map */
+ bool_ old_wild_mode = FALSE; /* TRUE = Small map, FLASE = Big map */
+
+ s16b mhp = 0; /* Max hit pts */
+ s16b chp = 0; /* Cur hit pts */
+ u16b chp_frac = 0; /* Cur hit frac (times 2^16) */
+ s16b hp_mod = 0; /* A modificator (permanent) */
+
+ s16b msp = 0; /* Max mana pts */
+ s16b csp = 0; /* Cur mana pts */
+ u16b csp_frac = 0; /* Cur mana frac (times 2^16) */
+
+ s16b msane = 0; /* Max sanity */
+ s16b csane = 0; /* Cur sanity */
+ u16b csane_frac = 0; /* Cur sanity frac */
+
+ s32b grace = 0; /* Your God's appreciation factor. */
+ s32b grace_delay = 0; /* Delay factor for granting piety. */
+ byte pgod = 0; /* Your God. */
+ bool_ praying = FALSE; /* Praying to your god. */
+ s16b melkor_sacrifice = 0; /* How much hp has been sacrified for damage */
+
+ s16b max_plv = 0; /* Max Player Level */
+
+ s16b stat_max[6] = { 0 }; /* Current "maximal" stat values */
+ s16b stat_cur[6] = { 0 }; /* Current "natural" stat values */
+
+ s16b luck_cur = 0; /* Current "natural" luck value (range -30 <> 30) */
+ s16b luck_max = 0; /* Current "maximal base" luck value (range -30 <> 30) */
+ s16b luck_base = 0; /* Current "base" luck value (range -30 <> 30) */
+
+ s16b speed_factor = 0; /* Timed -- Fast */
+ s16b fast = 0; /* Timed -- Fast */
+ s16b lightspeed = 0; /* Timed -- Light Speed */
+ s16b slow = 0; /* Timed -- Slow */
+ s16b blind = 0; /* Timed -- Blindness */
+ s16b paralyzed = 0; /* Timed -- Paralysis */
+ s16b confused = 0; /* Timed -- Confusion */
+ s16b afraid = 0; /* Timed -- Fear */
+ s16b image = 0; /* Timed -- Hallucination */
+ s16b poisoned = 0; /* Timed -- Poisoned */
+ s16b cut = 0; /* Timed -- Cut */
+ s16b stun = 0; /* Timed -- Stun */
+
+ s16b protevil = 0; /* Timed -- Protection from Evil*/
+ s16b invuln = 0; /* Timed -- Invulnerable */
+ s16b hero = 0; /* Timed -- Heroism */
+ s16b shero = 0; /* Timed -- Super Heroism */
+ s16b shield = 0; /* Timed -- Shield Spell */
+ s16b shield_power = 0; /* Timed -- Shield Spell Power */
+ s16b shield_opt = 0; /* Timed -- Shield Spell options */
+ s16b shield_power_opt = 0; /* Timed -- Shield Spell Power */
+ s16b shield_power_opt2 = 0; /* Timed -- Shield Spell Power */
+ s16b blessed = 0; /* Timed -- Blessed */
+ s16b tim_invis = 0; /* Timed -- See Invisible */
+ s16b tim_infra = 0; /* Timed -- Infra Vision */
+
+ s16b oppose_acid = 0; /* Timed -- oppose acid */
+ s16b oppose_elec = 0; /* Timed -- oppose lightning */
+ s16b oppose_fire = 0; /* Timed -- oppose heat */
+ s16b oppose_cold = 0; /* Timed -- oppose cold */
+ s16b oppose_pois = 0; /* Timed -- oppose poison */
+ s16b oppose_cc = 0; /* Timed -- oppose chaos & confusion */
+
+ s16b tim_esp = 0; /* Timed ESP */
+ s16b tim_wraith = 0; /* Timed wraithform */
+ s16b tim_ffall = 0; /* Timed Levitation */
+ s16b tim_fly = 0; /* Timed Levitation */
+ s16b tim_poison = 0; /* Timed poison hands */
+ s16b tim_thunder = 0; /* Timed thunderstorm */
+ s16b tim_thunder_p1 = 0; /* Timed thunderstorm */
+ s16b tim_thunder_p2 = 0; /* Timed thunderstorm */
+
+ s16b tim_project = 0; /* Timed project upon melee blow */
+ s16b tim_project_dam = 0;
+ s16b tim_project_gf = 0;
+ s16b tim_project_rad = 0;
+ s16b tim_project_flag = 0;
+
+ s16b tim_roots = 0; /* Timed roots */
+ s16b tim_roots_ac = 0;
+ s16b tim_roots_dam = 0;
+
+ s16b tim_invisible = 0; /* Timed Invisibility */
+ s16b tim_inv_pow = 0; /* Power of timed invisibility */
+ s16b tim_mimic = 0; /* Timed Mimic */
+ s16b tim_lite = 0; /* Timed Lite */
+ s16b tim_regen = 0; /* Timed extra regen */
+ s16b tim_regen_pow = 0; /* Timed extra regen power */
+ s16b holy = 0; /* Holy Aura */
+ s16b strike = 0; /* True Strike(+25 hit) */
+ s16b tim_reflect = 0; /* Timed Reflection */
+ s16b tim_deadly = 0; /* Timed deadly blow */
+ s16b prob_travel = 0; /* Timed probability travel */
+ s16b disrupt_shield = 0; /* Timed disruption shield */
+ s16b parasite = 0; /* Timed parasite */
+ s16b parasite_r_idx = 0; /* Timed parasite monster */
+ s16b absorb_soul = 0; /* Timed soul absordtion */
+ s16b tim_magic_breath = 0; /* Magical breathing -- can breath anywhere */
+ s16b tim_water_breath = 0; /* Water breathing -- can breath underwater */
+ s16b tim_precognition = 0; /* Timed precognition */
+
+ s16b immov_cntr = 0; /* Timed -- Last ``immovable'' command. */
+
+ byte recall_dungeon = 0; /* Recall in which dungeon */
+ s16b word_recall = 0; /* Word of recall counter */
+
+ s32b energy = 0; /* Current energy */
+
+ s16b food = 0; /* Current nutrition */
+
+ byte confusing = 0; /* Glowing hands */
+
+ bool_ old_cumber_armor = FALSE;
+ bool_ old_cumber_glove = FALSE;
+ bool_ old_heavy_wield = FALSE;
+ bool_ old_heavy_shoot = FALSE;
+ bool_ old_icky_wield = FALSE;
+
+ s16b old_lite = 0; /* Old radius of lite (if any) */
+ s16b old_view = 0; /* Old radius of view (if any) */
+
+ s16b old_food_aux = 0; /* Old value of food */
+
+ bool_ cumber_armor = FALSE; /* Mana draining armor */
+ bool_ cumber_glove = FALSE; /* Mana draining gloves */
+ bool_ heavy_wield = FALSE; /* Heavy weapon */
+ bool_ heavy_shoot = FALSE; /* Heavy shooter */
+ bool_ icky_wield = FALSE; /* Icky weapon */
+ bool_ immovable = FALSE; /* Immovable character */
+
+ s16b cur_lite = 0; /* Radius of lite (if any) */
+
+ u32b notice = 0; /* Special Updates (bit flags) */
+ u32b update = 0; /* Pending Updates (bit flags) */
+ u32b redraw = 0; /* Normal Redraws (bit flags) */
+ u32b window = 0; /* Window Redraws (bit flags) */
+
+ s16b stat_use[6] = { 0 }; /* Current modified stats */
+ s16b stat_top[6] = { 0 }; /* Maximal modified stats */
+
+ s16b stat_add[6] = { 0 }; /* Modifiers to stat values */
+ s16b stat_ind[6] = { 0 }; /* Indexes into stat tables */
+ s16b stat_cnt[6] = { 0 }; /* Counter for temporary drains */
+ s16b stat_los[6] = { 0 }; /* Amount of temporary drains */
+
+ bool_ immune_acid = FALSE; /* Immunity to acid */
+ bool_ immune_elec = FALSE; /* Immunity to lightning */
+ bool_ immune_fire = FALSE; /* Immunity to fire */
+ bool_ immune_cold = FALSE; /* Immunity to cold */
+ bool_ immune_neth = FALSE; /* Immunity to nether */
+
+ bool_ resist_acid = FALSE; /* Resist acid */
+ bool_ resist_elec = FALSE; /* Resist lightning */
+ bool_ resist_fire = FALSE; /* Resist fire */
+ bool_ resist_cold = FALSE; /* Resist cold */
+ bool_ resist_pois = FALSE; /* Resist poison */
+
+ bool_ resist_conf = FALSE; /* Resist confusion */
+ bool_ resist_sound = FALSE; /* Resist sound */
+ bool_ resist_lite = FALSE; /* Resist light */
+ bool_ resist_dark = FALSE; /* Resist darkness */
+ bool_ resist_chaos = FALSE; /* Resist chaos */
+ bool_ resist_disen = FALSE; /* Resist disenchant */
+ bool_ resist_shard = FALSE; /* Resist shards */
+ bool_ resist_nexus = FALSE; /* Resist nexus */
+ bool_ resist_blind = FALSE; /* Resist blindness */
+ bool_ resist_neth = FALSE; /* Resist nether */
+ bool_ resist_fear = FALSE; /* Resist fear */
+ bool_ resist_continuum = FALSE; /* Resist space-time continuum disruption */
+
+ bool_ sensible_fire = FALSE; /* Fire does more damage on the player */
+ bool_ sensible_lite = FALSE; /* Lite does more damage on the player and blinds her/him */
+
+ bool_ reflect = FALSE; /* Reflect 'bolt' attacks */
+ bool_ sh_fire = FALSE; /* Fiery 'immolation' effect */
+ bool_ sh_elec = FALSE; /* Electric 'immolation' effect */
+ bool_ wraith_form = FALSE; /* wraithform */
+
+ bool_ anti_magic = FALSE; /* Anti-magic */
+ bool_ anti_tele = FALSE; /* Prevent teleportation */
+
+ bool_ sustain_str = FALSE; /* Keep strength */
+ bool_ sustain_int = FALSE; /* Keep intelligence */
+ bool_ sustain_wis = FALSE; /* Keep wisdom */
+ bool_ sustain_dex = FALSE; /* Keep dexterity */
+ bool_ sustain_con = FALSE; /* Keep constitution */
+ bool_ sustain_chr = FALSE; /* Keep charisma */
+
+ bool_ aggravate = FALSE; /* Aggravate monsters */
+ bool_ teleport = FALSE; /* Random teleporting */
+
+ bool_ exp_drain = FALSE; /* Experience draining */
+ byte drain_mana = FALSE; /* mana draining */
+ byte drain_life = FALSE; /* hp draining */
+
+ bool_ magical_breath = FALSE; /* Magical breathing -- can breath anywhere */
+ bool_ water_breath = FALSE; /* Water breathing -- can breath underwater */
+ bool_ climb = FALSE; /* Can climb mountains */
+ bool_ fly = FALSE; /* Can fly over some features */
+ bool_ ffall = FALSE; /* No damage falling */
+ bool_ lite = FALSE; /* Permanent light */
+ bool_ free_act = FALSE; /* Never paralyzed */
+ bool_ see_inv = FALSE; /* Can see invisible */
+ bool_ regenerate = FALSE; /* Regenerate hit pts */
+ bool_ hold_life = FALSE; /* Resist life draining */
+ bool_ slow_digest = FALSE; /* Slower digestion */
+ bool_ bless_blade = FALSE; /* Blessed blade */
+ byte xtra_might = 0; /* Extra might bow */
+ bool_ impact = FALSE; /* Earthquake blows */
+ bool_ auto_id = FALSE; /* Auto id items */
+
+ s16b invis = 0; /* Invisibility */
+
+ s16b dis_to_h = 0; /* Known bonus to hit */
+ s16b dis_to_d = 0; /* Known bonus to dam */
+ s16b dis_to_a = 0; /* Known bonus to ac */
+
+ s16b dis_ac = 0; /* Known base ac */
+
+ s16b to_l = 0; /* Bonus to life */
+ s16b to_m = 0; /* Bonus to mana */
+ s16b to_s = 0; /* Bonus to spell */
+ s16b to_h = 0; /* Bonus to hit */
+ s16b to_d = 0; /* Bonus to dam */
+ s16b to_h_melee = 0; /* Bonus to hit for melee */
+ s16b to_d_melee = 0; /* Bonus to dam for melee */
+ s16b to_h_ranged = 0; /* Bonus to hit for ranged */
+ s16b to_d_ranged = 0; /* Bonus to dam for ranged */
+ s16b to_a = 0; /* Bonus to ac */
+
+ s16b ac = 0; /* Base ac */
+
+ byte antimagic = 0; /* Power of the anti magic field */
+ byte antimagic_dis = 0; /* Radius of the anti magic field */
+
+ s16b see_infra; /* Infravision range */
+
+ s16b skill_dev = 0; /* Skill: Magic Devices */
+ s16b skill_sav = 0; /* Skill: Saving throw */
+ s16b skill_stl = 0; /* Skill: Stealth factor */
+ s16b skill_thn = 0; /* Skill: To hit (normal) */
+ s16b skill_thb = 0; /* Skill: To hit (shooting) */
+ s16b skill_tht = 0; /* Skill: To hit (throwing) */
+ s16b skill_dig = 0; /* Skill: Digging */
+
+ s16b num_blow = 0; /* Number of blows */
+ s16b num_fire = 0; /* Number of shots */
+ s16b xtra_crit = 0; /* % of increased crits */
+
+ byte throw_mult = 0; /* Multiplier for throw damage */
+
+ byte tval_ammo = 0; /* Correct ammo tval */
+
+ s16b pspeed = 0; /* Current speed */
+
+ u32b mimic_extra = 0; /* Mimicry powers use that */
+ u32b antimagic_extra = 0; /* Antimagic powers */
+ u32b music_extra = 0; /* Music songs */
+ u32b necro_extra = 0; /* Necro powers */
+ u32b necro_extra2 = 0; /* Necro powers */
+
+ s16b dodge_chance = 0; /* Dodging chance */
+
+ u32b maintain_sum = 0; /* Do we have partial summons */
+
+ struct spellbinder spellbinder;
+
+ cptr mimic_name = nullptr;
+
+ char tactic = '\0'; /* from 128-4 "extremely coward" to, 128+4 "berserker" */
+ char movement = '\0'; /* base movement way */
+
+ s16b companion_killed = 0; /* Number of companion death */
+
+ bool_ no_mortal = FALSE; /* Fated to never die by the hand of a mortal being */
+
+ bool_ black_breath = FALSE; /* The Tolkien's Black Breath */
+
+ bool_ precognition = FALSE; /* Like the cheat mode */
+
+ /*** Extra flags ***/
+ object_flag_set xtra_flags;
+
+ /** Computed flags based on all worn items, etc. */
+ object_flag_set computed_flags;
+
+ /* Corruptions */
+ bool_ corruptions[CORRUPTIONS_MAX] = { FALSE };
+ bool_ corrupt_anti_teleport_stopped = FALSE;
+
+ /*** Pet commands ***/
+ byte pet_follow_distance = 0; /* Length of the imaginary "leash" for pets */
+ byte pet_open_doors = 0; /* flag - allow pets to open doors */
+ byte pet_pickup_items = 0; /* flag - allow pets to pickup items */
+
+ s16b control = 0; /* Controlled monster */
+ byte control_dir; /* Controlled monster */
+
+ /*** Body changing variables ***/
+ u16b body_monster = 0; /* In which body is the player */
+ bool_ disembodied = FALSE; /* Is the player in a body ? */
+ std::array<byte, INVEN_TOTAL-INVEN_WIELD> body_parts = /* Which body parts does he have ? */
+ { };
+
+ /* Astral */
+ bool_ astral = FALSE; /* We started at the bottom ? */
+
+ /* Powers */
+ bool_ powers[POWER_MAX] = { FALSE }; /* Actual powers */
+ bool_ powers_mod[POWER_MAX] = { FALSE }; /* Intrinsinc powers */
+
+ /* Acquired abilities; indexes into ab_info[] */
+ std::vector<u16b> abilities;
+
+ /* Known inscriptions; true if known, false otherwise. */
+ std::array<bool, MAX_INSCRIPTIONS> inscriptions;
+
+ /* Skills */
+ s16b skill_points = 0;
+ s16b skill_last_level = 0; /* Prevents gaining skills by losing level and regaining them */
+ s16b melee_style = 0; /* How are */
+ s16b use_piercing_shots = 0; /* for archery */
+
+ /* Dripping Tread spell timer */
+ s16b dripping_tread = 0;
+
+ /* Help */
+ help_info help;
+
+ /* Inertia control */
+ s32b inertia_controlled_spell = 0;
+
+ /* For automatic stat-gain */
+ s16b last_rewarded_level = 0;
+
+ /*** Temporary fields ***/
+
+ bool_ did_nothing = FALSE; /* True if the last action wasnt a real action */
+ bool_ leaving = FALSE; /* True if player is leaving */
+
+ /**
+ * Random spells.
+ */
+ std::vector<random_spell> random_spells;
+
+ /**
+ * Does the player have the given ability?
+ */
+ bool has_ability(u16b ability_idx) const;
+
+ /**
+ * Gain the given ability.
+ */
+ void gain_ability(u16b ability_idx);
+
+ /**
+ * Lose the given ability.
+ */
+ void lose_ability(u16b ability_idx);
+
+};
diff --git a/src/player_type_fwd.hpp b/src/player_type_fwd.hpp
new file mode 100644
index 00000000..45a4bbcf
--- /dev/null
+++ b/src/player_type_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct player_type;
diff --git a/src/plots.c b/src/plots.c
deleted file mode 100644
index 53d3e1bc..00000000
--- a/src/plots.c
+++ /dev/null
@@ -1,473 +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 "lua/lua.h"
-#include "tolua.h"
-extern lua_State* L;
-
-/* #define DEBUG_HOOK */
-
-/******** 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_INIT; i++)
- {
- if ((quest[i].type == HOOK_TYPE_C) && (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);
-#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_);
- }
- else return (c);
-}
-
-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)
-{
- 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)
- {
-#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);
- }
- }
-}
-
-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)
- {
-#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);
- }
- }
-}
-
-/* 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;
- }
- }
-}
-
-/* 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)
- {
-#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;
-
- /* 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_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
- {
- msg_format("Unkown hook type %d, name %s", c->type, c->name);
- }
- }
-
- 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);
-}
-
-/******** 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)
-{
- /* Do nothing */
- return (FALSE);
-}
-
-/************************** Random Quests *************************/
-#include "q_rand.c"
-
-/**************************** Main plot ***************************/
-#include "q_main.c"
-#include "q_one.c"
-#include "q_ultrag.c"
-#include "q_ultrae.c"
-
-/**************************** Bree plot ***************************/
-#include "q_thief.c"
-#include "q_hobbit.c"
-#include "q_troll.c"
-#include "q_wight.c"
-#include "q_nazgul.c"
-#include "q_shroom.c"
-
-/*************************** Lorien plot **************************/
-#include "q_wolves.c"
-#include "q_spider.c"
-#include "q_poison.c"
-
-/************************** Gondolin plot *************************/
-#include "q_dragons.c"
-#include "q_eol.c"
-#include "q_nirna.c"
-#include "q_invas.c"
-
-/************************* Minas Anor plot ************************/
-#include "q_haunted.c"
-#include "q_betwen.c"
-
-/************************* Khazad-dum plot ************************/
-#include "q_evil.c"
-
-/*************************** Other plot ***************************/
-#include "q_narsil.c"
-#include "q_thrain.c"
diff --git a/src/plots.h b/src/plots.h
deleted file mode 100644
index a1a11e6c..00000000
--- a/src/plots.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* File: plots.h */
-
-/* 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);
-
-/******* 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);
-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);
-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);
-
-/******* 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);
-
-/******* 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);
-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 Khazad-dum *********/
-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);
diff --git a/src/point.hpp b/src/point.hpp
new file mode 100644
index 00000000..c0c12f58
--- /dev/null
+++ b/src/point.hpp
@@ -0,0 +1,24 @@
+#pragma once
+
+#include <cstdint>
+
+struct point {
+
+private:
+ std::uint8_t m_x;
+ std::uint8_t m_y;
+
+public:
+ point(std::uint8_t x, std::uint8_t y)
+ : m_x(x), m_y(y) {
+ }
+
+ std::uint8_t x() const {
+ return m_x;
+ }
+
+ std::uint8_t y() const {
+ return m_y;
+ }
+
+};
diff --git a/src/power_type.hpp b/src/power_type.hpp
new file mode 100644
index 00000000..6cf8c29b
--- /dev/null
+++ b/src/power_type.hpp
@@ -0,0 +1,19 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * Power descriptor. (Racial, class, mutation, artifacts, ...)
+ */
+struct power_type
+{
+ 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 */
+ byte stat; /* Stat used */
+ byte diff; /* Difficulty */
+};
diff --git a/src/powers.c b/src/powers.cc
index 12b2c2c0..f3ffe668 100644
--- a/src/powers.c
+++ b/src/powers.cc
@@ -1,7 +1,3 @@
-/* File: powers.c */
-
-/* Purpose: Powers */
-
/*
* Copyright (c) 2001 James E. Wilson, Robert A. Koeneke, DarkGod
*
@@ -10,12 +6,45 @@
* included in all such copies.
*/
-#include "angband.h"
+#include "powers.hpp"
+
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "cmd1.hpp"
+#include "cmd2.hpp"
+#include "cmd7.hpp"
+#include "dungeon_flag.hpp"
+#include "feature_flag.hpp"
+#include "feature_type.hpp"
+#include "files.hpp"
+#include "game.hpp"
+#include "hooks.hpp"
+#include "mimic.hpp"
+#include "monster2.hpp"
+#include "monster3.hpp"
+#include "monster_race.hpp"
+#include "monster_race_flag.hpp"
+#include "monster_type.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_kind.hpp"
+#include "options.hpp"
+#include "player_type.hpp"
+#include "spells1.hpp"
+#include "spells2.hpp"
+#include "stats.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "util.h"
+#include "variable.h"
+#include "variable.hpp"
+#include "xtra2.hpp"
+#include "z-rand.hpp"
/*
* Note: return value indicates the amount of mana to use
*/
-bool_ power_chance(power_type *x_ptr)
+static bool_ power_chance(power_type *x_ptr)
{
bool_ use_hp = FALSE;
int diff = x_ptr->diff;
@@ -80,7 +109,7 @@ bool_ power_chance(power_type *x_ptr)
energy_use = 100;
/* Redraw mana and hp */
- p_ptr->redraw |= (PR_HP | PR_MANA);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
@@ -92,7 +121,7 @@ bool_ power_chance(power_type *x_ptr)
return (TRUE);
}
- if (flush_failure) flush();
+ flush_on_failure();
msg_print("You've failed to concentrate hard enough.");
return (FALSE);
@@ -100,6 +129,9 @@ bool_ power_chance(power_type *x_ptr)
static void power_activate(int power)
{
+ auto const &f_info = game->edit_data.f_info;
+ auto const &k_info = game->edit_data.k_info;
+
s16b plev = p_ptr->lev;
char ch = 0;
int amber_power = 0;
@@ -168,204 +200,6 @@ static void power_activate(int power)
}
}
break;
- case PWR_MERCHANT:
- /* Select power to use */
- while (TRUE)
- {
- if (!get_com("[A]ppraise item, [W]arp item or [I]dentify item? ", &ch))
- {
- amber_power = 0;
- break;
- }
-
- if (ch == 'A' || ch == 'a')
- {
- amber_power = 1;
- break;
- }
-
- if (ch == 'W' || ch == 'w')
- {
- amber_power = 2;
- break;
- }
-
- if (ch == 'I' || ch == 'i')
- {
- amber_power = 3;
- break;
- }
- }
-
- if (amber_power == 1)
- {
- x_ptr_foo.level = 5;
- x_ptr_foo.cost = 5;
- x_ptr_foo.stat = A_INT;
- x_ptr_foo.diff = 5;
- if (power_chance(&x_ptr_foo))
- {
- /* Appraise an object */
- int idx;
- cptr q, s;
-
- /* Get the item */
- q = "Appraise which item? ";
- s = "You have nothing to appraise.";
- if (get_item(&idx, q, s, (USE_EQUIP | USE_INVEN | USE_FLOOR)))
- {
- object_type *o_ptr;
- char out_val[80], value[16];
-
- /* The item is in the pack */
- if (idx >= 0) o_ptr = &p_ptr->inventory[idx];
- /* The item is on the floor */
- else o_ptr = &o_list[0 - idx];
-
- /* Appraise it */
- sprintf(value, "%i au", (int)object_value(o_ptr));
-
- /* Inscribe the value */
- /* Get the original inscription */
- if (o_ptr->note)
- {
- strcpy(out_val, quark_str(o_ptr->note));
- strcat(out_val, " ");
- }
- else
- out_val[0] = '\0';
-
- strcat(out_val, value);
-
- /* Save the new 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);
- }
- }
- }
- if (amber_power == 2)
- {
- x_ptr_foo.level = 15;
- x_ptr_foo.cost = 10;
- x_ptr_foo.stat = A_INT;
- x_ptr_foo.diff = 7;
- if (power_chance(&x_ptr_foo))
- {
- int chest, item;
- cptr q1, s1, q2, s2;
- u32b flag = (USE_EQUIP | USE_INVEN | USE_FLOOR);
- object_type *o1_ptr = &p_ptr->inventory[0], *o2_ptr = &p_ptr->inventory[1];
- int ok = 0;
-
- q1 = "Select a chest! ";
- s1 = "You need a chest to warp items.";
-
- q2 = "Warp which item? ";
- s2 = "You have nothing to warp.";
-
- item_tester_tval = TV_CHEST;
-
- /* Get the chest */
- if (get_item(&chest, q1, s1, flag))
- {
- if (chest >= 0) o1_ptr = &p_ptr->inventory[chest];
- else o1_ptr = &o_list[0 - chest];
-
- /* Is the chest disarmed? */
- if (o1_ptr->pval > 0)
- msg_print("This chest may be trapped.");
-
- /* Is it ruined? */
- else if (k_info[o1_ptr->k_idx].level <= 0)
- msg_print("This chest is broken.");
-
- /* Is it empty? */
- else if (o1_ptr->pval2 >= (o1_ptr->sval % SV_CHEST_MIN_LARGE) * 2)
- msg_print("This chest is full.");
-
- else ok = 1;
- }
-
- /* Get the item */
- if (ok && get_item(&item, q2, s2, flag))
- {
- ok = 0;
-
- o2_ptr = get_object(item);
-
- /* Is the item cursed? */
- if ((item >= INVEN_WIELD) && cursed_p(o2_ptr))
- msg_print("Hmmm, it seems to be cursed.");
-
- /* Is it the same chest? */
- if (item == chest)
- msg_print("You can't put a chest into itself.");
-
- /* Is it another chest? */
- if (o2_ptr->tval == TV_CHEST)
- msg_print("You can't put a chest into another one.");
-
- /* Try to use the power */
- else ok = 1;
- }
-
- if (ok)
- {
- int tmp, level;
-
- /* Calculate the level of objects */
- tmp = o1_ptr->pval;
-
- /* Get the level of the current object */
- /* Cursed items/cheap items always break */
- if (k_info[o2_ptr->k_idx].cost < 20) level = 0;
- /* Not-so-cheap items break 90% of the time */
- else if (k_info[o2_ptr->k_idx].cost < 100) level = 1;
- else level = k_info[o2_ptr->k_idx].level;
-
- /* Break some items */
- if (randint(10) > level)
- msg_print("The item disappeared!");
- else
- {
- level /= (o1_ptr->sval % SV_CHEST_MIN_LARGE) * 2;
-
- /* Increase the number of objects in
- * the chest */
- o1_ptr->pval2++;
-
- /* Set the level of chest */
- tmp = tmp - level;
- o1_ptr->pval = tmp;
- }
-
- /* Destroy item */
- inc_stack_size(item, -1);
- }
- }
- }
- if (amber_power == 3)
- {
- x_ptr_foo.level = 30;
- x_ptr_foo.cost = 20;
- x_ptr_foo.stat = A_INT;
- x_ptr_foo.diff = 7;
- if (power_chance(&x_ptr_foo))
- {
- ident_spell();
- }
- }
- break;
- case PWR_LAY_TRAP:
- {
- do_cmd_set_trap();
- }
- break;
case PWR_MAGIC_MAP:
{
msg_print("You sense the world around you.");
@@ -401,17 +235,17 @@ static void power_activate(int power)
case PWR_UNFEAR:
{
msg_print("You play tough.");
- (void)set_afraid(0);
+ set_afraid(0);
}
break;
case PWR_BERSERK:
{
msg_print("RAAAGH!");
- (void)set_afraid(0);
+ set_afraid(0);
- (void)set_shero(p_ptr->shero + 10 + randint(plev));
- (void)hp_player(30);
+ set_shero(p_ptr->shero + 10 + randint(plev));
+ hp_player(30);
}
break;
@@ -426,7 +260,7 @@ static void power_activate(int power)
{
if (!get_aim_dir(&dir)) break;
msg_print("You bash at a stone wall.");
- (void)wall_to_mud(dir);
+ wall_to_mud(dir);
}
break;
@@ -477,7 +311,7 @@ static void power_activate(int power)
x_ptr_foo.diff = 7;
if (power_chance(&x_ptr_foo))
{
- (void)set_light_speed(p_ptr->lightspeed + 3);
+ set_light_speed(p_ptr->lightspeed + 3);
}
}
break;
@@ -494,9 +328,8 @@ static void power_activate(int power)
case PWR_DETECT_TD:
{
msg_print("You examine your surroundings.");
- (void)detect_traps(DEFAULT_RADIUS);
- (void)detect_doors(DEFAULT_RADIUS);
- (void)detect_stairs(DEFAULT_RADIUS);
+ detect_doors(DEFAULT_RADIUS);
+ detect_stairs(DEFAULT_RADIUS);
}
break;
@@ -556,7 +389,7 @@ static void power_activate(int power)
}
if (amber_power == 2)
{
- if (dungeon_flags2 & DF2_NO_TELEPORT)
+ if (dungeon_flags & DF_NO_TELEPORT)
{
msg_print("No teleport on special levels ...");
break;
@@ -583,7 +416,7 @@ static void power_activate(int power)
}
if (amber_power == 3)
{
- if (dungeon_flags2 & DF2_NO_TELEPORT)
+ if (dungeon_flags & DF_NO_TELEPORT)
{
msg_print("No recall on special levels..");
break;
@@ -677,7 +510,7 @@ static void power_activate(int power)
{
if (p_ptr->food < PY_FOOD_FULL)
/* No heal if we are "full" */
- (void)hp_player(dummy);
+ hp_player(dummy);
else
msg_print("You were not hungry.");
/* Gain nutritional sustenance: 150/hp drained */
@@ -686,7 +519,7 @@ static void power_activate(int power)
/* But if we ARE Gorged, it won't cure us */
dummy = p_ptr->food + MIN(5000, 100 * dummy);
if (p_ptr->food < PY_FOOD_MAX) /* Not gorged already */
- (void)set_food(dummy >= PY_FOOD_MAX ? PY_FOOD_MAX - 1 : dummy);
+ set_food(dummy >= PY_FOOD_MAX ? PY_FOOD_MAX - 1 : dummy);
}
else
msg_print("Yechh. That tastes foul.");
@@ -697,14 +530,14 @@ static void power_activate(int power)
{
msg_print("You emit an eldritch howl!");
if (!get_aim_dir(&dir)) break;
- (void)fear_monster(dir, plev);
+ fear_monster(dir, plev);
}
break;
case PWR_REST_LIFE:
{
msg_print("You attempt to restore your lost energies.");
- (void)restore_level();
+ restore_level();
}
break;
@@ -713,7 +546,6 @@ static void power_activate(int power)
int dir, x, y;
cave_type *c_ptr;
monster_type *m_ptr;
- monster_race *r_ptr;
object_type *q_ptr;
object_type forge;
@@ -725,9 +557,9 @@ static void power_activate(int power)
if (c_ptr->m_idx)
{
m_ptr = &m_list[c_ptr->m_idx];
- r_ptr = race_inf(m_ptr);
+ auto const r_ptr = m_ptr->race();
- if ((r_ptr->flags1 & RF1_NEVER_MOVE) && (m_ptr->status == MSTATUS_PET) && (!(r_ptr->flags9 & RF9_SPECIAL_GENE)))
+ if ((r_ptr->flags & RF_NEVER_MOVE) && (m_ptr->status == MSTATUS_PET) && (!(r_ptr->flags & RF_SPECIAL_GENE)))
{
q_ptr = &forge;
object_prep(q_ptr, lookup_kind(TV_HYPNOS, 1));
@@ -760,13 +592,10 @@ static void power_activate(int power)
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;
+ if (!get_item(&item, q, s, (USE_FLOOR), object_filter::TVal(TV_HYPNOS))) return;
o_ptr = &o_list[0 - item];
@@ -824,7 +653,7 @@ static void power_activate(int power)
{
msg_print("Your eyes look mesmerising...");
if (get_aim_dir(&dir))
- (void) charm_monster(dir, p_ptr->lev);
+ charm_monster(dir, p_ptr->lev);
}
break;
@@ -860,13 +689,13 @@ static void power_activate(int power)
case PWR_SMELL_MET:
{
- (void)detect_treasure(DEFAULT_RADIUS);
+ detect_treasure(DEFAULT_RADIUS);
}
break;
case PWR_SMELL_MON:
{
- (void)detect_monsters_normal(DEFAULT_RADIUS);
+ detect_monsters_normal(DEFAULT_RADIUS);
}
break;
@@ -890,7 +719,7 @@ static void power_activate(int power)
msg_print("You bite into thin air!");
break;
}
- else if ((f_info[c_ptr->feat].flags1 & FF1_PERMANENT) || (c_ptr->feat == FEAT_MOUNTAIN))
+ else if ((f_info[c_ptr->feat].flags & FF_PERMANENT) || (c_ptr->feat == FEAT_MOUNTAIN))
{
msg_print("Ouch! This wall is harder than your teeth!");
break;
@@ -910,25 +739,25 @@ static void power_activate(int power)
if ((c_ptr->feat >= FEAT_DOOR_HEAD) &&
(c_ptr->feat <= FEAT_RUBBLE))
{
- (void)set_food(p_ptr->food + 3000);
+ set_food(p_ptr->food + 3000);
}
else if ((c_ptr->feat >= FEAT_MAGMA) &&
(c_ptr->feat <= FEAT_QUARTZ_K))
{
- (void)set_food(p_ptr->food + 5000);
+ set_food(p_ptr->food + 5000);
}
else if ((c_ptr->feat >= FEAT_SANDWALL) &&
(c_ptr->feat <= FEAT_SANDWALL_K))
{
- (void)set_food(p_ptr->food + 500);
+ set_food(p_ptr->food + 500);
}
else
{
msg_print("This granite is very filling!");
- (void)set_food(p_ptr->food + 10000);
+ set_food(p_ptr->food + 10000);
}
}
- (void)wall_to_mud(dir);
+ wall_to_mud(dir);
oy = p_ptr->py;
ox = p_ptr->px;
@@ -950,20 +779,20 @@ static void power_activate(int power)
case PWR_SWAP_POS:
{
if (!get_aim_dir(&dir)) return;
- (void)teleport_swap(dir);
+ teleport_swap(dir);
}
break;
case PWR_SHRIEK:
{
- (void)fire_ball(GF_SOUND, 0, 4 * p_ptr->lev, 8);
- (void)aggravate_monsters(0);
+ fire_ball(GF_SOUND, 0, 4 * p_ptr->lev, 8);
+ aggravate_monsters(0);
}
break;
case PWR_ILLUMINE:
{
- (void)lite_area(damroll(2, (p_ptr->lev / 2)), (p_ptr->lev / 10) + 1);
+ lite_area(damroll(2, (p_ptr->lev / 2)), (p_ptr->lev / 10) + 1);
}
break;
@@ -991,7 +820,7 @@ static void power_activate(int power)
case PWR_MIDAS_TCH:
{
- (void)alchemy();
+ alchemy();
}
break;
@@ -1012,27 +841,27 @@ static void power_activate(int power)
if (rand_int(5) < num)
{
- (void)set_oppose_acid(p_ptr->oppose_acid + dur);
+ set_oppose_acid(p_ptr->oppose_acid + dur);
num--;
}
if (rand_int(4) < num)
{
- (void)set_oppose_elec(p_ptr->oppose_elec + dur);
+ set_oppose_elec(p_ptr->oppose_elec + dur);
num--;
}
if (rand_int(3) < num)
{
- (void)set_oppose_fire(p_ptr->oppose_fire + dur);
+ set_oppose_fire(p_ptr->oppose_fire + dur);
num--;
}
if (rand_int(2) < num)
{
- (void)set_oppose_cold(p_ptr->oppose_cold + dur);
+ set_oppose_cold(p_ptr->oppose_cold + dur);
num--;
}
if (num)
{
- (void)set_oppose_pois(p_ptr->oppose_pois + dur);
+ set_oppose_pois(p_ptr->oppose_pois + dur);
num--;
}
}
@@ -1051,12 +880,10 @@ static void power_activate(int power)
object_type * o_ptr;
int lev, item;
- item_tester_hook = item_tester_hook_recharge;
-
/* Get an item */
q = "Drain which item? ";
s = "You have nothing to drain.";
- if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) break;
+ if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR), item_tester_hook_recharge())) break;
o_ptr = get_object(item);
@@ -1150,7 +977,7 @@ static void power_activate(int power)
case PWR_RECALL:
{
- if (!(dungeon_flags2 & DF2_ASK_LEAVE) || ((dungeon_flags2 & DF2_ASK_LEAVE) && !get_check("Leave this unique level forever? ")))
+ if (!(dungeon_flags & DF_ASK_LEAVE) || ((dungeon_flags & DF_ASK_LEAVE) && !get_check("Leave this unique level forever? ")))
{
recall_player(21, 15);
}
@@ -1159,25 +986,20 @@ static void power_activate(int power)
case PWR_BANISH:
{
- int x, y;
- cave_type *c_ptr;
- monster_type *m_ptr;
- monster_race *r_ptr;
-
if (!get_rep_dir(&dir)) return;
- y = p_ptr->py + ddy[dir];
- x = p_ptr->px + ddx[dir];
- c_ptr = &cave[y][x];
+ const int x = p_ptr->px + ddx[dir];
+ const int y = p_ptr->py + ddy[dir];
+ cave_type *c_ptr = &cave[y][x];
if (!(c_ptr->m_idx))
{
msg_print("You sense no evil there!");
break;
}
- m_ptr = &m_list[c_ptr->m_idx];
- r_ptr = race_inf(m_ptr);
+ monster_type *m_ptr = &m_list[c_ptr->m_idx];
+ auto const r_ptr = m_ptr->race();
- if (r_ptr->flags3 & RF3_EVIL)
+ if (r_ptr->flags & RF_EVIL)
{
/* Delete the monster, rather than killing it. */
delete_monster_idx(c_ptr->m_idx);
@@ -1221,29 +1043,49 @@ static void power_activate(int power)
use_ability_blade();
break;
- default:
- if (!process_hooks(HOOK_ACTIVATE_POWER, "(d)", power))
+ 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)
{
- msg_format("Warning power_activate() called with invalid power(%d).", power);
- energy_use = 0;
+ 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:
+ abort();
break;
}
- p_ptr->redraw |= (PR_HP | PR_MANA);
+ p_ptr->redraw |= (PR_FRAME);
p_ptr->window |= (PW_PLAYER);
}
/*
* 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++)
{
@@ -1254,10 +1096,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);
}
@@ -1271,12 +1113,10 @@ static power_type* select_power(int *x_idx)
char which;
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])
{
@@ -1298,7 +1138,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)
@@ -1307,12 +1147,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;
@@ -1350,8 +1184,6 @@ static power_type* select_power(int *x_idx)
character_icky = FALSE;
}
- C_FREE(p, power_max, int);
-
return ret;
}
@@ -1365,7 +1197,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;
}
@@ -1373,7 +1205,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/powers.hpp b/src/powers.hpp
new file mode 100644
index 00000000..aa24e7d0
--- /dev/null
+++ b/src/powers.hpp
@@ -0,0 +1,73 @@
+#pragma once
+
+void do_cmd_power();
+
+/*
+ * Powers (mutation, activations, ...)
+ */
+#define POWER_MAX 65
+
+#define PWR_SPIT_ACID 0
+#define PWR_BR_FIRE 1
+#define PWR_HYPN_GAZE 2
+#define PWR_TELEKINES 3
+#define PWR_VTELEPORT 4
+#define PWR_MIND_BLST 5
+#define PWR_RADIATION 6
+#define PWR_VAMPIRISM 7
+#define PWR_SMELL_MET 8
+#define PWR_SMELL_MON 9
+#define PWR_BLINK 10
+#define PWR_EAT_ROCK 11
+#define PWR_SWAP_POS 12
+#define PWR_SHRIEK 13
+#define PWR_ILLUMINE 14
+#define PWR_DET_CURSE 15
+#define PWR_BERSERK 16
+#define PWR_POLYMORPH 17
+#define PWR_MIDAS_TCH 18
+#define PWR_GROW_MOLD 19
+#define PWR_RESIST 20
+#define PWR_EARTHQUAKE 21
+#define PWR_EAT_MAGIC 22
+#define PWR_WEIGH_MAG 23
+#define PWR_STERILITY 24
+#define PWR_PANIC_HIT 25
+#define PWR_DAZZLE 26
+#define PWR_DARKRAY 27
+#define PWR_RECALL 28
+#define PWR_BANISH 29
+#define PWR_COLD_TOUCH 30
+#define PWR_LAUNCHER 31
+
+#define PWR_PASSWALL 32
+#define PWR_DETECT_TD 33
+#define PWR_COOK_FOOD 34
+#define PWR_UNFEAR 35
+#define PWR_EXPL_RUNE 36
+#define PWR_STM 37
+#define PWR_POIS_DART 38
+#define PWR_MAGIC_MISSILE 39
+#define PWR_GROW_TREE 40
+#define PWR_BR_COLD 41
+#define PWR_BR_CHAOS 42
+#define PWR_BR_ELEM 43
+#define PWR_WRECK_WORLD 44
+#define PWR_SCARE 45
+#define PWR_REST_LIFE 46
+#define PWR_SUMMON_MONSTER 47
+#define PWR_NECRO 48
+#define PWR_ROHAN 49
+#define PWR_THUNDER 50
+#define PWR_DEATHMOLD 51
+#define PWR_HYPNO 52
+#define PWR_UNHYPNO 53
+#define PWR_INCARNATE 54
+#define PWR_MAGIC_MAP 55
+#define PWR_COMPANION 58
+#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
diff --git a/src/q_betwen.c b/src/q_betwen.cc
index e6452dd9..ca8243b4 100644
--- a/src/q_betwen.c
+++ b/src/q_betwen.cc
@@ -1,17 +1,37 @@
-#undef cquest
+#include "q_betwen.hpp"
+
+#include "cave.hpp"
+#include "dungeon_flag.hpp"
+#include "cave_type.hpp"
+#include "hook_chardump_in.hpp"
+#include "hook_init_quest_in.hpp"
+#include "hook_move_in.hpp"
+#include "hook_quest_finish_in.hpp"
+#include "hooks.hpp"
+#include "init1.hpp"
+#include "monster2.hpp"
+#include "monster_type.hpp"
+#include "object2.hpp"
+#include "player_type.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+
#define cquest (quest[QUEST_BETWEEN])
-bool_ quest_between_move_hook(char *fmt)
+static bool quest_between_move_hook(void *, void *in_, void *)
{
- s32b y;
- s32b x;
+ struct hook_move_in *in = static_cast<struct hook_move_in *>(in_);
+ s32b y = in->y;
+ s32b x = in->x;
cave_type *c_ptr;
- y = get_next_arg(fmt);
- x = get_next_arg(fmt);
c_ptr = &cave[y][x];
- if (cquest.status != QUEST_STATUS_TAKEN) return FALSE;
+ if (cquest.status != QUEST_STATUS_TAKEN)
+ {
+ return false;
+ }
/* The tower of Turgon */
if ((c_ptr->feat == FEAT_SHOP) && (c_ptr->special == 27))
@@ -21,19 +41,28 @@ bool_ quest_between_move_hook(char *fmt)
cquest.status = QUEST_STATUS_COMPLETED;
- return TRUE;
+ return true;
}
/* Only 1 ambush */
- if (cquest.data[0]) return (FALSE);
+ if (cquest.data[0])
+ {
+ return false;
+ }
if (!p_ptr->wild_mode)
{
- if (p_ptr->wilderness_y > 19) return (FALSE);
+ if (p_ptr->wilderness_y > 19)
+ {
+ return false;
+ }
}
else
{
- if (p_ptr->py > 19) return (FALSE);
+ if (p_ptr->py > 19)
+ {
+ return false;
+ }
}
/* Mark as entered */
@@ -47,15 +76,19 @@ bool_ quest_between_move_hook(char *fmt)
cmsg_print(TERM_YELLOW, "Trone steps forth and speaks: 'The secret of the Void Jumpgates");
cmsg_print(TERM_YELLOW, "will not be used by any but the thunderlords!'");
- return FALSE;
+ return false;
}
-bool_ quest_between_gen_hook(char *fmt)
+
+static bool quest_between_gen_hook(void *, void *, void *)
{
int x, y;
int xstart = 2;
int ystart = 2;
- if (p_ptr->inside_quest != QUEST_BETWEEN) return FALSE;
+ if (p_ptr->inside_quest != QUEST_BETWEEN)
+ {
+ return false;
+ }
/* Start with perm walls */
for (y = 0; y < cur_hgt; y++)
@@ -79,18 +112,18 @@ bool_ quest_between_gen_hook(char *fmt)
/* Otherwise instadeath */
energy_use = 0;
- dungeon_flags2 |= DF2_NO_GENO;
+ dungeon_flags |= DF_NO_GENO;
- return TRUE;
+ return true;
}
-bool_ quest_between_finish_hook(char *fmt)
+
+static bool quest_between_finish_hook(void *, void *in_, void *)
{
- s32b q_idx;
+ struct hook_quest_finish_in *in = static_cast<struct hook_quest_finish_in *>(in_);
+ s32b q_idx = in->q_idx;
object_type forge, *q_ptr;
- q_idx = get_next_arg(fmt);
-
- if (q_idx != QUEST_BETWEEN) return FALSE;
+ if (q_idx != QUEST_BETWEEN) return false;
c_put_str(TERM_YELLOW, "Ah you finally arrived, I hope your travel wasn't too hard.", 8, 0);
c_put_str(TERM_YELLOW, "As a reward you can freely use the Void Jumpgates for quick travel.", 9, 0);
@@ -111,21 +144,25 @@ bool_ quest_between_finish_hook(char *fmt)
object_known(q_ptr);
q_ptr->discount = 100;
q_ptr->ident |= IDENT_STOREB;
- (void)inven_carry(q_ptr, FALSE);
+ inven_carry(q_ptr, FALSE);
/* Continue the plot */
*(quest[q_idx].plot) = QUEST_NULL;
- del_hook(HOOK_QUEST_FINISH, quest_between_finish_hook);
+ del_hook_new(HOOK_QUEST_FINISH, quest_between_finish_hook);
process_hooks_restart = TRUE;
- return TRUE;
+ return true;
}
-bool_ quest_between_death_hook(char *fmt)
+
+static bool quest_between_death_hook(void *, void *, void *)
{
int i, mcnt = 0;
- if (p_ptr->inside_quest != QUEST_BETWEEN) return FALSE;
+ if (p_ptr->inside_quest != QUEST_BETWEEN)
+ {
+ return false;
+ }
for (i = m_max - 1; i >= 1; i--)
{
@@ -144,45 +181,50 @@ bool_ quest_between_death_hook(char *fmt)
cave_set_feat(p_ptr->py, p_ptr->px, FEAT_LESS);
cave[p_ptr->py][p_ptr->px].special = 0;
- return FALSE;
+ return false;
}
- return FALSE;
+ return false;
}
-bool_ quest_between_dump_hook(char *fmt)
+
+static bool quest_between_dump_hook(void *, void *in_, void *)
{
+ struct hook_chardump_in *in = static_cast<struct hook_chardump_in *>(in_);
+ FILE *f = in->file;
+
if (cquest.status >= QUEST_STATUS_COMPLETED)
{
- fprintf(hook_file, "\n You established a permanent void jumpgates liaison between Minas Anor and Gondolin,");
- fprintf(hook_file, "\n thus allowing the last alliance to exist.");
+ fprintf(f, "\n You established a permanent void jumpgates liaison between Minas Anor and Gondolin,");
+ fprintf(f, "\n thus allowing the last alliance to exist.");
}
- return (FALSE);
+ return false;
}
-bool_ quest_between_forbid_hook(char *fmt)
+
+static bool quest_between_forbid_hook(void *, void *in_, void *)
{
- s32b q_idx;
- q_idx = get_next_arg(fmt);
+ hook_init_quest_in *in = static_cast<struct hook_init_quest_in *>(in_);
+ s32b q_idx = in->q_idx;
if (q_idx != QUEST_BETWEEN) return (FALSE);
if (p_ptr->lev < 45)
{
c_put_str(TERM_WHITE, "I fear you are not ready for the next quest, come back later.", 8, 0);
- return (TRUE);
+ return true;
}
- return (FALSE);
+ return false;
}
-bool_ quest_between_init_hook(int q)
+
+void quest_between_init_hook()
{
if ((cquest.status >= QUEST_STATUS_TAKEN) && (cquest.status < QUEST_STATUS_FINISHED))
{
- add_hook(HOOK_MOVE, quest_between_move_hook, "between_move");
- add_hook(HOOK_GEN_QUEST, quest_between_gen_hook, "between_gen");
- add_hook(HOOK_QUEST_FINISH, quest_between_finish_hook, "between_finish");
- add_hook(HOOK_MONSTER_DEATH, quest_between_death_hook, "between_death");
+ add_hook_new(HOOK_MOVE, quest_between_move_hook, "between_move", NULL);
+ add_hook_new(HOOK_GEN_QUEST, quest_between_gen_hook, "between_gen", NULL);
+ add_hook_new(HOOK_QUEST_FINISH, quest_between_finish_hook, "between_finish", NULL);
+ add_hook_new(HOOK_MONSTER_DEATH, quest_between_death_hook, "between_death", NULL);
}
- add_hook(HOOK_CHAR_DUMP, quest_between_dump_hook, "between_dump");
- add_hook(HOOK_INIT_QUEST, quest_between_forbid_hook, "between_forbid");
- return (FALSE);
+ add_hook_new(HOOK_CHAR_DUMP, quest_between_dump_hook, "between_dump", NULL);
+ add_hook_new(HOOK_INIT_QUEST, quest_between_forbid_hook, "between_forbid", NULL);
}
diff --git a/src/q_betwen.hpp b/src/q_betwen.hpp
new file mode 100644
index 00000000..54042a24
--- /dev/null
+++ b/src/q_betwen.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+void quest_between_init_hook();
diff --git a/src/q_bounty.cc b/src/q_bounty.cc
new file mode 100644
index 00000000..f0a431de
--- /dev/null
+++ b/src/q_bounty.cc
@@ -0,0 +1,180 @@
+#include "q_bounty.hpp"
+
+#include "game.hpp"
+#include "monster2.hpp"
+#include "monster_race.hpp"
+#include "monster_race_flag.hpp"
+#include "monster_spell_flag.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_type.hpp"
+#include "player_type.hpp"
+#include "skill_type.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+
+#include <fmt/format.h>
+
+#define cquest (quest[QUEST_BOUNTY])
+
+#define bounty_quest_monster (cquest.data[0])
+
+static bool_ lua_mon_hook_bounty(int r_idx)
+{
+ auto const &r_info = game->edit_data.r_info;
+
+ auto r_ptr = &r_info[r_idx];
+
+ /* Reject uniques */
+ if (r_ptr->flags & RF_UNIQUE) return (FALSE);
+
+ /* Reject those who cannot leave anything */
+ if (!(r_ptr->flags & RF_DROP_CORPSE)) return (FALSE);
+
+ /* Accept only monsters that can be generated */
+ if (r_ptr->flags & RF_SPECIAL_GENE) return (FALSE);
+ if (r_ptr->flags & RF_NEVER_GENE) return (FALSE);
+
+ /* Reject pets */
+ if (r_ptr->flags & RF_PET) return (FALSE);
+
+ /* Reject friendly creatures */
+ if (r_ptr->flags & RF_FRIENDLY) return (FALSE);
+
+ /* Accept only monsters that are not breeders */
+ if (r_ptr->spells & SF_MULTIPLY) return (FALSE);
+
+ /* Forbid joke monsters */
+ if (r_ptr->flags & RF_JOKEANGBAND) return (FALSE);
+
+ /* Accept only monsters that are not good */
+ if (r_ptr->flags & RF_GOOD) return (FALSE);
+
+ /* The rest are acceptable */
+ return (TRUE);
+}
+
+static int get_new_bounty_monster(int lev)
+{
+ int r_idx;
+
+ /*
+ * Set up the hooks -- no bounties on uniques or monsters
+ * with no corpses
+ */
+ get_mon_num_hook = lua_mon_hook_bounty;
+ get_mon_num_prep();
+
+ /* Set up the quest monster. */
+ r_idx = get_mon_num(lev);
+
+ /* Undo the filters */
+ get_mon_num_hook = NULL;
+ get_mon_num_prep();
+
+ return r_idx;
+}
+
+static bool bounty_item_tester_hook(object_type const *o_ptr)
+{
+ return ((o_ptr->tval == TV_CORPSE) && (o_ptr->pval2 == bounty_quest_monster));
+}
+
+void quest_bounty_init_hook()
+{
+ // Initialized by building action
+}
+
+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 = 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()
+{
+ auto &s_info = game->s_info;
+
+ if (cquest.status != QUEST_STATUS_TAKEN)
+ {
+ msg_print("You do not have any bounty quest yet.");
+ return FALSE;
+ }
+
+ // Get the corpse.
+ int item = -1;
+ bool_ ret =
+ get_item(&item,
+ "What corpse to return?",
+ "You have no corpse to return.",
+ USE_INVEN,
+ bounty_item_tester_hook);
+ 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;
+}
+
+std::string quest_bounty_describe()
+{
+ char mdesc[512];
+ fmt::MemoryWriter w;
+
+ if (cquest.status == QUEST_STATUS_TAKEN)
+ {
+ monster_race_desc(mdesc, bounty_quest_monster, 0);
+
+ w.write("#####yBounty quest!\n");
+ w.write("You must bring back {} corpse to the beastmaster.", mdesc);
+ }
+
+ return w.str();
+}
diff --git a/src/q_bounty.hpp b/src/q_bounty.hpp
new file mode 100644
index 00000000..fe9742ef
--- /dev/null
+++ b/src/q_bounty.hpp
@@ -0,0 +1,10 @@
+#pragma once
+
+#include "h-basic.h"
+
+#include <string>
+
+void quest_bounty_init_hook();
+bool_ quest_bounty_drop_item();
+bool_ quest_bounty_get_item();
+std::string quest_bounty_describe();
diff --git a/src/q_dragons.c b/src/q_dragons.cc
index 025e8ecd..9f89089c 100644
--- a/src/q_dragons.c
+++ b/src/q_dragons.cc
@@ -1,8 +1,28 @@
-#undef cquest
+#include "q_dragons.hpp"
+
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "dungeon_flag.hpp"
+#include "feature_flag.hpp"
+#include "feature_type.hpp"
+#include "game.hpp"
+#include "hook_quest_finish_in.hpp"
+#include "hooks.hpp"
+#include "init1.hpp"
+#include "monster2.hpp"
+#include "monster_type.hpp"
+#include "player_type.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+#include "z-rand.hpp"
+
#define cquest (quest[QUEST_DRAGONS])
-bool_ quest_dragons_gen_hook(char *fmt)
+static bool quest_dragons_gen_hook(void *, void *, void *)
{
+ auto const &f_info = game->edit_data.f_info;
+
int x, y, i;
int xstart = 2;
int ystart = 2;
@@ -32,18 +52,17 @@ bool_ quest_dragons_gen_hook(char *fmt)
init_flags = INIT_CREATE_DUNGEON;
process_dungeon_file("dragons.map", &ystart, &xstart, cur_hgt, cur_wid, TRUE, FALSE);
- dungeon_flags2 |= DF2_NO_GENO;
+ dungeon_flags |= DF_NO_GENO;
/* Place some columns */
for (i = 35; i > 0; )
{
- int flags;
y = rand_int(21) + 3;
x = rand_int(31) + 3;
/* Bar columns on even squares so the whole level is guaranteed to be
accessible */
- flags = f_info[cave[y][x].feat].flags1;
- if (!(flags % 2) && !(flags & FF1_PERMANENT) && (flags & FF1_FLOOR))
+ auto const flags = f_info[cave[y][x].feat].flags;
+ if (!(x % 2) && !(flags & FF_PERMANENT) && (flags & FF_FLOOR))
{
--i;
cave_set_feat(y, x, FEAT_MOUNTAIN);
@@ -53,11 +72,10 @@ bool_ quest_dragons_gen_hook(char *fmt)
/* Place some random dragons */
for (i = 25; i > 0; )
{
- int m_idx, flags;
y = rand_int(21) + 3;
x = rand_int(31) + 3;
- flags = f_info[cave[y][x].feat].flags1;
- if (!(flags & FF1_PERMANENT) && (flags & FF1_FLOOR))
+ auto const flags = f_info[cave[y][x].feat].flags;
+ if (!(flags & FF_PERMANENT) && (flags & FF_FLOOR))
{
/* blue, white, red, black, bronze, gold, green, multi-hued */
int baby_dragons[8] = {163, 164, 167, 166, 218, 219, 165, 204};
@@ -79,7 +97,7 @@ bool_ quest_dragons_gen_hook(char *fmt)
dragon = mature_dragons[color];
--i;
- m_idx = place_monster_one(y, x, dragon, 0, magik(33), MSTATUS_ENEMY);
+ int m_idx = place_monster_one(y, x, dragon, 0, magik(33), MSTATUS_ENEMY);
if (m_idx) m_list[m_idx].mflag |= MFLAG_QUEST;
}
}
@@ -89,7 +107,7 @@ bool_ quest_dragons_gen_hook(char *fmt)
return TRUE;
}
-bool_ quest_dragons_death_hook(char *fmt)
+static bool quest_dragons_death_hook(void *, void *, void *)
{
int i, mcnt = 0;
@@ -102,32 +120,41 @@ bool_ quest_dragons_death_hook(char *fmt)
monster_type *m_ptr = &m_list[i];
/* Ignore "dead" monsters */
- if (!m_ptr->r_idx) continue;
+ if (!m_ptr->r_idx)
+ {
+ continue;
+ }
- if (m_ptr->status <= MSTATUS_ENEMY) mcnt++;
+ if (m_ptr->status <= MSTATUS_ENEMY)
+ {
+ mcnt++;
+ }
}
/* Nobody left ? */
if (mcnt <= 1)
{
quest[p_ptr->inside_quest].status = QUEST_STATUS_COMPLETED;
- del_hook(HOOK_MONSTER_DEATH, quest_dragons_death_hook);
- del_hook(HOOK_GEN_QUEST, quest_dragons_gen_hook);
+ del_hook_new(HOOK_MONSTER_DEATH, quest_dragons_death_hook);
+ del_hook_new(HOOK_GEN_QUEST, quest_dragons_gen_hook);
process_hooks_restart = TRUE;
cmsg_print(TERM_YELLOW, "Gondolin is safer now.");
- return (FALSE);
+ return false;
}
- return FALSE;
+
+ return false;
}
-bool_ quest_dragons_finish_hook(char *fmt)
+static bool quest_dragons_finish_hook(void *, void *in_, void *)
{
- s32b q_idx;
-
- q_idx = get_next_arg(fmt);
+ struct hook_quest_finish_in *in = static_cast<struct hook_quest_finish_in *>(in_);
+ s32b q_idx = in->q_idx;
- if (q_idx != QUEST_DRAGONS) return FALSE;
+ if (q_idx != QUEST_DRAGONS)
+ {
+ return false;
+ }
c_put_str(TERM_YELLOW, "Thank you for killing the dragons!", 8, 0);
c_put_str(TERM_YELLOW, "You can use the cave as your house as a reward.", 9, 0);
@@ -135,16 +162,15 @@ bool_ quest_dragons_finish_hook(char *fmt)
/* Continue the plot */
*(quest[q_idx].plot) = QUEST_EOL;
- return TRUE;
+ return true;
}
-bool_ quest_dragons_init_hook(int q_idx)
+void quest_dragons_init_hook()
{
if ((cquest.status >= QUEST_STATUS_UNTAKEN) && (cquest.status < QUEST_STATUS_FINISHED))
{
- add_hook(HOOK_MONSTER_DEATH, quest_dragons_death_hook, "dragons_monster_death");
- add_hook(HOOK_QUEST_FINISH, quest_dragons_finish_hook, "dragons_finish");
- add_hook(HOOK_GEN_QUEST, quest_dragons_gen_hook, "dragons_geb");
+ add_hook_new(HOOK_MONSTER_DEATH, quest_dragons_death_hook, "dragons_monster_death", NULL);
+ add_hook_new(HOOK_QUEST_FINISH, quest_dragons_finish_hook, "dragons_finish", NULL);
+ add_hook_new(HOOK_GEN_QUEST, quest_dragons_gen_hook, "dragons_geb", NULL);
}
- return (FALSE);
}
diff --git a/src/q_dragons.hpp b/src/q_dragons.hpp
new file mode 100644
index 00000000..cda41321
--- /dev/null
+++ b/src/q_dragons.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+void quest_dragons_init_hook();
diff --git a/src/q_eol.c b/src/q_eol.c
deleted file mode 100644
index 5b1cf78e..00000000
--- a/src/q_eol.c
+++ /dev/null
@@ -1,195 +0,0 @@
-#undef cquest
-#define cquest (quest[QUEST_EOL])
-
-bool_ quest_eol_gen_hook(char *fmt)
-{
- int x, y;
- bool_ done = FALSE;
- int xsize = 50, ysize = 30, y0, x0;
- int m_idx = 0;
-
- if (p_ptr->inside_quest != QUEST_EOL) return FALSE;
-
- x0 = 2 + (xsize / 2);
- y0 = 2 + (ysize / 2);
-
- feat_wall_outer = FEAT_WALL_OUTER;
- feat_wall_inner = FEAT_WALL_INNER;
-
- for (y = 0; y < 100; y++)
- {
- floor_type[y] = FEAT_FLOOR;
- fill_type[y] = FEAT_WALL_OUTER;
- }
-
- /* Start with perm walls */
- for (y = 0; y < cur_hgt; y++)
- {
- for (x = 0; x < cur_wid; x++)
- {
- cave_set_feat(y, x, FEAT_PERM_SOLID);
- }
- }
- dun_level = quest[p_ptr->inside_quest].level;
-
- while (!done)
- {
- int grd, roug, cutoff;
-
- /* testing values for these parameters feel free to adjust*/
- grd = 2 ^ (randint(4));
-
- /* want average of about 16 */
- roug = randint(8) * randint(4);
-
- /* about size/2 */
- cutoff = randint(xsize / 4) + randint(ysize / 4) + randint(xsize / 4) + randint(ysize / 4);
-
- /* make it */
- generate_hmap(y0, x0, xsize, ysize, grd, roug, cutoff);
-
- /* Convert to normal format+ clean up*/
- done = generate_fracave(y0, x0, xsize, ysize, cutoff, FALSE, TRUE);
- }
-
- /* Place a few traps */
- for (x = xsize - 1; x >= 2; x--)
- for (y = ysize - 1; y >= 2; y--)
- {
- if (!cave_clean_bold(y, x)) continue;
-
- /* Place eol at the other end */
- if (!m_idx)
- {
- m_allow_special[test_monster_name("Eol, the Dark Elf")] = TRUE;
- m_idx = place_monster_one(y, x, test_monster_name("Eol, the Dark Elf"), 0, FALSE, MSTATUS_ENEMY);
- m_allow_special[test_monster_name("Eol, the Dark Elf")] = FALSE;
- if (m_idx) m_list[m_idx].mflag |= MFLAG_QUEST;
- }
-
- if (magik(18))
- {
- place_trap(y, x);
- }
-
- /* Place player at one end */
- p_ptr->py = y;
- p_ptr->px = x;
- }
-
- cave_set_feat(p_ptr->py, p_ptr->px, FEAT_LESS);
-
- return TRUE;
-}
-bool_ quest_eol_finish_hook(char *fmt)
-{
- object_type forge, *q_ptr;
- s32b q_idx;
-
- q_idx = get_next_arg(fmt);
-
- if (q_idx != QUEST_EOL) return FALSE;
-
- c_put_str(TERM_YELLOW, "A tragedy, but the deed needed to be done.", 8, 0);
- c_put_str(TERM_YELLOW, "Accept my thanks, and that reward.", 9, 0);
-
- q_ptr = &forge;
- object_prep(q_ptr, lookup_kind(TV_LITE, SV_LITE_DWARVEN));
- q_ptr->found = OBJ_FOUND_REWARD;
- q_ptr->name2 = EGO_LITE_MAGI;
- apply_magic(q_ptr, 1, FALSE, FALSE, FALSE);
- q_ptr->number = 1;
- object_aware(q_ptr);
- object_known(q_ptr);
- q_ptr->ident |= IDENT_STOREB;
- (void)inven_carry(q_ptr, FALSE);
-
- /* Continue the plot */
- *(quest[q_idx].plot) = QUEST_NIRNAETH;
- quest[*(quest[q_idx].plot)].init(*(quest[q_idx].plot));
-
- del_hook(HOOK_QUEST_FINISH, quest_eol_finish_hook);
- process_hooks_restart = TRUE;
-
- return TRUE;
-}
-bool_ quest_eol_fail_hook(char *fmt)
-{
- s32b q_idx;
-
- q_idx = get_next_arg(fmt);
-
- if (q_idx != QUEST_EOL) return FALSE;
-
- c_put_str(TERM_YELLOW, "You fled ! I did not think you would flee...", 8, 0);
-
- /* Continue the plot */
- *(quest[q_idx].plot) = QUEST_NULL;
-
- del_hook(HOOK_QUEST_FAIL, quest_eol_fail_hook);
- process_hooks_restart = TRUE;
-
- return TRUE;
-}
-bool_ quest_eol_death_hook(char *fmt)
-{
- s32b r_idx, m_idx;
-
- m_idx = get_next_arg(fmt);
- r_idx = m_list[m_idx].r_idx;
-
- if (p_ptr->inside_quest != QUEST_EOL) return FALSE;
-
- if (r_idx == test_monster_name("Eol, the Dark Elf"))
- {
- cmsg_print(TERM_YELLOW, "Such a sad end...");
- cquest.status = QUEST_STATUS_COMPLETED;
- del_hook(HOOK_MONSTER_DEATH, quest_eol_death_hook);
- process_hooks_restart = TRUE;
- return (FALSE);
- }
-
- return FALSE;
-}
-bool_ quest_eol_stair_hook(char *fmt)
-{
- monster_race *r_ptr = &r_info[test_monster_name("Eol, the Dark Elf")];
- cptr down;
-
- down = get_next_arg_str(fmt);
-
- if (p_ptr->inside_quest != QUEST_EOL) return FALSE;
-
- if (cave[p_ptr->py][p_ptr->px].feat != FEAT_LESS) return TRUE;
-
- if (r_ptr->max_num)
- {
- if (!strcmp(down, "up"))
- {
- /* Flush input */
- flush();
-
- if (!get_check("Really abandon the quest?")) return TRUE;
-
- cmsg_print(TERM_YELLOW, "You flee away from Eol...");
- cquest.status = QUEST_STATUS_FAILED;
- del_hook(HOOK_STAIR, quest_eol_stair_hook);
- process_hooks_restart = TRUE;
- return (FALSE);
- }
- }
-
- return FALSE;
-}
-bool_ quest_eol_init_hook(int q)
-{
- if ((cquest.status >= QUEST_STATUS_TAKEN) && (cquest.status < QUEST_STATUS_FINISHED))
- {
- add_hook(HOOK_MONSTER_DEATH, quest_eol_death_hook, "eol_death");
- add_hook(HOOK_GEN_QUEST, quest_eol_gen_hook, "eol_gen");
- add_hook(HOOK_STAIR, quest_eol_stair_hook, "eol_stair");
- add_hook(HOOK_QUEST_FAIL, quest_eol_fail_hook, "eol_fail");
- add_hook(HOOK_QUEST_FINISH, quest_eol_finish_hook, "eol_finish");
- }
- return (FALSE);
-}
diff --git a/src/q_eol.cc b/src/q_eol.cc
new file mode 100644
index 00000000..815b3107
--- /dev/null
+++ b/src/q_eol.cc
@@ -0,0 +1,243 @@
+#include "q_eol.hpp"
+
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "game.hpp"
+#include "generate.hpp"
+#include "hook_stair_in.hpp"
+#include "hook_quest_finish_in.hpp"
+#include "hook_quest_fail_in.hpp"
+#include "hook_monster_death_in.hpp"
+#include "hooks.hpp"
+#include "monster2.hpp"
+#include "monster_race.hpp"
+#include "monster_type.hpp"
+#include "object2.hpp"
+#include "player_type.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+#include "z-rand.hpp"
+
+#include <cassert>
+
+#define cquest (quest[QUEST_EOL])
+
+GENERATE_MONSTER_LOOKUP_FN(get_eol, "Eol, the Dark Elf")
+
+static bool quest_eol_gen_hook(void *, void *, void *)
+{
+ int x, y;
+ bool_ done = FALSE;
+ int xsize = 50, ysize = 30, y0, x0;
+ int m_idx = 0;
+
+ if (p_ptr->inside_quest != QUEST_EOL)
+ {
+ return false;
+ }
+
+ x0 = 2 + (xsize / 2);
+ y0 = 2 + (ysize / 2);
+
+ feat_wall_outer = FEAT_WALL_OUTER;
+ feat_wall_inner = FEAT_WALL_INNER;
+
+ for (y = 0; y < 100; y++)
+ {
+ floor_type[y] = FEAT_FLOOR;
+ fill_type[y] = FEAT_WALL_OUTER;
+ }
+
+ /* Start with perm walls */
+ for (y = 0; y < cur_hgt; y++)
+ {
+ for (x = 0; x < cur_wid; x++)
+ {
+ cave_set_feat(y, x, FEAT_PERM_SOLID);
+ }
+ }
+ dun_level = quest[p_ptr->inside_quest].level;
+
+ while (!done)
+ {
+ int grd, roug, cutoff;
+
+ /* testing values for these parameters feel free to adjust*/
+ grd = 2 ^ (randint(4));
+
+ /* want average of about 16 */
+ roug = randint(8) * randint(4);
+
+ /* about size/2 */
+ cutoff = randint(xsize / 4) + randint(ysize / 4) + randint(xsize / 4) + randint(ysize / 4);
+
+ /* make it */
+ generate_hmap(y0, x0, xsize, ysize, grd, roug, cutoff);
+
+ /* Convert to normal format+ clean up*/
+ done = generate_fracave(y0, x0, xsize, ysize, cutoff, FALSE, TRUE);
+ }
+
+ /* Place a few traps */
+ for (x = xsize - 1; x >= 2; x--)
+ for (y = ysize - 1; y >= 2; y--)
+ {
+ if (!cave_clean_bold(y, x)) continue;
+
+ /* Place eol at the other end */
+ if (!m_idx)
+ {
+ // Find Eol's r_info entry
+ int r_idx = get_eol();
+ // "Summon" Eol
+ m_allow_special[r_idx] = TRUE;
+ m_idx = place_monster_one(y, x, r_idx, 0, FALSE, MSTATUS_ENEMY);
+ m_allow_special[r_idx] = FALSE;
+ // Mark with the QUEST flag
+ if (m_idx) m_list[m_idx].mflag |= MFLAG_QUEST;
+ }
+
+ /* Place player at one end */
+ p_ptr->py = y;
+ p_ptr->px = x;
+ }
+
+ cave_set_feat(p_ptr->py, p_ptr->px, FEAT_LESS);
+
+ return true;
+}
+
+static bool quest_eol_finish_hook(void *, void *in_, void *)
+{
+ struct hook_quest_finish_in *in = static_cast<struct hook_quest_finish_in *>(in_);
+ s32b q_idx = in->q_idx;
+ object_type forge, *q_ptr;
+
+ if (q_idx != QUEST_EOL)
+ {
+ return false;
+ }
+
+ c_put_str(TERM_YELLOW, "A tragedy, but the deed needed to be done.", 8, 0);
+ c_put_str(TERM_YELLOW, "Accept my thanks, and that reward.", 9, 0);
+
+ q_ptr = &forge;
+ object_prep(q_ptr, lookup_kind(TV_LITE, SV_LITE_DWARVEN));
+ q_ptr->found = OBJ_FOUND_REWARD;
+ q_ptr->name2 = EGO_LITE_MAGI;
+ apply_magic(q_ptr, 1, FALSE, FALSE, FALSE);
+ q_ptr->number = 1;
+ object_aware(q_ptr);
+ object_known(q_ptr);
+ q_ptr->ident |= IDENT_STOREB;
+ inven_carry(q_ptr, FALSE);
+
+ /* Continue the plot */
+ *(quest[q_idx].plot) = QUEST_NIRNAETH;
+ quest[*(quest[q_idx].plot)].init();
+
+ del_hook_new(HOOK_QUEST_FINISH, quest_eol_finish_hook);
+ process_hooks_restart = TRUE;
+
+ return true;
+}
+
+static bool quest_eol_fail_hook(void *, void *in_, void *)
+{
+ struct hook_quest_fail_in *in = static_cast<struct hook_quest_fail_in *>(in_);
+ s32b q_idx = in->q_idx;
+
+ if (q_idx != QUEST_EOL)
+ {
+ return false;
+ }
+
+ c_put_str(TERM_YELLOW, "You fled ! I did not think you would flee...", 8, 0);
+
+ /* Continue the plot */
+ *(quest[q_idx].plot) = QUEST_NULL;
+
+ del_hook_new(HOOK_QUEST_FAIL, quest_eol_fail_hook);
+ process_hooks_restart = TRUE;
+
+ return true;
+}
+
+static bool quest_eol_death_hook(void *, void *in_, void *)
+{
+ struct hook_monster_death_in *in = static_cast<struct hook_monster_death_in *>(in_);
+ s32b m_idx = in->m_idx;
+ s32b r_idx = m_list[m_idx].r_idx;
+
+ if (p_ptr->inside_quest != QUEST_EOL)
+ {
+ return false;
+ }
+
+ if (r_idx == get_eol())
+ {
+ cmsg_print(TERM_YELLOW, "Such a sad end...");
+ cquest.status = QUEST_STATUS_COMPLETED;
+
+ del_hook_new(HOOK_MONSTER_DEATH, quest_eol_death_hook);
+ process_hooks_restart = TRUE;
+
+ return false;
+ }
+
+ return false;
+}
+
+static bool quest_eol_stair_hook(void *, void *in_, void *)
+{
+ auto const &r_info = game->edit_data.r_info;
+
+ struct hook_stair_in *in = static_cast<struct hook_stair_in *>(in_);
+ auto r_ptr = &r_info[get_eol()];
+
+ if (p_ptr->inside_quest != QUEST_EOL)
+ {
+ return false;
+ }
+
+ if (cave[p_ptr->py][p_ptr->px].feat != FEAT_LESS)
+ {
+ return true;
+ }
+
+ if (r_ptr->max_num)
+ {
+ if (in->direction == STAIRS_UP)
+ {
+ /* Flush input */
+ flush();
+
+ if (!get_check("Really abandon the quest?"))
+ {
+ return true;
+ }
+
+ cmsg_print(TERM_YELLOW, "You flee away from Eol...");
+ cquest.status = QUEST_STATUS_FAILED;
+
+ del_hook_new(HOOK_STAIR, quest_eol_stair_hook);
+ process_hooks_restart = TRUE;
+ return false;
+ }
+ }
+
+ return false;
+}
+
+void quest_eol_init_hook()
+{
+ if ((cquest.status >= QUEST_STATUS_TAKEN) && (cquest.status < QUEST_STATUS_FINISHED))
+ {
+ add_hook_new(HOOK_MONSTER_DEATH, quest_eol_death_hook, "eol_death", NULL);
+ add_hook_new(HOOK_GEN_QUEST, quest_eol_gen_hook, "eol_gen", NULL);
+ add_hook_new(HOOK_STAIR, quest_eol_stair_hook, "eol_stair", NULL);
+ add_hook_new(HOOK_QUEST_FAIL, quest_eol_fail_hook, "eol_fail", NULL);
+ add_hook_new(HOOK_QUEST_FINISH, quest_eol_finish_hook, "eol_finish", NULL);
+ }
+}
diff --git a/src/q_eol.hpp b/src/q_eol.hpp
new file mode 100644
index 00000000..19af3583
--- /dev/null
+++ b/src/q_eol.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+void quest_eol_init_hook();
diff --git a/src/q_evil.c b/src/q_evil.cc
index a143f65c..4636356a 100644
--- a/src/q_evil.c
+++ b/src/q_evil.cc
@@ -1,17 +1,42 @@
-#undef cquest
+#include "q_evil.hpp"
+
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "dungeon_flag.hpp"
+#include "feature_flag.hpp"
+#include "feature_type.hpp"
+#include "game.hpp"
+#include "hook_quest_finish_in.hpp"
+#include "hooks.hpp"
+#include "init1.hpp"
+#include "monster2.hpp"
+#include "monster_type.hpp"
+#include "player_type.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+#include "z-rand.hpp"
+
#define cquest (quest[QUEST_EVIL])
-bool_ quest_evil_gen_hook(char *fmt)
+static bool quest_evil_gen_hook(void *, void *, void *)
{
+ auto const &f_info = game->edit_data.f_info;
+
int x, y, i;
int xstart = 2;
int ystart = 2;
- if (p_ptr->inside_quest != QUEST_EVIL) return FALSE;
+ if (p_ptr->inside_quest != QUEST_EVIL)
+ {
+ return false;
+ }
/* Just in case we didnt talk the the mayor */
if (cquest.status == QUEST_STATUS_UNTAKEN)
+ {
cquest.status = QUEST_STATUS_TAKEN;
+ }
/* Start with perm walls */
for (y = 0; y < cur_hgt; y++)
@@ -32,18 +57,17 @@ bool_ quest_evil_gen_hook(char *fmt)
init_flags = INIT_CREATE_DUNGEON;
process_dungeon_file("evil.map", &ystart, &xstart, cur_hgt, cur_wid, TRUE, FALSE);
- dungeon_flags2 |= DF2_NO_GENO;
+ dungeon_flags |= DF_NO_GENO;
/* Place some random balrogs */
for (i = 6; i > 0; )
{
- int m_idx, flags;
y = rand_int(21) + 3;
x = rand_int(31) + 3;
- flags = f_info[cave[y][x].feat].flags1;
- if (!(flags & FF1_PERMANENT) && (flags & FF1_FLOOR))
+ auto const flags = f_info[cave[y][x].feat].flags;
+ if (!(flags & FF_PERMANENT) && (flags & FF_FLOOR))
{
- m_idx = place_monster_one(y, x, 996, 0, FALSE, MSTATUS_ENEMY);
+ int m_idx = place_monster_one(y, x, 996, 0, FALSE, MSTATUS_ENEMY);
if (m_idx) m_list[m_idx].mflag |= MFLAG_QUEST;
--i;
}
@@ -51,14 +75,17 @@ bool_ quest_evil_gen_hook(char *fmt)
process_hooks_restart = TRUE;
- return TRUE;
+ return true;
}
-bool_ quest_evil_death_hook(char *fmt)
+static bool quest_evil_death_hook(void *, void *, void *)
{
int i, mcnt = 0;
- if (p_ptr->inside_quest != QUEST_EVIL) return FALSE;
+ if (p_ptr->inside_quest != QUEST_EVIL)
+ {
+ return false;
+ }
/* Process the monsters (backwards) */
for (i = m_max - 1; i >= 1; i--)
@@ -78,23 +105,26 @@ bool_ quest_evil_death_hook(char *fmt)
/* TODO: change to COMPLETED and remove NULL when mayor is added */
quest[p_ptr->inside_quest].status = QUEST_STATUS_FINISHED;
*(quest[p_ptr->inside_quest].plot) = QUEST_NULL;
- del_hook(HOOK_MONSTER_DEATH, quest_evil_death_hook);
- del_hook(HOOK_GEN_QUEST, quest_evil_gen_hook);
+
+ del_hook_new(HOOK_MONSTER_DEATH, quest_evil_death_hook);
+ del_hook_new(HOOK_GEN_QUEST, quest_evil_gen_hook);
process_hooks_restart = TRUE;
cmsg_print(TERM_YELLOW, "Khazad-Dum is safer now.");
- return (FALSE);
+ return false;
}
- return FALSE;
+ return false;
}
-bool_ quest_evil_finish_hook(char *fmt)
+static bool quest_evil_finish_hook(void *, void *in_, void *)
{
- s32b q_idx;
+ struct hook_quest_finish_in *in = static_cast<struct hook_quest_finish_in *>(in_);
+ s32b q_idx = in->q_idx;
- q_idx = get_next_arg(fmt);
-
- if (q_idx != QUEST_EVIL) return FALSE;
+ if (q_idx != QUEST_EVIL)
+ {
+ return false;
+ }
c_put_str(TERM_YELLOW, "Thank you for saving us!", 8, 0);
c_put_str(TERM_YELLOW, "You can use the cave as your house as a reward.", 9, 0);
@@ -102,16 +132,15 @@ bool_ quest_evil_finish_hook(char *fmt)
/* End the plot */
*(quest[q_idx].plot) = QUEST_NULL;
- return TRUE;
+ return true;
}
-bool_ quest_evil_init_hook(int q_idx)
+void quest_evil_init_hook()
{
if ((cquest.status >= QUEST_STATUS_UNTAKEN) && (cquest.status < QUEST_STATUS_FINISHED))
{
- add_hook(HOOK_MONSTER_DEATH, quest_evil_death_hook, "evil_monster_death");
- add_hook(HOOK_QUEST_FINISH, quest_evil_finish_hook, "evil_finish");
- add_hook(HOOK_GEN_QUEST, quest_evil_gen_hook, "evil_geb");
+ add_hook_new(HOOK_MONSTER_DEATH, quest_evil_death_hook, "evil_monster_death", NULL);
+ add_hook_new(HOOK_QUEST_FINISH, quest_evil_finish_hook, "evil_finish", NULL);
+ add_hook_new(HOOK_GEN_QUEST, quest_evil_gen_hook, "evil_geb", NULL);
}
- return (FALSE);
}
diff --git a/src/q_evil.hpp b/src/q_evil.hpp
new file mode 100644
index 00000000..0079e56c
--- /dev/null
+++ b/src/q_evil.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+void quest_evil_init_hook();
diff --git a/src/q_fireprof.cc b/src/q_fireprof.cc
new file mode 100644
index 00000000..26bf75af
--- /dev/null
+++ b/src/q_fireprof.cc
@@ -0,0 +1,514 @@
+#include "q_fireprof.hpp"
+
+#include "cave_type.hpp"
+#include "dungeon_flag.hpp"
+#include "feature_flag.hpp"
+#include "feature_type.hpp"
+#include "hook_get_in.hpp"
+#include "hooks.hpp"
+#include "lua_bind.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_flag.hpp"
+#include "object_type.hpp"
+#include "player_type.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+#include "z-rand.hpp"
+
+#include <cassert>
+#include <fmt/format.h>
+
+#define cquest (quest[QUEST_FIREPROOF])
+
+/*
+ * Per-module "settings"
+ */
+typedef struct fireproof_settings fireproof_settings;
+struct fireproof_settings
+{
+ byte tval; /* tval of object to use. */
+ byte sval; /* sval of object to use. */
+ cptr tval_name; /* descriptive name of tval */
+ cptr tval_name_plural; /* descriptive name of tval (plural) */
+ s32b total_points; /* total number of points awarded */
+};
+
+static fireproof_settings const *fireproof_get_settings()
+{
+ static fireproof_settings fireproof_settings =
+ { TV_SCROLL, SV_SCROLL_FIRE, "scroll", "scrolls", 24 };
+ return &fireproof_settings;
+}
+
+/* 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 bool item_tester_hook_eligible(object_type const *o_ptr)
+{
+ fireproof_settings const *settings = fireproof_get_settings();
+ /* check it's the 'marked' item */
+ return ((o_ptr->tval == settings->tval) &&
+ (o_ptr->sval == settings->sval) &&
+ (o_ptr->pval2 == settings->sval));
+}
+
+static object_filter_t const &item_tester_hook_proofable()
+{
+ using namespace object_filter;
+ static auto instance = And(
+ // Must be the correct item base type
+ Or(
+ TVal(TV_BOOK),
+ TVal(TV_SCROLL),
+ TVal(TV_STAFF)),
+ // Must NOT already be fireproof
+ Not(
+ HasFlags(TR_IGNORE_FIRE)));
+ return instance;
+}
+
+/*
+ * 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 */
+ switch (o_ptr->tval)
+ {
+ case TV_BOOK:
+ item_value = FIREPROOF_BOOK_POINTS * (*stack);
+ break;
+ case TV_STAFF:
+ item_value = FIREPROOF_STAFF_POINTS * (*stack);
+ break;
+ case TV_SCROLL:
+ item_value = FIREPROOF_SCROLL_POINTS * (*stack);
+ break;
+ default:
+ assert(FALSE);
+ }
+
+ /* 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 item;
+ if (!get_item(&item,
+ "Which item shall I fireproof?",
+ "You have no more items I can fireproof, come back when you have some.",
+ USE_INVEN,
+ item_tester_hook_proofable()))
+ {
+ return FALSE;
+ }
+
+ /* get the object type from the number */
+ object_type *obj2 = get_object(item);
+
+ /* check we have enough points (if we 'got' an item) */
+ int stack = 0;
+ if (!fireproof_enough_points(obj2, &stack))
+ {
+ return FALSE;
+ }
+
+ /* Do the actual fireproofing */
+ {
+ 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 */
+ ret = get_item(&item_idx, p, pni, USE_INVEN, item_tester_hook_eligible);
+
+ /* 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(void *, void *in_, void *)
+{
+ struct hook_get_in *in = static_cast<struct hook_get_in *>(in_);
+ object_type *o_ptr = in->o_ptr;
+
+ /* 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_settings()->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(void *, void *, void *)
+{
+ /* 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;
+ }
+ }
+}
+
+std::string quest_fireproof_describe()
+{
+ 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;
+
+ fmt::MemoryWriter w;
+
+ if (status == QUEST_STATUS_TAKEN)
+ {
+ /* Quest taken */
+ w.write("#####yAn Old Mages Quest!\n");
+ w.write("Retrieve the strange {} for the old mage in Lothlorien.", settings->tval_name);
+ }
+ else if (status == QUEST_STATUS_COMPLETED)
+ {
+ /* essence retrieved, not taken to mage */
+ w.write("#####yAn Old Mages Quest!\n");
+ w.write("You have retrieved the {} for the old mage in Lothlorien.\n", settings->tval_name);
+ w.write("Perhaps you should see about a reward.");
+ }
+ else if ((status == QUEST_STATUS_FINISHED) &&
+ (get_item_points_remaining() > 0))
+ {
+ /* essence returned, not all books fireproofed */
+ w.write("#####yAn Old Mages Quest!\n");
+ w.write("You have retrieved the {} for the old "
+ "mage in Lothlorien. He will still\n", settings->tval_name);
+ w.write("fireproof {} book(s) or {} staff/staves "
+ "or {} scroll(s) for you.",
+ num_books, num_staff, num_scroll);
+ }
+
+ return w.str();
+}
+
+static bool fireproof_gen_hook(void *, void *, void *)
+{
+ fireproof_settings const *settings = fireproof_get_settings();
+
+ /* Only if player doing this quest */
+ if (p_ptr->inside_quest != QUEST_FIREPROOF)
+ {
+ return false;
+ }
+
+ /* Go ahead */
+ {
+ /* load the map */
+ {
+ int x0 = 2;
+ int y0 = 2;
+ load_map("fireprof.map", &y0, &x0);
+ }
+
+ /* no teleport */
+ dungeon_flags = DF_NO_TELEPORT;
+
+ /* create quest item */
+ {
+ object_type forge;
+ object_prep(&forge, lookup_kind(settings->tval, settings->sval));
+
+ /* mark item */
+ forge.pval2 = settings->sval;
+ forge.inscription = "quest";
+
+ /* roll for co-ordinates in top half of map */
+ int const y = randint(3) + 2;
+ int const x = randint(45) + 2;
+
+ /* drop it */
+ drop_near(&forge, -1, y, x);
+ }
+
+ return true;
+ }
+}
+
+void quest_fireproof_init_hook()
+{
+ /* Only need hooks if the quest is unfinished. */
+ if ((cquest.status >= QUEST_STATUS_UNTAKEN) &&
+ (cquest.status < QUEST_STATUS_FINISHED))
+ {
+ add_hook_new(HOOK_GEN_QUEST, fireproof_gen_hook , "fireproof_gen_hook", NULL);
+ add_hook_new(HOOK_GET , fireproof_get_hook , "fireproof_get_hook", NULL);
+ add_hook_new(HOOK_STAIR , fireproof_stair_hook, "fireproof_stair_hook", NULL);
+ }
+}
diff --git a/src/q_fireprof.hpp b/src/q_fireprof.hpp
new file mode 100644
index 00000000..361d45ad
--- /dev/null
+++ b/src/q_fireprof.hpp
@@ -0,0 +1,9 @@
+#pragma once
+
+#include "h-basic.h"
+
+#include <string>
+
+void quest_fireproof_building(bool_ *paid, bool_ *recreate);
+void quest_fireproof_init_hook();
+std::string quest_fireproof_describe();
diff --git a/src/q_god.cc b/src/q_god.cc
new file mode 100644
index 00000000..68296f36
--- /dev/null
+++ b/src/q_god.cc
@@ -0,0 +1,1234 @@
+#include "q_god.hpp"
+
+#include "cave_type.hpp"
+#include "dungeon_flag.hpp"
+#include "dungeon_info_type.hpp"
+#include "feature_flag.hpp"
+#include "feature_type.hpp"
+#include "game.hpp"
+#include "hook_chardump_in.hpp"
+#include "hook_get_in.hpp"
+#include "hook_enter_dungeon_in.hpp"
+#include "hook_player_level_in.hpp"
+#include "hooks.hpp"
+#include "monster_race_flag.hpp"
+#include "monster_spell_flag.hpp"
+#include "object2.hpp"
+#include "player_type.hpp"
+#include "skill_type.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+#include "wilderness_map.hpp"
+#include "wilderness_type_info.hpp"
+#include "z-rand.hpp"
+
+#include <assert.h>
+#include <fmt/format.h>
+
+#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
+ * 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.
+ */
+static std::string compass(int y, int x, int y2, int x2)
+{
+ // 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)) {
+ return ""; // Handled specially by caller
+ }
+ // Maybe it is (almost) due N/S
+ else if (!x_axis) {
+ return y_axis;
+ }
+ // Maybe it is (almost) due E/W
+ else if (!y_axis) {
+ return x_axis;
+ }
+ // or if it is neither
+ else {
+ return fmt::format("{}-{}", y_axis, x_axis);
+ }
+}
+
+/* Returns a relative approximation of the 'distance' of y2, x2 from y, x. */
+static std::string 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";
+ }
+}
+
+static int MAX_NUM_GOD_QUESTS()
+{
+ if (game_module_idx == MODULE_TOME)
+ {
+ return 5;
+ }
+ if (game_module_idx == MODULE_THEME)
+ {
+ return 7;
+ }
+ /* Uh, oh. */
+ assert(FALSE);
+ return 0;
+}
+
+static byte get_relic_num()
+{
+ 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];
+ return sval;
+ }
+ }
+
+ /* Uh, oh. */
+ assert(FALSE);
+}
+
+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)
+ {
+ *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 */
+ }
+}
+
+static std::string make_directions(bool feel_it)
+{
+ int home1_y, home1_x;
+ int home2_y, home2_x;
+ const char *home1 = NULL;
+ const char *home2 = NULL;
+ cptr feel_it_str = feel_it ? ", I can feel it.'" : ".";
+
+ get_home_coordinates(
+ &home1_y, &home1_x, &home1,
+ &home2_y, &home2_x, &home2);
+
+ auto home1_axis = compass(home1_y, home1_x, cquest_dung_y, cquest_dung_x);
+ auto home2_axis = compass(home2_y, home2_x, cquest_dung_y, cquest_dung_x);
+
+ /* Build the message */
+ if (home1_axis.empty())
+ {
+ return fmt::format("The temple lies very close to {}, ",
+ home1);
+ }
+ else
+ {
+ auto home1_distance = approximate_distance(home1_y, home1_x, cquest_dung_y, cquest_dung_x);
+ return fmt::format("The temple lies {} to the {} of {}, ",
+ home1_distance,
+ home1_axis,
+ home1);
+ }
+
+ if (home2_axis.empty())
+ {
+ return fmt::format("and very close to {}{}",
+ home2,
+ feel_it_str);
+ }
+ else
+ {
+ auto home2_distance = approximate_distance(home2_y, home2_x, cquest_dung_y, cquest_dung_x);
+ return fmt::format("and {} to the {} of {}{}",
+ home2_distance,
+ home2_axis,
+ home2,
+ feel_it_str);
+ }
+}
+
+std::string quest_god_describe()
+{
+ fmt::MemoryWriter w;
+
+ if (cquest.status == QUEST_STATUS_TAKEN)
+ {
+ auto directions = make_directions(false);
+ w.write("#####yGod quest {}!\n", cquest_quests_given);
+ w.write("Thou art to find the lost temple of thy God and\n");
+ w.write("to retrieve the lost part of the relic for thy God!\n");
+ w.write("{}", directions.c_str());
+ }
+
+ return w.str();
+}
+
+static void quest_god_place_rand_dung()
+{
+ auto &wilderness = game->wilderness;
+ auto const &wf_info = game->edit_data.wf_info;
+
+ int x = -1, y = -1, tries;
+
+ /* erase old dungeon */
+ if (cquest_quests_given > 0)
+ {
+ wilderness(cquest_dung_x, cquest_dung_y).entrance = 0;
+
+ /* erase old recall level */
+ max_dlv[DUNGEON_GOD] = 0;
+ }
+
+ /* initialise tries variable */
+ tries = 1000;
+ while (tries > 0)
+ {
+ 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, wilderness.width()-2);
+ y = rand_range(1, wilderness.height()-2);
+
+ /* Is there a town/dungeon/potentially impassable feature there, ? */
+ wilderness_map const *w_ptr = &wilderness(x, y);
+ wilderness_type_info const *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 */
+ wilderness(x, y).entrance = 1000 + DUNGEON_GOD;
+
+ /* set quest variables */
+ cquest_dung_x = x;
+ cquest_dung_y = y;
+}
+
+static void quest_god_generate_relic()
+{
+ auto const &f_info = game->edit_data.f_info;
+
+ 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].flags & FF_FLOOR) &&
+ (!(f_info[c_ptr->feat].flags & FF_PERMANENT)))
+ {
+ break;
+ }
+ }
+
+ /* create relic */
+ object_prep(&relic, lookup_kind(TV_JUNK, get_relic_num()));
+
+ /* inscribe it to prevent automatizer 'accidents' */
+ relic.inscription = "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! */
+ cquest_relic_generated = TRUE;
+
+ /* Reset some variables */
+ cquest_relic_gen_tries = 0;
+}
+
+static void quest_god_set_god_dungeon_attributes_eru()
+{
+ auto &d_info = game->edit_data.d_info;
+
+ /* 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].flags =
+ DF_BIG |
+ DF_NO_DOORS |
+ DF_CIRCULAR_ROOMS |
+ DF_EMPTY |
+ DF_TOWER |
+ DF_FLAT |
+ DF_ADJUST_LEVEL_2 |
+ DF_ADJUST_LEVEL_1_2 |
+ DF_NO_SHAFT |
+ DF_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].mflags = RF_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].mflags = RF_CAN_FLY;
+}
+
+static void quest_god_set_god_dungeon_attributes_manwe()
+{
+ auto &d_info = game->edit_data.d_info;
+
+ /* 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].flags =
+ DF_NO_DOORS |
+ DF_TOWER |
+ DF_CAVERN |
+ DF_ADJUST_LEVEL_2 |
+ DF_NO_SHAFT |
+ DF_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].mflags = RF_INVISIBLE;
+ d_info[DUNGEON_GOD].rules[1].mflags = RF_ORC | RF_IM_POIS;
+ d_info[DUNGEON_GOD].rules[2].mspells = SF_BR_POIS | SF_BR_GRAV;
+ d_info[DUNGEON_GOD].rules[3].mspells = SF_BA_POIS;
+ d_info[DUNGEON_GOD].rules[4].mflags = RF_CAN_FLY;
+}
+
+static void quest_god_set_god_dungeon_attributes_tulkas()
+{
+ auto &d_info = game->edit_data.d_info;
+
+ /* 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].flags =
+ DF_NO_DESTROY |
+ DF_ADJUST_LEVEL_2 |
+ DF_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].mflags = RF_DEMON | RF_EVIL;
+}
+
+static void quest_god_set_god_dungeon_attributes_melkor()
+{
+ auto &d_info = game->edit_data.d_info;
+
+ /* 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].flags =
+ DF_SMALL |
+ DF_LAVA_RIVERS |
+ DF_ADJUST_LEVEL_1 |
+ DF_ADJUST_LEVEL_1_2 |
+ DF_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].mflags = RF_GOOD;
+}
+
+static void quest_god_set_god_dungeon_attributes_yavanna()
+{
+ auto &d_info = game->edit_data.d_info;
+
+ /* 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].flags =
+ DF_NO_DOORS |
+ DF_WATER_RIVERS |
+ DF_NO_DESTROY |
+ DF_ADJUST_LEVEL_1 |
+ DF_NO_RECALL |
+ DF_ADJUST_LEVEL_1_2 |
+ DF_NO_SHAFT |
+ DF_NO_GENO |
+ DF_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].mflags =
+ RF_DEMON | RF_UNDEAD | RF_NONLIVING;
+}
+
+static void quest_god_set_god_dungeon_attributes_aule()
+{
+ auto &d_info = game->edit_data.d_info;
+
+ 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].flags =
+ DF_SMALL |
+ DF_NO_DESTROY |
+ DF_ADJUST_LEVEL_1 |
+ DF_NO_STREAMERS;
+
+ /* R: No restrictions on monsters here */
+ d_info[DUNGEON_GOD].rules[0].mode = 0;
+ d_info[DUNGEON_GOD].rules[0].percent = 80;
+}
+
+static void quest_god_set_god_dungeon_attributes_varda()
+{
+ auto &d_info = game->edit_data.d_info;
+
+ /* 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].flags =
+ DF_NO_DOORS |
+ DF_TOWER |
+ DF_CAVERN |
+ DF_ADJUST_LEVEL_1 |
+ DF_NO_SHAFT |
+ DF_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].mflags = RF_INVISIBLE;
+ d_info[DUNGEON_GOD].rules[1].mflags = RF_ORC | RF_IM_POIS;
+ d_info[DUNGEON_GOD].rules[2].mspells = SF_BR_POIS | SF_BR_GRAV;
+ d_info[DUNGEON_GOD].rules[3].mspells = SF_BA_POIS;
+ d_info[DUNGEON_GOD].rules[4].mflags = RF_CAN_FLY;
+}
+
+static void quest_god_set_god_dungeon_attributes_ulmo()
+{
+ auto &d_info = game->edit_data.d_info;
+
+ /* 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].flags =
+ DF_NO_DESTROY |
+ DF_ADJUST_LEVEL_2 |
+ DF_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].mflags = RF_CAN_FLY;
+ d_info[DUNGEON_GOD].rules[1].mflags = RF_AQUATIC;
+ d_info[DUNGEON_GOD].rules[2].mflags = RF_RES_WATE;
+}
+
+static void quest_god_set_god_dungeon_attributes_mandos()
+{
+ auto &d_info = game->edit_data.d_info;
+
+ /* 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].flags =
+ DF_NO_DESTROY |
+ DF_ADJUST_LEVEL_2 |
+ DF_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].mflags = RF_UNDEAD | RF_EVIL;
+}
+
+static bool quest_god_level_end_gen_hook(void *, void *, void *)
+{
+ /* Check for dungeon */
+ if ((dungeon_type != DUNGEON_GOD) ||
+ (cquest.status == QUEST_STATUS_UNTAKEN))
+ {
+ return false;
+ }
+
+ /* 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 ((cquest_relic_generated == TRUE) &&
+ (cquest.status != QUEST_STATUS_FAILED))
+ {
+ /* fail the quest, don't give another one, don't give
+ * this message again */
+ 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);
+
+ 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 ((cquest_relic_gen_tries == 4) &&
+ (cquest_relic_generated == FALSE))
+ {
+ quest_god_generate_relic();
+ }
+
+ else
+ {
+ /* 1/5 chance of generation */
+ if (magik(20))
+ {
+ quest_god_generate_relic();
+ }
+ else
+ {
+ cquest_relic_gen_tries = cquest_relic_gen_tries + 1;
+ }
+ }
+
+ return false;
+}
+
+static bool quest_god_player_level_hook(void *, void *in_, void *)
+{
+ struct hook_player_level_in *in = static_cast<struct hook_player_level_in *>(in_);
+ s32b gained = in->gained_levels;
+
+ if (gained <= 0)
+ {
+ return false;
+ }
+
+ /* check player is worshipping a god, not already on a god quest. */
+ if ((p_ptr->astral) ||
+ (p_ptr->pgod <= 0) ||
+ (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 <= cquest_dun_minplev))
+ {
+ /* Don't let a player get quests with trickery */
+ if (p_ptr->lev > cquest_dun_minplev)
+ {
+ cquest_dun_minplev = p_ptr->lev;
+ }
+ return false;
+ }
+ else
+ {
+ /* This var will need resetting */
+ 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();
+
+ /* God issues instructions */
+ auto directions = make_directions(true);
+
+ 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!");
+ cmsg_print(TERM_YELLOW, directions.c_str());
+
+ /* 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! */
+ cquest_dun_mindepth = p_ptr->lev*2/3;
+ cquest_dun_maxdepth = cquest_dun_mindepth + 4;
+ }
+
+ return false;
+}
+
+static bool quest_god_get_hook(void *, void *in_, void *)
+{
+ auto &s_info = game->s_info;
+
+ hook_get_in *in = static_cast<hook_get_in *>(in_);
+
+ s32b item = -in->o_idx; /* Note the negation */
+
+ object_type *o_ptr = get_object(item);
+
+ /* -- Is it the relic, and check to make sure the relic hasn't already been identified */
+ if ((cquest.status == QUEST_STATUS_TAKEN) &&
+ (o_ptr->tval == TV_JUNK) &&
+ (o_ptr->sval == get_relic_num()) &&
+ (o_ptr->pval != TRUE) &&
+ (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 (cquest_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;
+ cquest_relics_found = cquest_relics_found + 1;
+
+ /* Make sure quests can be given again if neccesary */
+ cquest.status = QUEST_STATUS_UNTAKEN;
+
+ /* Prevent further processing of 'take' action; we've
+ destroyed the item. */
+ return true;
+ }
+
+ return false;
+}
+
+static bool quest_god_char_dump_hook(void *, void *in_, void *)
+{
+ struct hook_chardump_in *in = static_cast<struct hook_chardump_in *>(in_);
+ FILE *f = in->file;
+
+ if (cquest_quests_given > 0)
+ {
+ int relics = cquest_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 (cquest.status == QUEST_STATUS_FAILED)
+ {
+ append_text = " and failed in your quest";
+ }
+ }
+
+ fprintf(f, "\n You found %s of the relic pieces%s.", relics_text, append_text);
+ }
+
+ return false;
+}
+
+static void set_god_dungeon_attributes()
+{
+ auto &d_info = game->edit_data.d_info;
+
+ /* 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 == GOD_AULE)
+ {
+ quest_god_set_god_dungeon_attributes_aule();
+ }
+ else if (p_ptr->pgod == GOD_VARDA)
+ {
+ quest_god_set_god_dungeon_attributes_varda();
+ }
+ else if (p_ptr->pgod == GOD_ULMO)
+ {
+ quest_god_set_god_dungeon_attributes_ulmo();
+ }
+ else if (p_ptr->pgod == 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 */
+ {
+ auto d_ptr = &d_info[DUNGEON_GOD];
+ d_ptr->mindepth = cquest_dun_mindepth;
+ d_ptr->maxdepth = cquest_dun_maxdepth;
+ d_ptr->min_plev = cquest_dun_minplev;
+ }
+}
+
+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 */
+ if (d_idx != DUNGEON_GOD)
+ {
+ return;
+ }
+
+ set_god_dungeon_attributes();
+}
+
+static bool quest_god_enter_dungeon_hook(void *, void *in_, void *)
+{
+ struct hook_enter_dungeon_in *in = static_cast<struct hook_enter_dungeon_in *>(in_);
+ quest_god_dungeon_setup(in->d_idx);
+ return false;
+}
+
+static bool quest_god_gen_level_begin_hook(void *, void *, void *)
+{
+ quest_god_dungeon_setup(dungeon_type);
+ return false;
+}
+
+static bool quest_god_stair_hook(void *, void *, void *)
+{
+ quest_god_dungeon_setup(dungeon_type);
+ return false;
+}
+
+static bool quest_god_birth_objects_hook(void *, void *, void *)
+{
+ 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;
+}
+
+void quest_god_init_hook()
+{
+ /* Only need hooks if the quest is unfinished. */
+ if ((cquest.status >= QUEST_STATUS_UNTAKEN) &&
+ (cquest.status < QUEST_STATUS_FINISHED))
+ {
+ add_hook_new(HOOK_LEVEL_END_GEN, quest_god_level_end_gen_hook, "q_god_level_end_gen", NULL);
+ add_hook_new(HOOK_ENTER_DUNGEON, quest_god_enter_dungeon_hook, "q_god_enter_dungeon", NULL);
+ add_hook_new(HOOK_GEN_LEVEL_BEGIN, quest_god_gen_level_begin_hook, "q_god_gen_level_begin", NULL);
+ add_hook_new(HOOK_STAIR, quest_god_stair_hook, "q_god_hook_stair", NULL);
+ add_hook_new(HOOK_GET, quest_god_get_hook, "q_god_get", NULL);
+ add_hook_new(HOOK_CHAR_DUMP, quest_god_char_dump_hook, "q_god_char_dump", NULL);
+ add_hook_new(HOOK_PLAYER_LEVEL, quest_god_player_level_hook, "q_god_player_level", NULL);
+ }
+
+ /* Need this to re-initialize at birth; the quest data is
+ * zeroed which isn't quite right. */
+ add_hook_new(HOOK_BIRTH_OBJECTS, quest_god_birth_objects_hook, "q_god_birth_objects", NULL);
+}
diff --git a/src/q_god.hpp b/src/q_god.hpp
new file mode 100644
index 00000000..839d4eaa
--- /dev/null
+++ b/src/q_god.hpp
@@ -0,0 +1,8 @@
+#pragma once
+
+#include "h-basic.h"
+
+#include <string>
+
+std::string quest_god_describe();
+void quest_god_init_hook();
diff --git a/src/q_haunted.c b/src/q_haunted.cc
index db8992bc..f460ee80 100644
--- a/src/q_haunted.c
+++ b/src/q_haunted.cc
@@ -1,13 +1,36 @@
-#undef cquest
+#include "q_haunted.hpp"
+
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "dungeon_flag.hpp"
+#include "feature_flag.hpp"
+#include "feature_type.hpp"
+#include "game.hpp"
+#include "hook_quest_finish_in.hpp"
+#include "hooks.hpp"
+#include "init1.hpp"
+#include "monster2.hpp"
+#include "monster_type.hpp"
+#include "player_type.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+#include "z-rand.hpp"
+
#define cquest (quest[QUEST_HAUNTED])
-bool_ quest_haunted_gen_hook(char *fmt)
+static bool quest_haunted_gen_hook(void *, void *, void *)
{
+ auto const &f_info = game->edit_data.f_info;
+
int x, y, i, m_idx;
int xstart = 2;
int ystart = 2;
- if (p_ptr->inside_quest != QUEST_HAUNTED) return FALSE;
+ if (p_ptr->inside_quest != QUEST_HAUNTED)
+ {
+ return false;
+ }
/* Just in case we didnt talk the the mayor */
if (cquest.status == QUEST_STATUS_UNTAKEN)
@@ -32,16 +55,15 @@ bool_ quest_haunted_gen_hook(char *fmt)
init_flags = INIT_CREATE_DUNGEON;
process_dungeon_file("haunted.map", &ystart, &xstart, cur_hgt, cur_wid, TRUE, FALSE);
- dungeon_flags2 |= DF2_NO_GENO;
+ dungeon_flags |= DF_NO_GENO;
/* Place some ghosts */
for (i = 12; i > 0; )
{
- int flags;
y = rand_int(21) + 3;
x = rand_int(31) + 3;
- flags = f_info[cave[y][x].feat].flags1;
- if (!(flags & FF1_PERMANENT) && (flags & FF1_FLOOR))
+ auto const flags = f_info[cave[y][x].feat].flags;
+ if (!(flags & FF_PERMANENT) && (flags & FF_FLOOR))
{
m_idx = place_monster_one(y, x, 477, 0, FALSE, MSTATUS_ENEMY);
if (m_idx) m_list[m_idx].mflag |= MFLAG_QUEST;
@@ -52,11 +74,10 @@ bool_ quest_haunted_gen_hook(char *fmt)
/* Place some random monsters to haunt us */
for (i = damroll(4, 4); i > 0; )
{
- int flags;
y = rand_int(21) + 3;
x = rand_int(31) + 3;
- flags = f_info[cave[y][x].feat].flags1;
- if (!(flags & FF1_PERMANENT) && (flags & FF1_FLOOR))
+ auto const flags = f_info[cave[y][x].feat].flags;
+ if (!(flags & FF_PERMANENT) && (flags & FF_FLOOR))
{
int monsters[22] = { 65, 100, 124, 125, 133, 231, 273, 327, 365, 416, 418,
507, 508, 533, 534, 553, 554, 555, 577, 607, 622, 665};
@@ -67,30 +88,19 @@ bool_ quest_haunted_gen_hook(char *fmt)
}
}
- /* Place some random traps */
- for (i = 10 + damroll(4, 4); i > 0; )
- {
- int flags;
- y = rand_int(21) + 3;
- x = rand_int(31) + 3;
- flags = f_info[cave[y][x].feat].flags1;
- if (!(flags & FF1_PERMANENT) && (flags & FF1_FLOOR))
- {
- --i;
- place_trap(y, x);
- }
- }
-
process_hooks_restart = TRUE;
- return TRUE;
+ return true;
}
-bool_ quest_haunted_death_hook(char *fmt)
+static bool quest_haunted_death_hook(void *, void *, void *)
{
int i, mcnt = 0;
- if (p_ptr->inside_quest != QUEST_HAUNTED) return FALSE;
+ if (p_ptr->inside_quest != QUEST_HAUNTED)
+ {
+ return false;
+ }
/* Process the monsters (backwards) */
for (i = m_max - 1; i >= 1; i--)
@@ -99,32 +109,42 @@ bool_ quest_haunted_death_hook(char *fmt)
monster_type *m_ptr = &m_list[i];
/* Ignore "dead" monsters */
- if (!m_ptr->r_idx) continue;
+ if (!m_ptr->r_idx)
+ {
+ continue;
+ }
- if (m_ptr->status <= MSTATUS_ENEMY) mcnt++;
+ if (m_ptr->status <= MSTATUS_ENEMY)
+ {
+ mcnt++;
+ }
}
/* Nobody left ? */
if (mcnt <= 1)
{
quest[p_ptr->inside_quest].status = QUEST_STATUS_COMPLETED;
- del_hook(HOOK_MONSTER_DEATH, quest_haunted_death_hook);
- del_hook(HOOK_GEN_QUEST, quest_haunted_gen_hook);
+
+ del_hook_new(HOOK_MONSTER_DEATH, quest_haunted_death_hook);
+ del_hook_new(HOOK_GEN_QUEST, quest_haunted_gen_hook);
process_hooks_restart = TRUE;
cmsg_print(TERM_YELLOW, "Minas Anor is safer now.");
- return (FALSE);
+ return false;
}
- return FALSE;
+
+ return false;
}
-bool_ quest_haunted_finish_hook(char *fmt)
+static bool quest_haunted_finish_hook(void *, void *in_, void *)
{
- s32b q_idx;
-
- q_idx = get_next_arg(fmt);
+ struct hook_quest_finish_in *in = static_cast<struct hook_quest_finish_in *>(in_);
+ s32b q_idx = in->q_idx;
- if (q_idx != QUEST_HAUNTED) return FALSE;
+ if (q_idx != QUEST_HAUNTED)
+ {
+ return false;
+ }
c_put_str(TERM_YELLOW, "Thank you for saving us!", 8, 0);
c_put_str(TERM_YELLOW, "You can use the building as your house as a reward.", 9, 0);
@@ -132,16 +152,15 @@ bool_ quest_haunted_finish_hook(char *fmt)
/* Continue the plot */
*(quest[q_idx].plot) = QUEST_BETWEEN;
- return TRUE;
+ return true;
}
-bool_ quest_haunted_init_hook(int q_idx)
+void quest_haunted_init_hook()
{
if ((cquest.status >= QUEST_STATUS_UNTAKEN) && (cquest.status < QUEST_STATUS_FINISHED))
{
- add_hook(HOOK_MONSTER_DEATH, quest_haunted_death_hook, "haunted_monster_death");
- add_hook(HOOK_QUEST_FINISH, quest_haunted_finish_hook, "haunted_finish");
- add_hook(HOOK_GEN_QUEST, quest_haunted_gen_hook, "haunted_geb");
+ add_hook_new(HOOK_MONSTER_DEATH, quest_haunted_death_hook, "haunted_monster_death", NULL);
+ add_hook_new(HOOK_QUEST_FINISH, quest_haunted_finish_hook, "haunted_finish", NULL);
+ add_hook_new(HOOK_GEN_QUEST, quest_haunted_gen_hook, "haunted_geb", NULL);
}
- return (FALSE);
}
diff --git a/src/q_haunted.hpp b/src/q_haunted.hpp
new file mode 100644
index 00000000..3965f0c3
--- /dev/null
+++ b/src/q_haunted.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+void quest_haunted_init_hook();
diff --git a/src/q_hobbit.c b/src/q_hobbit.c
deleted file mode 100644
index f3b7d856..00000000
--- a/src/q_hobbit.c
+++ /dev/null
@@ -1,195 +0,0 @@
-#undef cquest
-#define cquest (quest[QUEST_HOBBIT])
-
-bool_ quest_hobbit_town_gen_hook(char *fmt)
-{
- int x = 1, y = 1, tries = 10000;
- s32b small;
-
- small = get_next_arg(fmt);
-
- if ((turn < (cquest.data[1] + (DAY * 10L))) || (cquest.status > QUEST_STATUS_COMPLETED) || (small) || (p_ptr->town_num != 1)) return (FALSE);
-
- /* Find a good position */
- while (tries)
- {
- /* Get a random spot */
- y = randint(20) + (cur_hgt / 2) - 10;
- x = randint(20) + (cur_wid / 2) - 10;
-
- /* Is it a good spot ? */
- /* Not in player los, and avoid shop grids */
- if (!los(p_ptr->py, p_ptr->px, y, x) && cave_empty_bold(y, x) &&
- cave_plain_floor_bold(y, x)) break;
-
- /* One less try */
- tries--;
- }
-
- /* Place Melinda */
- m_allow_special[test_monster_name("Melinda Proudfoot")] = TRUE;
- place_monster_one(y, x, test_monster_name("Melinda Proudfoot"), 0, FALSE, MSTATUS_ENEMY);
- m_allow_special[test_monster_name("Melinda Proudfoot")] = FALSE;
-
- return FALSE;
-}
-bool_ quest_hobbit_gen_hook(char *fmt)
-{
- int x = 1, y = 1, tries = 10000;
-
- if ((cquest.status != QUEST_STATUS_TAKEN) || (dun_level != cquest.data[0]) || (dungeon_type != DUNGEON_MAZE)) return FALSE;
-
- /* Find a good position */
- while (tries)
- {
- /* Get a random spot */
- y = randint(cur_hgt - 4) + 2;
- x = randint(cur_wid - 4) + 2;
-
- /* Is it a good spot ? */
- if (cave_empty_bold(y, x)) break;
-
- /* One less try */
- tries--;
- }
-
- /* Place the hobbit */
- m_allow_special[test_monster_name("Merton Proudfoot, the lost hobbit")] = TRUE;
- place_monster_one(y, x, test_monster_name("Merton Proudfoot, the lost hobbit"), 0, FALSE, MSTATUS_FRIEND);
- m_allow_special[test_monster_name("Merton Proudfoot, the lost hobbit")] = FALSE;
-
- return FALSE;
-}
-bool_ quest_hobbit_give_hook(char *fmt)
-{
- object_type *o_ptr;
- monster_type *m_ptr;
- s32b m_idx, item;
-
- m_idx = get_next_arg(fmt);
- item = get_next_arg(fmt);
-
- o_ptr = &p_ptr->inventory[item];
- m_ptr = &m_list[m_idx];
-
- if (m_ptr->r_idx != test_monster_name("Merton Proudfoot, the lost hobbit")) return (FALSE);
-
- if ((o_ptr->tval != TV_SCROLL) || (o_ptr->sval != SV_SCROLL_WORD_OF_RECALL)) return (FALSE);
-
- msg_print("'Oh, thank you, noble one!'");
- msg_print("Merton Proudfoot reads the scroll and is recalled to the safety of his home.");
-
- delete_monster_idx(m_idx);
-
- inc_stack_size_ex(item, -1, OPTIMIZE, NO_DESCRIBE);
-
- cquest.status = QUEST_STATUS_COMPLETED;
-
- del_hook(HOOK_GIVE, quest_hobbit_give_hook);
- process_hooks_restart = TRUE;
-
- return TRUE;
-}
-bool_ quest_hobbit_speak_hook(char *fmt)
-{
- s32b m_idx = get_next_arg(fmt);
-
- if (m_list[m_idx].r_idx != test_monster_name("Melinda Proudfoot")) return (FALSE);
-
- if (cquest.status < QUEST_STATUS_COMPLETED)
- {
- cptr m_name;
-
- m_name = get_next_arg_str(fmt);
-
- msg_format("%^s begs for your help.", m_name);
- }
- return (TRUE);
-}
-bool_ quest_hobbit_chat_hook(char *fmt)
-{
- monster_type *m_ptr;
- s32b m_idx;
-
- m_idx = get_next_arg(fmt);
-
- m_ptr = &m_list[m_idx];
-
- if (m_ptr->r_idx != test_monster_name("Melinda Proudfoot")) return (FALSE);
-
- if (cquest.status < QUEST_STATUS_COMPLETED)
- {
- msg_print("Oh! Oh!");
- msg_print("My poor Merton, where is my poor Merton? He was playing near that dreadful");
- msg_print("maze and never been seen again! Could you find him for me?");
-
- cquest.status = QUEST_STATUS_TAKEN;
- quest[QUEST_HOBBIT].init(QUEST_HOBBIT);
- }
- else if (cquest.status == QUEST_STATUS_COMPLETED)
- {
- object_type forge, *q_ptr;
-
- msg_print("My Merton is back! You saved him, hero.");
- msg_print("Take this as a proof of my gratitude. It was given to my family");
- msg_print("by a famed wizard, but it should serve you better than me.");
-
- q_ptr = &forge;
- object_prep(q_ptr, lookup_kind(TV_ROD, SV_ROD_RECALL));
- q_ptr->number = 1;
- q_ptr->found = OBJ_FOUND_REWARD;
- object_aware(q_ptr);
- object_known(q_ptr);
- q_ptr->ident |= IDENT_STOREB;
- (void)inven_carry(q_ptr, FALSE);
-
- cquest.status = QUEST_STATUS_FINISHED;
-
- del_hook(HOOK_MON_SPEAK, quest_hobbit_speak_hook);
- process_hooks_restart = TRUE;
- delete_monster_idx(m_idx);
-
- return TRUE;
- }
- else
- {
- msg_print("Thanks again.");
- }
-
- return TRUE;
-}
-bool_ quest_hobbit_dump_hook(char *fmt)
-{
- if (cquest.status >= QUEST_STATUS_COMPLETED)
- {
- fprintf(hook_file, "\n You saved a young hobbit from an horrible fate.");
- }
- return (FALSE);
-}
-bool_ quest_hobbit_init_hook(int q_idx)
-{
- /* Get a level to place the hobbit */
- if (!cquest.data[0])
- {
- 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 ((cquest.status >= QUEST_STATUS_TAKEN) && (cquest.status < QUEST_STATUS_FINISHED))
- {
- add_hook(HOOK_GIVE, quest_hobbit_give_hook, "hobbit_give");
- add_hook(HOOK_GEN_LEVEL, quest_hobbit_gen_hook, "hobbit_gen");
- add_hook(HOOK_WILD_GEN, quest_hobbit_town_gen_hook, "hobbit_town_gen");
- add_hook(HOOK_CHAT, quest_hobbit_chat_hook, "hobbit_chat");
- add_hook(HOOK_MON_SPEAK, quest_hobbit_speak_hook, "hobbit_speak");
- }
- if (cquest.status == QUEST_STATUS_UNTAKEN)
- {
- add_hook(HOOK_MON_SPEAK, quest_hobbit_speak_hook, "hobbit_speak");
- add_hook(HOOK_WILD_GEN, quest_hobbit_town_gen_hook, "hobbit_town_gen");
- add_hook(HOOK_CHAT, quest_hobbit_chat_hook, "hobbit_chat");
- }
- add_hook(HOOK_CHAR_DUMP, quest_hobbit_dump_hook, "hobbit_dump");
- return (FALSE);
-}
diff --git a/src/q_hobbit.cc b/src/q_hobbit.cc
new file mode 100644
index 00000000..655755a3
--- /dev/null
+++ b/src/q_hobbit.cc
@@ -0,0 +1,241 @@
+#include "q_hobbit.hpp"
+
+#include "cave.hpp"
+#include "game.hpp"
+#include "hook_chardump_in.hpp"
+#include "hook_chat_in.hpp"
+#include "hook_give_in.hpp"
+#include "hook_mon_speak_in.hpp"
+#include "hook_wild_gen_in.hpp"
+#include "hooks.hpp"
+#include "messages.hpp"
+#include "monster2.hpp"
+#include "monster_type.hpp"
+#include "object2.hpp"
+#include "object_type.hpp"
+#include "player_type.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+#include "z-rand.hpp"
+
+#include <cassert>
+
+#define cquest (quest[QUEST_HOBBIT])
+
+GENERATE_MONSTER_LOOKUP_FN(get_melinda_proudfoot, "Melinda Proudfoot")
+GENERATE_MONSTER_LOOKUP_FN(get_merton_proudfoot, "Merton Proudfoot, the lost hobbit")
+
+static bool quest_hobbit_town_gen_hook(void *, void *in_, void *)
+{
+ struct hook_wild_gen_in *in = static_cast<struct hook_wild_gen_in *>(in_);
+ int x = 1, y = 1, tries = 10000;
+ bool_ small = in->small;
+
+ if ((turn < (cquest.data[1] + (DAY * 10L))) || (cquest.status > QUEST_STATUS_COMPLETED) || (small) || (p_ptr->town_num != 1))
+ {
+ return false;
+ }
+
+ /* Find a good position */
+ while (tries)
+ {
+ /* Get a random spot */
+ y = randint(20) + (cur_hgt / 2) - 10;
+ x = randint(20) + (cur_wid / 2) - 10;
+
+ /* Is it a good spot ? */
+ /* Not in player los, and avoid shop grids */
+ if (!los(p_ptr->py, p_ptr->px, y, x) && cave_empty_bold(y, x) &&
+ cave_plain_floor_bold(y, x)) break;
+
+ /* One less try */
+ tries--;
+ }
+
+ /* Place Melinda */
+ int r_idx = get_melinda_proudfoot();
+ m_allow_special[r_idx] = TRUE;
+ place_monster_one(y, x, r_idx, 0, FALSE, MSTATUS_ENEMY);
+ m_allow_special[r_idx] = FALSE;
+
+ return false;
+}
+
+static bool quest_hobbit_gen_hook(void *, void *, void *)
+{
+ int x = 1, y = 1, tries = 10000;
+
+ if ((cquest.status != QUEST_STATUS_TAKEN) || (dun_level != cquest.data[0]) || (dungeon_type != DUNGEON_MAZE))
+ {
+ return false;
+ }
+
+ /* Find a good position */
+ while (tries)
+ {
+ /* Get a random spot */
+ y = randint(cur_hgt - 4) + 2;
+ x = randint(cur_wid - 4) + 2;
+
+ /* Is it a good spot ? */
+ if (cave_empty_bold(y, x)) break;
+
+ /* One less try */
+ tries--;
+ }
+
+ /* Place the hobbit */
+ int r_idx = get_merton_proudfoot();
+ m_allow_special[r_idx] = TRUE;
+ place_monster_one(y, x, r_idx, 0, FALSE, MSTATUS_FRIEND);
+ m_allow_special[r_idx] = FALSE;
+
+ return false;
+}
+
+static bool quest_hobbit_give_hook(void *, void *in_, void *)
+{
+ struct hook_give_in *in = static_cast<struct hook_give_in *>(in_);
+ object_type *o_ptr;
+ monster_type *m_ptr;
+ s32b m_idx = in->m_idx;
+ s32b item = in->item;
+
+ o_ptr = &p_ptr->inventory[item];
+ m_ptr = &m_list[m_idx];
+
+ if (m_ptr->r_idx != get_merton_proudfoot()) return false;
+
+ if ((o_ptr->tval != TV_SCROLL) || (o_ptr->sval != SV_SCROLL_WORD_OF_RECALL)) return false;
+
+ msg_print("'Oh, thank you, noble one!'");
+ msg_print("Merton Proudfoot reads the scroll and is recalled to the safety of his home.");
+
+ delete_monster_idx(m_idx);
+
+ inc_stack_size_ex(item, -1, OPTIMIZE, NO_DESCRIBE);
+
+ cquest.status = QUEST_STATUS_COMPLETED;
+
+ del_hook_new(HOOK_GIVE, quest_hobbit_give_hook);
+ process_hooks_restart = TRUE;
+
+ return true;
+}
+
+static bool quest_hobbit_speak_hook(void *, void *in_, void *)
+{
+ struct hook_mon_speak_in *in = static_cast<struct hook_mon_speak_in *>(in_);
+ s32b m_idx = in->m_idx;
+
+ if (m_list[m_idx].r_idx != get_melinda_proudfoot())
+ {
+ return false;
+ }
+
+ if (cquest.status < QUEST_STATUS_COMPLETED)
+ {
+ msg_format("%^s begs for your help.", in->m_name);
+ }
+ return true;
+}
+
+static bool quest_hobbit_chat_hook(void *, void *in_, void *)
+{
+ struct hook_chat_in *in = static_cast<struct hook_chat_in *>(in_);
+ s32b m_idx = in->m_idx;
+ monster_type *m_ptr;
+
+ m_ptr = &m_list[m_idx];
+
+ if (m_ptr->r_idx != get_melinda_proudfoot())
+ {
+ return false;
+ }
+
+ if (cquest.status < QUEST_STATUS_COMPLETED)
+ {
+ msg_print("Oh! Oh!");
+ msg_print("My poor Merton, where is my poor Merton? He was playing near that dreadful");
+ msg_print("maze and never been seen again! Could you find him for me?");
+
+ cquest.status = QUEST_STATUS_TAKEN;
+ quest[QUEST_HOBBIT].init();
+ }
+ else if (cquest.status == QUEST_STATUS_COMPLETED)
+ {
+ object_type forge, *q_ptr;
+
+ msg_print("My Merton is back! You saved him, hero.");
+ msg_print("Take this as a proof of my gratitude. It was given to my family");
+ msg_print("by a famed wizard, but it should serve you better than me.");
+
+ q_ptr = &forge;
+ object_prep(q_ptr, lookup_kind(TV_ROD, SV_ROD_RECALL));
+ q_ptr->number = 1;
+ q_ptr->found = OBJ_FOUND_REWARD;
+ object_aware(q_ptr);
+ object_known(q_ptr);
+ q_ptr->ident |= IDENT_STOREB;
+ inven_carry(q_ptr, FALSE);
+
+ cquest.status = QUEST_STATUS_FINISHED;
+
+ del_hook_new(HOOK_MON_SPEAK, quest_hobbit_speak_hook);
+ process_hooks_restart = TRUE;
+ delete_monster_idx(m_idx);
+
+ return true;
+ }
+ else
+ {
+ msg_print("Thanks again.");
+ }
+
+ return true;
+}
+
+static bool quest_hobbit_dump_hook(void *, void *in_, void *)
+{
+ struct hook_chardump_in *in = static_cast<struct hook_chardump_in *>(in_);
+ FILE *f = in->file;
+
+ if (cquest.status >= QUEST_STATUS_COMPLETED)
+ {
+ fprintf(f, "\n You saved a young hobbit from an horrible fate.");
+ }
+ return false;
+}
+
+void quest_hobbit_init_hook()
+{
+ auto &messages = game->messages;
+
+ /* Get a level to place the hobbit */
+ if (!cquest.data[0])
+ {
+ cquest.data[0] = rand_range(26, 34);
+ cquest.data[1] = turn;
+ if (wizard)
+ {
+ messages.add(format("Hobbit level %d", cquest.data[0]), TERM_BLUE);
+ }
+ }
+
+ if ((cquest.status >= QUEST_STATUS_TAKEN) && (cquest.status < QUEST_STATUS_FINISHED))
+ {
+ add_hook_new(HOOK_GIVE, quest_hobbit_give_hook, "hobbit_give", NULL);
+ add_hook_new(HOOK_GEN_LEVEL, quest_hobbit_gen_hook, "hobbit_gen", NULL);
+ add_hook_new(HOOK_WILD_GEN, quest_hobbit_town_gen_hook, "hobbit_town_gen", NULL);
+ add_hook_new(HOOK_CHAT, quest_hobbit_chat_hook, "hobbit_chat", NULL);
+ add_hook_new(HOOK_MON_SPEAK, quest_hobbit_speak_hook, "hobbit_speak", NULL);
+ }
+ if (cquest.status == QUEST_STATUS_UNTAKEN)
+ {
+ add_hook_new(HOOK_MON_SPEAK, quest_hobbit_speak_hook, "hobbit_speak", NULL);
+ add_hook_new(HOOK_WILD_GEN, quest_hobbit_town_gen_hook, "hobbit_town_gen", NULL);
+ add_hook_new(HOOK_CHAT, quest_hobbit_chat_hook, "hobbit_chat", NULL);
+ }
+ add_hook_new(HOOK_CHAR_DUMP, quest_hobbit_dump_hook, "hobbit_dump", NULL);
+}
diff --git a/src/q_hobbit.hpp b/src/q_hobbit.hpp
new file mode 100644
index 00000000..c3482fd9
--- /dev/null
+++ b/src/q_hobbit.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+void quest_hobbit_init_hook();
diff --git a/src/q_invas.c b/src/q_invas.cc
index 59c71d62..60ca0b65 100644
--- a/src/q_invas.c
+++ b/src/q_invas.cc
@@ -1,13 +1,34 @@
-#undef cquest
+#include "q_invas.hpp"
+
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "hook_chardump_in.hpp"
+#include "hook_monster_death_in.hpp"
+#include "hook_monster_ai_in.hpp"
+#include "hook_monster_ai_out.hpp"
+#include "hook_stair_in.hpp"
+#include "hooks.hpp"
+#include "init1.hpp"
+#include "monster2.hpp"
+#include "monster_type.hpp"
+#include "player_type.hpp"
+#include "tables.hpp"
+#include "town_type.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+
#define cquest (quest[QUEST_INVASION])
-bool_ quest_invasion_gen_hook(char *fmt)
+static bool quest_invasion_gen_hook(void *, void *, void *)
{
int x, y;
int xstart = 2;
int ystart = 2;
- if (p_ptr->inside_quest != QUEST_INVASION) return FALSE;
+ if (p_ptr->inside_quest != QUEST_INVASION)
+ {
+ return false;
+ }
/* Start with perm walls */
for (y = 0; y < cur_hgt; y++)
@@ -29,6 +50,7 @@ bool_ quest_invasion_gen_hook(char *fmt)
process_dungeon_file("maeglin.map", &ystart, &xstart, cur_hgt, cur_wid, TRUE, TRUE);
for (x = 3; x < xstart; x++)
+ {
for (y = 3; y < ystart; y++)
{
if (cave[y][x].feat == FEAT_MARKER)
@@ -40,18 +62,22 @@ bool_ quest_invasion_gen_hook(char *fmt)
cave_set_feat(p_ptr->py, p_ptr->px, FEAT_LESS);
}
}
+ }
- return TRUE;
+ return true;
}
-bool_ quest_invasion_ai_hook(char *fmt)
-{
- monster_type *m_ptr;
- s32b m_idx;
- m_idx = get_next_arg(fmt);
- m_ptr = &m_list[m_idx];
+static bool quest_invasion_ai_hook(void *, void *in_, void *out_)
+{
+ struct hook_monster_ai_in *in = static_cast<struct hook_monster_ai_in *>(in_);
+ struct hook_monster_ai_out *out = static_cast<struct hook_monster_ai_out *>(out_);
+ monster_type *m_ptr = in->m_ptr;
+ s32b m_idx = in->m_idx;
- if (p_ptr->inside_quest != QUEST_INVASION) return FALSE;
+ if (p_ptr->inside_quest != QUEST_INVASION)
+ {
+ return false;
+ }
/* Ugly but thats better than a call to test_monster_name which is SLOW */
if (m_ptr->r_idx == 825)
@@ -64,28 +90,27 @@ bool_ quest_invasion_ai_hook(char *fmt)
cmsg_print(TERM_YELLOW, "Maeglin found the way to Gondolin! All hope is lost now!");
cquest.status = QUEST_STATUS_FAILED;
town_info[2].destroyed = TRUE;
- return (FALSE);
+ return false;
}
/* Attack or flee ?*/
if (distance(m_ptr->fy, m_ptr->fx, p_ptr->py, p_ptr->px) <= 2)
{
- return (FALSE);
+ return false;
}
else
{
- process_hooks_return[0].num = cquest.data[0];
- process_hooks_return[1].num = cquest.data[1];
- return (TRUE);
+ out->y = cquest.data[0];
+ out->x = cquest.data[1];
+ return true;
}
}
- return (FALSE);
+ return false;
}
-bool_ quest_invasion_turn_hook(char *fmt)
-{
- bool_ old_quick_messages = quick_messages;
+static bool quest_invasion_turn_hook(void *, void *, void *)
+{
if (cquest.status != QUEST_STATUS_UNTAKEN) return (FALSE);
if (p_ptr->lev < 45) return (FALSE);
@@ -96,7 +121,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,56 +128,63 @@ 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);
+ quest_invasion_init_hook();
+ del_hook_new(HOOK_END_TURN, quest_invasion_turn_hook);
process_hooks_restart = TRUE;
- return (FALSE);
+
+ return false;
}
-bool_ quest_invasion_dump_hook(char *fmt)
+
+static bool quest_invasion_dump_hook(void *, void *in_, void *)
{
+ struct hook_chardump_in *in = static_cast<struct hook_chardump_in *>(in_);
+ FILE *f = in->file;
+
if (cquest.status == QUEST_STATUS_FAILED)
{
- fprintf(hook_file, "\n You abandoned Gondolin when it most needed you, thus causing its destruction.");
+ fprintf(f, "\n You abandoned Gondolin when it most needed you, thus causing its destruction.");
}
if ((cquest.status == QUEST_STATUS_FINISHED) || (cquest.status == QUEST_STATUS_REWARDED) || (cquest.status == QUEST_STATUS_COMPLETED))
{
- fprintf(hook_file, "\n You saved Gondolin from destruction.");
+ fprintf(f, "\n You saved Gondolin from destruction.");
}
- return (FALSE);
+ return false;
}
-bool_ quest_invasion_death_hook(char *fmt)
-{
- s32b r_idx, m_idx;
- m_idx = get_next_arg(fmt);
- r_idx = m_list[m_idx].r_idx;
+static bool quest_invasion_death_hook(void *, void *in_, void *)
+{
+ struct hook_monster_death_in *in = static_cast<struct hook_monster_death_in *>(in_);
+ s32b m_idx = in->m_idx;
+ s32b r_idx = m_list[m_idx].r_idx;
- if (p_ptr->inside_quest != QUEST_INVASION) return FALSE;
+ if (p_ptr->inside_quest != QUEST_INVASION)
+ {
+ return false;
+ }
if (r_idx == test_monster_name("Maeglin, the Traitor of Gondolin"))
{
cmsg_print(TERM_YELLOW, "You did it! Gondolin will remain hidden.");
cquest.status = QUEST_STATUS_COMPLETED;
- del_hook(HOOK_MONSTER_DEATH, quest_invasion_death_hook);
+
+ del_hook_new(HOOK_MONSTER_DEATH, quest_invasion_death_hook);
process_hooks_restart = TRUE;
- return (FALSE);
+
+ return false;
}
- return FALSE;
+ return false;
}
-bool_ quest_invasion_stair_hook(char *fmt)
-{
- cptr down;
- down = get_next_arg_str(fmt);
+static bool quest_invasion_stair_hook(void *, void *in_, void *)
+{
+ struct hook_stair_in *in = static_cast<struct hook_stair_in *>(in_);
if (p_ptr->inside_quest != QUEST_INVASION) return FALSE;
if (cave[p_ptr->py][p_ptr->px].feat != FEAT_LESS) return TRUE;
- if (!strcmp(down, "up"))
+ if (in->direction == STAIRS_UP)
{
if (cquest.status == QUEST_STATUS_FAILED)
{
@@ -179,23 +210,23 @@ bool_ quest_invasion_stair_hook(char *fmt)
cquest.status = QUEST_STATUS_FAILED;
town_info[2].destroyed = TRUE;
}
- del_hook(HOOK_STAIR, quest_invasion_stair_hook);
+ del_hook_new(HOOK_STAIR, quest_invasion_stair_hook);
process_hooks_restart = TRUE;
- return (FALSE);
+ return false;
}
- return TRUE;
+ return true;
}
-bool_ quest_invasion_init_hook(int q_idx)
+
+void quest_invasion_init_hook()
{
- add_hook(HOOK_END_TURN, quest_invasion_turn_hook, "invasion_turn");
- add_hook(HOOK_CHAR_DUMP, quest_invasion_dump_hook, "invasion_dump");
+ add_hook_new(HOOK_END_TURN, quest_invasion_turn_hook, "invasion_turn", NULL);
+ add_hook_new(HOOK_CHAR_DUMP, quest_invasion_dump_hook, "invasion_dump", NULL);
if ((cquest.status >= QUEST_STATUS_TAKEN) && (cquest.status < QUEST_STATUS_FINISHED))
{
- add_hook(HOOK_MONSTER_AI, quest_invasion_ai_hook, "invasion_ai");
- add_hook(HOOK_GEN_QUEST, quest_invasion_gen_hook, "invasion_gen");
- add_hook(HOOK_MONSTER_DEATH, quest_invasion_death_hook, "invasion_death");
- add_hook(HOOK_STAIR, quest_invasion_stair_hook, "invasion_stair");
+ add_hook_new(HOOK_MONSTER_AI, quest_invasion_ai_hook, "invasion_ai", NULL);
+ add_hook_new(HOOK_GEN_QUEST, quest_invasion_gen_hook, "invasion_gen", NULL);
+ add_hook_new(HOOK_MONSTER_DEATH, quest_invasion_death_hook, "invasion_death", NULL);
+ add_hook_new(HOOK_STAIR, quest_invasion_stair_hook, "invasion_stair", NULL);
}
- return (FALSE);
}
diff --git a/src/q_invas.hpp b/src/q_invas.hpp
new file mode 100644
index 00000000..dc2d8780
--- /dev/null
+++ b/src/q_invas.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+void quest_invasion_init_hook();
diff --git a/src/q_library.cc b/src/q_library.cc
new file mode 100644
index 00000000..e267e2b7
--- /dev/null
+++ b/src/q_library.cc
@@ -0,0 +1,514 @@
+#include "q_library.hpp"
+
+#include "cave_type.hpp"
+#include "dungeon_flag.hpp"
+#include "game.hpp"
+#include "hooks.hpp"
+#include "lua_bind.hpp"
+#include "monster2.hpp"
+#include "monster_type.hpp"
+#include "object2.hpp"
+#include "player_type.hpp"
+#include "spells3.hpp"
+#include "spells4.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "util.h"
+#include "variable.h"
+#include "variable.hpp"
+#include "z-rand.hpp"
+
+#include <cassert>
+#include <fmt/format.h>
+
+#define cquest (quest[QUEST_LIBRARY])
+
+#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
+
+#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(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;
+ 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--;
+ }
+ }
+}
+
+static s32b library_quest_book_get_slot(int slot)
+{
+ return cquest.data[slot-1];
+}
+
+static void library_quest_book_set_slot(int slot, s32b spell)
+{
+ cquest.data[slot-1] = spell;
+}
+
+static 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)
+{
+ int i;
+ for (i = 1; i <= 3; i++)
+ {
+ if (library_quest_book_get_slot(i) == spell)
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static void quest_library_finalize_book()
+{
+ int i = 0;
+ for (i = 1; i <= 3; i++)
+ {
+ school_book *school_book = school_books_at(BOOK_PLAYER);
+ school_book_add_spell(school_book, 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);
+ } 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 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;
+
+ for (index = 0; index < bookable_spells_size; index++) {
+ int spell = bookable_spells[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;
+ }
+
+ print_spell(NULL, color, row, spell);
+
+ if (row == height - 1) {
+ return;
+ }
+ row = row + 1;
+ }
+ }
+}
+
+static void library_quest_fill_book()
+{
+ int width, height, margin, first, current;
+ bool_ done;
+
+ /* Always start with a cleared book */
+ 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);
+
+ /* room for legend */
+ margin = 3;
+
+ first = 0;
+ current = 0;
+ done = FALSE;
+
+ while (done == FALSE)
+ {
+ char ch;
+ int dir, spell_idx;
+
+ library_quest_print_spells(first, current);
+
+ ch = inkey();
+ dir = get_keymap_dir(ch);
+
+ spell_idx = bookable_spells[current];
+
+ 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') {
+ 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(spell_idx) == FALSE)
+ {
+ library_quest_add_spell(spell_idx);
+ }
+ } else if (dir == 4) {
+ library_quest_remove_spell(spell_idx);
+ }
+
+ if (current >= bookable_spells_size) {
+ current = bookable_spells_size - 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();
+}
+
+static bool quest_library_gen_hook(void *, void *, void *)
+{
+ /* Only if player doing this quest */
+ if (p_ptr->inside_quest != QUEST_LIBRARY)
+ {
+ return false;
+ }
+
+ {
+ int y = 2;
+ int x = 2;
+ load_map("library.map", &y, &x);
+ dungeon_flags = DF_NO_GENO;
+ }
+
+ /* Generate monsters */
+ 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);
+
+ return true;
+}
+
+static bool quest_library_stair_hook(void *, void *, void *)
+{
+ /* only ask this if player about to go up stairs of quest and hasn't won yet */
+ if ((p_ptr->inside_quest != QUEST_LIBRARY) ||
+ (cquest.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 */
+ if (get_check("Really abandon the quest?"))
+ {
+ /* fail the quest */
+ cquest.status = QUEST_STATUS_FAILED;
+ return false;
+ }
+ else
+ {
+ /* if no, they stay in the quest */
+ return true;
+ }
+}
+
+static bool quest_library_monster_death_hook(void *, void *, void *)
+{
+ int i, count = -1;
+
+ /* if they're in the quest and haven't won, continue */
+ if ((p_ptr->inside_quest != QUEST_LIBRARY) ||
+ (cquest.status == QUEST_STATUS_COMPLETED))
+ {
+ return false;
+ }
+
+ /* 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)
+ {
+ 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 = cquest.status;
+
+ /* the quest hasn't been requested already, right? */
+ if (status == QUEST_STATUS_UNTAKEN)
+ {
+ /* quest has been taken now */
+ cquest.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)
+ {
+ cquest.status = QUEST_STATUS_REWARDED;
+
+ {
+ object_type forge;
+ object_type *q_ptr = &forge;
+ object_prep(q_ptr, lookup_kind(TV_BOOK, 61));
+ q_ptr->artifact_name = game->player_name;
+ q_ptr->found = OBJ_FOUND_REWARD;
+ object_aware(q_ptr);
+ object_known(q_ptr);
+ inven_carry(q_ptr, FALSE);
+ }
+
+ quest_library_finalize_book();
+ }
+ }
+
+ /* 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.");
+ }
+}
+
+std::string quest_library_describe()
+{
+ fmt::MemoryWriter w;
+
+ if (cquest.status == QUEST_STATUS_TAKEN)
+ {
+ w.write("#####yAn Old Mages Quest! (Danger Level: 35)\n");
+ w.write("Make the library safe for the old mage in Minas Anor.");
+ }
+ else if (cquest.status == QUEST_STATUS_COMPLETED)
+ {
+ w.write("#####yAn Old Mages Quest!\n");
+ w.write("You have made the library safe for the old mage in Minas Anor.\n");
+ w.write("Perhaps you should see about a reward.");
+ }
+
+ return w.str();
+}
+
+void quest_library_init_hook()
+{
+ /* Only need hooks if the quest is unfinished. */
+ if ((cquest.status >= QUEST_STATUS_UNTAKEN) &&
+ (cquest.status < QUEST_STATUS_FINISHED))
+ {
+ add_hook_new(HOOK_GEN_QUEST , quest_library_gen_hook , "library_gen_hook", NULL);
+ add_hook_new(HOOK_STAIR , quest_library_stair_hook , "library_stair_hook", NULL);
+ add_hook_new(HOOK_MONSTER_DEATH, quest_library_monster_death_hook, "library_monster_death_hook", NULL);
+ }
+
+ /* If quest was rewarded we need to initialize the real player's spellbook. */
+ if (cquest.status == QUEST_STATUS_REWARDED)
+ {
+ quest_library_finalize_book();
+ }
+}
diff --git a/src/q_library.hpp b/src/q_library.hpp
new file mode 100644
index 00000000..266accc3
--- /dev/null
+++ b/src/q_library.hpp
@@ -0,0 +1,10 @@
+#pragma once
+
+#include "h-basic.h"
+
+#include <string>
+
+void quest_library_init_hook();
+std::string quest_library_describe();
+void quest_library_building(bool_ *paid, bool_ *recreate);
+void initialize_bookable_spells();
diff --git a/src/q_main.c b/src/q_main.c
deleted file mode 100644
index a13b0790..00000000
--- a/src/q_main.c
+++ /dev/null
@@ -1,176 +0,0 @@
-bool_ quest_main_monsters_hook(char *fmt)
-{
- s32b r_idx;
- r_idx = get_next_arg(fmt);
-
- /* Sauron */
- if (r_idx == 860)
- {
- /* No Sauron until Necromancer dies */
- if (r_info[819].max_num) return TRUE;
- }
- /* Morgoth */
- else if (r_idx == 862)
- {
- /* No Morgoth until Sauron dies */
- if (r_info[860].max_num) return TRUE;
- }
- return FALSE;
-}
-bool_ quest_morgoth_hook(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];
-
- /* Need to kill him */
- if (!r_ptr->max_num)
- {
- /* Total winner */
- total_winner = WINNER_NORMAL;
- has_won = WINNER_NORMAL;
- quest[QUEST_MORGOTH].status = QUEST_STATUS_FINISHED;
-
- /* Redraw the "title" */
- p_ptr->redraw |= (PR_TITLE);
-
- /* Congratulations */
- if (quest[QUEST_ONE].status == QUEST_STATUS_FINISHED)
- {
- cmsg_print(TERM_L_GREEN, "*** CONGRATULATIONS ***");
- cmsg_print(TERM_L_GREEN, "You have banished Morgoth's foul spirit from Ea, and as you watch, a cleansing");
- cmsg_print(TERM_L_GREEN, "wind roars through the dungeon, dispersing the nether mists around where the");
- cmsg_print(TERM_L_GREEN, "body fell. You feel thanks, and a touch of sorrow, from the Valar");
- cmsg_print(TERM_L_GREEN, "for your deed. You will be forever heralded, your deed forever legendary.");
- cmsg_print(TERM_L_GREEN, "You may retire (commit suicide) when you are ready.");
- }
- else
- {
- cmsg_print(TERM_VIOLET, "*** CONGRATULATIONS ***");
- cmsg_print(TERM_VIOLET, "You have banished Morgoth from Arda, and made Ea a safer place.");
- cmsg_print(TERM_VIOLET, "As you look down at the dispersing mists around Morgoth, a sudden intuition");
- cmsg_print(TERM_VIOLET, "grasps you. Fingering the One Ring, you gather the nether mists around");
- cmsg_print(TERM_VIOLET, "yourself, and inhale deeply their seductive power.");
- cmsg_print(TERM_VIOLET, "You will be forever feared, your orders forever obeyed.");
- cmsg_print(TERM_VIOLET, "You may retire (commit suicide) when you are ready.");
- }
-
- /* Continue the plot(maybe) */
- del_hook(HOOK_MONSTER_DEATH, quest_morgoth_hook);
- process_hooks_restart = TRUE;
-
- /* Either ultra good if the one Ring is destroyed, or ultra evil if used */
- if (quest[QUEST_ONE].status == QUEST_STATUS_FINISHED)
- *(quest[QUEST_MORGOTH].plot) = QUEST_ULTRA_GOOD;
- else
- *(quest[QUEST_MORGOTH].plot) = QUEST_ULTRA_EVIL;
- quest[*(quest[QUEST_MORGOTH].plot)].init(*(quest[QUEST_MORGOTH].plot));
- }
- return (FALSE);
-}
-bool_ quest_morgoth_dump_hook(char *fmt)
-{
- if (quest[QUEST_MORGOTH].status >= QUEST_STATUS_COMPLETED)
- {
- if (quest[QUEST_ONE].status == QUEST_STATUS_FINISHED)
- fprintf(hook_file, "\n You saved Arda and became a famed %s.", sp_ptr->winner);
- else
- fprintf(hook_file, "\n You became a new force of darkness and enslaved all free people.");
- }
- 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))
- {
- add_hook(HOOK_MONSTER_DEATH, quest_morgoth_hook, "morgort_death");
- }
- add_hook(HOOK_CHAR_DUMP, quest_morgoth_dump_hook, "morgoth_dump");
- add_hook(HOOK_NEW_MONSTER, quest_main_monsters_hook, "main_new_monster");
- return (FALSE);
-}
-
-bool_ quest_sauron_hook(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];
-
- /* Need to kill him */
- if (!r_ptr->max_num)
- {
- cmsg_print(TERM_YELLOW, "Well done! You are on the way to slaying Morgoth...");
- quest[QUEST_SAURON].status = QUEST_STATUS_FINISHED;
-
- quest[QUEST_MORGOTH].status = QUEST_STATUS_TAKEN;
- quest_describe(QUEST_MORGOTH);
-
- del_hook(HOOK_MONSTER_DEATH, quest_sauron_hook);
- add_hook(HOOK_MONSTER_DEATH, quest_morgoth_hook, "morgort_death");
- *(quest[QUEST_SAURON].plot) = QUEST_MORGOTH;
- quest_morgoth_init_hook(QUEST_MORGOTH);
-
- process_hooks_restart = TRUE;
- }
- return (FALSE);
-}
-
-bool_ quest_sauron_resurect_hook(char *fmt)
-{
- s32b m_idx = get_next_arg(fmt);
- monster_type *m_ptr = &m_list[m_idx];
- monster_race *r_ptr = &r_info[m_ptr->r_idx];
-
- if ((r_ptr->flags7 & RF7_NAZGUL) && r_info[860].max_num)
- {
- msg_format("Somehow you feel %s is not totally destroyed...", (r_ptr->flags1 & RF1_FEMALE ? "she" : "he"));
- r_ptr->max_num = 1;
- }
- else if ((m_ptr->r_idx == 860) && (quest[QUEST_ONE].status < QUEST_STATUS_FINISHED))
- {
- msg_print("Sauron will not be permanently defeated until the One Ring is either destroyed or used...");
- r_ptr->max_num = 1;
- }
- return FALSE;
-}
-
-bool_ quest_sauron_init_hook(int q_idx)
-{
- if ((quest[QUEST_SAURON].status >= QUEST_STATUS_TAKEN) && (quest[QUEST_SAURON].status < QUEST_STATUS_FINISHED))
- {
- add_hook(HOOK_MONSTER_DEATH, quest_sauron_hook, "sauron_death");
- }
- add_hook(HOOK_NEW_MONSTER, quest_main_monsters_hook, "main_new_monster");
- add_hook(HOOK_MONSTER_DEATH, quest_sauron_resurect_hook, "sauron_resurect_death");
- return (FALSE);
-}
-
-bool_ quest_necro_hook(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];
-
- /* Need to kill him */
- if (!r_ptr->max_num)
- {
- cmsg_print(TERM_YELLOW, "You see the spirit of the necromancer rise and flee...");
- cmsg_print(TERM_YELLOW, "It looks like it was indeed Sauron...");
- cmsg_print(TERM_YELLOW, "You should report that to Galadriel as soon as possible.");
-
- quest[QUEST_NECRO].status = QUEST_STATUS_FINISHED;
-
- *(quest[QUEST_NECRO].plot) = QUEST_ONE;
- quest[*(quest[QUEST_NECRO].plot)].init(*(quest[QUEST_NECRO].plot));
-
- del_hook(HOOK_MONSTER_DEATH, quest_necro_hook);
- process_hooks_restart = TRUE;
- }
- 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))
- {
- add_hook(HOOK_MONSTER_DEATH, quest_necro_hook, "necro_death");
- }
- add_hook(HOOK_NEW_MONSTER, quest_main_monsters_hook, "main_new_monster");
- return (FALSE);
-}
diff --git a/src/q_main.cc b/src/q_main.cc
new file mode 100644
index 00000000..2d3473f1
--- /dev/null
+++ b/src/q_main.cc
@@ -0,0 +1,231 @@
+#include "q_main.hpp"
+
+#include "game.hpp"
+#include "hook_chardump_in.hpp"
+#include "hook_monster_death_in.hpp"
+#include "hook_new_monster_in.hpp"
+#include "hooks.hpp"
+#include "monster_race.hpp"
+#include "monster_race_flag.hpp"
+#include "monster_type.hpp"
+#include "player_type.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+
+#include <cassert>
+
+GENERATE_MONSTER_LOOKUP_FN(get_necromancer, "The Necromancer of Dol Guldur")
+GENERATE_MONSTER_LOOKUP_FN(get_sauron, "Sauron, the Sorcerer")
+GENERATE_MONSTER_LOOKUP_FN(get_morgoth, "Morgoth, Lord of Darkness")
+
+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++]);
+ }
+}
+
+static bool quest_main_monsters_hook(void *, void *in_, void *)
+{
+ auto const &r_info = game->edit_data.r_info;
+
+ struct hook_new_monster_in *in = static_cast<struct hook_new_monster_in *>(in_);
+ s32b r_idx = in->r_idx;
+
+ /* Sauron */
+ if (r_idx == get_sauron())
+ {
+ /* No Sauron until Necromancer dies */
+ if (r_info[get_necromancer()].max_num)
+ {
+ return true;
+ }
+ }
+ /* Morgoth */
+ else if (r_idx == get_morgoth())
+ {
+ /* No Morgoth until Sauron dies */
+ if (r_info[get_sauron()].max_num)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool quest_morgoth_hook(void *, void *, void *)
+{
+ auto const &r_info = game->edit_data.r_info;
+
+ auto r_ptr = &r_info[get_morgoth()];
+
+ /* Need to kill him */
+ if (!r_ptr->max_num)
+ {
+ /* Total winner */
+ total_winner = WINNER_NORMAL;
+ has_won = WINNER_NORMAL;
+ quest[QUEST_MORGOTH].status = QUEST_STATUS_FINISHED;
+
+ /* Redraw the "title" */
+ p_ptr->redraw |= (PR_FRAME);
+
+ /* Congratulations */
+ if (quest[QUEST_ONE].status == QUEST_STATUS_FINISHED)
+ {
+ cmsg_print(TERM_L_GREEN, "*** CONGRATULATIONS ***");
+ cmsg_print(TERM_L_GREEN, "You have banished Morgoth's foul spirit from Ea, and as you watch, a cleansing");
+ cmsg_print(TERM_L_GREEN, "wind roars through the dungeon, dispersing the nether mists around where the");
+ cmsg_print(TERM_L_GREEN, "body fell. You feel thanks, and a touch of sorrow, from the Valar");
+ cmsg_print(TERM_L_GREEN, "for your deed. You will be forever heralded, your deed forever legendary.");
+ cmsg_print(TERM_L_GREEN, "You may retire (commit suicide) when you are ready.");
+ }
+ else
+ {
+ cmsg_print(TERM_VIOLET, "*** CONGRATULATIONS ***");
+ cmsg_print(TERM_VIOLET, "You have banished Morgoth from Arda, and made Ea a safer place.");
+ cmsg_print(TERM_VIOLET, "As you look down at the dispersing mists around Morgoth, a sudden intuition");
+ cmsg_print(TERM_VIOLET, "grasps you. Fingering the One Ring, you gather the nether mists around");
+ cmsg_print(TERM_VIOLET, "yourself, and inhale deeply their seductive power.");
+ cmsg_print(TERM_VIOLET, "You will be forever feared, your orders forever obeyed.");
+ cmsg_print(TERM_VIOLET, "You may retire (commit suicide) when you are ready.");
+ }
+
+ /* Continue the plot(maybe) */
+ del_hook_new(HOOK_MONSTER_DEATH, quest_morgoth_hook);
+ process_hooks_restart = TRUE;
+
+ /* Either ultra good if the one Ring is destroyed, or ultra evil if used */
+ if (quest[QUEST_ONE].status == QUEST_STATUS_FINISHED)
+ *(quest[QUEST_MORGOTH].plot) = QUEST_ULTRA_GOOD;
+ else
+ *(quest[QUEST_MORGOTH].plot) = QUEST_ULTRA_EVIL;
+ quest[*(quest[QUEST_MORGOTH].plot)].init();
+ }
+ return false;
+}
+
+static bool quest_morgoth_dump_hook(void *, void *in_, void *)
+{
+ struct hook_chardump_in *in = static_cast<struct hook_chardump_in *>(in_);
+ FILE *f = in->file;
+
+ if (quest[QUEST_MORGOTH].status >= QUEST_STATUS_COMPLETED)
+ {
+ if (quest[QUEST_ONE].status == QUEST_STATUS_FINISHED)
+ {
+ fprintf(f, "\n You saved Arda and became a famed hero.");
+ }
+ else
+ {
+ fprintf(f, "\n You became a new force of darkness and enslaved all free people.");
+ }
+ }
+ return false;
+}
+
+void quest_morgoth_init_hook()
+{
+ if ((quest[QUEST_MORGOTH].status >= QUEST_STATUS_TAKEN) && (quest[QUEST_MORGOTH].status < QUEST_STATUS_FINISHED))
+ {
+ add_hook_new(HOOK_MONSTER_DEATH, quest_morgoth_hook, "morgoth_death", NULL);
+ }
+ add_hook_new(HOOK_CHAR_DUMP, quest_morgoth_dump_hook, "morgoth_dump", NULL);
+ add_hook_new(HOOK_NEW_MONSTER, quest_main_monsters_hook, "main_new_monster", NULL);
+}
+
+static bool quest_sauron_hook(void *, void *, void *)
+{
+ auto const &r_info = game->edit_data.r_info;
+
+ auto r_ptr = &r_info[get_sauron()];
+
+ /* Need to kill him */
+ if (!r_ptr->max_num)
+ {
+ cmsg_print(TERM_YELLOW, "Well done! You are on the way to slaying Morgoth...");
+ quest[QUEST_SAURON].status = QUEST_STATUS_FINISHED;
+
+ quest[QUEST_MORGOTH].status = QUEST_STATUS_TAKEN;
+ quest_describe(QUEST_MORGOTH);
+
+ del_hook_new(HOOK_MONSTER_DEATH, quest_sauron_hook);
+ add_hook_new(HOOK_MONSTER_DEATH, quest_morgoth_hook, "morgort_death", NULL);
+ *(quest[QUEST_SAURON].plot) = QUEST_MORGOTH;
+ quest_morgoth_init_hook();
+
+ process_hooks_restart = TRUE;
+ }
+
+ return false;
+}
+
+static bool quest_sauron_resurrect_hook(void *, void *in_, void *)
+{
+ auto &r_info = game->edit_data.r_info;
+
+ struct hook_monster_death_in *in = static_cast<struct hook_monster_death_in *>(in_);
+ s32b m_idx = in->m_idx;
+ monster_type *m_ptr = &m_list[m_idx];
+ auto r_ptr = &r_info[m_ptr->r_idx];
+
+ if ((r_ptr->flags & RF_NAZGUL) && r_info[get_sauron()].max_num)
+ {
+ msg_format("Somehow you feel %s is not totally destroyed...", (r_ptr->flags & RF_FEMALE ? "she" : "he"));
+ r_ptr->max_num = 1;
+ }
+ else if ((m_ptr->r_idx == get_sauron()) && (quest[QUEST_ONE].status < QUEST_STATUS_FINISHED))
+ {
+ msg_print("Sauron will not be permanently defeated until the One Ring is either destroyed or used...");
+ r_ptr->max_num = 1;
+ }
+ return false;
+}
+
+void quest_sauron_init_hook()
+{
+ if ((quest[QUEST_SAURON].status >= QUEST_STATUS_TAKEN) && (quest[QUEST_SAURON].status < QUEST_STATUS_FINISHED))
+ {
+ add_hook_new(HOOK_MONSTER_DEATH, quest_sauron_hook, "sauron_death", NULL);
+ }
+ add_hook_new(HOOK_NEW_MONSTER, quest_main_monsters_hook, "main_new_monster", NULL);
+ add_hook_new(HOOK_MONSTER_DEATH, quest_sauron_resurrect_hook, "sauron_resurect_death", NULL);
+}
+
+static bool quest_necro_hook(void *, void *, void *)
+{
+ auto const &r_info = game->edit_data.r_info;
+
+ auto r_ptr = &r_info[get_necromancer()];
+
+ /* Need to kill him */
+ if (!r_ptr->max_num)
+ {
+ cmsg_print(TERM_YELLOW, "You see the spirit of the necromancer rise and flee...");
+ cmsg_print(TERM_YELLOW, "It looks like it was indeed Sauron...");
+ cmsg_print(TERM_YELLOW, "You should report that to Galadriel as soon as possible.");
+
+ quest[QUEST_NECRO].status = QUEST_STATUS_FINISHED;
+
+ *(quest[QUEST_NECRO].plot) = QUEST_ONE;
+ quest[*(quest[QUEST_NECRO].plot)].init();
+
+ del_hook_new(HOOK_MONSTER_DEATH, quest_necro_hook);
+ process_hooks_restart = TRUE;
+ }
+
+ return false;
+}
+
+void quest_necro_init_hook()
+{
+ if ((quest[QUEST_NECRO].status >= QUEST_STATUS_TAKEN) && (quest[QUEST_NECRO].status < QUEST_STATUS_FINISHED))
+ {
+ add_hook_new(HOOK_MONSTER_DEATH, quest_necro_hook, "necro_death", NULL);
+ }
+ add_hook_new(HOOK_NEW_MONSTER, quest_main_monsters_hook, "main_new_monster", NULL);
+}
diff --git a/src/q_main.hpp b/src/q_main.hpp
new file mode 100644
index 00000000..be33897b
--- /dev/null
+++ b/src/q_main.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "h-basic.h"
+
+void quest_necro_init_hook();
+void quest_sauron_init_hook();
+void quest_morgoth_init_hook();
diff --git a/src/q_narsil.c b/src/q_narsil.c
deleted file mode 100644
index 27ec218e..00000000
--- a/src/q_narsil.c
+++ /dev/null
@@ -1,108 +0,0 @@
-#undef cquest
-#define cquest (quest[QUEST_NARSIL])
-
-bool_ quest_narsil_move_hook(char *fmt)
-{
- s32b y, x;
- cave_type *c_ptr;
- int i;
- object_type *o_ptr;
-
- y = get_next_arg(fmt);
- x = get_next_arg(fmt);
- c_ptr = &cave[y][x];
-
- if (cquest.status != QUEST_STATUS_TAKEN) return FALSE;
-
- /* The castle of Aragorn */
- if ((c_ptr->feat != FEAT_SHOP) || (c_ptr->special != 14)) return FALSE;
-
- /* Look out for Narsil */
- for (i = 0; i < INVEN_TOTAL; i++)
- {
- o_ptr = get_object(i);
-
- if (!o_ptr->k_idx) continue;
-
- if (o_ptr->name1 == ART_NARSIL) break;
- }
-
- if (i == INVEN_TOTAL) return FALSE;
-
- cmsg_print(TERM_YELLOW, "I heard that the broken sword had been found!");
- cmsg_print(TERM_YELLOW, "I thought it was only a rumor... until now.");
- cmsg_print(TERM_YELLOW, "What you have is really the sword that was broken.");
- cmsg_print(TERM_YELLOW, "I will get it reforged...");
- cmsg_print(TERM_L_BLUE, "Aragorn leaves for a few hours then comes back...");
- cmsg_print(TERM_YELLOW, "Here it is, Anduril, the sword that was forged and is");
- cmsg_print(TERM_YELLOW, "reforged again. Take it; you will surely need it for your quest.");
-
- object_prep(o_ptr, lookup_kind(TV_SWORD, SV_LONG_SWORD));
- o_ptr->name1 = ART_ANDURIL;
- apply_magic(o_ptr, -1, TRUE, TRUE, TRUE);
- object_aware(o_ptr);
- object_known(o_ptr);
- inven_item_describe(i);
- inven_item_optimize(i);
-
- /* Window stuff */
- p_ptr->window |= (PW_EQUIP | PW_PLAYER | PW_INVEN);
-
- /* Continue the plot */
- cquest.status = QUEST_STATUS_FINISHED;
-
- del_hook(HOOK_MOVE, quest_narsil_move_hook);
- process_hooks_restart = TRUE;
-
- return TRUE;
-}
-bool_ quest_narsil_dump_hook(char *fmt)
-{
- if (cquest.status >= QUEST_STATUS_COMPLETED)
- {
- fprintf(hook_file, "\n The sword that was broken is now reforged.");
- }
- return (FALSE);
-}
-bool_ quest_narsil_identify_hook(char *fmt)
-{
- if (cquest.status == QUEST_STATUS_UNTAKEN)
- {
- int i;
- object_type *o_ptr;
- s32b item;
-
- item = get_next_arg(fmt);
-
- o_ptr = get_object(item);
-
- if (o_ptr->name1 == ART_NARSIL)
- {
- cquest.status = QUEST_STATUS_TAKEN;
-
- for (i = 0; i < 5; i++)
- {
- if (quest[QUEST_NARSIL].desc[i][0] != '\0')
- {
- cmsg_print(TERM_YELLOW, quest[QUEST_NARSIL].desc[i]);
- }
- }
-
- add_hook(HOOK_MOVE, quest_narsil_move_hook, "narsil_move");
- del_hook(HOOK_IDENTIFY, quest_narsil_identify_hook);
- process_hooks_restart = TRUE;
- }
- }
-
- return (FALSE);
-}
-bool_ quest_narsil_init_hook(int q_idx)
-{
- if ((cquest.status >= QUEST_STATUS_TAKEN) && (cquest.status < QUEST_STATUS_FINISHED))
- {
- add_hook(HOOK_MOVE, quest_narsil_move_hook, "narsil_move");
- }
- if (cquest.status == QUEST_STATUS_UNTAKEN) add_hook(HOOK_IDENTIFY, quest_narsil_identify_hook, "narsil_id");
- add_hook(HOOK_CHAR_DUMP, quest_narsil_dump_hook, "narsil_dump");
- return (FALSE);
-}
diff --git a/src/q_narsil.cc b/src/q_narsil.cc
new file mode 100644
index 00000000..8d3c2775
--- /dev/null
+++ b/src/q_narsil.cc
@@ -0,0 +1,130 @@
+#include "q_narsil.hpp"
+
+#include "cave_type.hpp"
+#include "hook_chardump_in.hpp"
+#include "hook_identify_in.hpp"
+#include "hook_move_in.hpp"
+#include "hooks.hpp"
+#include "object2.hpp"
+#include "object_type.hpp"
+#include "player_type.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+
+#define cquest (quest[QUEST_NARSIL])
+
+static bool quest_narsil_move_hook(void *, void *in_, void *)
+{
+ struct hook_move_in *in = static_cast<struct hook_move_in *>(in_);
+ s32b y = in->y;
+ s32b x = in->x;
+ cave_type *c_ptr = &cave[y][x];
+ int i;
+ object_type *o_ptr;
+
+ if (cquest.status != QUEST_STATUS_TAKEN)
+ {
+ return false;
+ }
+
+ /* The castle of Aragorn */
+ if ((c_ptr->feat != FEAT_SHOP) || (c_ptr->special != 14))
+ {
+ return false;
+ }
+
+ /* Look out for Narsil */
+ for (i = 0; i < INVEN_TOTAL; i++)
+ {
+ o_ptr = get_object(i);
+
+ if (!o_ptr->k_idx) continue;
+
+ if (o_ptr->name1 == ART_NARSIL) break;
+ }
+
+ if (i == INVEN_TOTAL)
+ {
+ return false;
+ }
+
+ cmsg_print(TERM_YELLOW, "I heard that the broken sword had been found!");
+ cmsg_print(TERM_YELLOW, "I thought it was only a rumor... until now.");
+ cmsg_print(TERM_YELLOW, "What you have is really the sword that was broken.");
+ cmsg_print(TERM_YELLOW, "I will get it reforged...");
+ cmsg_print(TERM_L_BLUE, "Aragorn leaves for a few hours then comes back...");
+ cmsg_print(TERM_YELLOW, "Here it is, Anduril, the sword that was forged and is");
+ cmsg_print(TERM_YELLOW, "reforged again. Take it; you will surely need it for your quest.");
+
+ object_prep(o_ptr, lookup_kind(TV_SWORD, SV_LONG_SWORD));
+ o_ptr->name1 = ART_ANDURIL;
+ apply_magic(o_ptr, -1, TRUE, TRUE, TRUE);
+ object_aware(o_ptr);
+ object_known(o_ptr);
+ inven_item_describe(i);
+ inven_item_optimize(i);
+
+ /* Window stuff */
+ p_ptr->window |= (PW_EQUIP | PW_PLAYER | PW_INVEN);
+
+ /* Continue the plot */
+ cquest.status = QUEST_STATUS_FINISHED;
+
+ del_hook_new(HOOK_MOVE, quest_narsil_move_hook);
+ process_hooks_restart = TRUE;
+
+ return true;
+}
+
+static bool quest_narsil_dump_hook(void *, void *in_, void *)
+{
+ struct hook_chardump_in *in = static_cast<struct hook_chardump_in *>(in_);
+ FILE *f = in->file;
+
+ if (cquest.status >= QUEST_STATUS_COMPLETED)
+ {
+ fprintf(f, "\n The sword that was broken is now reforged.");
+ }
+ return false;
+}
+
+static bool quest_narsil_identify_hook(void *, void *in_, void *)
+{
+ struct hook_identify_in *in = static_cast<struct hook_identify_in *>(in_);
+
+ if (cquest.status == QUEST_STATUS_UNTAKEN)
+ {
+ if (in->o_ptr->name1 == ART_NARSIL)
+ {
+ cquest.status = QUEST_STATUS_TAKEN;
+
+ for (int i = 0; i < 5; i++)
+ {
+ if (quest[QUEST_NARSIL].desc[i][0] != '\0')
+ {
+ cmsg_print(TERM_YELLOW, quest[QUEST_NARSIL].desc[i]);
+ }
+ }
+
+ add_hook_new(HOOK_MOVE, quest_narsil_move_hook, "narsil_move", NULL);
+ del_hook_new(HOOK_IDENTIFY, quest_narsil_identify_hook);
+ process_hooks_restart = TRUE;
+ }
+ }
+
+ return false;
+}
+
+void quest_narsil_init_hook()
+{
+ if ((cquest.status >= QUEST_STATUS_TAKEN) && (cquest.status < QUEST_STATUS_FINISHED))
+ {
+ add_hook_new(HOOK_MOVE, quest_narsil_move_hook, "narsil_move", NULL);
+ }
+ if (cquest.status == QUEST_STATUS_UNTAKEN)
+ {
+ add_hook_new(HOOK_IDENTIFY, quest_narsil_identify_hook, "narsil_id", NULL);
+ }
+ add_hook_new(HOOK_CHAR_DUMP, quest_narsil_dump_hook, "narsil_dump", NULL);
+}
diff --git a/src/q_narsil.hpp b/src/q_narsil.hpp
new file mode 100644
index 00000000..da0fa85d
--- /dev/null
+++ b/src/q_narsil.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+void quest_narsil_init_hook();
diff --git a/src/q_nazgul.c b/src/q_nazgul.c
deleted file mode 100644
index 66d3dc98..00000000
--- a/src/q_nazgul.c
+++ /dev/null
@@ -1,116 +0,0 @@
-#undef cquest
-#define cquest (quest[QUEST_NAZGUL])
-
-bool_ quest_nazgul_gen_hook(char *fmt)
-{
- int m_idx, x = 1, y = 1, tries = 10000;
- s32b small;
-
- small = get_next_arg(fmt);
-
- if ((cquest.status != QUEST_STATUS_TAKEN) || (small) || (p_ptr->town_num != 1)) return (FALSE);
-
- /* Find a good position */
- while (tries)
- {
- /* Get a random spot */
- y = randint(cur_hgt - 4) + 2;
- x = randint(cur_wid - 4) + 2;
-
- /* Is it a good spot ? */
- /* Not in player los */
- if ((!los(p_ptr->py, p_ptr->px, y, x)) && cave_empty_bold(y, x)) break;
-
- /* One less try */
- tries--;
- }
-
- /* Place the nazgul */
- m_allow_special[test_monster_name("Uvatha the Horseman")] = TRUE;
- m_idx = place_monster_one(y, x, test_monster_name("Uvatha the Horseman"), 0, FALSE, MSTATUS_ENEMY);
- if (m_idx) m_list[m_idx].mflag |= MFLAG_QUEST;
- m_allow_special[test_monster_name("Uvatha the Horseman")] = FALSE;
-
- return FALSE;
-}
-bool_ quest_nazgul_finish_hook(char *fmt)
-{
- object_type forge, *q_ptr;
- s32b q_idx;
-
- q_idx = get_next_arg(fmt);
-
- if (q_idx != QUEST_NAZGUL) return FALSE;
-
- c_put_str(TERM_YELLOW, "I believe he will not come back! Thank you.", 8, 0);
- c_put_str(TERM_YELLOW, "Some time ago a ranger gave me this.", 9, 0);
- c_put_str(TERM_YELLOW, "I believe it will help you on your quest.", 10, 0);
-
- q_ptr = &forge;
- object_prep(q_ptr, lookup_kind(TV_FOOD, SV_FOOD_ATHELAS));
- q_ptr->found = OBJ_FOUND_REWARD;
- q_ptr->number = 6;
- object_aware(q_ptr);
- object_known(q_ptr);
- q_ptr->ident |= IDENT_STOREB;
- (void)inven_carry(q_ptr, FALSE);
-
- /* End the plot */
- *(quest[q_idx].plot) = QUEST_NULL;
-
- del_hook(HOOK_QUEST_FINISH, quest_nazgul_finish_hook);
- process_hooks_restart = TRUE;
-
- return TRUE;
-}
-bool_ quest_nazgul_dump_hook(char *fmt)
-{
- if (cquest.status >= QUEST_STATUS_COMPLETED)
- {
- fprintf(hook_file, "\n You saved Bree from a dreadful Nazgul.");
- }
- return (FALSE);
-}
-bool_ quest_nazgul_forbid_hook(char *fmt)
-{
- s32b q_idx;
- q_idx = get_next_arg(fmt);
-
- if (q_idx != QUEST_NAZGUL) return (FALSE);
-
- if (p_ptr->lev < 30)
- {
- c_put_str(TERM_WHITE, "I fear you are not ready for the next quest, come back later.", 8, 0);
- return (TRUE);
- }
- return (FALSE);
-}
-bool_ quest_nazgul_death_hook(char *fmt)
-{
- s32b r_idx, m_idx;
-
- m_idx = get_next_arg(fmt);
- r_idx = m_list[m_idx].r_idx;
-
- if (cquest.status != QUEST_STATUS_TAKEN) return (FALSE);
- if (r_idx != test_monster_name("Uvatha the Horseman")) return (FALSE);
-
- cquest.status = QUEST_STATUS_COMPLETED;
-
- del_hook(HOOK_MONSTER_DEATH, quest_nazgul_death_hook);
- process_hooks_restart = TRUE;
-
- return (FALSE);
-}
-bool_ quest_nazgul_init_hook(int q_idx)
-{
- if ((cquest.status >= QUEST_STATUS_TAKEN) && (cquest.status < QUEST_STATUS_FINISHED))
- {
- add_hook(HOOK_MONSTER_DEATH, quest_nazgul_death_hook, "nazgul_death");
- add_hook(HOOK_WILD_GEN, quest_nazgul_gen_hook, "nazgul_gen");
- add_hook(HOOK_QUEST_FINISH, quest_nazgul_finish_hook, "nazgul_finish");
- }
- add_hook(HOOK_CHAR_DUMP, quest_nazgul_dump_hook, "nazgul_dump");
- add_hook(HOOK_INIT_QUEST, quest_nazgul_forbid_hook, "nazgul_forbid");
- return (FALSE);
-}
diff --git a/src/q_nazgul.cc b/src/q_nazgul.cc
new file mode 100644
index 00000000..99735eed
--- /dev/null
+++ b/src/q_nazgul.cc
@@ -0,0 +1,161 @@
+#include "q_nazgul.hpp"
+
+#include "cave.hpp"
+#include "hook_chardump_in.hpp"
+#include "hook_init_quest_in.hpp"
+#include "hook_monster_death_in.hpp"
+#include "hook_quest_finish_in.hpp"
+#include "hook_wild_gen_in.hpp"
+#include "hooks.hpp"
+#include "monster2.hpp"
+#include "monster_type.hpp"
+#include "object2.hpp"
+#include "player_type.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+#include "z-rand.hpp"
+
+#include <cassert>
+
+#define cquest (quest[QUEST_NAZGUL])
+
+GENERATE_MONSTER_LOOKUP_FN(get_uvatha, "Uvatha the Horseman")
+
+static bool quest_nazgul_gen_hook(void *, void *in_, void *)
+{
+ struct hook_wild_gen_in *in = static_cast<struct hook_wild_gen_in *>(in_);
+ int m_idx, x = 1, y = 1, tries = 10000;
+ bool_ small = in->small;
+
+ if ((cquest.status != QUEST_STATUS_TAKEN) || (small) || (p_ptr->town_num != 1))
+ {
+ return false;
+ }
+
+ /* Find a good position */
+ while (tries)
+ {
+ /* Get a random spot */
+ y = randint(cur_hgt - 4) + 2;
+ x = randint(cur_wid - 4) + 2;
+
+ /* Is it a good spot ? */
+ /* Not in player los */
+ if ((!los(p_ptr->py, p_ptr->px, y, x)) && cave_empty_bold(y, x)) break;
+
+ /* One less try */
+ tries--;
+ }
+
+ /* Place the nazgul */
+ int r_idx = get_uvatha();
+
+ m_allow_special[r_idx] = TRUE;
+ m_idx = place_monster_one(y, x, r_idx, 0, FALSE, MSTATUS_ENEMY);
+ m_allow_special[r_idx] = FALSE;
+
+ if (m_idx) m_list[m_idx].mflag |= MFLAG_QUEST;
+
+ return false;
+}
+
+static bool quest_nazgul_finish_hook(void *, void *in_, void *)
+{
+ struct hook_quest_finish_in *in = static_cast<struct hook_quest_finish_in *>(in_);
+ s32b q_idx = in->q_idx;
+ object_type forge, *q_ptr;
+
+ if (q_idx != QUEST_NAZGUL)
+ {
+ return false;
+ }
+
+ c_put_str(TERM_YELLOW, "I believe he will not come back! Thank you.", 8, 0);
+ c_put_str(TERM_YELLOW, "Some time ago a ranger gave me this.", 9, 0);
+ c_put_str(TERM_YELLOW, "I believe it will help you on your quest.", 10, 0);
+
+ q_ptr = &forge;
+ object_prep(q_ptr, lookup_kind(TV_FOOD, SV_FOOD_ATHELAS));
+ q_ptr->found = OBJ_FOUND_REWARD;
+ q_ptr->number = 6;
+ object_aware(q_ptr);
+ object_known(q_ptr);
+ q_ptr->ident |= IDENT_STOREB;
+ inven_carry(q_ptr, FALSE);
+
+ /* End the plot */
+ *(quest[q_idx].plot) = QUEST_NULL;
+
+ del_hook_new(HOOK_QUEST_FINISH, quest_nazgul_finish_hook);
+ process_hooks_restart = TRUE;
+
+ return true;
+}
+
+static bool quest_nazgul_dump_hook(void *, void *in_, void *)
+{
+ struct hook_chardump_in *in = static_cast<struct hook_chardump_in *>(in_);
+ FILE *f = in->file;
+
+ if (cquest.status >= QUEST_STATUS_COMPLETED)
+ {
+ fprintf(f, "\n You saved Bree from a dreadful Nazgul.");
+ }
+ return false;
+}
+
+static bool quest_nazgul_forbid_hook(void *, void *in_, void *)
+{
+ struct hook_init_quest_in *in = static_cast<struct hook_init_quest_in *>(in_);
+ s32b q_idx = in->q_idx;
+
+ if (q_idx != QUEST_NAZGUL)
+ {
+ return false;
+ }
+
+ if (p_ptr->lev < 30)
+ {
+ c_put_str(TERM_WHITE, "I fear you are not ready for the next quest, come back later.", 8, 0);
+ return true;
+ }
+
+ return false;
+}
+
+static bool quest_nazgul_death_hook(void *, void *in_, void *)
+{
+ struct hook_monster_death_in *in = static_cast<struct hook_monster_death_in *>(in_);
+ s32b m_idx = in->m_idx;
+ s32b r_idx = m_list[m_idx].r_idx;
+
+ if (cquest.status != QUEST_STATUS_TAKEN)
+ {
+ return false;
+ }
+
+ if (r_idx != get_uvatha())
+ {
+ return false;
+ }
+
+ cquest.status = QUEST_STATUS_COMPLETED;
+
+ del_hook_new(HOOK_MONSTER_DEATH, quest_nazgul_death_hook);
+ process_hooks_restart = TRUE;
+
+ return false;
+}
+
+void quest_nazgul_init_hook()
+{
+ if ((cquest.status >= QUEST_STATUS_TAKEN) && (cquest.status < QUEST_STATUS_FINISHED))
+ {
+ add_hook_new(HOOK_MONSTER_DEATH, quest_nazgul_death_hook, "nazgul_death", NULL);
+ add_hook_new(HOOK_WILD_GEN, quest_nazgul_gen_hook, "nazgul_gen", NULL);
+ add_hook_new(HOOK_QUEST_FINISH, quest_nazgul_finish_hook, "nazgul_finish", NULL);
+ }
+ add_hook_new(HOOK_CHAR_DUMP, quest_nazgul_dump_hook, "nazgul_dump", NULL);
+ add_hook_new(HOOK_INIT_QUEST, quest_nazgul_forbid_hook, "nazgul_forbid", NULL);
+}
diff --git a/src/q_nazgul.hpp b/src/q_nazgul.hpp
new file mode 100644
index 00000000..ad35e5b3
--- /dev/null
+++ b/src/q_nazgul.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+void quest_nazgul_init_hook();
diff --git a/src/q_nirna.c b/src/q_nirna.cc
index be856d31..822d8b6c 100644
--- a/src/q_nirna.c
+++ b/src/q_nirna.cc
@@ -1,13 +1,28 @@
-#undef cquest
+#include "q_nirna.hpp"
+
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "hook_quest_finish_in.hpp"
+#include "hooks.hpp"
+#include "init1.hpp"
+#include "monster2.hpp"
+#include "player_type.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+
#define cquest (quest[QUEST_NIRNAETH])
-bool_ quest_nirnaeth_gen_hook(char *fmt)
+static bool quest_nirnaeth_gen_hook(void *, void *, void *)
{
int x, y;
int xstart = 2;
int ystart = 2;
- if (p_ptr->inside_quest != QUEST_NIRNAETH) return FALSE;
+ if (p_ptr->inside_quest != QUEST_NIRNAETH)
+ {
+ return false;
+ }
/* Start with perm walls */
for (y = 0; y < cur_hgt; y++)
@@ -32,20 +47,25 @@ bool_ quest_nirnaeth_gen_hook(char *fmt)
cquest.data[0] = 0;
cquest.data[1] = 0;
for (x = 2; x < xstart; x++)
+ {
for (y = 2; y < ystart; y++)
{
if (cave[y][x].m_idx) cquest.data[0]++;
}
+ }
- return TRUE;
+ return true;
}
-bool_ quest_nirnaeth_finish_hook(char *fmt)
-{
- s32b q_idx;
- q_idx = get_next_arg(fmt);
+static bool quest_nirnaeth_finish_hook(void *, void *in_, void *)
+{
+ struct hook_quest_finish_in *in = static_cast<struct hook_quest_finish_in *>(in_);
+ s32b q_idx = in->q_idx;
- if (q_idx != QUEST_NIRNAETH) return FALSE;
+ if (q_idx != QUEST_NIRNAETH)
+ {
+ return false;
+ }
/* Killed at least 2/3 of them ? better reward ! */
if (cquest.data[1] >= (2 * cquest.data[0] / 3))
@@ -57,7 +77,7 @@ bool_ quest_nirnaeth_finish_hook(char *fmt)
p_ptr->au += 200000;
/* Redraw gold */
- p_ptr->redraw |= (PR_GOLD);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
@@ -71,39 +91,48 @@ bool_ quest_nirnaeth_finish_hook(char *fmt)
/* Continue the plot */
*(quest[q_idx].plot) = QUEST_NULL;
- del_hook(HOOK_QUEST_FINISH, quest_nirnaeth_finish_hook);
+ del_hook_new(HOOK_QUEST_FINISH, quest_nirnaeth_finish_hook);
process_hooks_restart = TRUE;
- return TRUE;
+ return true;
}
-bool_ quest_nirnaeth_death_hook(char *fmt)
+
+static bool quest_nirnaeth_death_hook(void *, void *, void *)
{
if (p_ptr->inside_quest != QUEST_NIRNAETH) return FALSE;
cquest.data[1]++;
- return FALSE;
+ return false;
}
-bool_ quest_nirnaeth_stair_hook(char *fmt)
+
+static bool quest_nirnaeth_stair_hook(void *, void *, void *)
{
- if (p_ptr->inside_quest != QUEST_NIRNAETH) return FALSE;
+ if (p_ptr->inside_quest != QUEST_NIRNAETH)
+ {
+ return false;
+ }
- if (cave[p_ptr->py][p_ptr->px].feat != FEAT_LESS) return (FALSE);
+ if (cave[p_ptr->py][p_ptr->px].feat != FEAT_LESS)
+ {
+ return false;
+ }
cmsg_print(TERM_YELLOW, "You found a way out!");
cquest.status = QUEST_STATUS_COMPLETED;
- del_hook(HOOK_STAIR, quest_nirnaeth_stair_hook);
+
+ del_hook_new(HOOK_STAIR, quest_nirnaeth_stair_hook);
process_hooks_restart = TRUE;
- return (FALSE);
+ return false;
}
-bool_ quest_nirnaeth_init_hook(int q_idx)
+
+void quest_nirnaeth_init_hook()
{
if ((cquest.status >= QUEST_STATUS_TAKEN) && (cquest.status < QUEST_STATUS_FINISHED))
{
- add_hook(HOOK_MONSTER_DEATH, quest_nirnaeth_death_hook, "nirnaeth_death");
- add_hook(HOOK_GEN_QUEST, quest_nirnaeth_gen_hook, "nirnaeth_gen");
- add_hook(HOOK_STAIR, quest_nirnaeth_stair_hook, "nirnaeth_stair");
- add_hook(HOOK_QUEST_FINISH, quest_nirnaeth_finish_hook, "nirnaeth_finish");
+ add_hook_new(HOOK_MONSTER_DEATH, quest_nirnaeth_death_hook, "nirnaeth_death", NULL);
+ add_hook_new(HOOK_GEN_QUEST, quest_nirnaeth_gen_hook, "nirnaeth_gen", NULL);
+ add_hook_new(HOOK_STAIR, quest_nirnaeth_stair_hook, "nirnaeth_stair", NULL);
+ add_hook_new(HOOK_QUEST_FINISH, quest_nirnaeth_finish_hook, "nirnaeth_finish", NULL);
}
- return (FALSE);
}
diff --git a/src/q_nirna.hpp b/src/q_nirna.hpp
new file mode 100644
index 00000000..1aaeae54
--- /dev/null
+++ b/src/q_nirna.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+void quest_nirnaeth_init_hook();
diff --git a/src/q_one.c b/src/q_one.cc
index 4bfeaf3e..8985b695 100644
--- a/src/q_one.c
+++ b/src/q_one.cc
@@ -1,21 +1,51 @@
-#undef cquest
+#include "q_one.hpp"
+
+#include "artifact_type.hpp"
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "game.hpp"
+#include "gods.hpp"
+#include "hook_calculate_hp_in.hpp"
+#include "hook_calculate_hp_out.hpp"
+#include "hook_chardump_in.hpp"
+#include "hook_drop_in.hpp"
+#include "hook_identify_in.hpp"
+#include "hook_monster_death_in.hpp"
+#include "hook_move_in.hpp"
+#include "hook_wield_in.hpp"
+#include "hooks.hpp"
+#include "monster2.hpp"
+#include "monster_type.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "player_type.hpp"
+#include "tables.hpp"
+#include "town_type.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+#include "z-rand.hpp"
+
#define cquest (quest[QUEST_ONE])
-bool_ quest_one_move_hook(char *fmt)
+static bool quest_one_move_hook(void *, void *in_, void *)
{
- s32b y, x;
- cave_type *c_ptr;
-
- y = get_next_arg(fmt);
- x = get_next_arg(fmt);
- c_ptr = &cave[y][x];
+ struct hook_move_in *in = static_cast<struct hook_move_in *>(in_);
+ s32b y = in->y;
+ s32b x = in->x;
+ cave_type *c_ptr = &cave[y][x];
if (cquest.status == QUEST_STATUS_UNTAKEN)
{
- if (quest[QUEST_NECRO].status < QUEST_STATUS_FINISHED) return (FALSE);
+ if (quest[QUEST_NECRO].status < QUEST_STATUS_FINISHED)
+ {
+ return false;
+ }
/* The mirror of Galadriel */
- if ((c_ptr->feat != FEAT_SHOP) || (c_ptr->special != 23)) return (FALSE);
+ if ((c_ptr->feat != FEAT_SHOP) || (c_ptr->special != 23))
+ {
+ return false;
+ }
cmsg_print(TERM_YELLOW, "You meet Galadriel; she seems worried.");
cmsg_print(TERM_YELLOW, "'So it was Sauron that lurked in Dol Guldur...'");
@@ -25,22 +55,22 @@ bool_ quest_one_move_hook(char *fmt)
cmsg_print(TERM_YELLOW, "'and destroy it. I know it will tempt you, but *NEVER* use it'");
cmsg_print(TERM_YELLOW, "'or it will corrupt you forever.'");
- GOD(GOD_ERU)
+ if (p_ptr->pgod == GOD_ERU)
{
cmsg_print(TERM_YELLOW, "'Also, Eru will abandon you if you wear it.'");
}
- GOD(GOD_MANWE)
+ if (p_ptr->pgod == GOD_MANWE)
{
cmsg_print(TERM_YELLOW, "'Also, Manwe will abandon you if you wear it.'");
}
- GOD(GOD_TULKAS)
+ if (p_ptr->pgod == GOD_TULKAS)
{
cmsg_print(TERM_YELLOW, "'Also, Tulkas will abandon you if you wear it.'");
}
- GOD(GOD_YAVANNA)
+ if (p_ptr->pgod == GOD_YAVANNA)
{
cmsg_print(TERM_YELLOW, "'Also, Yavanna will abandon you if you wear it.'");
}
@@ -52,32 +82,41 @@ bool_ quest_one_move_hook(char *fmt)
cmsg_print(TERM_YELLOW, "'are other people that might know.'");
cmsg_print(TERM_YELLOW, "'Do not forget: the Ring must be cast back into the fires of Mount Doom!'");
- GOD(GOD_MELKOR)
+ if (p_ptr->pgod == GOD_MELKOR)
{
cmsg_print(TERM_YELLOW, "'Melkor will abandon you when you do, but you must do it anyway!'");
}
/* Continue the plot */
cquest.status = QUEST_STATUS_TAKEN;
- cquest.init(QUEST_ONE);
+ cquest.init();
- return TRUE;
+ return true;
}
- return FALSE;
+ return false;
}
-bool_ quest_one_drop_hook(char *fmt)
+
+static bool quest_one_drop_hook(void *, void *in_, void *)
{
- s32b o_idx;
- object_type *o_ptr;
+ struct hook_drop_in *in = static_cast<struct hook_drop_in *>(in_);
+ s32b o_idx = in->o_idx;
+ object_type *o_ptr = &p_ptr->inventory[o_idx];
- o_idx = get_next_arg(fmt);
- o_ptr = &p_ptr->inventory[o_idx];
+ if (cquest.status != QUEST_STATUS_TAKEN)
+ {
+ return false;
+ }
- if (cquest.status != QUEST_STATUS_TAKEN) return FALSE;
+ if (o_ptr->name1 != ART_POWER)
+ {
+ return false;
+ }
- if (o_ptr->name1 != ART_POWER) return FALSE;
- if (cave[p_ptr->py][p_ptr->px].feat != FEAT_GREAT_FIRE) return FALSE;
+ if (cave[p_ptr->py][p_ptr->px].feat != FEAT_GREAT_FIRE)
+ {
+ return false;
+ }
cmsg_print(TERM_YELLOW, "You throw the One Ring into the #RGreat Fire#y; it is rapidly consumed");
cmsg_print(TERM_YELLOW, "by the searing flames.");
@@ -92,36 +131,46 @@ bool_ quest_one_drop_hook(char *fmt)
cquest.status = QUEST_STATUS_FINISHED;
*(quest[QUEST_ONE].plot) = QUEST_SAURON;
quest[*(quest[QUEST_ONE].plot)].status = QUEST_STATUS_TAKEN;
- quest[*(quest[QUEST_ONE].plot)].init(*(quest[QUEST_ONE].plot));
+ quest[*(quest[QUEST_ONE].plot)].init();
- return TRUE;
+ return true;
}
-bool_ quest_one_wield_hook(char *fmt)
-{
- s32b o_idx;
- object_type *o_ptr;
- o_idx = get_next_arg(fmt);
- o_ptr = &p_ptr->inventory[o_idx];
+static bool quest_one_wield_hook(void *, void *in_, void *)
+{
+ struct hook_wield_in *in = static_cast<struct hook_wield_in *>(in_);
+ object_type *o_ptr = in->o_ptr;
- if (cquest.status != QUEST_STATUS_TAKEN) return FALSE;
+ if (cquest.status != QUEST_STATUS_TAKEN)
+ {
+ return false;
+ }
- if (o_ptr->name1 != ART_POWER) return FALSE;
+ if (o_ptr->name1 != ART_POWER)
+ {
+ return false;
+ }
- /* Flush input */
+ // Make sure player is **really** warned
flush();
+ if (!get_check("You were warned not to wear it; are you sure?"))
+ {
+ return true;
+ }
- if (!get_check("You were warned not to wear it; are you sure?")) return TRUE;
- /* Flush input */
flush();
+ if (!get_check("You were warned not to wear it; are you *REALLY* sure?"))
+ {
+ return true;
+ }
- if (!get_check("You were warned not to wear it; are you *REALLY* sure?")) return TRUE;
-
- /* Flush input */
flush();
+ if (!get_check("You were *WARNED* not to wear it; are you *R*E*A*L*L*Y* sure?"))
+ {
+ return true;
+ }
- if (!get_check("You were *WARNED* not to wear it; are you *R*E*A*L*L*Y* sure?")) return TRUE;
-
+ // Ok, that's enough warning
cmsg_print(TERM_YELLOW, "As you put it on your finger you feel #Ddark powers #ysapping your soul.");
cmsg_print(TERM_YELLOW, "The ring firmly binds to your finger!");
cmsg_print(TERM_YELLOW, "You feel you are drawn to the shadow world! Your material form weakens.");
@@ -146,31 +195,36 @@ bool_ quest_one_wield_hook(char *fmt)
cquest.status = QUEST_STATUS_FAILED_DONE;
*(quest[QUEST_ONE].plot) = QUEST_SAURON;
quest[*(quest[QUEST_ONE].plot)].status = QUEST_STATUS_TAKEN;
- quest[*(quest[QUEST_ONE].plot)].init(*(quest[QUEST_ONE].plot));
+ quest[*(quest[QUEST_ONE].plot)].init();
/* Ok lets reset the lives counter */
p_ptr->lives = 0;
- return FALSE;
+ return false;
}
-bool_ quest_one_hp_hook(char *fmt)
+
+static bool quest_one_hp_hook(void *, void *in_, void *out_)
{
+ struct hook_calculate_hp_in *in = static_cast<struct hook_calculate_hp_in *>(in_);
+ struct hook_calculate_hp_out *out = static_cast<struct hook_calculate_hp_out *>(out_);
+
if (cquest.status == QUEST_STATUS_FAILED_DONE)
{
- s32b mhp;
- int i;
+ s32b mhp = in->mhp;
- mhp = get_next_arg(fmt);
-
- for (i = 0; i < p_ptr->lives + 1; i++)
+ for (int i = 0; i < p_ptr->lives + 1; i++)
+ {
mhp = (mhp * 2) / 3;
+ }
- process_hooks_return[0].num = mhp;
- return (TRUE);
+ out->mhp = mhp;
+ return true;
}
- return (FALSE);
+
+ return false;
}
-bool_ quest_one_die_hook(char *fmt)
+
+static bool quest_one_die_hook(void *, void *, void *)
{
if (cquest.status == QUEST_STATUS_FAILED_DONE)
{
@@ -178,29 +232,25 @@ bool_ quest_one_die_hook(char *fmt)
{
cmsg_print(TERM_YELLOW, "You feel the power of the One Ring sustaining your life,");
cmsg_print(TERM_YELLOW, "but it drags you even more into the shadow world.");
- return (TRUE);
+ return true;
}
else
{
cmsg_print(TERM_YELLOW, "The One Ring finally drags you totally to the shadow world.");
cmsg_print(TERM_YELLOW, "Your mortal existence ends there.");
- strcpy(died_from, "being drawn to the shadow world");
+ game->died_from = "being drawn to the shadow world";
}
}
- return (FALSE);
+ return false;
}
-bool_ quest_one_identify_hook(char *fmt)
-{
- s32b item;
- item = get_next_arg(fmt);
+static bool quest_one_identify_hook(void *, void *in_, void *)
+{
+ struct hook_identify_in *in = static_cast<struct hook_identify_in *>(in_);
+ object_type *o_ptr = in->o_ptr;
if (cquest.status == QUEST_STATUS_TAKEN)
{
- object_type *o_ptr;
-
- o_ptr = get_object(item);
-
if ((o_ptr->name1 == ART_POWER) && (!object_known_p(o_ptr)))
{
cmsg_print(TERM_YELLOW, "You finally found the One Ring, source of Sauron's power, and key to");
@@ -209,44 +259,52 @@ bool_ quest_one_identify_hook(char *fmt)
}
}
- return (FALSE);
+ return false;
}
-bool_ quest_one_death_hook(char *fmt)
+
+static bool quest_one_death_hook(void *, void *in_, void *)
{
- s32b r_idx, m_idx;
- bool_ ok = FALSE;
+ auto const &a_info = game->edit_data.a_info;
- m_idx = get_next_arg(fmt);
- r_idx = m_list[m_idx].r_idx;
+ struct hook_monster_death_in *in = static_cast<struct hook_monster_death_in *>(in_);
+ s32b m_idx = in->m_idx;
+ s32b r_idx = m_list[m_idx].r_idx;
+ bool ok = false;
- if (a_info[ART_POWER].cur_num) return FALSE;
+ if (a_info[ART_POWER].cur_num)
+ {
+ return false;
+ }
/* Paranoia */
- if (cquest.status != QUEST_STATUS_TAKEN) return (FALSE);
+ if (cquest.status != QUEST_STATUS_TAKEN)
+ {
+ return false;
+ }
if (magik(30) && (r_idx == test_monster_name("Sauron, the Sorcerer")))
{
- ok = TRUE;
+ ok = true;
}
else if (magik(10) && (r_idx == test_monster_name("Ar-Pharazon the Golden")))
{
- ok = TRUE;
+ ok = true;
}
else if (magik(10) && (r_idx == test_monster_name("Shelob, Spider of Darkness")))
{
- ok = TRUE;
+ ok = true;
}
else if (magik(10) && (r_idx == test_monster_name("The Watcher in the Water")))
{
- ok = TRUE;
+ ok = true;
}
else if (magik(10) && (r_idx == test_monster_name("Glaurung, Father of the Dragons")))
{
- ok = TRUE;
+ ok = true;
}
else if (magik(10) && (r_idx == test_monster_name("Feagwath, the Undead Sorcerer")))
{
- ok = TRUE;
+ ok = true;
}
if (ok)
@@ -269,7 +327,10 @@ bool_ quest_one_death_hook(char *fmt)
for (i = 0; i < INVEN_PACK; i++)
{
/* Skip non-objects */
- if (!p_ptr->inventory[i].k_idx) break;
+ if (!p_ptr->inventory[i].k_idx)
+ {
+ break;
+ }
}
/* Arg, no space ! */
if (i == INVEN_PACK)
@@ -289,27 +350,38 @@ bool_ quest_one_death_hook(char *fmt)
inven_carry(q_ptr, FALSE);
}
- return (FALSE);
+ return false;
}
-bool_ quest_one_dump_hook(char *fmt)
+
+static bool quest_one_dump_hook(void *, void *in_, void *)
{
+ struct hook_chardump_in *in = static_cast<struct hook_chardump_in *>(in_);
+ FILE *f = in->file;
+
if (cquest.status == QUEST_STATUS_FINISHED)
{
- fprintf(hook_file, "\n You destroyed the One Ring, thus weakening Sauron.");
+ fprintf(f, "\n You destroyed the One Ring, thus weakening Sauron.");
}
if (cquest.status == QUEST_STATUS_FAILED_DONE)
{
- fprintf(hook_file, "\n You fell under the evil influence of the One Ring and decided to wear it.");
+ fprintf(f, "\n You fell under the evil influence of the One Ring and decided to wear it.");
}
- return (FALSE);
+ return false;
}
-bool_ quest_one_gen_hook(char *fmt)
+
+static bool quest_one_gen_hook(void *, void *, void *)
{
s32b x, y, tries = 10000;
/* Paranoia */
- if (cquest.status != QUEST_STATUS_TAKEN) return (FALSE);
- if ((dungeon_type != DUNGEON_ANGBAND) || (dun_level != 99)) return (FALSE);
+ if (cquest.status != QUEST_STATUS_TAKEN)
+ {
+ return false;
+ }
+ if ((dungeon_type != DUNGEON_ANGBAND) || (dun_level != 99))
+ {
+ return false;
+ }
/* Find a good position */
while (tries)
@@ -331,24 +403,24 @@ bool_ quest_one_gen_hook(char *fmt)
if (m_idx) m_list[m_idx].mflag |= MFLAG_QUEST;
}
- return (FALSE);
+ return false;
}
-bool_ quest_one_init_hook(int q_idx)
+
+void quest_one_init_hook()
{
if ((cquest.status >= QUEST_STATUS_TAKEN) && (cquest.status < QUEST_STATUS_FINISHED))
{
- add_hook(HOOK_LEVEL_END_GEN, quest_one_gen_hook, "one_gen");
- add_hook(HOOK_MONSTER_DEATH, quest_one_death_hook, "one_death");
- add_hook(HOOK_DROP, quest_one_drop_hook, "one_drop");
- add_hook(HOOK_WIELD, quest_one_wield_hook, "one_wield");
- add_hook(HOOK_IDENTIFY, quest_one_identify_hook, "one_id");
+ add_hook_new(HOOK_LEVEL_END_GEN, quest_one_gen_hook, "one_gen", NULL);
+ add_hook_new(HOOK_MONSTER_DEATH, quest_one_death_hook, "one_death", NULL);
+ add_hook_new(HOOK_DROP, quest_one_drop_hook, "one_drop", NULL);
+ add_hook_new(HOOK_WIELD, quest_one_wield_hook, "one_wield", NULL);
+ add_hook_new(HOOK_IDENTIFY, quest_one_identify_hook, "one_id", NULL);
}
if (cquest.status == QUEST_STATUS_UNTAKEN)
{
- add_hook(HOOK_MOVE, quest_one_move_hook, "one_move");
+ add_hook_new(HOOK_MOVE, quest_one_move_hook, "one_move", NULL);
}
- add_hook(HOOK_CHAR_DUMP, quest_one_dump_hook, "one_dump");
- add_hook(HOOK_CALC_HP, quest_one_hp_hook, "one_hp");
- add_hook(HOOK_DIE, quest_one_die_hook, "one_die");
- return (FALSE);
+ add_hook_new(HOOK_CHAR_DUMP, quest_one_dump_hook, "one_dump", NULL);
+ add_hook_new(HOOK_CALC_HP, quest_one_hp_hook, "one_hp", NULL);
+ add_hook_new(HOOK_DIE, quest_one_die_hook, "one_die", NULL);
}
diff --git a/src/q_one.hpp b/src/q_one.hpp
new file mode 100644
index 00000000..13389968
--- /dev/null
+++ b/src/q_one.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+void quest_one_init_hook();
diff --git a/src/q_poison.c b/src/q_poison.c
deleted file mode 100644
index e6fed3a1..00000000
--- a/src/q_poison.c
+++ /dev/null
@@ -1,238 +0,0 @@
-#undef cquest
-#define cquest (quest[QUEST_POISON])
-
-static int wild_locs[4][2] =
-{
- { 32, 49, },
- { 32, 48, },
- { 33, 48, },
- { 34, 48, },
-};
-
-static bool_ create_molds_hook(int r_idx)
-{
- monster_race *r_ptr = &r_info[r_idx];
-
- if (r_ptr->flags4 & RF4_MULTIPLY) return FALSE;
-
- if (r_ptr->d_char == 'm') return TRUE;
- else if (r_ptr->d_char == ',') return TRUE;
- else if (r_ptr->d_char == 'e') return TRUE;
- else return FALSE;
-}
-
-bool_ quest_poison_gen_hook(char *fmt)
-{
- int cy = 1, cx = 1, x, y, tries = 10000, r_idx;
- bool_ (*old_get_mon_num_hook)(int r_idx);
-
- if (cquest.status != QUEST_STATUS_TAKEN) return FALSE;
- if (p_ptr->wilderness_y != wild_locs[cquest.data[0]][0]) return FALSE;
- if (p_ptr->wilderness_x != wild_locs[cquest.data[0]][1]) return FALSE;
- if (p_ptr->wild_mode) return FALSE;
-
- /* Find a good position */
- while (tries)
- {
- /* Get a random spot */
- cy = randint(cur_hgt - 24) + 22;
- cx = randint(cur_wid - 34) + 32;
-
- /* Is it a good spot ? */
- if (cave_empty_bold(cy, cx)) break;
-
- /* One less try */
- tries--;
- }
-
- /* Place the baddies */
-
- /* Backup the old hook */
- old_get_mon_num_hook = get_mon_num_hook;
-
- /* Require "okay" monsters */
- get_mon_num_hook = create_molds_hook;
-
- /* Prepare allocation table */
- get_mon_num_prep();
-
- /* Pick a monster, using the level calculation */
- for (x = cx - 25; x <= cx + 25; x++)
- for (y = cy - 25; y <= cy + 25; y++)
- {
- if (!in_bounds(y, x)) continue;
-
- if (distance(cy, cx, y, x) > 25) continue;
-
- if (magik(80) && ((cave[y][x].feat == FEAT_DEEP_WATER) || (cave[y][x].feat == FEAT_SHAL_WATER))) cave_set_feat(y, x, FEAT_TAINTED_WATER);
-
- if (distance(cy, cx, y, x) > 10) continue;
-
- if (magik(60))
- {
- int m_idx;
-
- r_idx = get_mon_num(30);
- m_idx = place_monster_one(y, x, r_idx, 0, FALSE, MSTATUS_ENEMY);
- if (m_idx) m_list[m_idx].mflag |= MFLAG_QUEST;
-
- /* Sometimes make it up some levels */
- if (magik(80) && m_idx)
- {
- monster_type *m_ptr = &m_list[m_idx];
-
- if (m_ptr->level < p_ptr->lev)
- {
- m_ptr->exp = MONSTER_EXP(m_ptr->level + randint(p_ptr->lev - m_ptr->level));
- monster_check_experience(m_idx, TRUE);
- }
- }
- }
- }
-
- /* Reset restriction */
- get_mon_num_hook = old_get_mon_num_hook;
-
- /* Prepare allocation table */
- get_mon_num_prep();
-
- return FALSE;
-}
-bool_ quest_poison_finish_hook(char *fmt)
-{
- object_type forge, *q_ptr;
- s32b q_idx;
-
- q_idx = get_next_arg(fmt);
-
- if (q_idx != QUEST_POISON) return FALSE;
-
- c_put_str(TERM_YELLOW, "The water is clean again! Thank you so much.", 8, 0);
- c_put_str(TERM_YELLOW, "The beautiful Mallorns are safe. Take this as a proof of our gratitude.", 9, 0);
-
- q_ptr = &forge;
- object_prep(q_ptr, lookup_kind(TV_DRAG_ARMOR, SV_DRAGON_BLUE));
- q_ptr->found = OBJ_FOUND_REWARD;
- q_ptr->number = 1;
- q_ptr->name2 = EGO_ELVENKIND;
- apply_magic(q_ptr, 1, FALSE, FALSE, FALSE);
- object_aware(q_ptr);
- object_known(q_ptr);
- q_ptr->ident |= IDENT_STOREB;
- (void)inven_carry(q_ptr, FALSE);
-
- /* Continue the plot */
- *(quest[q_idx].plot) = QUEST_NULL;
-
- del_hook(HOOK_QUEST_FINISH, quest_poison_finish_hook);
- process_hooks_restart = TRUE;
-
- return TRUE;
-}
-bool_ quest_poison_dump_hook(char *fmt)
-{
- if (cquest.status >= QUEST_STATUS_COMPLETED)
- {
- fprintf(hook_file, "\n You saved the beautiful Mallorns of Lothlorien.");
- }
- return (FALSE);
-}
-bool_ quest_poison_quest_hook(char *fmt)
-{
- object_type forge, *q_ptr;
- s32b q_idx;
-
- q_idx = get_next_arg(fmt);
-
- if (q_idx != QUEST_POISON) return FALSE;
-
- q_ptr = &forge;
- object_prep(q_ptr, lookup_kind(TV_POTION2, SV_POTION2_CURE_WATER));
- q_ptr->number = 99;
- object_aware(q_ptr);
- object_known(q_ptr);
- q_ptr->ident |= IDENT_STOREB;
- q_ptr->note = quark_add("quest");
- (void)inven_carry(q_ptr, FALSE);
-
- del_hook(HOOK_INIT_QUEST, quest_poison_quest_hook);
- process_hooks_restart = TRUE;
-
- return FALSE;
-}
-bool_ quest_poison_drop_hook(char *fmt)
-{
- s32b mcnt = 0, i, x, y, o_idx;
- object_type *o_ptr;
-
- o_idx = get_next_arg(fmt);
- o_ptr = &p_ptr->inventory[o_idx];
-
- if (cquest.status != QUEST_STATUS_TAKEN) return FALSE;
- if (p_ptr->wilderness_y != wild_locs[cquest.data[0]][0]) return FALSE;
- if (p_ptr->wilderness_x != wild_locs[cquest.data[0]][1]) return FALSE;
- if (p_ptr->wild_mode) return FALSE;
-
- if (o_ptr->tval != TV_POTION2) return FALSE;
- if (o_ptr->sval != SV_POTION2_CURE_WATER) return FALSE;
-
- for (i = m_max - 1; i >= 1; i--)
- {
- /* Access the monster */
- monster_type *m_ptr = &m_list[i];
-
- /* Ignore "dead" monsters */
- if (!m_ptr->r_idx) continue;
-
- if (m_ptr->status <= MSTATUS_NEUTRAL) mcnt++;
- }
-
- if (mcnt < 10)
- {
- for (x = 1; x < cur_wid - 1; x++)
- for (y = 1; y < cur_hgt - 1; y++)
- {
- if (!in_bounds(y, x)) continue;
-
- if (cave[y][x].feat == FEAT_TAINTED_WATER) cave_set_feat(y, x, FEAT_SHAL_WATER);
- }
-
- cmsg_print(TERM_YELLOW, "Well done! The water seems to be clean now.");
-
- cquest.status = QUEST_STATUS_COMPLETED;
-
- del_hook(HOOK_DROP, quest_poison_drop_hook);
- process_hooks_restart = TRUE;
-
- return FALSE;
- }
- else
- {
- msg_print("There are too many monsters left to cure the water.");
- return TRUE;
- }
- return FALSE;
-}
-bool_ quest_poison_init_hook(int q_idx)
-{
- /* Get a place to place the poison */
- if (!cquest.data[1])
- {
- 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 ((cquest.status >= QUEST_STATUS_TAKEN) && (cquest.status < QUEST_STATUS_FINISHED))
- {
- add_hook(HOOK_DROP, quest_poison_drop_hook, "poison_drop");
- add_hook(HOOK_WILD_GEN, quest_poison_gen_hook, "poison_gen");
- add_hook(HOOK_QUEST_FINISH, quest_poison_finish_hook, "poison_finish");
- }
- if (cquest.status < QUEST_STATUS_COMPLETED)
- {
- add_hook(HOOK_INIT_QUEST, quest_poison_quest_hook, "poison_iquest");
- }
- add_hook(HOOK_CHAR_DUMP, quest_poison_dump_hook, "poison_dump");
- return (FALSE);
-}
diff --git a/src/q_poison.cc b/src/q_poison.cc
new file mode 100644
index 00000000..e7f1c71b
--- /dev/null
+++ b/src/q_poison.cc
@@ -0,0 +1,339 @@
+#include "q_poison.hpp"
+
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "game.hpp"
+#include "hook_chardump_in.hpp"
+#include "hook_drop_in.hpp"
+#include "hook_init_quest_in.hpp"
+#include "hook_quest_finish_in.hpp"
+#include "hooks.hpp"
+#include "messages.hpp"
+#include "monster2.hpp"
+#include "monster_race.hpp"
+#include "monster_race_flag.hpp"
+#include "monster_spell_flag.hpp"
+#include "monster_type.hpp"
+#include "object2.hpp"
+#include "player_type.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+#include "z-rand.hpp"
+
+#define cquest (quest[QUEST_POISON])
+
+static int wild_locs[4][2] =
+{
+ { 32, 49, },
+ { 32, 48, },
+ { 33, 48, },
+ { 34, 48, },
+};
+
+static bool_ create_molds_hook(int r_idx)
+{
+ auto const &r_info = game->edit_data.r_info;
+
+ auto r_ptr = &r_info[r_idx];
+
+ if (r_ptr->spells & SF_MULTIPLY) return FALSE;
+
+ if (r_ptr->d_char == 'm') return TRUE;
+ else if (r_ptr->d_char == ',') return TRUE;
+ else if (r_ptr->d_char == 'e') return TRUE;
+ else return FALSE;
+}
+
+static bool quest_poison_gen_hook(void *, void *, void *)
+{
+ int cy = 1, cx = 1, x, y, tries = 10000, r_idx;
+ bool_ (*old_get_mon_num_hook)(int r_idx);
+
+ if (cquest.status != QUEST_STATUS_TAKEN)
+ {
+ return false;
+ }
+ if (p_ptr->wilderness_y != wild_locs[cquest.data[0]][0])
+ {
+ return false;
+ }
+ if (p_ptr->wilderness_x != wild_locs[cquest.data[0]][1])
+ {
+ return false;
+ }
+ if (p_ptr->wild_mode)
+ {
+ return false;
+ }
+
+ /* Find a good position */
+ while (tries)
+ {
+ /* Get a random spot */
+ cy = randint(cur_hgt - 24) + 22;
+ cx = randint(cur_wid - 34) + 32;
+
+ /* Is it a good spot ? */
+ if (cave_empty_bold(cy, cx))
+ {
+ break;
+ }
+
+ /* One less try */
+ tries--;
+ }
+
+ /* Place the baddies */
+
+ /* Backup the old hook */
+ old_get_mon_num_hook = get_mon_num_hook;
+
+ /* Require "okay" monsters */
+ get_mon_num_hook = create_molds_hook;
+
+ /* Prepare allocation table */
+ get_mon_num_prep();
+
+ /* Pick a monster, using the level calculation */
+ for (x = cx - 25; x <= cx + 25; x++)
+ {
+ for (y = cy - 25; y <= cy + 25; y++)
+ {
+ if (!in_bounds(y, x))
+ {
+ continue;
+ }
+
+ if (distance(cy, cx, y, x) > 25)
+ {
+ continue;
+ }
+
+ if (magik(80) && ((cave[y][x].feat == FEAT_DEEP_WATER) || (cave[y][x].feat == FEAT_SHAL_WATER)))
+ {
+ cave_set_feat(y, x, FEAT_TAINTED_WATER);
+ }
+
+ if (distance(cy, cx, y, x) > 10)
+ {
+ continue;
+ }
+
+ if (magik(60))
+ {
+ int m_idx;
+
+ r_idx = get_mon_num(30);
+ m_idx = place_monster_one(y, x, r_idx, 0, FALSE, MSTATUS_ENEMY);
+ if (m_idx) m_list[m_idx].mflag |= MFLAG_QUEST;
+
+ /* Sometimes make it up some levels */
+ if (magik(80) && m_idx)
+ {
+ monster_type *m_ptr = &m_list[m_idx];
+
+ if (m_ptr->level < p_ptr->lev)
+ {
+ m_ptr->exp = monster_exp(m_ptr->level + randint(p_ptr->lev - m_ptr->level));
+ monster_check_experience(m_idx, TRUE);
+ }
+ }
+ }
+ }
+ }
+
+ /* Reset restriction */
+ get_mon_num_hook = old_get_mon_num_hook;
+
+ /* Prepare allocation table */
+ get_mon_num_prep();
+
+ return false;
+}
+
+static bool quest_poison_finish_hook(void *, void *in_, void *)
+{
+ struct hook_quest_finish_in *in = static_cast<struct hook_quest_finish_in *>(in_);
+ s32b q_idx = in->q_idx;
+ object_type forge, *q_ptr;
+
+ if (q_idx != QUEST_POISON)
+ {
+ return false;
+ }
+
+ c_put_str(TERM_YELLOW, "The water is clean again! Thank you so much.", 8, 0);
+ c_put_str(TERM_YELLOW, "The beautiful Mallorns are safe. Take this as a proof of our gratitude.", 9, 0);
+
+ q_ptr = &forge;
+ object_prep(q_ptr, lookup_kind(TV_DRAG_ARMOR, SV_DRAGON_BLUE));
+ q_ptr->found = OBJ_FOUND_REWARD;
+ q_ptr->number = 1;
+ q_ptr->name2 = EGO_ELVENKIND;
+ apply_magic(q_ptr, 1, FALSE, FALSE, FALSE);
+ object_aware(q_ptr);
+ object_known(q_ptr);
+ q_ptr->ident |= IDENT_STOREB;
+ inven_carry(q_ptr, FALSE);
+
+ /* Continue the plot */
+ *(quest[q_idx].plot) = QUEST_NULL;
+
+ del_hook_new(HOOK_QUEST_FINISH, quest_poison_finish_hook);
+ process_hooks_restart = TRUE;
+
+ return true;
+}
+
+static bool quest_poison_dump_hook(void *, void *in_, void *)
+{
+ hook_chardump_in *in = static_cast<struct hook_chardump_in *>(in_);
+ FILE *f = in->file;
+
+ if (cquest.status >= QUEST_STATUS_COMPLETED)
+ {
+ fprintf(f, "\n You saved the beautiful Mallorns of Lothlorien.");
+ }
+ return false;
+}
+
+static bool quest_poison_quest_hook(void *, void *in_, void *)
+{
+ struct hook_init_quest_in *in = static_cast<struct hook_init_quest_in *>(in_);
+ s32b q_idx = in->q_idx;
+ object_type forge, *q_ptr;
+
+ if (q_idx != QUEST_POISON)
+ {
+ return false;
+ }
+
+ q_ptr = &forge;
+ object_prep(q_ptr, lookup_kind(TV_POTION2, SV_POTION2_CURE_WATER));
+ q_ptr->number = 99;
+ object_aware(q_ptr);
+ object_known(q_ptr);
+ q_ptr->ident |= IDENT_STOREB;
+ q_ptr->inscription = "quest";
+
+ inven_carry(q_ptr, FALSE);
+
+ del_hook_new(HOOK_INIT_QUEST, quest_poison_quest_hook);
+ process_hooks_restart = TRUE;
+
+ return false;
+}
+
+static bool quest_poison_drop_hook(void *, void *in_, void *)
+{
+ struct hook_drop_in *in = static_cast<struct hook_drop_in *>(in_);
+ s32b mcnt = 0, i, x, y;
+ s32b o_idx = in->o_idx;
+ object_type *o_ptr = &p_ptr->inventory[o_idx];
+
+ if (cquest.status != QUEST_STATUS_TAKEN)
+ {
+ return false;
+ }
+ if (p_ptr->wilderness_y != wild_locs[cquest.data[0]][0])
+ {
+ return false;
+ }
+ if (p_ptr->wilderness_x != wild_locs[cquest.data[0]][1])
+ {
+ return false;
+ }
+ if (p_ptr->wild_mode)
+ {
+ return false;
+ }
+
+ if (o_ptr->tval != TV_POTION2)
+ {
+ return false;
+ }
+ if (o_ptr->sval != SV_POTION2_CURE_WATER)
+ {
+ return false;
+ }
+
+ for (i = m_max - 1; i >= 1; i--)
+ {
+ /* Access the monster */
+ monster_type *m_ptr = &m_list[i];
+
+ /* Ignore "dead" monsters */
+ if (!m_ptr->r_idx)
+ {
+ continue;
+ }
+
+ if (m_ptr->status <= MSTATUS_NEUTRAL)
+ {
+ mcnt++;
+ }
+ }
+
+ if (mcnt < 10)
+ {
+ for (x = 1; x < cur_wid - 1; x++)
+ {
+ for (y = 1; y < cur_hgt - 1; y++)
+ {
+ if (!in_bounds(y, x))
+ {
+ continue;
+ }
+
+ if (cave[y][x].feat == FEAT_TAINTED_WATER)
+ {
+ cave_set_feat(y, x, FEAT_SHAL_WATER);
+ }
+ }
+ }
+
+ cmsg_print(TERM_YELLOW, "Well done! The water seems to be clean now.");
+
+ cquest.status = QUEST_STATUS_COMPLETED;
+
+ del_hook_new(HOOK_DROP, quest_poison_drop_hook);
+ process_hooks_restart = TRUE;
+
+ return false;
+ }
+ else
+ {
+ msg_print("There are too many monsters left to cure the water.");
+ return true;
+ }
+ return false;
+}
+
+void quest_poison_init_hook()
+{
+ auto &messages = game->messages;
+
+ /* Get a place to place the poison */
+ if (!cquest.data[1])
+ {
+ cquest.data[1] = TRUE;
+ cquest.data[0] = rand_int(4);
+ if (wizard)
+ {
+ messages.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))
+ {
+ add_hook_new(HOOK_DROP, quest_poison_drop_hook, "poison_drop", NULL);
+ add_hook_new(HOOK_WILD_GEN, quest_poison_gen_hook, "poison_gen", NULL);
+ add_hook_new(HOOK_QUEST_FINISH, quest_poison_finish_hook, "poison_finish", NULL);
+ }
+ if (cquest.status < QUEST_STATUS_COMPLETED)
+ {
+ add_hook_new(HOOK_INIT_QUEST, quest_poison_quest_hook, "poison_iquest", NULL);
+ }
+ add_hook_new(HOOK_CHAR_DUMP, quest_poison_dump_hook, "poison_dump", NULL);
+}
diff --git a/src/q_poison.hpp b/src/q_poison.hpp
new file mode 100644
index 00000000..6c4e771b
--- /dev/null
+++ b/src/q_poison.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+void quest_poison_init_hook();
diff --git a/src/q_rand.c b/src/q_rand.c
deleted file mode 100644
index 5a3b3ab2..00000000
--- a/src/q_rand.c
+++ /dev/null
@@ -1,465 +0,0 @@
-static int randquest_hero[] = { 20, 13, 15, 16, 9, 17, 18, 8, -1 };
-
-bool_ is_randhero(int level)
-{
- int i;
- bool_ result = FALSE;
-
- for (i = 0; randquest_hero[i] != -1; i++)
- {
- if (random_quests[level].type == randquest_hero[i])
- {
- result = TRUE;
- break;
- }
- }
-
- return result;
-}
-
-void do_get_new_obj(int y, int x)
-{
- obj_theme theme;
- char *items[3];
- object_type *q_ptr[3], forge[3];
- int max = 0, res, i;
-
- /* Create 3 ones */
- max = 0;
- for (i = 0; i < 3; i++)
- {
- /* Get local object */
- q_ptr[max] = &forge[max];
-
- /* Wipe the object */
- object_wipe(q_ptr[max]);
-
- /* No themes */
- theme.treasure = 100;
- theme.combat = 100;
- theme.magic = 100;
- theme.tools = 100;
-
- /* Make a great object */
- make_object(q_ptr[max], TRUE, TRUE, theme);
- q_ptr[max]->found = OBJ_FOUND_REWARD;
-
- C_MAKE(items[max], 100, char);
- object_desc(items[max], q_ptr[max], 0, 0);
- max++;
- }
-
-
- while (TRUE)
- {
- res = ask_menu("Choose a reward to get(a-c to choose, ESC to cancel)?", (char **)items, 3);
-
- /* Ok ? lets learn ! */
- if (res > -1)
- {
- /* Drop it in the dungeon */
- drop_near(q_ptr[res], -1, y + 1, x);
-
- cmsg_print(TERM_YELLOW, "There, Noble Hero. I put it there. Thanks again!");
- break;
- }
- }
-
- for (i = 0; i < 3; i++)
- {
-
- object_type *o_ptr = q_ptr[i];
-
- /* Check if there is any not chosen artifact */
- if (i != res && artifact_p(o_ptr))
- {
- /* Mega-Hack -- Preserve the artifact */
- if (o_ptr->tval == TV_RANDART)
- {
- random_artifacts[o_ptr->sval].generated = FALSE;
- }
- else if (k_info[o_ptr->k_idx].flags3 & TR3_NORM_ART)
- {
- k_info[o_ptr->k_idx].artifact = FALSE;
- }
- else if (o_ptr->name1)
- {
- a_info[o_ptr->name1].cur_num = 0;
- }
- }
- }
-
- for (i = 0; i < 3; i++)
- C_KILL(items[i], 100, char);
-
-}
-
-void princess_death(s32b m_idx, s32b r_idx)
-{
- int r;
-
- cmsg_print(TERM_YELLOW, "O Great And Noble Hero, you saved me!");
- cmsg_print(TERM_YELLOW, "I am heading home now. I cannot reward you as I should, but please take this.");
-
- /* Look for the princess */
- for (r = m_max - 1; r >= 1; r--)
- {
- /* Access the monster */
- monster_type *m_ptr = &m_list[r];
-
- /* Ignore "dead" monsters */
- if (!m_ptr->r_idx) continue;
-
- /* Is it the princess? */
- if (m_ptr->r_idx == 969)
- {
- int x = m_ptr->fx;
- int y = m_ptr->fy;
- int i, j;
-
- delete_monster_idx(r);
-
- /* Wipe the glass walls and create a stair */
- for (i = x - 1; i <= x + 1; i++)
- for (j = y - 1; j <= y + 1; j++)
- {
- if (in_bounds(j, i)) cave_set_feat(j, i, FEAT_FLOOR);
- }
- cave_set_feat(y, x, FEAT_MORE);
-
- do_get_new_obj(y, x);
-
- random_quests[dun_level].done = TRUE;
-
- break;
- }
- }
-}
-
-void hero_death(s32b m_idx, s32b r_idx)
-{
- random_quests[dun_level].done = TRUE;
-
- cmsg_print(TERM_YELLOW, "The adventurer steps out of the shadows and picks up his sword:");
- cmsg_print(TERM_YELLOW, "'Ah! My sword! My trusty sword! Thanks.");
-
- if (!can_create_companion())
- {
- cmsg_print(TERM_YELLOW, "I must go on my own way now.");
- cmsg_print(TERM_YELLOW, "But before I go, I can help your skills.'");
- cmsg_print(TERM_YELLOW, "He touches your forehead.");
- do_get_new_skill();
- return;
- }
- cmsg_print(TERM_YELLOW, "If you wish, I can help you in your adventures.'");
-
- /* Flush input */
- flush();
-
- if (get_check("Do you want him to join you? "))
- {
- int x, y, i;
-
- /* Look for a location */
- for (i = 0; i < 20; ++i)
- {
- /* Pick a distance */
- int d = (i / 15) + 1;
-
- /* Pick a location */
- scatter(&y, &x, p_ptr->py, p_ptr->px, d);
-
- /* Require "empty" floor grid */
- if (!cave_empty_bold(y, x)) continue;
-
- /* Hack -- no summon on glyph of warding */
- if (cave[y][x].feat == FEAT_GLYPH) continue;
- if (cave[y][x].feat == FEAT_MINOR_GLYPH) continue;
-
- /* Nor on the between */
- if (cave[y][x].feat == FEAT_BETWEEN) continue;
-
- /* ... nor on the Pattern */
- if ((cave[y][x].feat >= FEAT_PATTERN_START) &&
- (cave[y][x].feat <= FEAT_PATTERN_XTRA2))
- continue;
-
- /* Okay */
- break;
- }
-
- if (i < 20)
- {
- int m_idx;
-
- m_allow_special[test_monster_name("Adventurer")] = TRUE;
- m_idx = place_monster_one(y, x, test_monster_name("Adventurer"), 0, FALSE, MSTATUS_COMPANION);
- m_allow_special[test_monster_name("Adventurer")] = FALSE;
- if (m_idx)
- {
- m_list[m_idx].exp = MONSTER_EXP(1 + (dun_level * 3 / 2));
- m_list[m_idx].status = MSTATUS_COMPANION;
- monster_check_experience(m_idx, TRUE);
- }
- }
- else
- msg_print("The adventurer suddenly seems afraid and flees...");
- }
- else
- {
- cmsg_print(TERM_YELLOW, "'As you wish, but I want to do something for you.'");
- cmsg_print(TERM_YELLOW, "He touches your forehead.");
- do_get_new_skill();
- }
-}
-
-bool_ quest_random_death_hook(char *fmt)
-{
- int r_idx;
- s32b m_idx;
-
- m_idx = get_next_arg(fmt);
- r_idx = m_list[m_idx].r_idx;
-
- if (!(dungeon_flags1 & DF1_PRINCIPAL)) return (FALSE);
- if ((dun_level < 1) || (dun_level >= MAX_RANDOM_QUEST)) return (FALSE);
- if (!random_quests[dun_level].type) return (FALSE);
- if (random_quests[dun_level].done) return (FALSE);
- if (p_ptr->inside_quest) return (FALSE);
- if (random_quests[dun_level].r_idx != r_idx) return (FALSE);
-
- if (!(m_list[m_idx].mflag & MFLAG_QUEST)) return (FALSE);
-
- /* Killed enough ?*/
- quest[QUEST_RANDOM].data[0]++;
- if (quest[QUEST_RANDOM].data[0] == random_quests[dun_level].type)
- {
- if (is_randhero(dun_level))
- hero_death(m_idx, r_idx);
- else
- princess_death(m_idx, r_idx);
- }
-
- return (FALSE);
-}
-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)
-{
- if (!(dungeon_flags1 & DF1_PRINCIPAL)) return (FALSE);
- if ((dun_level < 1) || (dun_level >= MAX_RANDOM_QUEST)) return (FALSE);
- if (!random_quests[dun_level].type) return (FALSE);
- if (random_quests[dun_level].done) return (FALSE);
- if (p_ptr->inside_quest) return (FALSE);
- if (!dun_level) return (FALSE);
-
- if (is_randhero(dun_level))
- {
- cmsg_format(TERM_YELLOW, "A strange man wrapped in a dark cloak steps out of the shadows:");
- cmsg_format(TERM_YELLOW, "'Oh, please help me! A horrible %s stole my sword! I'm nothing without it.'", r_info[random_quests[dun_level].r_idx].name + r_name);
- }
- else
- 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)
-{
- int i;
-
- if (!(dungeon_flags1 & DF1_PRINCIPAL)) return (FALSE);
- if ((dun_level < 1) || (dun_level >= MAX_RANDOM_QUEST)) return (FALSE);
- if (!random_quests[dun_level].type) return (FALSE);
- if (random_quests[dun_level].done) return (FALSE);
- if (p_ptr->inside_quest) return (FALSE);
- if (!is_randhero(dun_level)) return (FALSE);
-
- i = random_quests[dun_level].type;
-
- m_allow_special[random_quests[dun_level].r_idx] = TRUE;
- while (i)
- {
- int m_idx, y = rand_range(1, cur_hgt - 2), x = rand_range(1, cur_wid - 2);
-
- m_idx = place_monster_one(y, x, random_quests[dun_level].r_idx, 0, FALSE, MSTATUS_ENEMY);
- if (m_idx)
- {
- monster_type *m_ptr = &m_list[m_idx];
- m_ptr->mflag |= MFLAG_QUEST;
- i--;
- }
- }
- m_allow_special[random_quests[dun_level].r_idx] = FALSE;
-
- return (FALSE);
-}
-bool_ quest_random_gen_hook(char *fmt)
-{
- s32b x, y, bx0, by0;
- int xstart;
- int ystart;
- int y2, x2, yval, xval;
- int y1, x1, xsize, ysize;
-
- if (!(dungeon_flags1 & DF1_PRINCIPAL)) return (FALSE);
- if ((dun_level < 1) || (dun_level >= MAX_RANDOM_QUEST)) return (FALSE);
- if (!random_quests[dun_level].type) return (FALSE);
- if (random_quests[dun_level].done) return (FALSE);
- if (p_ptr->inside_quest) return (FALSE);
- if (quest[QUEST_RANDOM].data[1]) return (FALSE);
- if (is_randhero(dun_level)) return (FALSE);
-
- by0 = get_next_arg(fmt);
- bx0 = get_next_arg(fmt);
-
- /* Pick a room size */
- get_map_size(format("qrand%d.map", random_quests[dun_level].type), &ysize, &xsize);
-
- /* 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 = y1 + ysize - 1;
- x2 = x1 + xsize - 1;
-
- /* Place a full floor under the room */
- for (y = y1; y <= y2; y++)
- {
- for (x = x1; x <= x2; x++)
- {
- cave_set_feat(y, x, floor_type[rand_int(100)]);
- cave[y][x].info |= (CAVE_ROOM|CAVE_GLOW);
- }
- }
-
- build_rectangle(y1 - 1, x1 - 1, y2 + 1, x2 + 1, feat_wall_outer, CAVE_ROOM | CAVE_GLOW);
-
- /* Set the correct monster hook */
- set_mon_num_hook();
-
- /* Prepare allocation table */
- get_mon_num_prep();
-
- xstart = x1;
- ystart = y1;
- init_flags = INIT_CREATE_DUNGEON;
- process_dungeon_file(format("qrand%d.map", random_quests[dun_level].type), &ystart, &xstart, cur_hgt, cur_wid, TRUE, TRUE);
-
- for (x = x1; x < xstart; x++)
- for (y = y1; y < ystart; y++)
- {
- cave[y][x].info |= CAVE_ICKY | CAVE_ROOM;
- if (cave[y][x].feat == FEAT_MARKER)
- {
- monster_type *m_ptr;
- int i;
-
- m_allow_special[random_quests[dun_level].r_idx] = TRUE;
- i = place_monster_one(y, x, random_quests[dun_level].r_idx, 0, FALSE, MSTATUS_ENEMY);
- m_allow_special[random_quests[dun_level].r_idx] = FALSE;
- if (i)
- {
- m_ptr = &m_list[i];
- m_ptr->mflag |= MFLAG_QUEST;
- }
- }
- }
-
- /* Dont try another one for this generation */
- quest[QUEST_RANDOM].data[1] = 1;
-
- /* Boost level feeling a bit - a la pits */
- rating += 10;
-
- return (TRUE);
-}
-bool_ quest_random_dump_hook(char *fmt)
-{
- static char *number[] =
- { "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten" };
- int i, valid = 0, lscnt = 0, pcnt = 0;
-
- for (i = 0; i < MAX_RANDOM_QUEST; i++)
- {
- if (random_quests[i].type)
- {
- valid++;
- if (random_quests[i].done)
- {
- if (is_randhero(i))
- lscnt++;
- else
- pcnt++;
- }
- }
- }
-
- if (valid)
- {
- if (pcnt > 10)
- fprintf(hook_file, "\n You have completed %d princess quests.", pcnt);
- else if (pcnt > 1)
- fprintf(hook_file, "\n You have completed %s princess quests.", number[pcnt-2]);
- else if (pcnt == 1)
- fprintf(hook_file, "\n You have completed one princess quest.");
- else
- fprintf(hook_file, "\n You haven't completed a single princess quest.");
-
- if (lscnt > 10)
- fprintf(hook_file, "\n You have completed %d lost sword quests.", lscnt);
- else if (lscnt > 1)
- fprintf(hook_file, "\n You have completed %s lost sword quests.", number[lscnt-2]);
- else if (lscnt == 1)
- fprintf(hook_file, "\n You have completed one lost sword quest.");
- else
- fprintf(hook_file, "\n You haven't completed a single lost sword quest.");
- }
-
- return (FALSE);
-}
-
-bool_ quest_random_describe(FILE *fff)
-{
- if (!(dungeon_flags1 & DF1_PRINCIPAL)) return FALSE;
- if ((dun_level < 1) || (dun_level >= MAX_RANDOM_QUEST)) return FALSE;
- if (!random_quests[dun_level].type) return FALSE;
- if (random_quests[dun_level].done) return FALSE;
- if (p_ptr->inside_quest) return FALSE;
- if (!dun_level) return FALSE;
-
- if (!is_randhero(dun_level))
- {
- fprintf(fff, "#####yCaptured princess!\n");
- fprintf(fff, "A princess is being held prisoner and tortured here!\n");
- fprintf(fff, "Save her from the horrible %s.\n",
- r_info[random_quests[dun_level].r_idx].name + r_name);
- }
- else
- {
- fprintf(fff, "#####yLost sword!\n");
- fprintf(fff, "An adventurer lost his sword to a bunch of %s!\n",
- r_info[random_quests[dun_level].r_idx].name + r_name);
- fprintf(fff, "Kill them all to get it back.\n");
- }
- fprintf(fff, "Number: %d, Killed: %ld.\n",
- random_quests[dun_level].type, (long int) quest[QUEST_RANDOM].data[0]);
- fprintf(fff, "\n");
- return TRUE;
-}
-
-bool_ quest_random_init_hook(int q_idx)
-{
- add_hook(HOOK_MONSTER_DEATH, quest_random_death_hook, "rand_death");
- add_hook(HOOK_NEW_LEVEL, quest_random_turn_hook, "rand_new_lvl");
- add_hook(HOOK_LEVEL_REGEN, quest_random_turn_hook, "rand_regen_lvl");
- add_hook(HOOK_LEVEL_END_GEN, quest_random_gen_hero_hook, "rand_gen_hero");
- add_hook(HOOK_BUILD_ROOM1, quest_random_gen_hook, "rand_gen");
- add_hook(HOOK_FEELING, quest_random_feeling_hook, "rand_feel");
- add_hook(HOOK_CHAR_DUMP, quest_random_dump_hook, "rand_dump");
- return (FALSE);
-}
diff --git a/src/q_rand.cc b/src/q_rand.cc
new file mode 100644
index 00000000..b643ca39
--- /dev/null
+++ b/src/q_rand.cc
@@ -0,0 +1,687 @@
+#include "q_rand.hpp"
+
+#include "artifact_type.hpp"
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "dungeon_flag.hpp"
+#include "dungeon_info_type.hpp"
+#include "game.hpp"
+#include "generate.hpp"
+#include "hook_build_room1_in.hpp"
+#include "hook_chardump_in.hpp"
+#include "hook_monster_death_in.hpp"
+#include "hooks.hpp"
+#include "init1.hpp"
+#include "lua_bind.hpp"
+#include "messages.hpp"
+#include "monster2.hpp"
+#include "monster3.hpp"
+#include "monster_race.hpp"
+#include "monster_race_flag.hpp"
+#include "monster_spell_flag.hpp"
+#include "monster_type.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_flag.hpp"
+#include "object_kind.hpp"
+#include "object_type.hpp"
+#include "player_type.hpp"
+#include "skills.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+#include "z-rand.hpp"
+
+#include <cassert>
+#include <fmt/format.h>
+
+static int randquest_hero[] = { 20, 13, 15, 16, 9, 17, 18, 8, -1 };
+
+/* Possible number(and layout) or random quests */
+#define MAX_RANDOM_QUESTS_TYPES ((8 * 3) + (8 * 1))
+static 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
+
+// Generate lookup function
+GENERATE_MONSTER_LOOKUP_FN(get_adventurer, "Adventurer")
+
+void initialize_random_quests(int n)
+{
+ auto const &d_info = game->edit_data.d_info;
+ auto &r_info = game->edit_data.r_info;
+ auto &messages = game->messages;
+
+ int step, lvl, i, k;
+ int old_type = dungeon_type;
+
+ /* Zero out everything first */
+ for (i = 0; i < MAX_RANDOM_QUEST; i++) random_quests[i].type = 0;
+
+ if (n == 0) return;
+
+ /* 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 = nullptr;
+
+ int rl = (lvl / 1000) + 1;
+
+ int min_level;
+
+ int tries = 5000;
+
+ random_quest *q_ptr = &random_quests[rl];
+
+ /* Find the appropriate dungeon */
+ for (std::size_t j = 0; j < d_info.size(); j++)
+ {
+ auto d_ptr = &d_info[j];
+
+ if (!(d_ptr->flags & DF_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->flags & RF_SPECIAL_GENE) continue;
+ if (r_ptr->flags & RF_NEVER_GENE) continue;
+
+ /* Accept only monsters that are not breeders */
+ if (r_ptr->spells & SF_MULTIPLY) continue;
+
+ /* Forbid joke monsters */
+ if (r_ptr->flags & RF_JOKEANGBAND) continue;
+
+ /* Accept only monsters that are not friends */
+ if (r_ptr->flags & RF_PET) continue;
+
+ /* Refuse nazguls */
+ if (r_ptr->flags & RF_NAZGUL) continue;
+
+ /* Accept only monsters that are not good */
+ if (r_ptr->flags & RF_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->flags & RF_UNIQUE) &&
+ ((q_ptr->type != 1) || (r_ptr->max_num == -1))) continue;
+
+ /* No single non uniques */
+ if ((!(r_ptr->flags & RF_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)
+ {
+ messages.add(format("Could not find quest monster on lvl %d", rl), TERM_RED);
+ }
+ q_ptr->type = 0;
+ }
+ else
+ {
+ if (r_ptr->flags & RF_UNIQUE)
+ {
+ r_ptr->max_num = -1;
+ }
+
+ q_ptr->done = false;
+
+ if (wizard)
+ {
+ messages.add(format("Quest for %d on lvl %d", q_ptr->r_idx, rl), TERM_RED);
+ }
+ }
+
+ lvl += step;
+ }
+
+ dungeon_type = old_type;
+}
+
+bool_ is_randhero(int level)
+{
+ int i;
+ bool_ result = FALSE;
+
+ for (i = 0; randquest_hero[i] != -1; i++)
+ {
+ if (random_quests[level].type == randquest_hero[i])
+ {
+ result = TRUE;
+ break;
+ }
+ }
+
+ return result;
+}
+
+static void do_get_new_obj(int y, int x)
+{
+ auto &k_info = game->edit_data.k_info;
+ auto &a_info = game->edit_data.a_info;
+
+ object_type *q_ptr[3], forge[3];
+ int res, i;
+
+ /* Create objects */
+ std::vector<std::string> items;
+ for (i = 0; i < 3; i++)
+ {
+ /* Get local object */
+ q_ptr[i] = &forge[i];
+
+ /* Wipe the object */
+ object_wipe(q_ptr[i]);
+
+ /* Make a great object */
+ make_object(q_ptr[i], TRUE, TRUE, obj_theme::no_theme());
+ q_ptr[i]->found = OBJ_FOUND_REWARD;
+
+ char buf[100];
+ object_desc(buf, q_ptr[i], 0, 0);
+ items.push_back(buf);
+ }
+
+
+ while (TRUE)
+ {
+ res = ask_menu("Choose a reward to get(a-c to choose, ESC to cancel)?", items);
+
+ /* Ok ? lets learn ! */
+ if (res > -1)
+ {
+ /* Drop it in the dungeon */
+ drop_near(q_ptr[res], -1, y + 1, x);
+
+ cmsg_print(TERM_YELLOW, "There, Noble Hero. I put it there. Thanks again!");
+ break;
+ }
+ }
+
+ for (i = 0; i < 3; i++)
+ {
+
+ object_type *o_ptr = q_ptr[i];
+
+ /* Check if there is any not chosen artifact */
+ if (i != res && artifact_p(o_ptr))
+ {
+ /* Mega-Hack -- Preserve the artifact */
+ if (o_ptr->tval == TV_RANDART)
+ {
+ game->random_artifacts[o_ptr->sval].generated = FALSE;
+ }
+ else if (k_info[o_ptr->k_idx].flags & TR_NORM_ART)
+ {
+ k_info[o_ptr->k_idx].artifact = FALSE;
+ }
+ else if (o_ptr->name1)
+ {
+ a_info[o_ptr->name1].cur_num = 0;
+ }
+ }
+ }
+}
+
+static void princess_death(s32b m_idx, s32b r_idx)
+{
+ int r;
+
+ cmsg_print(TERM_YELLOW, "O Great And Noble Hero, you saved me!");
+ cmsg_print(TERM_YELLOW, "I am heading home now. I cannot reward you as I should, but please take this.");
+
+ /* Look for the princess */
+ for (r = m_max - 1; r >= 1; r--)
+ {
+ /* Access the monster */
+ monster_type *m_ptr = &m_list[r];
+
+ /* Ignore "dead" monsters */
+ if (!m_ptr->r_idx) continue;
+
+ /* Is it the princess? */
+ if (m_ptr->r_idx == 969)
+ {
+ int x = m_ptr->fx;
+ int y = m_ptr->fy;
+ int i, j;
+
+ delete_monster_idx(r);
+
+ /* Wipe the glass walls and create a stair */
+ for (i = x - 1; i <= x + 1; i++)
+ for (j = y - 1; j <= y + 1; j++)
+ {
+ if (in_bounds(j, i)) cave_set_feat(j, i, FEAT_FLOOR);
+ }
+ cave_set_feat(y, x, FEAT_MORE);
+
+ do_get_new_obj(y, x);
+
+ random_quests[dun_level].done = true;
+
+ break;
+ }
+ }
+}
+
+static void hero_death(s32b m_idx, s32b r_idx)
+{
+ random_quests[dun_level].done = true;
+
+ cmsg_print(TERM_YELLOW, "The adventurer steps out of the shadows and picks up his sword:");
+ cmsg_print(TERM_YELLOW, "'Ah! My sword! My trusty sword! Thanks.");
+
+ if (!can_create_companion())
+ {
+ cmsg_print(TERM_YELLOW, "I must go on my own way now.");
+ cmsg_print(TERM_YELLOW, "But before I go, I can help your skills.'");
+ cmsg_print(TERM_YELLOW, "He touches your forehead.");
+ do_get_new_skill();
+ return;
+ }
+ cmsg_print(TERM_YELLOW, "If you wish, I can help you in your adventures.'");
+
+ /* Flush input */
+ flush();
+
+ if (get_check("Do you want him to join you? "))
+ {
+ int x, y, i;
+
+ /* Look for a location */
+ for (i = 0; i < 20; ++i)
+ {
+ /* Pick a distance */
+ int d = (i / 15) + 1;
+
+ /* Pick a location */
+ scatter(&y, &x, p_ptr->py, p_ptr->px, d);
+
+ /* Require "empty" floor grid */
+ if (!cave_empty_bold(y, x)) continue;
+
+ /* Hack -- no summon on glyph of warding */
+ if (cave[y][x].feat == FEAT_GLYPH) continue;
+ if (cave[y][x].feat == FEAT_MINOR_GLYPH) continue;
+
+ /* Nor on the between */
+ if (cave[y][x].feat == FEAT_BETWEEN) continue;
+
+ /* ... nor on the Pattern */
+ if ((cave[y][x].feat >= FEAT_PATTERN_START) &&
+ (cave[y][x].feat <= FEAT_PATTERN_XTRA2))
+ continue;
+
+ /* Okay */
+ break;
+ }
+
+ if (i < 20)
+ {
+ int r_idx = get_adventurer();
+
+ m_allow_special[r_idx] = TRUE;
+ int m_idx = place_monster_one(y, x, r_idx, 0, FALSE, MSTATUS_COMPANION);
+ m_allow_special[r_idx] = FALSE;
+
+ if (m_idx)
+ {
+ m_list[m_idx].exp = monster_exp(1 + (dun_level * 3 / 2));
+ m_list[m_idx].status = MSTATUS_COMPANION;
+ monster_check_experience(m_idx, TRUE);
+ }
+ }
+ else
+ msg_print("The adventurer suddenly seems afraid and flees...");
+ }
+ else
+ {
+ cmsg_print(TERM_YELLOW, "'As you wish, but I want to do something for you.'");
+ cmsg_print(TERM_YELLOW, "He touches your forehead.");
+ do_get_new_skill();
+ }
+}
+
+static bool quest_random_death_hook(void *, void *in_, void *)
+{
+ struct hook_monster_death_in *in = static_cast<struct hook_monster_death_in *>(in_);
+ s32b m_idx = in->m_idx;
+ int r_idx = m_list[m_idx].r_idx;
+
+ if ((!(dungeon_flags & DF_PRINCIPAL)) ||
+ ((dun_level < 1) || (dun_level >= MAX_RANDOM_QUEST)) ||
+ (!random_quests[dun_level].type) ||
+ (random_quests[dun_level].done) ||
+ (p_ptr->inside_quest) ||
+ (random_quests[dun_level].r_idx != r_idx) ||
+ (!(m_list[m_idx].mflag & MFLAG_QUEST)))
+ {
+ return false;
+ }
+
+ /* Killed enough ?*/
+ quest[QUEST_RANDOM].data[0]++;
+ if (quest[QUEST_RANDOM].data[0] == random_quests[dun_level].type)
+ {
+ if (is_randhero(dun_level))
+ {
+ hero_death(m_idx, r_idx);
+ }
+ else
+ {
+ princess_death(m_idx, r_idx);
+ }
+ }
+
+ return false;
+}
+
+static bool quest_random_turn_hook(void *, void *, void *)
+{
+ quest[QUEST_RANDOM].data[0] = 0;
+ quest[QUEST_RANDOM].data[1] = 0;
+ return false;
+}
+
+static bool quest_random_feeling_hook(void *, void *, void *)
+{
+ auto const &r_info = game->edit_data.r_info;
+
+ if ((!(dungeon_flags & DF_PRINCIPAL)) ||
+ ((dun_level < 1) || (dun_level >= MAX_RANDOM_QUEST)) ||
+ (!random_quests[dun_level].type) ||
+ (random_quests[dun_level].done) ||
+ (p_ptr->inside_quest) ||
+ (!dun_level))
+ {
+ return false;
+ }
+
+ if (is_randhero(dun_level))
+ {
+ cmsg_format(TERM_YELLOW, "A strange man wrapped in a dark cloak steps out of the shadows:");
+ cmsg_format(TERM_YELLOW, "'Oh, please help me! A horrible %s stole my sword! I'm nothing without it.'", r_info[random_quests[dun_level].r_idx].name);
+ }
+ else
+ {
+ cmsg_format(TERM_YELLOW, "You hear someone shouting: 'Leave me alone, stupid %s'", r_info[random_quests[dun_level].r_idx].name);
+ }
+ return false;
+}
+
+static bool quest_random_gen_hero_hook(void *, void *, void *)
+{
+ if ((!(dungeon_flags & DF_PRINCIPAL)) ||
+ ((dun_level < 1) || (dun_level >= MAX_RANDOM_QUEST)) ||
+ (!random_quests[dun_level].type) ||
+ (random_quests[dun_level].done) ||
+ (p_ptr->inside_quest) ||
+ (!is_randhero(dun_level)))
+ {
+ return false;
+ }
+
+ int i = random_quests[dun_level].type;
+
+ m_allow_special[random_quests[dun_level].r_idx] = TRUE;
+ while (i)
+ {
+ int m_idx, y = rand_range(1, cur_hgt - 2), x = rand_range(1, cur_wid - 2);
+
+ m_idx = place_monster_one(y, x, random_quests[dun_level].r_idx, 0, FALSE, MSTATUS_ENEMY);
+ if (m_idx)
+ {
+ monster_type *m_ptr = &m_list[m_idx];
+ m_ptr->mflag |= MFLAG_QUEST;
+ i--;
+ }
+ }
+ m_allow_special[random_quests[dun_level].r_idx] = FALSE;
+
+ return false;
+}
+
+static bool quest_random_gen_hook(void *, void *in_, void *)
+{
+ struct hook_build_room1_in *in = static_cast<struct hook_build_room1_in *>(in_);
+ s32b bx0 = in->x;
+ s32b by0 = in->y;
+ s32b x, y;
+ int xstart;
+ int ystart;
+ int y2, x2, yval, xval;
+ int y1, x1, xsize, ysize;
+
+ if ((!(dungeon_flags & DF_PRINCIPAL)) ||
+ ((dun_level < 1) || (dun_level >= MAX_RANDOM_QUEST)) ||
+ (!random_quests[dun_level].type) ||
+ (random_quests[dun_level].done) ||
+ (p_ptr->inside_quest) ||
+ (quest[QUEST_RANDOM].data[1]) ||
+ (is_randhero(dun_level)))
+ {
+ return false;
+ }
+
+ /* Pick a room size */
+ get_map_size(format("qrand%d.map", random_quests[dun_level].type), &ysize, &xsize);
+
+ /* 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 = y1 + ysize - 1;
+ x2 = x1 + xsize - 1;
+
+ /* Place a full floor under the room */
+ for (y = y1; y <= y2; y++)
+ {
+ for (x = x1; x <= x2; x++)
+ {
+ cave_set_feat(y, x, floor_type[rand_int(100)]);
+ cave[y][x].info |= (CAVE_ROOM|CAVE_GLOW);
+ }
+ }
+
+ build_rectangle(y1 - 1, x1 - 1, y2 + 1, x2 + 1, feat_wall_outer, CAVE_ROOM | CAVE_GLOW);
+
+ /* Set the correct monster hook */
+ set_mon_num_hook();
+
+ /* Prepare allocation table */
+ get_mon_num_prep();
+
+ xstart = x1;
+ ystart = y1;
+ init_flags = INIT_CREATE_DUNGEON;
+ process_dungeon_file(format("qrand%d.map", random_quests[dun_level].type), &ystart, &xstart, cur_hgt, cur_wid, TRUE, TRUE);
+
+ for (x = x1; x < xstart; x++)
+ {
+ for (y = y1; y < ystart; y++)
+ {
+ cave[y][x].info |= CAVE_ICKY | CAVE_ROOM;
+ if (cave[y][x].feat == FEAT_MARKER)
+ {
+ m_allow_special[random_quests[dun_level].r_idx] = TRUE;
+ int i = place_monster_one(y, x, random_quests[dun_level].r_idx, 0, FALSE, MSTATUS_ENEMY);
+ m_allow_special[random_quests[dun_level].r_idx] = FALSE;
+ if (i)
+ {
+ auto m_ptr = &m_list[i];
+ m_ptr->mflag |= MFLAG_QUEST;
+ }
+ }
+ }
+ }
+
+ /* Dont try another one for this generation */
+ quest[QUEST_RANDOM].data[1] = 1;
+
+ /* Boost level feeling a bit - a la pits */
+ rating += 10;
+
+ return true;
+}
+
+static bool quest_random_dump_hook(void *, void *in_, void *)
+{
+ static const char *number[] = { "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten" };
+ struct hook_chardump_in *in = static_cast<struct hook_chardump_in *>(in_);
+ FILE *f = in->file;
+ int i, valid = 0, lscnt = 0, pcnt = 0;
+
+ for (i = 0; i < MAX_RANDOM_QUEST; i++)
+ {
+ if (random_quests[i].type)
+ {
+ valid++;
+ if (random_quests[i].done)
+ {
+ if (is_randhero(i))
+ lscnt++;
+ else
+ pcnt++;
+ }
+ }
+ }
+
+ if (valid)
+ {
+ if (pcnt > 10)
+ fprintf(f, "\n You have completed %d princess quests.", pcnt);
+ else if (pcnt > 1)
+ fprintf(f, "\n You have completed %s princess quests.", number[pcnt-2]);
+ else if (pcnt == 1)
+ fprintf(f, "\n You have completed one princess quest.");
+ else
+ fprintf(f, "\n You haven't completed a single princess quest.");
+
+ if (lscnt > 10)
+ fprintf(f, "\n You have completed %d lost sword quests.", lscnt);
+ else if (lscnt > 1)
+ fprintf(f, "\n You have completed %s lost sword quests.", number[lscnt-2]);
+ else if (lscnt == 1)
+ fprintf(f, "\n You have completed one lost sword quest.");
+ else
+ fprintf(f, "\n You haven't completed a single lost sword quest.");
+ }
+
+ return false;
+}
+
+std::string quest_random_describe()
+{
+ auto const &r_info = game->edit_data.r_info;
+
+ // Only emit description if we're actually on a
+ // random quest level.
+ if ((!(dungeon_flags & DF_PRINCIPAL)) ||
+ ((dun_level < 1) || (dun_level >= MAX_RANDOM_QUEST)) ||
+ (!random_quests[dun_level].type) ||
+ (random_quests[dun_level].done) ||
+ (p_ptr->inside_quest) ||
+ (!dun_level))
+ {
+ return "";
+ }
+
+ fmt::MemoryWriter w;
+
+ if (!is_randhero(dun_level))
+ {
+ w.write("#####yCaptured princess!\n");
+ w.write("A princess is being held prisoner and tortured here!\n");
+ w.write("Save her from the horrible {}.\n", r_info[random_quests[dun_level].r_idx].name);
+ }
+ else
+ {
+ w.write("#####yLost sword!\n");
+ w.write("An adventurer lost his sword to a bunch of {}!\n", r_info[random_quests[dun_level].r_idx].name);
+ w.write("Kill them all to get it back.\n");
+ }
+
+ w.write("Number: {}, Killed: {}.",
+ random_quests[dun_level].type,
+ quest[QUEST_RANDOM].data[0]);
+
+ return w.str();
+}
+
+void quest_random_init_hook()
+{
+ add_hook_new(HOOK_MONSTER_DEATH, quest_random_death_hook, "rand_death", NULL);
+ add_hook_new(HOOK_NEW_LEVEL, quest_random_turn_hook, "rand_new_lvl", NULL);
+ add_hook_new(HOOK_LEVEL_REGEN, quest_random_turn_hook, "rand_regen_lvl", NULL);
+ add_hook_new(HOOK_LEVEL_END_GEN, quest_random_gen_hero_hook, "rand_gen_hero", NULL);
+ add_hook_new(HOOK_BUILD_ROOM1, quest_random_gen_hook, "rand_gen", NULL);
+ add_hook_new(HOOK_FEELING, quest_random_feeling_hook, "rand_feel", NULL);
+ add_hook_new(HOOK_CHAR_DUMP, quest_random_dump_hook, "rand_dump", NULL);
+}
diff --git a/src/q_rand.hpp b/src/q_rand.hpp
new file mode 100644
index 00000000..a992aa98
--- /dev/null
+++ b/src/q_rand.hpp
@@ -0,0 +1,10 @@
+#pragma once
+
+#include "h-basic.h"
+
+#include <string>
+
+void initialize_random_quests(int n);
+bool_ is_randhero(int level);
+void quest_random_init_hook();
+std::string quest_random_describe();
diff --git a/src/q_shroom.c b/src/q_shroom.c
deleted file mode 100644
index b6e26cdf..00000000
--- a/src/q_shroom.c
+++ /dev/null
@@ -1,293 +0,0 @@
-#undef cquest
-#define cquest (quest[QUEST_SHROOM])
-
-bool_ quest_shroom_speak_hook(char *fmt);
-
-bool_ quest_shroom_town_gen_hook(char *fmt)
-{
- int m_idx, x = 1, y = 1, tries = 10000;
- s32b small;
-
- small = get_next_arg(fmt);
-
- /* Generate the shrooms field */
- if ((!small) && (p_ptr->wilderness_y == 21) && (p_ptr->wilderness_x == 33))
- {
- /* Create the field */
- for (x = (cur_wid / 2) - 7; x <= (cur_wid / 2) + 7; x++)
- for (y = (cur_hgt / 2) - 5; y <= (cur_hgt / 2) + 5; y++)
- cave_set_feat(y, x, 181);
-
- /* Throw in some 'shrooms */
- for (x = 0; x < (cquest.data[1] - cquest.data[0]); x++)
- {
- object_type forge, *q_ptr = &forge;
-
- object_prep(q_ptr, lookup_kind(TV_FOOD, rand_range(1, 18)));
- q_ptr->number = 1;
- /* Mark them */
- q_ptr->pval2 = 1;
- drop_near(q_ptr, -1, rand_range((cur_hgt / 2) - 5, (cur_hgt / 2) + 5), rand_range((cur_wid / 2) - 7, (cur_wid / 2) + 7));
- }
-
- /* Throw in some dogs ;) */
- y = rand_range((cur_hgt / 2) - 5, (cur_hgt / 2) + 5);
- x = rand_range((cur_wid / 2) - 7, (cur_wid / 2) + 7);
- m_allow_special[test_monster_name("Grip, Farmer Maggot's dog")] = TRUE;
- m_idx = place_monster_one(y, x, test_monster_name("Grip, Farmer Maggot's dog"), 0, FALSE, MSTATUS_ENEMY);
- if (m_idx) m_list[m_idx].mflag |= MFLAG_QUEST;
- m_allow_special[test_monster_name("Grip, Farmer Maggot's dog")] = FALSE;
-
- y = rand_range((cur_hgt / 2) - 5, (cur_hgt / 2) + 5);
- x = rand_range((cur_wid / 2) - 7, (cur_wid / 2) + 7);
- m_allow_special[test_monster_name("Wolf, Farmer Maggot's dog")] = TRUE;
- m_idx = place_monster_one(y, x, test_monster_name("Wolf, Farmer Maggot's dog"), 0, FALSE, MSTATUS_ENEMY);
- if (m_idx) m_list[m_idx].mflag |= MFLAG_QUEST;
- m_allow_special[test_monster_name("Wolf, Farmer Maggot's dog")] = FALSE;
-
- y = rand_range((cur_hgt / 2) - 5, (cur_hgt / 2) + 5);
- x = rand_range((cur_wid / 2) - 7, (cur_wid / 2) + 7);
- m_allow_special[test_monster_name("Fang, Farmer Maggot's dog")] = TRUE;
- m_idx = place_monster_one(y, x, test_monster_name("Fang, Farmer Maggot's dog"), 0, FALSE, MSTATUS_ENEMY);
- if (m_idx) m_list[m_idx].mflag |= MFLAG_QUEST;
- m_allow_special[test_monster_name("Fang, Farmer Maggot's dog")] = FALSE;
-
- msg_print("You hear frenzied barking.");
- }
-
- /* Generate maggot in town, in daylight */
- if ((bst(HOUR, turn) < 6) || (bst(HOUR, turn) >= 18) || (cquest.status > QUEST_STATUS_COMPLETED) || (small) || (p_ptr->town_num != 1)) return (FALSE);
-
- /* Find a good position */
- while (tries)
- {
- /* Get a random spot */
- y = randint(20) + (cur_hgt / 2) - 10;
- x = randint(20) + (cur_wid / 2) - 10;
-
- /* Is it a good spot ? */
- /* Not in player los, and avoid shop grids */
- if (!los(p_ptr->py, p_ptr->px, y, x) && cave_empty_bold(y, x) &&
- cave_plain_floor_bold(y, x)) break;
-
- /* One less try */
- tries--;
- }
-
- /* Place Farmer Maggot */
- m_allow_special[test_monster_name("Farmer Maggot")] = TRUE;
- place_monster_one(y, x, test_monster_name("Farmer Maggot"), 0, FALSE, MSTATUS_ENEMY);
- m_allow_special[test_monster_name("Farmer Maggot")] = FALSE;
-
- return FALSE;
-}
-bool_ quest_shroom_death_hook(char *fmt)
-{
- s32b r_idx, m_idx;
-
- m_idx = get_next_arg(fmt);
- r_idx = m_list[m_idx].r_idx;
-
- if (cquest.status > QUEST_STATUS_COMPLETED) return FALSE;
-
- if ((r_idx == test_monster_name("Wolf, Farmer Maggot's dog")) ||
- (r_idx == test_monster_name("Grip, Farmer Maggot's dog")) ||
- (r_idx == test_monster_name("Fang, Farmer Maggot's dog")))
- {
- msg_print("The dog yells a last time and drops dead on the grass.");
- }
-
- return FALSE;
-}
-bool_ quest_shroom_give_hook(char *fmt)
-{
- object_type *o_ptr;
- monster_type *m_ptr;
- s32b m_idx, item;
-
- m_idx = get_next_arg(fmt);
- item = get_next_arg(fmt);
-
- o_ptr = &p_ptr->inventory[item];
- m_ptr = &m_list[m_idx];
-
- if (m_ptr->r_idx != test_monster_name("Farmer Maggot")) return (FALSE);
-
- /* If one is dead .. its bad */
- if ((r_info[test_monster_name("Grip, Farmer Maggot's dog")].max_num == 0) ||
- (r_info[test_monster_name("Wolf, Farmer Maggot's dog")].max_num == 0) ||
- (r_info[test_monster_name("Fang, Farmer Maggot's dog")].max_num == 0))
- {
- cquest.status = QUEST_STATUS_FAILED_DONE;
- msg_print("My puppy! My poor, defenceless puppy...");
- msg_print("YOU MURDERER! Out of my sight!");
- delete_monster_idx(m_idx);
-
- del_hook(HOOK_GIVE, quest_shroom_give_hook);
- del_hook(HOOK_CHAT, quest_shroom_speak_hook);
- del_hook(HOOK_WILD_GEN, quest_shroom_town_gen_hook);
- process_hooks_restart = TRUE;
- return TRUE;
- }
-
- if ((o_ptr->tval != TV_FOOD) || (o_ptr->pval2 != 1)) return (FALSE);
-
- /* Take a mushroom */
- inc_stack_size_ex(item, -1, OPTIMIZE, NO_DESCRIBE);
- cquest.data[0]++;
-
- if (cquest.data[0] == cquest.data[1])
- {
- object_type forge, *q_ptr;
-
- msg_print("Oh thank you!");
- msg_print("Take my sling and those mushrooms, may they help you!");
- msg_print("Farmer Maggot heads back to his house.");
-
- /* Mushrooms */
- q_ptr = &forge;
- object_prep(q_ptr, lookup_kind(TV_FOOD, SV_FOOD_CURE_SERIOUS));
- q_ptr->found = OBJ_FOUND_REWARD;
- q_ptr->number = rand_range(15, 20);
- object_aware(q_ptr);
- object_known(q_ptr);
- q_ptr->discount = 100;
- q_ptr->ident |= IDENT_STOREB;
- if (inven_carry_okay(q_ptr))
- inven_carry(q_ptr, FALSE);
- else
- drop_near(q_ptr, 0, p_ptr->py, p_ptr->px);
-
- /* The sling of farmer maggot */
- q_ptr = &forge;
- object_prep(q_ptr, lookup_kind(TV_BOW, SV_SLING));
- q_ptr->found = OBJ_FOUND_REWARD;
- q_ptr->number = 1;
- q_ptr->name1 = 149;
- apply_magic(q_ptr, -1, TRUE, TRUE, TRUE);
- object_aware(q_ptr);
- object_known(q_ptr);
- q_ptr->discount = 100;
- q_ptr->ident |= IDENT_STOREB;
- (void)inven_carry(q_ptr, FALSE);
-
- delete_monster_idx(m_idx);
-
- cquest.status = QUEST_STATUS_FINISHED;
-
- del_hook(HOOK_GIVE, quest_shroom_give_hook);
- process_hooks_restart = TRUE;
- }
- else
- msg_format("Oh thank you, but you still have %d mushrooms to bring back!", cquest.data[1] - cquest.data[0]);
-
- return TRUE;
-}
-bool_ quest_shroom_speak_hook(char *fmt)
-{
- s32b m_idx = get_next_arg(fmt);
-
- if (m_list[m_idx].r_idx != test_monster_name("Farmer Maggot")) return (FALSE);
-
- if (cquest.status == QUEST_STATUS_UNTAKEN)
- {
- cptr m_name;
-
- m_name = get_next_arg_str(fmt);
-
- msg_format("%^s asks your help.", m_name);
- exec_lua("ingame_help('monster_chat')");
- }
- else
- {
- /* If one is dead .. its bad */
- if ((r_info[test_monster_name("Grip, Farmer Maggot's dog")].max_num == 0) ||
- (r_info[test_monster_name("Wolf, Farmer Maggot's dog")].max_num == 0) ||
- (r_info[test_monster_name("Fang, Farmer Maggot's dog")].max_num == 0))
- {
- cquest.status = QUEST_STATUS_FAILED_DONE;
- msg_print("My puppy! My poor, defenceless puppy...");
- msg_print("YOU MURDERER! Out of my sight!");
- delete_monster_idx(m_idx);
-
- del_hook(HOOK_GIVE, quest_shroom_give_hook);
- del_hook(HOOK_CHAT, quest_shroom_speak_hook);
- del_hook(HOOK_WILD_GEN, quest_shroom_town_gen_hook);
- process_hooks_restart = TRUE;
- return TRUE;
- }
- msg_format("You still have %d mushrooms to bring back!", cquest.data[1] - cquest.data[0]);
- }
- return (TRUE);
-}
-bool_ quest_shroom_chat_hook(char *fmt)
-{
- monster_type *m_ptr;
- s32b m_idx;
-
- m_idx = get_next_arg(fmt);
-
- m_ptr = &m_list[m_idx];
-
- if (m_ptr->r_idx != test_monster_name("Farmer Maggot")) return (FALSE);
-
- if (cquest.status == QUEST_STATUS_UNTAKEN)
- {
- msg_print("My mushrooms, my mushrooms!");
- msg_print("The rain, a dark horrible rain, began so I had to return to my home.");
- msg_print("But when I came back my dogs were all mad and didn't let me near the field.");
- msg_print("Could you please bring me back all the mushrooms that have grown in my field");
- msg_print("to the west of Bree? Please try to not harm my dogs. They are so lovely...");
-
- cquest.status = QUEST_STATUS_TAKEN;
- quest[QUEST_SHROOM].init(QUEST_SHROOM);
- }
- else
- {
- /* If one is dead .. its bad */
- if ((r_info[test_monster_name("Grip, Farmer Maggot's dog")].max_num == 0) ||
- (r_info[test_monster_name("Wolf, Farmer Maggot's dog")].max_num == 0) ||
- (r_info[test_monster_name("Fang, Farmer Maggot's dog")].max_num == 0))
- {
- cquest.status = QUEST_STATUS_FAILED_DONE;
- msg_print("My puppy! My poor, defenceless puppy...");
- msg_print("YOU MURDERER! Out of my sight!");
- delete_monster_idx(m_idx);
-
- del_hook(HOOK_GIVE, quest_shroom_give_hook);
- del_hook(HOOK_CHAT, quest_shroom_speak_hook);
- del_hook(HOOK_WILD_GEN, quest_shroom_town_gen_hook);
- process_hooks_restart = TRUE;
- return TRUE;
- }
- msg_format("You still have %d mushrooms to bring back!", cquest.data[1] - cquest.data[0]);
- }
-
- return TRUE;
-}
-bool_ quest_shroom_init_hook(int q_idx)
-{
- /* Get a number of 'shrooms */
- if (!cquest.data[1])
- {
- 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 ((cquest.status >= QUEST_STATUS_TAKEN) && (cquest.status < QUEST_STATUS_FINISHED))
- {
- add_hook(HOOK_MONSTER_DEATH, quest_shroom_death_hook, "shroom_death");
- add_hook(HOOK_GIVE, quest_shroom_give_hook, "shroom_give");
- add_hook(HOOK_WILD_GEN, quest_shroom_town_gen_hook, "shroom_town_gen");
- add_hook(HOOK_CHAT, quest_shroom_chat_hook, "shroom_chat");
- add_hook(HOOK_MON_SPEAK, quest_shroom_speak_hook, "shroom_speak");
- }
- if (cquest.status == QUEST_STATUS_UNTAKEN)
- {
- add_hook(HOOK_MON_SPEAK, quest_shroom_speak_hook, "shroom_speak");
- add_hook(HOOK_WILD_GEN, quest_shroom_town_gen_hook, "shroom_town_gen");
- add_hook(HOOK_CHAT, quest_shroom_chat_hook, "shroom_chat");
- }
- return (FALSE);
-}
diff --git a/src/q_shroom.cc b/src/q_shroom.cc
new file mode 100644
index 00000000..627f2b39
--- /dev/null
+++ b/src/q_shroom.cc
@@ -0,0 +1,349 @@
+#include "q_shroom.hpp"
+
+#include "cave.hpp"
+#include "game.hpp"
+#include "hook_chat_in.hpp"
+#include "hook_give_in.hpp"
+#include "hook_monster_death_in.hpp"
+#include "hook_mon_speak_in.hpp"
+#include "hook_wild_gen_in.hpp"
+#include "hooks.hpp"
+#include "messages.hpp"
+#include "monster2.hpp"
+#include "monster_race.hpp"
+#include "monster_type.hpp"
+#include "object2.hpp"
+#include "player_type.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+#include "z-rand.hpp"
+
+#include <cassert>
+
+#define cquest (quest[QUEST_SHROOM])
+
+static bool quest_shroom_speak_hook(void *, void *, void *);
+static bool quest_shroom_chat_hook(void *, void *, void *);
+
+GENERATE_MONSTER_LOOKUP_FN(get_grip, "Grip, Farmer Maggot's dog")
+GENERATE_MONSTER_LOOKUP_FN(get_wolf, "Wolf, Farmer Maggot's dog")
+GENERATE_MONSTER_LOOKUP_FN(get_fang, "Fang, Farmer Maggot's dog")
+GENERATE_MONSTER_LOOKUP_FN(get_farmer_maggot, "Farmer Maggot")
+
+static bool quest_shroom_town_gen_hook(void *, void *in_, void *)
+{
+ struct hook_wild_gen_in *in = static_cast<struct hook_wild_gen_in *>(in_);
+ int m_idx, x = 1, y = 1, tries = 10000;
+ bool_ small = in->small;
+
+ /* Generate the shrooms field */
+ if ((!small) && (p_ptr->wilderness_y == 21) && (p_ptr->wilderness_x == 33))
+ {
+ /* Create the field */
+ for (x = (cur_wid / 2) - 7; x <= (cur_wid / 2) + 7; x++)
+ {
+ for (y = (cur_hgt / 2) - 5; y <= (cur_hgt / 2) + 5; y++)
+ {
+ cave_set_feat(y, x, 181);
+ }
+ }
+
+ /* Throw in some 'shrooms */
+ for (x = 0; x < (cquest.data[1] - cquest.data[0]); x++)
+ {
+ object_type forge, *q_ptr = &forge;
+
+ object_prep(q_ptr, lookup_kind(TV_FOOD, rand_range(1, 18)));
+ q_ptr->number = 1;
+ /* Mark them */
+ q_ptr->pval2 = 1;
+ drop_near(q_ptr, -1, rand_range((cur_hgt / 2) - 5, (cur_hgt / 2) + 5), rand_range((cur_wid / 2) - 7, (cur_wid / 2) + 7));
+ }
+
+ /* Throw in some dogs ;) */
+ y = rand_range((cur_hgt / 2) - 5, (cur_hgt / 2) + 5);
+ x = rand_range((cur_wid / 2) - 7, (cur_wid / 2) + 7);
+ m_allow_special[get_grip()] = TRUE;
+ m_idx = place_monster_one(y, x, get_grip(), 0, FALSE, MSTATUS_ENEMY);
+ if (m_idx) m_list[m_idx].mflag |= MFLAG_QUEST;
+ m_allow_special[get_grip()] = FALSE;
+
+ y = rand_range((cur_hgt / 2) - 5, (cur_hgt / 2) + 5);
+ x = rand_range((cur_wid / 2) - 7, (cur_wid / 2) + 7);
+ m_allow_special[get_wolf()] = TRUE;
+ m_idx = place_monster_one(y, x, get_wolf(), 0, FALSE, MSTATUS_ENEMY);
+ if (m_idx) m_list[m_idx].mflag |= MFLAG_QUEST;
+ m_allow_special[get_wolf()] = FALSE;
+
+ y = rand_range((cur_hgt / 2) - 5, (cur_hgt / 2) + 5);
+ x = rand_range((cur_wid / 2) - 7, (cur_wid / 2) + 7);
+ m_allow_special[get_fang()] = TRUE;
+ m_idx = place_monster_one(y, x, get_fang(), 0, FALSE, MSTATUS_ENEMY);
+ if (m_idx) m_list[m_idx].mflag |= MFLAG_QUEST;
+ m_allow_special[get_fang()] = FALSE;
+
+ msg_print("You hear frenzied barking.");
+ }
+
+ /* Generate maggot in town, in daylight */
+ if ((bst(HOUR, turn) < 6) || (bst(HOUR, turn) >= 18) || (cquest.status > QUEST_STATUS_COMPLETED) || (small) || (p_ptr->town_num != 1))
+ {
+ return false;
+ }
+
+ /* Find a good position */
+ while (tries)
+ {
+ /* Get a random spot */
+ y = randint(20) + (cur_hgt / 2) - 10;
+ x = randint(20) + (cur_wid / 2) - 10;
+
+ /* Is it a good spot ? */
+ /* Not in player los, and avoid shop grids */
+ if (!los(p_ptr->py, p_ptr->px, y, x) && cave_empty_bold(y, x) &&
+ cave_plain_floor_bold(y, x))
+ {
+ break;
+ }
+
+ /* One less try */
+ tries--;
+ }
+
+ /* Place Farmer Maggot */
+ m_allow_special[get_farmer_maggot()] = TRUE;
+ place_monster_one(y, x, get_farmer_maggot(), 0, FALSE, MSTATUS_ENEMY);
+ m_allow_special[get_farmer_maggot()] = FALSE;
+
+ return false;
+}
+
+static bool quest_shroom_death_hook(void *, void *in_, void *)
+{
+ struct hook_monster_death_in *in = static_cast<struct hook_monster_death_in *>(in_);
+ s32b m_idx = in->m_idx;
+ s32b r_idx = m_list[m_idx].r_idx;
+
+ if (cquest.status > QUEST_STATUS_COMPLETED)
+ {
+ return false;
+ }
+
+ if ((r_idx == get_wolf()) ||
+ (r_idx == get_grip()) ||
+ (r_idx == get_fang()))
+ {
+ msg_print("The dog yells a last time and drops dead on the grass.");
+ }
+
+ return false;
+}
+
+static bool quest_shroom_give_hook(void *, void *in_, void *)
+{
+ auto const &r_info = game->edit_data.r_info;
+
+ struct hook_give_in *in = static_cast<struct hook_give_in *>(in_);
+ object_type *o_ptr;
+ monster_type *m_ptr;
+
+ s32b m_idx = in->m_idx;
+ s32b item = in->item;
+
+ o_ptr = &p_ptr->inventory[item];
+ m_ptr = &m_list[m_idx];
+
+ if (m_ptr->r_idx != get_farmer_maggot())
+ {
+ return false;
+ }
+
+ /* If one is dead .. its bad */
+ if ((r_info[get_grip()].max_num == 0) ||
+ (r_info[get_wolf()].max_num == 0) ||
+ (r_info[get_fang()].max_num == 0))
+ {
+ cquest.status = QUEST_STATUS_FAILED_DONE;
+ msg_print("My puppy! My poor, defenceless puppy...");
+ msg_print("YOU MURDERER! Out of my sight!");
+ delete_monster_idx(m_idx);
+
+ del_hook_new(HOOK_GIVE, quest_shroom_give_hook);
+ del_hook_new(HOOK_CHAT, quest_shroom_speak_hook);
+ del_hook_new(HOOK_WILD_GEN, quest_shroom_town_gen_hook);
+ process_hooks_restart = TRUE;
+ return true;
+ }
+
+ if ((o_ptr->tval != TV_FOOD) || (o_ptr->pval2 != 1))
+ {
+ return false;
+ }
+
+ /* Take a mushroom */
+ inc_stack_size_ex(item, -1, OPTIMIZE, NO_DESCRIBE);
+ cquest.data[0]++;
+
+ if (cquest.data[0] == cquest.data[1])
+ {
+ object_type forge, *q_ptr;
+
+ msg_print("Oh thank you!");
+ msg_print("Take my sling and those mushrooms, may they help you!");
+ msg_print("Farmer Maggot heads back to his house.");
+
+ /* Mushrooms */
+ q_ptr = &forge;
+ object_prep(q_ptr, lookup_kind(TV_FOOD, SV_FOOD_CURE_SERIOUS));
+ q_ptr->found = OBJ_FOUND_REWARD;
+ q_ptr->number = rand_range(15, 20);
+ object_aware(q_ptr);
+ object_known(q_ptr);
+ q_ptr->discount = 100;
+ q_ptr->ident |= IDENT_STOREB;
+ if (inven_carry_okay(q_ptr))
+ {
+ inven_carry(q_ptr, FALSE);
+ }
+ else
+ {
+ drop_near(q_ptr, 0, p_ptr->py, p_ptr->px);
+ }
+
+ /* The sling of farmer maggot */
+ q_ptr = &forge;
+ object_prep(q_ptr, lookup_kind(TV_BOW, SV_SLING));
+ q_ptr->found = OBJ_FOUND_REWARD;
+ q_ptr->number = 1;
+ q_ptr->name1 = 149;
+ apply_magic(q_ptr, -1, TRUE, TRUE, TRUE);
+ object_aware(q_ptr);
+ object_known(q_ptr);
+ q_ptr->discount = 100;
+ q_ptr->ident |= IDENT_STOREB;
+ inven_carry(q_ptr, FALSE);
+
+ delete_monster_idx(m_idx);
+
+ cquest.status = QUEST_STATUS_FINISHED;
+
+ del_hook_new(HOOK_GIVE, quest_shroom_give_hook);
+ process_hooks_restart = TRUE;
+ }
+ else
+ {
+ msg_format("Oh thank you, but you still have %d mushrooms to bring back!", cquest.data[1] - cquest.data[0]);
+ }
+
+ return true;
+}
+
+static void check_dogs_alive(s32b m_idx)
+{
+ auto const &r_info = game->edit_data.r_info;
+
+ if ((r_info[get_grip()].max_num == 0) ||
+ (r_info[get_wolf()].max_num == 0) ||
+ (r_info[get_fang()].max_num == 0))
+ {
+ cquest.status = QUEST_STATUS_FAILED_DONE;
+ msg_print("My puppy! My poor, defenceless puppy...");
+ msg_print("YOU MURDERER! Out of my sight!");
+ delete_monster_idx(m_idx);
+
+ del_hook_new(HOOK_GIVE, quest_shroom_give_hook);
+ del_hook_new(HOOK_MON_SPEAK, quest_shroom_speak_hook);
+ del_hook_new(HOOK_CHAT, quest_shroom_chat_hook);
+ del_hook_new(HOOK_WILD_GEN, quest_shroom_town_gen_hook);
+ process_hooks_restart = TRUE;
+ }
+ else
+ {
+ msg_format("You still have %d mushrooms to bring back!", cquest.data[1] - cquest.data[0]);
+ }
+}
+
+static bool quest_shroom_speak_hook(void *, void *in_, void *)
+{
+ struct hook_mon_speak_in *in = static_cast<struct hook_mon_speak_in *>(in_);
+ s32b m_idx = in->m_idx;
+
+ if (m_list[m_idx].r_idx != get_farmer_maggot())
+ {
+ return false;
+ }
+
+ if (cquest.status == QUEST_STATUS_UNTAKEN)
+ {
+ msg_format("%^s asks your help.", in->m_name);
+ process_hooks_new(HOOK_MON_ASK_HELP, NULL, NULL);
+ }
+ else
+ {
+ check_dogs_alive(m_idx);
+ }
+
+ return true;
+}
+
+static bool quest_shroom_chat_hook(void *, void *in_, void *)
+{
+ struct hook_chat_in *in = static_cast<struct hook_chat_in *>(in_);
+ s32b m_idx = in->m_idx;
+ monster_type *m_ptr = &m_list[m_idx];
+
+ if (m_ptr->r_idx != get_farmer_maggot())
+ {
+ return false;
+ }
+
+ if (cquest.status == QUEST_STATUS_UNTAKEN)
+ {
+ msg_print("My mushrooms, my mushrooms!");
+ msg_print("The rain, a dark horrible rain, began so I had to return to my home.");
+ msg_print("But when I came back my dogs were all mad and didn't let me near the field.");
+ msg_print("Could you please bring me back all the mushrooms that have grown in my field");
+ msg_print("to the west of Bree? Please try to not harm my dogs. They are so lovely...");
+
+ cquest.status = QUEST_STATUS_TAKEN;
+ quest[QUEST_SHROOM].init();
+ }
+ else
+ {
+ check_dogs_alive(m_idx);
+ }
+
+ return true;
+}
+
+void quest_shroom_init_hook()
+{
+ auto &messages = game->messages;
+
+ /* Get a number of 'shrooms */
+ if (!cquest.data[1])
+ {
+ cquest.data[0] = 0;
+ cquest.data[1] = rand_range(7, 14);
+ if (wizard)
+ {
+ messages.add(format("Shrooms number %d", cquest.data[1]), TERM_BLUE);
+ }
+ }
+
+ if ((cquest.status >= QUEST_STATUS_TAKEN) && (cquest.status < QUEST_STATUS_FINISHED))
+ {
+ add_hook_new(HOOK_MONSTER_DEATH, quest_shroom_death_hook, "shroom_death", NULL);
+ add_hook_new(HOOK_GIVE, quest_shroom_give_hook, "shroom_give", NULL);
+ add_hook_new(HOOK_WILD_GEN, quest_shroom_town_gen_hook, "shroom_town_gen", NULL);
+ add_hook_new(HOOK_CHAT, quest_shroom_chat_hook, "shroom_chat", NULL);
+ add_hook_new(HOOK_MON_SPEAK, quest_shroom_speak_hook, "shroom_speak", NULL);
+ }
+ if (cquest.status == QUEST_STATUS_UNTAKEN)
+ {
+ add_hook_new(HOOK_MON_SPEAK, quest_shroom_speak_hook, "shroom_speak", NULL);
+ add_hook_new(HOOK_WILD_GEN, quest_shroom_town_gen_hook, "shroom_town_gen", NULL);
+ add_hook_new(HOOK_CHAT, quest_shroom_chat_hook, "shroom_chat", NULL);
+ }
+}
diff --git a/src/q_shroom.hpp b/src/q_shroom.hpp
new file mode 100644
index 00000000..4478aee2
--- /dev/null
+++ b/src/q_shroom.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+void quest_shroom_init_hook();
diff --git a/src/q_spider.c b/src/q_spider.cc
index a739535b..a5fa3486 100644
--- a/src/q_spider.c
+++ b/src/q_spider.cc
@@ -1,13 +1,31 @@
-#undef cquest
+#include "q_spider.hpp"
+
+#include "cave.hpp"
+#include "gods.hpp"
+#include "hook_quest_finish_in.hpp"
+#include "hooks.hpp"
+#include "init1.hpp"
+#include "monster2.hpp"
+#include "monster_type.hpp"
+#include "object2.hpp"
+#include "object_type.hpp"
+#include "player_type.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+
#define cquest (quest[QUEST_SPIDER])
-bool_ quest_spider_gen_hook(char *fmt)
+static bool quest_spider_gen_hook(void *, void *, void *)
{
int x, y;
int xstart = 2;
int ystart = 2;
- if (p_ptr->inside_quest != QUEST_SPIDER) return FALSE;
+ if (p_ptr->inside_quest != QUEST_SPIDER)
+ {
+ return false;
+ }
/* Start with perm walls */
for (y = 0; y < cur_hgt; y++)
@@ -28,13 +46,17 @@ bool_ quest_spider_gen_hook(char *fmt)
init_flags = INIT_CREATE_DUNGEON;
process_dungeon_file("spiders.map", &ystart, &xstart, cur_hgt, cur_wid, TRUE, TRUE);
- return TRUE;
+ return true;
}
-bool_ quest_spider_death_hook(char *fmt)
+
+static bool quest_spider_death_hook(void *, void *, void *)
{
int i, mcnt = 0;
- if (p_ptr->inside_quest != QUEST_SPIDER) return FALSE;
+ if (p_ptr->inside_quest != QUEST_SPIDER)
+ {
+ return false;
+ }
for (i = m_max - 1; i >= 1; i--)
{
@@ -42,9 +64,15 @@ bool_ quest_spider_death_hook(char *fmt)
monster_type *m_ptr = &m_list[i];
/* Ignore "dead" monsters */
- if (!m_ptr->r_idx) continue;
+ if (!m_ptr->r_idx)
+ {
+ continue;
+ }
- if (m_ptr->status <= MSTATUS_ENEMY) mcnt++;
+ if (m_ptr->status <= MSTATUS_ENEMY)
+ {
+ mcnt++;
+ }
}
if (mcnt <= 1)
@@ -52,28 +80,33 @@ bool_ quest_spider_death_hook(char *fmt)
cmsg_print(TERM_YELLOW, "The forest is now safer, thanks to you.");
/* Yavanna LOVES saving forests */
- GOD(GOD_YAVANNA)
+ if (p_ptr->pgod == GOD_YAVANNA)
{
cmsg_print(TERM_L_GREEN, "You feel the gentle touch of Yavanna, as she smiles at you.");
inc_piety(GOD_YAVANNA, 6000);
}
cquest.status = QUEST_STATUS_COMPLETED;
- del_hook(HOOK_MONSTER_DEATH, quest_spider_death_hook);
+
+ del_hook_new(HOOK_MONSTER_DEATH, quest_spider_death_hook);
process_hooks_restart = TRUE;
- return (FALSE);
+
+ return false;
}
- return (FALSE);
+ return false;
}
-bool_ quest_spider_finish_hook(char *fmt)
+
+static bool quest_spider_finish_hook(void *, void *in_, void *)
{
+ struct hook_quest_finish_in *in = static_cast<struct hook_quest_finish_in *>(in_);
object_type forge, *q_ptr;
- s32b q_idx;
+ s32b q_idx = in->q_idx;
- q_idx = get_next_arg(fmt);
-
- if (q_idx != QUEST_SPIDER) return FALSE;
+ if (q_idx != QUEST_SPIDER)
+ {
+ return false;
+ }
c_put_str(TERM_YELLOW, "All of us praise your mighty deed in driving back the", 8, 0);
c_put_str(TERM_YELLOW, "menace. Take this as a reward.", 9, 0);
@@ -85,24 +118,24 @@ bool_ quest_spider_finish_hook(char *fmt)
object_aware(q_ptr);
object_known(q_ptr);
q_ptr->ident |= IDENT_STOREB;
- (void)inven_carry(q_ptr, FALSE);
+ inven_carry(q_ptr, FALSE);
/* Continue the plot */
*(quest[q_idx].plot) = QUEST_POISON;
- quest[*(quest[q_idx].plot)].init(*(quest[q_idx].plot));
+ quest[*(quest[q_idx].plot)].init();
- del_hook(HOOK_QUEST_FINISH, quest_spider_finish_hook);
+ del_hook_new(HOOK_QUEST_FINISH, quest_spider_finish_hook);
process_hooks_restart = TRUE;
- return TRUE;
+ return true;
}
-bool_ quest_spider_init_hook(int q_idx)
+
+void quest_spider_init_hook()
{
if ((cquest.status >= QUEST_STATUS_TAKEN) && (cquest.status < QUEST_STATUS_FINISHED))
{
- add_hook(HOOK_MONSTER_DEATH, quest_spider_death_hook, "spider_death");
- add_hook(HOOK_GEN_QUEST, quest_spider_gen_hook, "spider_gen");
- add_hook(HOOK_QUEST_FINISH, quest_spider_finish_hook, "spider_finish");
+ add_hook_new(HOOK_MONSTER_DEATH, quest_spider_death_hook, "spider_death", NULL);
+ add_hook_new(HOOK_GEN_QUEST, quest_spider_gen_hook, "spider_gen", NULL);
+ add_hook_new(HOOK_QUEST_FINISH, quest_spider_finish_hook, "spider_finish", NULL);
}
- return (FALSE);
}
diff --git a/src/q_spider.hpp b/src/q_spider.hpp
new file mode 100644
index 00000000..bd16c06a
--- /dev/null
+++ b/src/q_spider.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+void quest_spider_init_hook();
diff --git a/src/q_thief.c b/src/q_thief.cc
index 6b033f8c..a4505d2a 100644
--- a/src/q_thief.c
+++ b/src/q_thief.cc
@@ -1,18 +1,44 @@
-#undef cquest
+#include "q_thief.hpp"
+
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "dungeon_flag.hpp"
+#include "game.hpp"
+#include "hook_quest_finish_in.hpp"
+#include "hooks.hpp"
+#include "init1.hpp"
+#include "monster2.hpp"
+#include "monster_type.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_type.hpp"
+#include "player_type.hpp"
+#include "skill_type.hpp"
+#include "spells2.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+#include "z-rand.hpp"
+
#define cquest (quest[QUEST_THIEVES])
-bool_ quest_thieves_gen_hook(char *fmt)
+static bool quest_thieves_gen_hook(void *, void *, void *)
{
int x, y;
int xstart = 2;
int ystart = 2;
bool_ again = TRUE;
- if (p_ptr->inside_quest != QUEST_THIEVES) return FALSE;
+ if (p_ptr->inside_quest != QUEST_THIEVES)
+ {
+ return false;
+ }
/* Just in case we didnt talk the the mayor */
if (cquest.status == QUEST_STATUS_UNTAKEN)
+ {
cquest.status = QUEST_STATUS_TAKEN;
+ }
/* Start with perm walls */
for (y = 0; y < cur_hgt; y++)
@@ -33,7 +59,7 @@ bool_ quest_thieves_gen_hook(char *fmt)
init_flags = INIT_CREATE_DUNGEON;
process_dungeon_file("thieves.map", &ystart, &xstart, cur_hgt, cur_wid, TRUE, FALSE);
- dungeon_flags2 |= DF2_NO_GENO;
+ dungeon_flags |= DF_NO_GENO;
/* Rip the inventory from the player */
cmsg_print(TERM_YELLOW, "You feel a vicious blow on your head.");
@@ -44,9 +70,15 @@ bool_ quest_thieves_gen_hook(char *fmt)
{
object_type *o_ptr = &p_ptr->inventory[x];
- if (!o_ptr->k_idx) continue;
+ if (!o_ptr->k_idx)
+ {
+ continue;
+ }
- if ((x >= INVEN_WIELD) && cursed_p(o_ptr)) continue;
+ if ((x >= INVEN_WIELD) && cursed_p(o_ptr))
+ {
+ continue;
+ }
inven_drop(x, 99, 4, 24, TRUE);
@@ -56,16 +88,20 @@ bool_ quest_thieves_gen_hook(char *fmt)
}
}
- del_hook(HOOK_GEN_QUEST, quest_thieves_gen_hook);
+ del_hook_new(HOOK_GEN_QUEST, quest_thieves_gen_hook);
process_hooks_restart = TRUE;
return TRUE;
}
-bool_ quest_thieves_hook(char *fmt)
+
+static bool quest_thieves_hook(void *, void *, void *)
{
int i, mcnt = 0;
- if (p_ptr->inside_quest != QUEST_THIEVES) return FALSE;
+ if (p_ptr->inside_quest != QUEST_THIEVES)
+ {
+ return false;
+ }
/* ALARM !!! */
if ((cave[17][22].feat == FEAT_OPEN) ||
@@ -105,21 +141,27 @@ bool_ quest_thieves_hook(char *fmt)
cave[23][4].special = 0;
quest[p_ptr->inside_quest].status = QUEST_STATUS_COMPLETED;
- del_hook(HOOK_END_TURN, quest_thieves_hook);
+
+ del_hook_new(HOOK_END_TURN, quest_thieves_hook);
process_hooks_restart = TRUE;
cmsg_print(TERM_YELLOW, "You stopped the thieves and saved Bree!");
- return (FALSE);
+ return false;
}
- return FALSE;
+ return false;
}
-bool_ quest_thieves_finish_hook(char *fmt)
+
+static bool quest_thieves_finish_hook(void *, void *in_, void *)
{
- s32b q_idx;
+ auto const &s_info = game->s_info;
- q_idx = get_next_arg(fmt);
+ struct hook_quest_finish_in *in = static_cast<struct hook_quest_finish_in *>(in_);
+ s32b q_idx = in->q_idx;
- if (q_idx != QUEST_THIEVES) return FALSE;
+ if (q_idx != QUEST_THIEVES)
+ {
+ return false;
+ }
c_put_str(TERM_YELLOW, "Thank you for killing the band of thieves!", 8, 0);
c_put_str(TERM_YELLOW, "You can use the hideout as your house as a reward.", 9, 0);
@@ -134,39 +176,45 @@ bool_ quest_thieves_finish_hook(char *fmt)
else
{
if (s_info[SKILL_COMBAT].value > s_info[SKILL_MAGIC].value)
+ {
*(quest[q_idx].plot) = QUEST_TROLL;
+ }
else
+ {
*(quest[q_idx].plot) = QUEST_WIGHT;
+ }
}
- quest[*(quest[q_idx].plot)].init(*(quest[q_idx].plot));
+ quest[*(quest[q_idx].plot)].init();
- del_hook(HOOK_QUEST_FINISH, quest_thieves_finish_hook);
+ del_hook_new(HOOK_QUEST_FINISH, quest_thieves_finish_hook);
process_hooks_restart = TRUE;
- return TRUE;
+ return true;
}
-bool_ quest_thieves_feeling_hook(char *fmt)
+static bool quest_thieves_feeling_hook(void *, void *, void *)
{
- if (p_ptr->inside_quest != QUEST_THIEVES) return FALSE;
+ if (p_ptr->inside_quest != QUEST_THIEVES)
+ {
+ return false;
+ }
msg_print("You wake up in a prison cell.");
msg_print("All your possessions have been stolen!");
- del_hook(HOOK_FEELING, quest_thieves_feeling_hook);
+ del_hook_new(HOOK_FEELING, quest_thieves_feeling_hook);
process_hooks_restart = TRUE;
- return TRUE;
+ return true;
}
-bool_ quest_thieves_init_hook(int q_idx)
+void quest_thieves_init_hook()
{
if ((cquest.status >= QUEST_STATUS_UNTAKEN) && (cquest.status < QUEST_STATUS_FINISHED))
{
- add_hook(HOOK_END_TURN, quest_thieves_hook, "thieves_end_turn");
- add_hook(HOOK_QUEST_FINISH, quest_thieves_finish_hook, "thieves_finish");
- add_hook(HOOK_GEN_QUEST, quest_thieves_gen_hook, "thieves_geb");
- add_hook(HOOK_FEELING, quest_thieves_feeling_hook, "thieves_feel");
+ add_hook_new(HOOK_END_TURN, quest_thieves_hook, "thieves_end_turn", NULL);
+ add_hook_new(HOOK_QUEST_FINISH, quest_thieves_finish_hook, "thieves_finish", NULL);
+ add_hook_new(HOOK_GEN_QUEST, quest_thieves_gen_hook, "thieves_geb", NULL);
+ add_hook_new(HOOK_FEELING, quest_thieves_feeling_hook, "thieves_feel", NULL);
}
- return (FALSE);
}
diff --git a/src/q_thief.hpp b/src/q_thief.hpp
new file mode 100644
index 00000000..0e191db7
--- /dev/null
+++ b/src/q_thief.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+void quest_thieves_init_hook();
diff --git a/src/q_thrain.c b/src/q_thrain.cc
index b2b1be9f..7b895695 100644
--- a/src/q_thrain.c
+++ b/src/q_thrain.cc
@@ -1,34 +1,81 @@
-#undef cquest
+#include "q_thrain.hpp"
+
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "dungeon_info_type.hpp"
+#include "game.hpp"
+#include "generate.hpp"
+#include "hook_build_room1_in.hpp"
+#include "hook_move_in.hpp"
+#include "hook_monster_death_in.hpp"
+#include "hooks.hpp"
+#include "init1.hpp"
+#include "lua_bind.hpp"
+#include "object_type.hpp"
+#include "randart.hpp"
+#include "messages.hpp"
+#include "monster2.hpp"
+#include "monster_type.hpp"
+#include "object2.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+#include "z-rand.hpp"
+
+#include <cassert>
+
#define cquest (quest[QUEST_THRAIN])
-bool_ quest_thrain_death_hook(char *fmt)
+GENERATE_MONSTER_LOOKUP_FN(get_thrain, "Thrain, the King Under the Mountain")
+GENERATE_MONSTER_LOOKUP_FN(get_dwar, "Dwar, Dog Lord of Waw")
+GENERATE_MONSTER_LOOKUP_FN(get_hoarmurath, "Hoarmurath of Dir")
+
+static bool quest_thrain_death_hook(void *, void *in_, void *)
{
- s32b m_idx;
+ struct hook_monster_death_in *in = static_cast<struct hook_monster_death_in *>(in_);
+ s32b m_idx = in->m_idx;
int r, x, y;
monster_type *m_ptr;
- m_idx = get_next_arg(fmt);
+ if ((cquest.status >= QUEST_STATUS_FINISHED) || (dun_level !=cquest.data[0]) || (dungeon_type != DUNGEON_DOL_GULDUR))
+ {
+ return false;
+ }
- if ((cquest.status >= QUEST_STATUS_FINISHED) || (dun_level !=cquest.data[0]) || (dungeon_type != DUNGEON_DOL_GULDUR)) return (FALSE);
m_ptr = &m_list[m_idx];
- if ((m_ptr->r_idx != test_monster_name("Dwar, Dog Lord of Waw")) && (m_ptr->r_idx != test_monster_name("Hoarmurath of Dir"))) return (FALSE);
+ if ((m_ptr->r_idx != get_dwar()) && (m_ptr->r_idx != get_hoarmurath()))
+ {
+ return false;
+ }
cquest.data[2]++;
- if (cquest.data[2] < 2) return (FALSE);
+ if (cquest.data[2] < 2)
+ {
+ return false;
+ }
cmsg_print(TERM_YELLOW, "The magic hiding the room dissipates.");
for (x = 0; x < cur_wid; x++)
+ {
for (y = 0; y < cur_hgt; y++)
{
cave_type *c_ptr = &cave[y][x];
- if (c_ptr->mimic != 61) continue;
- if (!(c_ptr->info & CAVE_FREE)) continue;
+ if (c_ptr->mimic != 61)
+ {
+ continue;
+ }
+
+ if (!(c_ptr->info & CAVE_FREE))
+ {
+ continue;
+ }
c_ptr->mimic = 0;
lite_spot(y, x);
}
+ }
cquest.status = QUEST_STATUS_FINISHED;
cmsg_print(TERM_YELLOW, "Thrain speaks:");
@@ -44,26 +91,31 @@ bool_ quest_thrain_death_hook(char *fmt)
monster_type *m_ptr = &m_list[r];
/* Ignore "dead" monsters */
- if (!m_ptr->r_idx) continue;
+ if (!m_ptr->r_idx)
+ {
+ continue;
+ }
/* Is it the princess? */
- if (m_ptr->r_idx == test_monster_name("Thrain, the King Under the Mountain"))
+ if (m_ptr->r_idx == get_thrain())
{
int x = m_ptr->fx;
int y = m_ptr->fy;
int i, j;
- object_type forge, *q_ptr;
delete_monster_idx(r);
/* Wipe the glass walls and create a stair */
for (i = x - 1; i <= x + 1; i++)
+ {
for (j = y - 1; j <= y + 1; j++)
{
if (in_bounds(j, i)) cave_set_feat(j, i, FEAT_FLOOR);
}
+ }
/* Get local object */
+ object_type forge, *q_ptr;
q_ptr = &forge;
/* Wipe the object */
@@ -72,7 +124,7 @@ bool_ quest_thrain_death_hook(char *fmt)
q_ptr->number = 1;
q_ptr->found = OBJ_FOUND_REWARD;
create_artifact(q_ptr, FALSE, TRUE);
- q_ptr->art_name = quark_add("of Thrain");
+ q_ptr->artifact_name = "of Thrain";
/* Drop it in the dungeon */
drop_near(q_ptr, -1, y, x);
@@ -81,33 +133,33 @@ bool_ quest_thrain_death_hook(char *fmt)
}
- del_hook(HOOK_MONSTER_DEATH, quest_thrain_death_hook);
+ del_hook_new(HOOK_MONSTER_DEATH, quest_thrain_death_hook);
process_hooks_restart = TRUE;
- return (FALSE);
+ return false;
}
-bool_ quest_thrain_gen_hook(char *fmt)
+static bool quest_thrain_gen_hook(void *, void *in_, void *)
{
- s32b x, y, bx0, by0;
+ struct hook_build_room1_in *in = static_cast<struct hook_build_room1_in *>(in_);
+ s32b bx0 = in->x;
+ s32b by0 = in->y;
+ s32b x, y;
int xstart;
int ystart;
int y2, x2, yval, xval;
int y1, x1, xsize, ysize;
- if (dungeon_type != DUNGEON_DOL_GULDUR) return (FALSE);
- if (cquest.data[0] != dun_level) return (FALSE);
- if (cquest.data[1]) return (FALSE);
- if ((cquest.status < QUEST_STATUS_TAKEN) || (cquest.status >= QUEST_STATUS_FINISHED)) return (FALSE);
-
- by0 = get_next_arg(fmt);
- bx0 = get_next_arg(fmt);
+ if (dungeon_type != DUNGEON_DOL_GULDUR) return false;
+ if (cquest.data[0] != dun_level) return false;
+ if (cquest.data[1]) return false;
+ if ((cquest.status < QUEST_STATUS_TAKEN) || (cquest.status >= QUEST_STATUS_FINISHED)) return false;
/* Pick a room size */
get_map_size("thrain.map", &ysize, &xsize);
/* Try to allocate space for room. If fails, exit */
- if (!room_alloc(xsize + 2, ysize + 2, FALSE, by0, bx0, &xval, &yval)) return FALSE;
+ if (!room_alloc(xsize + 2, ysize + 2, FALSE, by0, bx0, &xval, &yval)) return false;
/* Get corner values */
y1 = yval - ysize / 2;
@@ -144,50 +196,49 @@ bool_ quest_thrain_gen_hook(char *fmt)
cave[y][x].info |= CAVE_ICKY | CAVE_ROOM | CAVE_FREE;
if (cave[y][x].feat == FEAT_MARKER)
{
- int i;
+ m_allow_special[get_thrain()] = TRUE;
+ int i = place_monster_one(y, x, get_thrain(), 0, FALSE, MSTATUS_NEUTRAL);
+ m_allow_special[get_thrain()] = FALSE;
- m_allow_special[test_monster_name("Thrain, the King Under the Mountain")] = TRUE;
- i = place_monster_one(y, x, test_monster_name("Thrain, the King Under the Mountain"), 0, FALSE, MSTATUS_NEUTRAL);
if (i) m_list[i].mflag |= MFLAG_QUEST;
- m_allow_special[test_monster_name("Thrain, the King Under the Mountain")] = FALSE;
}
}
/* Don't try another one for this generation */
cquest.data[1] = 1;
- return (TRUE);
+ return true;
}
-bool_ quest_thrain_feeling_hook(char *fmt)
+
+static bool quest_thrain_feeling_hook(void *, void *, void *)
{
- if (dungeon_type != DUNGEON_DOL_GULDUR) return (FALSE);
- if (cquest.data[0] != dun_level) return (FALSE);
- if (cquest.status != QUEST_STATUS_UNTAKEN) return (FALSE);
+ if (dungeon_type != DUNGEON_DOL_GULDUR) return false;
+ if (cquest.data[0] != dun_level) return false;
+ if (cquest.status != QUEST_STATUS_UNTAKEN) return false;
cmsg_format(TERM_YELLOW, "You hear someone shouting under the torture.");
cquest.status = QUEST_STATUS_TAKEN;
- cquest.init(QUEST_THRAIN);
+ cquest.init();
- return (FALSE);
+ return false;
}
-bool_ quest_thrain_move_hook(char *fmt)
-{
- s32b y;
- s32b x;
- cave_type *c_ptr;
- y = get_next_arg(fmt);
- x = get_next_arg(fmt);
- c_ptr = &cave[y][x];
+static bool quest_thrain_move_hook(void *, void *in_, void *)
+{
+ struct hook_move_in *in = static_cast<struct hook_move_in *>(in_);
+ s32b y = in->y;
+ s32b x = in->x;
+ cave_type *c_ptr = &cave[y][x];
- if (dungeon_type != DUNGEON_DOL_GULDUR) return (FALSE);
- if (cquest.data[0] != dun_level) return (FALSE);
- if ((cquest.status < QUEST_STATUS_TAKEN) || (cquest.status >= QUEST_STATUS_FINISHED)) return (FALSE);
- if (!(c_ptr->info & CAVE_FREE)) return (FALSE);
- if (c_ptr->mimic != 61) return (FALSE);
+ if (dungeon_type != DUNGEON_DOL_GULDUR) return false;
+ if (cquest.data[0] != dun_level) return false;
+ if ((cquest.status < QUEST_STATUS_TAKEN) || (cquest.status >= QUEST_STATUS_FINISHED)) return false;
+ if (!(c_ptr->info & CAVE_FREE)) return false;
+ if (c_ptr->mimic != 61) return false;
cmsg_print(TERM_YELLOW, "The magic hiding the room dissipates.");
for (x = 0; x < cur_wid; x++)
+ {
for (y = 0; y < cur_hgt; y++)
{
c_ptr = &cave[y][x];
@@ -198,33 +249,41 @@ bool_ quest_thrain_move_hook(char *fmt)
c_ptr->mimic = 0;
lite_spot(y, x);
}
+ }
- return (FALSE);
+ return false;
}
-bool_ quest_thrain_turn_hook(char *fmt)
+
+static bool quest_thrain_turn_hook(void *, void *, void *)
{
cquest.data[1] = 0;
cquest.data[2] = 0;
- return (FALSE);
+ return false;
}
-bool_ quest_thrain_init_hook(int q)
+
+void quest_thrain_init_hook()
{
+ auto const &d_info = game->edit_data.d_info;
+ auto &messages = game->messages;
+
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)
+ {
+ messages.add(format("Thrain lvl %d", cquest.data[0]), TERM_BLUE);
+ }
}
if ((cquest.status >= QUEST_STATUS_TAKEN) && (cquest.status < QUEST_STATUS_FINISHED))
{
- add_hook(HOOK_MOVE, quest_thrain_move_hook, "thrain_move");
+ add_hook_new(HOOK_MOVE, quest_thrain_move_hook, "thrain_move", NULL);
}
if ((cquest.status >= QUEST_STATUS_UNTAKEN) && (cquest.status < QUEST_STATUS_FINISHED))
{
- add_hook(HOOK_LEVEL_REGEN, quest_thrain_turn_hook, "thrain_regen_lvl");
- add_hook(HOOK_NEW_LEVEL, quest_thrain_turn_hook, "thrain_new_lvl");
- add_hook(HOOK_BUILD_ROOM1, quest_thrain_gen_hook, "thrain_gen");
- add_hook(HOOK_FEELING, quest_thrain_feeling_hook, "thrain_feel");
- add_hook(HOOK_MONSTER_DEATH, quest_thrain_death_hook, "thrain_death");
+ add_hook_new(HOOK_LEVEL_REGEN, quest_thrain_turn_hook, "thrain_regen_lvl", NULL);
+ add_hook_new(HOOK_NEW_LEVEL, quest_thrain_turn_hook, "thrain_new_lvl", NULL);
+ add_hook_new(HOOK_BUILD_ROOM1, quest_thrain_gen_hook, "thrain_gen", NULL);
+ add_hook_new(HOOK_FEELING, quest_thrain_feeling_hook, "thrain_feel", NULL);
+ add_hook_new(HOOK_MONSTER_DEATH, quest_thrain_death_hook, "thrain_death", NULL);
}
- return (FALSE);
}
diff --git a/src/q_thrain.hpp b/src/q_thrain.hpp
new file mode 100644
index 00000000..aa42385d
--- /dev/null
+++ b/src/q_thrain.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+void quest_thrain_init_hook();
diff --git a/src/q_troll.c b/src/q_troll.cc
index c314d2a7..54eb3406 100644
--- a/src/q_troll.c
+++ b/src/q_troll.cc
@@ -1,13 +1,43 @@
-#undef cquest
+#include "q_troll.hpp"
+
+#include "artifact_type.hpp"
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "game.hpp"
+#include "hook_monster_death_in.hpp"
+#include "hook_quest_finish_in.hpp"
+#include "hooks.hpp"
+#include "init1.hpp"
+#include "monster2.hpp"
+#include "monster_type.hpp"
+#include "object2.hpp"
+#include "object_type.hpp"
+#include "player_type.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+#include "z-rand.hpp"
+
+#include <cassert>
+
#define cquest (quest[QUEST_TROLL])
-bool_ quest_troll_gen_hook(char *fmt)
+GENERATE_MONSTER_LOOKUP_FN(get_tom, "Tom the Stone Troll")
+GENERATE_MONSTER_LOOKUP_FN(get_stone_troll, "Stone troll")
+GENERATE_MONSTER_LOOKUP_FN(get_forest_troll, "Forest troll")
+
+static bool quest_troll_gen_hook(void *, void *, void *)
{
+ auto &a_info = game->edit_data.a_info;
+
int x, y;
int xstart = 2;
int ystart = 2;
- if (p_ptr->inside_quest != QUEST_TROLL) return FALSE;
+ if (p_ptr->inside_quest != QUEST_TROLL)
+ {
+ return false;
+ }
/* Start with perm walls */
for (y = 0; y < cur_hgt; y++)
@@ -33,11 +63,9 @@ bool_ quest_troll_gen_hook(char *fmt)
{
if (cave[y][x].feat == FEAT_MARKER)
{
- int m_idx;
-
- m_allow_special[test_monster_name("Tom the Stone Troll")] = TRUE;
- m_idx = place_monster_one(y, x, test_monster_name("Tom the Stone Troll"), 0, FALSE, MSTATUS_ENEMY);
- m_allow_special[test_monster_name("Tom the Stone Troll")] = FALSE;
+ m_allow_special[get_tom()] = TRUE;
+ int m_idx = place_monster_one(y, x, get_tom(), 0, FALSE, MSTATUS_ENEMY);
+ m_allow_special[get_tom()] = FALSE;
if (m_idx)
{
@@ -72,14 +100,11 @@ bool_ quest_troll_gen_hook(char *fmt)
/* Structure copy */
object_copy(o_ptr, q_ptr);
- /* Build a stack */
- o_ptr->next_o_idx = m_list[m_idx].hold_o_idx;
-
+ /* Add to monster's inventory */
o_ptr->held_m_idx = m_idx;
o_ptr->ix = 0;
o_ptr->iy = 0;
-
- m_list[m_idx].hold_o_idx = o_idx;
+ m_list[m_idx].hold_o_idxs.push_back(o_idx);
}
else
{
@@ -91,62 +116,70 @@ bool_ quest_troll_gen_hook(char *fmt)
/* Reinitialize the ambush ... hehehe */
cquest.data[0] = FALSE;
- return TRUE;
+ return true;
}
-bool_ quest_troll_finish_hook(char *fmt)
-{
- s32b q_idx;
- q_idx = get_next_arg(fmt);
+static bool quest_troll_finish_hook(void *, void *in_, void *)
+{
+ struct hook_quest_finish_in *in = static_cast<struct hook_quest_finish_in *>(in_);
+ s32b q_idx = in->q_idx;
- if (q_idx != QUEST_TROLL) return FALSE;
+ if (q_idx != QUEST_TROLL)
+ {
+ return false;
+ }
c_put_str(TERM_YELLOW, "I heard about your noble deeds.", 8, 0);
c_put_str(TERM_YELLOW, "Keep what you found... may it serve you well.", 9, 0);
/* Continue the plot */
*(quest[q_idx].plot) = QUEST_NAZGUL;
- quest[*(quest[q_idx].plot)].init(*(quest[q_idx].plot));
+ quest[*(quest[q_idx].plot)].init();
- del_hook(HOOK_QUEST_FINISH, quest_troll_finish_hook);
+ del_hook_new(HOOK_QUEST_FINISH, quest_troll_finish_hook);
process_hooks_restart = TRUE;
- return TRUE;
+ return true;
}
-bool_ quest_troll_death_hook(char *fmt)
+
+static bool quest_troll_death_hook(void *, void *in_, void *)
{
+ struct hook_monster_death_in *in = static_cast<struct hook_monster_death_in *>(in_);
+ s32b m_idx = in->m_idx;
+ s32b r_idx = m_list[m_idx].r_idx;
int x, y, xstart = 2, ystart = 2;
- s32b r_idx, m_idx;
- ;
-
- m_idx = get_next_arg(fmt);
-
- r_idx = m_list[m_idx].r_idx;
- if (p_ptr->inside_quest != QUEST_TROLL) return FALSE;
+ if (p_ptr->inside_quest != QUEST_TROLL)
+ {
+ return false;
+ }
- if (r_idx == test_monster_name("Tom the Stone Troll"))
+ if (r_idx == get_tom())
{
cave_set_feat(3, 3, FEAT_LESS);
cave[3][3].special = 0;
cmsg_print(TERM_YELLOW, "Without Tom, the trolls won't be able to do much.");
cquest.status = QUEST_STATUS_COMPLETED;
- del_hook(HOOK_MONSTER_DEATH, quest_troll_death_hook);
+ del_hook_new(HOOK_MONSTER_DEATH, quest_troll_death_hook);
process_hooks_restart = TRUE;
- return (FALSE);
+ return false;
}
init_flags = INIT_GET_SIZE;
process_dungeon_file("trolls.map", &ystart, &xstart, cur_hgt, cur_wid, TRUE, TRUE);
- if (cquest.data[0]) return FALSE;
+ if (cquest.data[0])
+ {
+ return false;
+ }
cquest.data[0] = TRUE;
msg_print("Oops, seems like an ambush...");
for (x = 3; x < xstart; x++)
+ {
for (y = 3; y < ystart; y++)
{
cave_type *c_ptr = &cave[y][x];
@@ -154,25 +187,24 @@ bool_ quest_troll_death_hook(char *fmt)
/* Ahah ! */
if (c_ptr->info & CAVE_SPEC)
{
- int r_idx;
-
cave_set_feat(y, x, FEAT_GRASS);
c_ptr->info &= ~CAVE_SPEC;
- r_idx = (rand_int(2) == 0) ? test_monster_name("Forest troll") : test_monster_name("Stone troll");
+ int r_idx = (rand_int(2) == 0) ? get_forest_troll() : get_stone_troll();
place_monster_one(y, x, r_idx, 0, FALSE, MSTATUS_ENEMY);
}
}
+ }
- return FALSE;
+ return false;
}
-bool_ quest_troll_init_hook(int q_idx)
+
+void quest_troll_init_hook()
{
if ((cquest.status >= QUEST_STATUS_TAKEN) && (cquest.status < QUEST_STATUS_FINISHED))
{
- add_hook(HOOK_MONSTER_DEATH, quest_troll_death_hook, "troll_death");
- add_hook(HOOK_GEN_QUEST, quest_troll_gen_hook, "troll_gen");
- add_hook(HOOK_QUEST_FINISH, quest_troll_finish_hook, "troll_finish");
+ add_hook_new(HOOK_MONSTER_DEATH, quest_troll_death_hook, "troll_death", NULL);
+ add_hook_new(HOOK_GEN_QUEST, quest_troll_gen_hook, "troll_gen", NULL);
+ add_hook_new(HOOK_QUEST_FINISH, quest_troll_finish_hook, "troll_finish", NULL);
}
- return (FALSE);
}
diff --git a/src/q_troll.hpp b/src/q_troll.hpp
new file mode 100644
index 00000000..08bba3dd
--- /dev/null
+++ b/src/q_troll.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+void quest_troll_init_hook();
diff --git a/src/q_ultrae.c b/src/q_ultrae.c
deleted file mode 100644
index 78471df5..00000000
--- a/src/q_ultrae.c
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Here takes place the Evil ultra ending
- */
-
-#undef cquest
-#define cquest (quest[QUEST_ULTRA_EVIL])
-
-bool_ quest_ultra_evil_init_hook(int q)
-{
- return (FALSE);
-}
diff --git a/src/q_ultrae.cc b/src/q_ultrae.cc
new file mode 100644
index 00000000..ff2a6a48
--- /dev/null
+++ b/src/q_ultrae.cc
@@ -0,0 +1,8 @@
+#include "q_ultrae.hpp"
+
+#define cquest (quest[QUEST_ULTRA_EVIL])
+
+void quest_ultra_evil_init_hook()
+{
+ // Initialized by other hook.
+}
diff --git a/src/q_ultrae.hpp b/src/q_ultrae.hpp
new file mode 100644
index 00000000..77ec2e38
--- /dev/null
+++ b/src/q_ultrae.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+void quest_ultra_evil_init_hook();
diff --git a/src/q_ultrag.c b/src/q_ultrag.cc
index a5a09f2d..e3da974f 100644
--- a/src/q_ultrag.c
+++ b/src/q_ultrag.cc
@@ -1,29 +1,48 @@
-/*
- * Here takes place the Good ultra ending
- */
+#include "q_ultrag.hpp"
+
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "hook_chardump_in.hpp"
+#include "hook_move_in.hpp"
+#include "hook_stair_in.hpp"
+#include "hook_monster_death_in.hpp"
+#include "hooks.hpp"
+#include "monster_type.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_flag.hpp"
+#include "object_type.hpp"
+#include "options.hpp"
+#include "player_type.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "variable.hpp"
-#undef cquest
#define cquest (quest[QUEST_ULTRA_GOOD])
-bool_ quest_ultra_good_move_hook(char *fmt)
+static bool quest_ultra_good_move_hook(void *, void *in_, void *)
{
- s32b y, x;
- cave_type *c_ptr;
-
- y = get_next_arg(fmt);
- x = get_next_arg(fmt);
- c_ptr = &cave[y][x];
+ struct hook_move_in *in = static_cast<struct hook_move_in *>(in_);
+ s32b y = in->y;
+ s32b x = in->x;
+ cave_type *c_ptr = &cave[y][x];
if (cquest.status == QUEST_STATUS_UNTAKEN)
{
- bool_ old_quick_messages = quick_messages;
-
- if (quest[QUEST_MORGOTH].status < QUEST_STATUS_FINISHED) return (FALSE);
+ if (quest[QUEST_MORGOTH].status < QUEST_STATUS_FINISHED)
+ {
+ return false;
+ }
/* The mirror of Galadriel */
- if ((c_ptr->feat != FEAT_SHOP) || (c_ptr->special != 23)) return (FALSE);
+ if ((c_ptr->feat != FEAT_SHOP) || (c_ptr->special != 23))
+ {
+ return false;
+ }
+
+ auto old_quick_messages = options->quick_messages;
+ options->quick_messages = FALSE;
- quick_messages = FALSE;
cmsg_print(TERM_L_BLUE, "You meet Galadriel.");
cmsg_print(TERM_YELLOW, "'I still cannot believe this is all over.'");
cmsg_print(TERM_YELLOW, "'Morgoth's reign of terror is over at last!'");
@@ -67,40 +86,44 @@ bool_ quest_ultra_good_move_hook(char *fmt)
/* Continue the plot */
cquest.status = QUEST_STATUS_TAKEN;
- cquest.init(QUEST_ULTRA_GOOD);
+ cquest.init();
}
- quick_messages = old_quick_messages;
- return TRUE;
+ options->quick_messages = old_quick_messages;
+
+ return true;
}
- return FALSE;
+ return false;
}
-bool_ quest_ultra_good_stair_hook(char *fmt)
+static bool quest_ultra_good_stair_hook(void *, void *in_, void *)
{
- cptr dir;
-
- dir = get_next_arg_str(fmt);
+ struct hook_stair_in *in = static_cast<struct hook_stair_in *>(in_);
+ stairs_direction dir = in->direction;
if (dungeon_type != DUNGEON_VOID)
- return FALSE;
+ {
+ return false;
+ }
/* Cant leave */
- if ((!strcmp(dir, "up")) && (dun_level == 128))
+ if ((dir == STAIRS_UP) && (dun_level == 128))
{
cmsg_print(TERM_YELLOW, "The portal to Arda is now closed.");
- return TRUE;
+ return true;
}
+
/* there is no coming back */
- if ((!strcmp(dir, "up")) && (dun_level == 150))
+ if ((dir == STAIRS_UP) && (dun_level == 150))
{
cmsg_print(TERM_YELLOW, "The barrier seems to be impenetrable from this side.");
cmsg_print(TERM_YELLOW, "You will have to move on.");
- return TRUE;
+ return true;
}
+
/* Cant enter without the flame imperishable */
- if ((!strcmp(dir, "down")) && (dun_level == 149))
+ if ((dir == STAIRS_DOWN) && (dun_level == 149))
{
int i;
bool_ ultimate = FALSE;
@@ -108,15 +131,16 @@ bool_ quest_ultra_good_stair_hook(char *fmt)
/* Now look for an ULTIMATE artifact, that is, one imbued with the flame */
for (i = INVEN_WIELD; i < INVEN_TOTAL; i++)
{
- u32b f1, f2, f3, f4, f5, esp;
object_type *o_ptr = get_object(i);
- if (!o_ptr->k_idx) continue;
+ if (!o_ptr->k_idx)
+ {
+ continue;
+ }
- /* Examine the gloves */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ auto const flags = object_flags(o_ptr);
- if (f4 & TR4_ULTIMATE)
+ if (flags & TR_ULTIMATE)
{
ultimate = TRUE;
break;
@@ -137,21 +161,24 @@ bool_ quest_ultra_good_stair_hook(char *fmt)
}
}
- return FALSE;
+ return false;
}
-bool_ quest_ultra_good_recall_hook(char *fmt)
+static bool quest_ultra_good_recall_hook(void *, void *, void *)
{
if ((dungeon_type != DUNGEON_VOID) && (dungeon_type != DUNGEON_NETHER_REALM))
- return FALSE;
+ {
+ return false;
+ }
cmsg_print(TERM_YELLOW, "You cannot recall. The portal to Arda is closed.");
- return TRUE;
+ return true;
}
-bool_ quest_ultra_good_death_hook(char *fmt)
+static bool quest_ultra_good_death_hook(void *, void *in_, void *)
{
- s32b m_idx = get_next_arg(fmt);
+ struct hook_monster_death_in *in = static_cast<struct hook_monster_death_in *>(in_);
+ s32b m_idx = in->m_idx;
monster_type *m_ptr = &m_list[m_idx];
@@ -164,7 +191,7 @@ bool_ quest_ultra_good_death_hook(char *fmt)
quest[QUEST_ULTRA_GOOD].status = QUEST_STATUS_FINISHED;
/* Redraw the "title" */
- p_ptr->redraw |= (PR_TITLE);
+ p_ptr->redraw |= (PR_FRAME);
/* Congratulations */
cmsg_print(TERM_L_GREEN, "****** CONGRATULATIONS ******");
@@ -180,7 +207,7 @@ bool_ quest_ultra_good_death_hook(char *fmt)
cave_set_feat(p_ptr->py, p_ptr->px, FEAT_MORE);
/* Remove now used hook */
- del_hook(HOOK_MONSTER_DEATH, quest_ultra_good_death_hook);
+ del_hook_new(HOOK_MONSTER_DEATH, quest_ultra_good_death_hook);
process_hooks_restart = TRUE;
/* End plot */
@@ -214,7 +241,10 @@ bool_ quest_ultra_good_death_hook(char *fmt)
for (i = 0; i < INVEN_PACK; i++)
{
/* Skip non-objects */
- if (!p_ptr->inventory[i].k_idx) break;
+ if (!p_ptr->inventory[i].k_idx)
+ {
+ break;
+ }
}
/* Arg, no space ! */
if (i == INVEN_PACK)
@@ -233,44 +263,49 @@ bool_ quest_ultra_good_death_hook(char *fmt)
cmsg_format(TERM_VIOLET, "You feel the urge to pick up the Flame Imperishable.");
inven_carry(q_ptr, FALSE);
}
- return (FALSE);
+
+ return false;
}
-bool_ quest_ultra_good_dump_hook(char *fmt)
+
+static bool quest_ultra_good_dump_hook(void *, void *in_, void *)
{
+ struct hook_chardump_in *in = static_cast<struct hook_chardump_in *>(in_);
+ FILE *f = in->file;
+
if (quest[QUEST_ULTRA_GOOD].status >= QUEST_STATUS_TAKEN)
{
/* Ultra winner ! */
if (total_winner == WINNER_ULTRA)
{
- fprintf(hook_file, "\n You destroyed Melkor forever and have been elevated to the status of Vala by Eru Iluvatar.");
- fprintf(hook_file, "\n Arda will forever be free.");
+ fprintf(f, "\n You destroyed Melkor forever and have been elevated to the status of Vala by Eru Iluvatar.");
+ fprintf(f, "\n Arda will forever be free.");
}
else
{
/* Tried and failed */
if (death)
{
- fprintf(hook_file, "\n You tried to destroy Melkor forever, but died in the attempt.");
- fprintf(hook_file, "\n Arda will be quiet, but not free from evil.");
+ fprintf(f, "\n You tried to destroy Melkor forever, but died in the attempt.");
+ fprintf(f, "\n Arda will be quiet, but not free from evil.");
}
}
}
- return (FALSE);
+
+ return false;
}
-bool_ quest_ultra_good_init_hook(int q)
+void quest_ultra_good_init_hook()
{
if ((cquest.status >= QUEST_STATUS_TAKEN) && (cquest.status < QUEST_STATUS_FINISHED))
{
- add_hook(HOOK_STAIR, quest_ultra_good_stair_hook, "ultrag_stair");
- add_hook(HOOK_RECALL, quest_ultra_good_recall_hook, "ultrag_recall");
- add_hook(HOOK_MONSTER_DEATH, quest_ultra_good_death_hook, "ultrag_death");
+ add_hook_new(HOOK_STAIR, quest_ultra_good_stair_hook, "ultrag_stair", NULL);
+ add_hook_new(HOOK_RECALL, quest_ultra_good_recall_hook, "ultrag_recall", NULL);
+ add_hook_new(HOOK_MONSTER_DEATH, quest_ultra_good_death_hook, "ultrag_death", NULL);
}
if (cquest.status == QUEST_STATUS_UNTAKEN)
{
- add_hook(HOOK_MOVE, quest_ultra_good_move_hook, "ultrag_move");
+ add_hook_new(HOOK_MOVE, quest_ultra_good_move_hook, "ultrag_move", NULL);
}
- add_hook(HOOK_CHAR_DUMP, quest_ultra_good_dump_hook, "ultrag_dump");
- return (FALSE);
+ add_hook_new(HOOK_CHAR_DUMP, quest_ultra_good_dump_hook, "ultrag_dump", NULL);
}
diff --git a/src/q_ultrag.hpp b/src/q_ultrag.hpp
new file mode 100644
index 00000000..cef81fa5
--- /dev/null
+++ b/src/q_ultrag.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+void quest_ultra_good_init_hook();
diff --git a/src/q_wight.c b/src/q_wight.c
deleted file mode 100644
index 3f6b2c34..00000000
--- a/src/q_wight.c
+++ /dev/null
@@ -1,156 +0,0 @@
-#undef cquest
-#define cquest (quest[QUEST_WIGHT])
-
-bool_ quest_wight_gen_hook(char *fmt)
-{
- int x, y;
- int xstart = 2;
- int ystart = 2;
-
- if (p_ptr->inside_quest != QUEST_WIGHT) return FALSE;
-
- /* Start with perm walls */
- for (y = 0; y < cur_hgt; y++)
- {
- for (x = 0; x < cur_wid; x++)
- {
- cave_set_feat(y, x, FEAT_PERM_SOLID);
- }
- }
- dun_level = quest[p_ptr->inside_quest].level;
-
- /* Set the correct monster hook */
- set_mon_num_hook();
-
- /* Prepare allocation table */
- get_mon_num_prep();
-
- init_flags = INIT_CREATE_DUNGEON;
- process_dungeon_file("wights.map", &ystart, &xstart, cur_hgt, cur_wid, TRUE, TRUE);
-
- for (x = 3; x < xstart; x++)
- for (y = 3; y < ystart; y++)
- {
- if (cave[y][x].feat == FEAT_MARKER)
- {
- int m_idx = 0;
-
- m_allow_special[test_monster_name("The Wight-King of the Barrow-downs")] = TRUE;
- m_idx = place_monster_one(y, x, test_monster_name("The Wight-King of the Barrow-downs"), 0, FALSE, MSTATUS_ENEMY);
- m_allow_special[test_monster_name("The Wight-King of the Barrow-downs")] = FALSE;
-
- if (m_idx)
- {
- int o_idx;
-
- /* Get local object */
- object_type forge, *q_ptr = &forge;
-
- m_list[m_idx].mflag |= MFLAG_QUEST;
-
- /* Prepare to make the */
- object_prep(q_ptr, lookup_kind(TV_SOFT_ARMOR, SV_FILTHY_RAG));
-
- /* Name the rags */
-
- q_ptr->art_name = quark_add("of the Wight");
-
- q_ptr->art_flags1 |= ( TR1_INT | TR1_SEARCH );
- q_ptr->art_flags2 |= ( TR2_RES_BLIND | TR2_SENS_FIRE | TR2_RES_CONF );
- q_ptr->art_flags3 |= ( TR3_IGNORE_ACID | TR3_IGNORE_ELEC |
- TR3_IGNORE_FIRE | TR3_IGNORE_COLD | TR3_SEE_INVIS);
-
- /* For game balance... */
- q_ptr->art_flags3 |= (TR3_CURSED | TR3_HEAVY_CURSE);
- q_ptr->ident |= IDENT_CURSED;
-
- if (randint(2) == 1)
- {
- q_ptr->art_flags1 |= (TR1_SPELL);
- q_ptr->pval = 6;
- }
- else
- {
- q_ptr->art_flags1 |= (TR1_MANA);
- q_ptr->pval = 2;
- }
-
- /* Get new object */
- o_idx = o_pop();
-
- if (o_idx)
- {
- /* Get the item */
- object_type *o_ptr = &o_list[o_idx];
-
- /* Structure copy */
- object_copy(o_ptr, q_ptr);
-
- /* Build a stack */
- o_ptr->next_o_idx = m_list[m_idx].hold_o_idx;
-
- o_ptr->held_m_idx = m_idx;
- o_ptr->ix = 0;
- o_ptr->iy = 0;
-
- m_list[m_idx].hold_o_idx = o_idx;
- }
- }
- }
- }
-
- return TRUE;
-}
-bool_ quest_wight_death_hook(char *fmt)
-{
- s32b r_idx, m_idx;
-
- m_idx = get_next_arg(fmt);
- r_idx = m_list[m_idx].r_idx;
-
- if (p_ptr->inside_quest != QUEST_WIGHT) return FALSE;
-
- if (r_idx == test_monster_name("The Wight-King of the Barrow-downs"))
- {
- cmsg_print(TERM_YELLOW, "Without their King the wights won't be able to do much.");
-
- cave_set_feat(p_ptr->py, p_ptr->px, FEAT_LESS);
- cave[p_ptr->py][p_ptr->px].special = 0;
-
- cquest.status = QUEST_STATUS_COMPLETED;
- del_hook(HOOK_MONSTER_DEATH, quest_wight_death_hook);
- process_hooks_restart = TRUE;
- return (FALSE);
- }
-
- return (FALSE);
-}
-bool_ quest_wight_finish_hook(char *fmt)
-{
- s32b q_idx;
- q_idx = get_next_arg(fmt);
-
- if (q_idx != QUEST_WIGHT) return FALSE;
-
- c_put_str(TERM_YELLOW, "I heard about your noble deeds.", 8, 0);
- c_put_str(TERM_YELLOW, "Keep what you found .. may it serve you well.", 9, 0);
-
- /* Continue the plot */
- *(quest[q_idx].plot) = QUEST_NAZGUL;
- quest[*(quest[q_idx].plot)].init(*(quest[q_idx].plot));
-
- del_hook(HOOK_QUEST_FINISH, quest_wight_finish_hook);
- process_hooks_restart = TRUE;
-
- return TRUE;
-}
-bool_ quest_wight_init_hook(int q_idx)
-{
- if ((cquest.status >= QUEST_STATUS_TAKEN) && (cquest.status < QUEST_STATUS_FINISHED))
- {
- add_hook(HOOK_MONSTER_DEATH, quest_wight_death_hook, "wight_death");
- add_hook(HOOK_GEN_QUEST, quest_wight_gen_hook, "wight_gen");
- add_hook(HOOK_QUEST_FINISH, quest_wight_finish_hook, "wight_finish");
- }
- return (FALSE);
-}
diff --git a/src/q_wight.cc b/src/q_wight.cc
new file mode 100644
index 00000000..ced87277
--- /dev/null
+++ b/src/q_wight.cc
@@ -0,0 +1,195 @@
+#include "q_wight.hpp"
+
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "hook_monster_death_in.hpp"
+#include "hook_quest_finish_in.hpp"
+#include "hooks.hpp"
+#include "init1.hpp"
+#include "monster2.hpp"
+#include "monster_type.hpp"
+#include "object2.hpp"
+#include "object_flag.hpp"
+#include "player_type.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+#include "z-rand.hpp"
+
+#include <cassert>
+
+#define cquest (quest[QUEST_WIGHT])
+
+GENERATE_MONSTER_LOOKUP_FN(get_wight_king, "The Wight-King of the Barrow-downs")
+
+static bool quest_wight_gen_hook(void *, void *, void *)
+{
+ int x, y;
+ int xstart = 2;
+ int ystart = 2;
+
+ if (p_ptr->inside_quest != QUEST_WIGHT)
+ {
+ return false;
+ }
+
+ /* Start with perm walls */
+ for (y = 0; y < cur_hgt; y++)
+ {
+ for (x = 0; x < cur_wid; x++)
+ {
+ cave_set_feat(y, x, FEAT_PERM_SOLID);
+ }
+ }
+ dun_level = quest[p_ptr->inside_quest].level;
+
+ /* Set the correct monster hook */
+ set_mon_num_hook();
+
+ /* Prepare allocation table */
+ get_mon_num_prep();
+
+ init_flags = INIT_CREATE_DUNGEON;
+ process_dungeon_file("wights.map", &ystart, &xstart, cur_hgt, cur_wid, TRUE, TRUE);
+
+ for (x = 3; x < xstart; x++)
+ {
+ for (y = 3; y < ystart; y++)
+ {
+ if (cave[y][x].feat == FEAT_MARKER)
+ {
+ int m_idx = 0;
+
+ m_allow_special[get_wight_king()] = TRUE;
+ m_idx = place_monster_one(y, x, get_wight_king(), 0, FALSE, MSTATUS_ENEMY);
+ m_allow_special[get_wight_king()] = FALSE;
+
+ if (m_idx)
+ {
+ int o_idx;
+
+ /* Get local object */
+ object_type forge, *q_ptr = &forge;
+
+ m_list[m_idx].mflag |= MFLAG_QUEST;
+
+ /* Prepare to make the */
+ object_prep(q_ptr, lookup_kind(TV_SOFT_ARMOR, SV_FILTHY_RAG));
+
+ /* Name the rags */
+
+ q_ptr->artifact_name = "of the Wight";
+
+ q_ptr->art_flags |=
+ TR_INT |
+ TR_RES_BLIND |
+ TR_SENS_FIRE |
+ TR_RES_CONF |
+ TR_IGNORE_ACID |
+ TR_IGNORE_ELEC |
+ TR_IGNORE_FIRE |
+ TR_IGNORE_COLD |
+ TR_SEE_INVIS |
+ TR_CURSED |
+ TR_HEAVY_CURSE;
+
+ q_ptr->ident |= IDENT_CURSED;
+
+ if (randint(2) == 1)
+ {
+ q_ptr->art_flags |= TR_SPELL;
+ q_ptr->pval = 6;
+ }
+ else
+ {
+ q_ptr->art_flags |= TR_MANA;
+ q_ptr->pval = 2;
+ }
+
+ /* Get new object */
+ o_idx = o_pop();
+
+ if (o_idx)
+ {
+ /* Get the item */
+ object_type *o_ptr = &o_list[o_idx];
+
+ /* Structure copy */
+ object_copy(o_ptr, q_ptr);
+
+ /* Build a stack */
+ o_ptr->held_m_idx = m_idx;
+ o_ptr->ix = 0;
+ o_ptr->iy = 0;
+
+ m_list[m_idx].hold_o_idxs.push_back(o_idx);
+ }
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+static bool quest_wight_death_hook(void *, void *in_, void *)
+{
+ struct hook_monster_death_in *in = static_cast<struct hook_monster_death_in *>(in_);
+ s32b m_idx = in->m_idx;
+ s32b r_idx = m_list[m_idx].r_idx;
+
+ if (p_ptr->inside_quest != QUEST_WIGHT)
+ {
+ return false;
+ }
+
+ if (r_idx == get_wight_king())
+ {
+ cmsg_print(TERM_YELLOW, "Without their King the wights won't be able to do much.");
+
+ cave_set_feat(p_ptr->py, p_ptr->px, FEAT_LESS);
+ cave[p_ptr->py][p_ptr->px].special = 0;
+
+ cquest.status = QUEST_STATUS_COMPLETED;
+
+ del_hook_new(HOOK_MONSTER_DEATH, quest_wight_death_hook);
+ process_hooks_restart = TRUE;
+
+ return false;
+ }
+
+ return false;
+}
+
+static bool quest_wight_finish_hook(void *, void *in_, void *)
+{
+ struct hook_quest_finish_in *in = static_cast<struct hook_quest_finish_in *>(in_);
+ s32b q_idx = in->q_idx;
+
+ if (q_idx != QUEST_WIGHT)
+ {
+ return false;
+ }
+
+ c_put_str(TERM_YELLOW, "I heard about your noble deeds.", 8, 0);
+ c_put_str(TERM_YELLOW, "Keep what you found .. may it serve you well.", 9, 0);
+
+ /* Continue the plot */
+ *(quest[q_idx].plot) = QUEST_NAZGUL;
+ quest[*(quest[q_idx].plot)].init();
+
+ del_hook_new(HOOK_QUEST_FINISH, quest_wight_finish_hook);
+ process_hooks_restart = TRUE;
+
+ return true;
+}
+
+void quest_wight_init_hook()
+{
+ if ((cquest.status >= QUEST_STATUS_TAKEN) && (cquest.status < QUEST_STATUS_FINISHED))
+ {
+ add_hook_new(HOOK_MONSTER_DEATH, quest_wight_death_hook, "wight_death", NULL);
+ add_hook_new(HOOK_GEN_QUEST, quest_wight_gen_hook, "wight_gen", NULL);
+ add_hook_new(HOOK_QUEST_FINISH, quest_wight_finish_hook, "wight_finish", NULL);
+ }
+}
diff --git a/src/q_wight.hpp b/src/q_wight.hpp
new file mode 100644
index 00000000..16713332
--- /dev/null
+++ b/src/q_wight.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+void quest_wight_init_hook();
diff --git a/src/q_wolves.c b/src/q_wolves.cc
index 2ec14cc2..0e811ce6 100644
--- a/src/q_wolves.c
+++ b/src/q_wolves.cc
@@ -1,17 +1,43 @@
-#undef cquest
+#include "q_wolves.hpp"
+
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "dungeon_flag.hpp"
+#include "feature_flag.hpp"
+#include "feature_type.hpp"
+#include "game.hpp"
+#include "hook_quest_finish_in.hpp"
+#include "hooks.hpp"
+#include "init1.hpp"
+#include "monster2.hpp"
+#include "monster_type.hpp"
+#include "player_type.hpp"
+#include "quest_type.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+#include "z-rand.hpp"
+
#define cquest (quest[QUEST_WOLVES])
-bool_ quest_wolves_gen_hook(char *fmt)
+static bool quest_wolves_gen_hook(void *, void *, void *)
{
+ auto const &f_info = game->edit_data.f_info;
+
int x, y, i;
int xstart = 2;
int ystart = 2;
- if (p_ptr->inside_quest != QUEST_WOLVES) return FALSE;
+ if (p_ptr->inside_quest != QUEST_WOLVES)
+ {
+ return false;
+ }
/* Just in case we didnt talk the the mayor */
if (cquest.status == QUEST_STATUS_UNTAKEN)
+ {
cquest.status = QUEST_STATUS_TAKEN;
+ }
/* Start with perm walls */
for (y = 0; y < cur_hgt; y++)
@@ -32,18 +58,17 @@ bool_ quest_wolves_gen_hook(char *fmt)
init_flags = INIT_CREATE_DUNGEON;
process_dungeon_file("wolves.map", &ystart, &xstart, cur_hgt, cur_wid, TRUE, FALSE);
- dungeon_flags2 |= DF2_NO_GENO;
+ dungeon_flags |= DF_NO_GENO;
/* Place some random wolves */
for (i = damroll(4, 4); i > 0; )
{
- int m_idx, flags;
y = rand_int(21) + 3;
x = rand_int(31) + 3;
- flags = f_info[cave[y][x].feat].flags1;
- if (!(flags & FF1_PERMANENT) && (flags & FF1_FLOOR))
+ auto const flags = f_info[cave[y][x].feat].flags;
+ if (!(flags & FF_PERMANENT) && (flags & FF_FLOOR))
{
- m_idx = place_monster_one(y, x, 196, 0, magik(50), MSTATUS_ENEMY);
+ int m_idx = place_monster_one(y, x, 196, 0, magik(50), MSTATUS_ENEMY);
if (m_idx) m_list[m_idx].mflag |= MFLAG_QUEST;
--i;
}
@@ -52,13 +77,12 @@ bool_ quest_wolves_gen_hook(char *fmt)
/* Place some random wargs */
for (i = damroll(4, 4); i > 0; )
{
- int m_idx, flags;
y = rand_int(21) + 3;
x = rand_int(31) + 3;
- flags = f_info[cave[y][x].feat].flags1;
- if (!(flags & FF1_PERMANENT) && (flags & FF1_FLOOR))
+ auto const flags = f_info[cave[y][x].feat].flags;
+ if (!(flags & FF_PERMANENT) && (flags & FF_FLOOR))
{
- m_idx = place_monster_one(y, x, 257, 0, magik(50), MSTATUS_ENEMY);
+ int m_idx = place_monster_one(y, x, 257, 0, magik(50), MSTATUS_ENEMY);
if (m_idx) m_list[m_idx].mflag |= MFLAG_QUEST;
--i;
}
@@ -66,14 +90,17 @@ bool_ quest_wolves_gen_hook(char *fmt)
process_hooks_restart = TRUE;
- return TRUE;
+ return true;
}
-bool_ quest_wolves_death_hook(char *fmt)
+static bool quest_wolves_death_hook(void *, void *, void *)
{
int i, mcnt = 0;
- if (p_ptr->inside_quest != QUEST_WOLVES) return FALSE;
+ if (p_ptr->inside_quest != QUEST_WOLVES)
+ {
+ return false;
+ }
/* Process the monsters (backwards) */
for (i = m_max - 1; i >= 1; i--)
@@ -91,23 +118,26 @@ bool_ quest_wolves_death_hook(char *fmt)
if (mcnt <= 1)
{
quest[p_ptr->inside_quest].status = QUEST_STATUS_COMPLETED;
- del_hook(HOOK_MONSTER_DEATH, quest_wolves_death_hook);
- del_hook(HOOK_GEN_QUEST, quest_wolves_gen_hook);
+
+ del_hook_new(HOOK_MONSTER_DEATH, quest_wolves_death_hook);
+ del_hook_new(HOOK_GEN_QUEST, quest_wolves_gen_hook);
process_hooks_restart = TRUE;
cmsg_print(TERM_YELLOW, "Lothlorien is safer now.");
- return (FALSE);
+ return false;
}
- return FALSE;
+ return false;
}
-bool_ quest_wolves_finish_hook(char *fmt)
+static bool quest_wolves_finish_hook(void *, void *in_, void *)
{
- s32b q_idx;
+ struct hook_quest_finish_in *in = static_cast<struct hook_quest_finish_in *>(in_);
+ s32b q_idx = in->q_idx;
- q_idx = get_next_arg(fmt);
-
- if (q_idx != QUEST_WOLVES) return FALSE;
+ if (q_idx != QUEST_WOLVES)
+ {
+ return false;
+ }
c_put_str(TERM_YELLOW, "Thank you for killing the pack of wolves!", 8, 0);
c_put_str(TERM_YELLOW, "You can use the hut as your house as a reward.", 9, 0);
@@ -115,16 +145,15 @@ bool_ quest_wolves_finish_hook(char *fmt)
/* Continue the plot */
*(quest[q_idx].plot) = QUEST_SPIDER;
- return TRUE;
+ return true;
}
-bool_ quest_wolves_init_hook(int q_idx)
+void quest_wolves_init_hook()
{
if ((cquest.status >= QUEST_STATUS_UNTAKEN) && (cquest.status < QUEST_STATUS_FINISHED))
{
- add_hook(HOOK_MONSTER_DEATH, quest_wolves_death_hook, "wolves_monster_death");
- add_hook(HOOK_QUEST_FINISH, quest_wolves_finish_hook, "wolves_finish");
- add_hook(HOOK_GEN_QUEST, quest_wolves_gen_hook, "wolves_geb");
+ add_hook_new(HOOK_MONSTER_DEATH, quest_wolves_death_hook, "wolves_monster_death", NULL);
+ add_hook_new(HOOK_QUEST_FINISH, quest_wolves_finish_hook, "wolves_finish", NULL);
+ add_hook_new(HOOK_GEN_QUEST, quest_wolves_gen_hook, "wolves_geb", NULL);
}
- return (FALSE);
}
diff --git a/src/q_wolves.hpp b/src/q_wolves.hpp
new file mode 100644
index 00000000..c5596fc6
--- /dev/null
+++ b/src/q_wolves.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+void quest_wolves_init_hook();
diff --git a/src/quest.cc b/src/quest.cc
new file mode 100644
index 00000000..181b46d2
--- /dev/null
+++ b/src/quest.cc
@@ -0,0 +1,16 @@
+#include "quest.hpp"
+
+#include "tables.hpp"
+
+#include <cstddef>
+
+void init_hooks_quests()
+{
+ for (auto const &q: quest)
+ {
+ if (q.init)
+ {
+ q.init();
+ }
+ }
+}
diff --git a/src/quest.hpp b/src/quest.hpp
new file mode 100644
index 00000000..1897bcfa
--- /dev/null
+++ b/src/quest.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+void init_hooks_quests();
diff --git a/src/quest.pkg b/src/quest.pkg
deleted file mode 100755
index 4ba93b7a..00000000
--- a/src/quest.pkg
+++ /dev/null
@@ -1,170 +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
-/** @} */
-
-/** @struct quest_type
- * @brief Quest
- */
-struct quest_type
-{
- /** @structvar silent
- * @brief Boolean
- * @note Does quest appear on quest list?
- */
- 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?
- */
- s16b status;
-
- /** @structvar level
- * @brief Number
- * @note Dungeon level
- */
- s16b level;
-
- /** @structvar type
- * @brief Number
- * @note Lua or C ?
- */
- 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;
-
-$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);
-
-/** @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);
-
-/** @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/quest_type.hpp b/src/quest_type.hpp
new file mode 100644
index 00000000..ae97af35
--- /dev/null
+++ b/src/quest_type.hpp
@@ -0,0 +1,29 @@
+#pragma once
+
+#include "h-basic.h"
+
+#include <string>
+
+/**
+ * Quest descriptor and runtime data.
+ */
+struct quest_type
+{
+ bool_ silent;
+
+ char name[40]; /* Quest name */
+
+ char desc[10][80]; /* Quest desc */
+
+ s16b status; /* Is the quest taken, completed, finished? */
+
+ s16b level; /* Dungeon level */
+
+ s16b *plot; /* Which plot does it belongs to? */
+
+ void (*init)(); /* Function that takes care of generating hardcoded quests */
+
+ s32b data[9]; /* Various datas used by the quests */
+
+ std::string (*gen_desc)(); /* Function for generating description. */
+};
diff --git a/src/randart.c b/src/randart.cc
index 298ee83a..a902d734 100644
--- a/src/randart.c
+++ b/src/randart.cc
@@ -1,7 +1,3 @@
-/* File: randart.c */
-
-/* Purpose: Randart creation code */
-
/*
* Copyright (c) 2001 DarkGod
*
@@ -10,75 +6,87 @@
* included in all such copies.
*/
-#include "angband.h"
+#include "randart.hpp"
+
+#include "game.hpp"
+#include "mimic.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_flag.hpp"
+#include "object_type.hpp"
+#include "options.hpp"
+#include "player_type.hpp"
+#include "spells2.hpp"
+#include "util.hpp"
+#include "variable.h"
+#include "variable.hpp"
+#include "z-rand.hpp"
/* Chance of using syllables to form the name instead of the "template" files */
-#define TABLE_NAME 45
#define A_CURSED 13
#define WEIRD_LUCK 12
-#define ACTIVATION_CHANCE 3
/*
* Attempt to add a power to a randart
*/
-static bool_ grab_one_power(int *ra_idx, object_type *o_ptr, bool_ good, s16b *max_times)
+static bool_ grab_one_power(int *ra_idx, object_type const *o_ptr, std::vector<s16b> &max_times)
{
- int i = 0, j;
- int *ok_ra, ok_num = 0;
+ auto const &ra_info = game->edit_data.ra_info;
+
+ assert(max_times.size() >= ra_info.size());
+
bool_ ret = FALSE;
- u32b f1, f2, f3, f4, f5, esp;
- C_MAKE(ok_ra, max_ra_idx, int);
+ std::vector<size_t> ok_ra;
/* Grab the ok randart */
- for (i = 0; i < max_ra_idx; i++)
+ for (size_t i = 0; i < ra_info.size(); i++)
{
- randart_part_type *ra_ptr = &ra_info[i];
+ auto ra_ptr = &ra_info[i];
bool_ ok = FALSE;
/* Must have the correct fields */
- for (j = 0; j < 20; j++)
+ for (auto const &filter: ra_ptr->kind_filter)
{
- if (ra_ptr->tval[j] == o_ptr->tval)
+ if ((filter.tval == o_ptr->tval) &&
+ (filter.min_sval <= o_ptr->sval) &&
+ (o_ptr->sval <= filter.max_sval))
{
- if ((ra_ptr->min_sval[j] <= o_ptr->sval) && (ra_ptr->max_sval[j] >= o_ptr->sval)) ok = TRUE;
+ ok = TRUE;
+ break;
}
+ }
- if (ok) break;
+ if ((0 < ra_ptr->max_pval) && (ra_ptr->max_pval < o_ptr->pval))
+ {
+ ok = FALSE;
}
- if ((0 < ra_ptr->max_pval) && (ra_ptr->max_pval < o_ptr->pval)) ok = FALSE;
+
if (!ok)
{
/* Doesnt count as a try*/
continue;
}
- /* Good should be good, bad should be bad */
- if (good && (ra_ptr->value <= 0)) continue;
- if ((!good) && (ra_ptr->value > 0)) continue;
+ /* Skip bad powers */
+ if (ra_ptr->value <= 0) continue;
+ /* Already chosen the maximum number of times? */
if (max_times[i] >= ra_ptr->max) continue;
/* Must NOT have the antagonic flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
- if (f1 & ra_ptr->aflags1) continue;
- if (f2 & ra_ptr->aflags2) continue;
- if (f3 & ra_ptr->aflags3) continue;
- if (f4 & ra_ptr->aflags4) continue;
- if (f5 & ra_ptr->aflags5) continue;
- if (esp & ra_ptr->aesp) continue;
+ auto const flags = object_flags(o_ptr);
+ if (flags & ra_ptr->aflags) continue;
/* ok */
- ok_ra[ok_num++] = i;
+ ok_ra.push_back(i);
}
/* Now test them a few times */
- for (i = 0; i < ok_num * 10; i++)
+ for (size_t count = 0; count < ok_ra.size() * 10; count++)
{
- randart_part_type *ra_ptr;
-
- i = ok_ra[rand_int(ok_num)];
- ra_ptr = &ra_info[i];
+ size_t i = *uniform_element(ok_ra);
+ auto ra_ptr = &ra_info[i];
/* XXX XXX Enforce minimum player level (loosely) */
if (ra_ptr->level > p_ptr->lev)
@@ -108,30 +116,10 @@ static bool_ grab_one_power(int *ra_idx, object_type *o_ptr, bool_ good, s16b *m
break;
}
- C_FREE(ok_ra, max_ra_idx, int);
-
/* Return */
return (ret);
}
-void give_activation_power (object_type * o_ptr)
-{
- o_ptr->xtra2 = 0;
- o_ptr->art_flags3 &= ~TR3_ACTIVATE;
- o_ptr->timeout = 0;
-}
-
-
-int get_activation_power()
-{
- object_type *o_ptr, forge;
-
- o_ptr = &forge;
-
- give_activation_power(o_ptr);
-
- return o_ptr->xtra2;
-}
#define MIN_NAME_LEN 5
#define MAX_NAME_LEN 9
@@ -186,7 +174,7 @@ void build_prob(cptr learn)
* set. Relies on European vowels (a, e, i, o, u). The generated name should
* be copied/used before calling this function again.
*/
-static char *make_word(void)
+static char *make_word()
{
static char word_buf[90];
int r, totalfreq;
@@ -257,12 +245,13 @@ void get_random_name(char * return_name)
bool_ create_artifact(object_type *o_ptr, bool_ a_scroll, bool_ get_name)
{
+ auto const &ra_gen = game->edit_data.ra_gen;
+ auto const &ra_info = game->edit_data.ra_info;
+
char new_name[80];
- int powers = 0, i;
+ int powers = 0;
s32b total_flags, total_power = 0;
bool_ a_cursed = FALSE;
- u32b f1, f2, f3, f4, f5, esp;
- s16b *max_times;
s16b pval = 0;
bool_ limit_blows = FALSE;
@@ -270,49 +259,46 @@ bool_ create_artifact(object_type *o_ptr, bool_ a_scroll, bool_ get_name)
if ((!a_scroll) && (randint(A_CURSED) == 1)) a_cursed = TRUE;
- i = 0;
- while (ra_gen[i].chance)
+ for (auto const &g: ra_gen)
{
- powers += damroll(ra_gen[i].dd, ra_gen[i].ds) + ra_gen[i].plus;
- i++;
+ powers += damroll(g.dd, g.ds) + g.plus;
}
if ((!a_cursed) && (randint(30) == 1)) powers *= 2;
if (a_cursed) powers /= 2;
- C_MAKE(max_times, max_ra_idx, s16b);
+ std::vector<s16b> max_times(ra_info.size(), 0);
/* Main loop */
while (powers)
{
- int ra_idx;
- randart_part_type *ra_ptr;
-
powers--;
- if (!grab_one_power(&ra_idx, o_ptr, TRUE, max_times)) continue;
+ int ra_idx;
+ if (!grab_one_power(&ra_idx, o_ptr, max_times))
+ {
+ continue;
+ }
- ra_ptr = &ra_info[ra_idx];
+ auto ra_ptr = &ra_info[ra_idx];
- if (wizard) msg_format("Adding randart power: %d", ra_idx);
+ if (wizard)
+ {
+ msg_format("Adding randart power: %d", ra_idx);
+ }
total_power += ra_ptr->value;
- o_ptr->art_flags1 |= ra_ptr->flags1;
- o_ptr->art_flags2 |= ra_ptr->flags2;
- o_ptr->art_flags3 |= ra_ptr->flags3;
- o_ptr->art_flags4 |= ra_ptr->flags4;
- o_ptr->art_flags5 |= ra_ptr->flags5;
- o_ptr->art_esp |= ra_ptr->esp;
+ o_ptr->art_flags |= ra_ptr->flags;
add_random_ego_flag(o_ptr, ra_ptr->fego, &limit_blows);
/* get flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ auto const flags = object_flags(o_ptr);
/* Hack -- acquire "cursed" flag */
- if (f3 & TR3_CURSED) o_ptr->ident |= (IDENT_CURSED);
+ if (flags & TR_CURSED) o_ptr->ident |= (IDENT_CURSED);
/* Hack -- obtain bonuses */
if (ra_ptr->max_to_h > 0) o_ptr->to_h += randint(ra_ptr->max_to_h);
@@ -325,29 +311,31 @@ bool_ create_artifact(object_type *o_ptr, bool_ a_scroll, bool_ get_name)
/* Hack -- obtain pval */
if (((pval > ra_ptr->max_pval) && ra_ptr->max_pval) || (!pval)) pval = ra_ptr->max_pval;
};
- C_FREE(max_times, max_ra_idx, s16b);
if (pval > 0) o_ptr->pval = randint(pval);
if (pval < 0) o_ptr->pval = randint( -pval);
/* No insane number of blows */
- if (limit_blows && (o_ptr->art_flags1 & TR1_BLOWS))
+ if (limit_blows && (o_ptr->art_flags & TR_BLOWS))
{
if (o_ptr->pval > 2) o_ptr->pval = randint(2);
}
/* Just to be sure */
- o_ptr->art_flags3 |= ( TR3_IGNORE_ACID | TR3_IGNORE_ELEC |
- TR3_IGNORE_FIRE | TR3_IGNORE_COLD);
+ o_ptr->art_flags |=
+ TR_IGNORE_ACID |
+ TR_IGNORE_ELEC |
+ TR_IGNORE_FIRE |
+ TR_IGNORE_COLD;
total_flags = flag_cost(o_ptr, o_ptr->pval);
- if (cheat_peek) msg_format("%ld", total_flags);
+ if (options->cheat_peek)
+ {
+ msg_format("%ld", total_flags);
+ }
if (a_cursed) curse_artifact(o_ptr);
- /* Extract the flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
-
if (get_name)
{
if (a_scroll)
@@ -370,7 +358,7 @@ bool_ create_artifact(object_type *o_ptr, bool_ a_scroll, bool_ get_name)
}
else
/* Default name = of 'player name' */
- sprintf(new_name, "of '%s'", player_name);
+ sprintf(new_name, "of '%s'", game->player_name.c_str());
}
else
{
@@ -379,20 +367,22 @@ bool_ create_artifact(object_type *o_ptr, bool_ a_scroll, bool_ get_name)
}
/* Save the inscription */
- o_ptr->art_name = quark_add(new_name);
+ o_ptr->artifact_name = new_name;
o_ptr->name2 = o_ptr->name2b = 0;
/* Window stuff */
p_ptr->window |= (PW_INVEN | PW_EQUIP);
+ /* Extract the flags */
+ auto const flags = object_flags(o_ptr);
+
/* 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)
+ else if (flags & TR_SPELL_CONTAIN)
{
o_ptr->pval2 = -1;
}
@@ -401,28 +391,26 @@ bool_ create_artifact(object_type *o_ptr, bool_ a_scroll, bool_ get_name)
}
-bool_ artifact_scroll(void)
+bool_ artifact_scroll()
{
- int item;
bool_ okay = FALSE;
- object_type *o_ptr;
- char o_name[80];
-
- cptr q, s;
-
-
- /* Enchant weapon/armour */
- item_tester_hook = item_tester_hook_artifactable;
/* Get an item */
- q = "Enchant which item? ";
- s = "You have nothing to enchant.";
- if (!get_item(&item, q, s, (USE_EQUIP | USE_INVEN | USE_FLOOR))) return (FALSE);
+ int item;
+ if (!get_item(&item,
+ "Enchant which item? ",
+ "You have nothing to enchant.",
+ (USE_EQUIP | USE_INVEN | USE_FLOOR),
+ item_tester_hook_artifactable()))
+ {
+ return (FALSE);
+ }
/* Get the item */
- o_ptr = get_object(item);
+ object_type *o_ptr = get_object(item);
/* Description */
+ char o_name[80];
object_desc(o_name, o_ptr, FALSE, 0);
/* Describe */
@@ -461,7 +449,7 @@ bool_ artifact_scroll(void)
if (!okay)
{
/* Flush */
- if (flush_failure) flush();
+ flush_on_failure();
/* Message */
msg_print("The enchantment failed.");
diff --git a/src/randart.hpp b/src/randart.hpp
new file mode 100644
index 00000000..6f91f36d
--- /dev/null
+++ b/src/randart.hpp
@@ -0,0 +1,8 @@
+#pragma once
+
+#include "h-basic.h"
+#include "object_type_fwd.hpp"
+
+void build_prob(cptr learn);
+bool_ create_artifact(object_type *o_ptr, bool_ a_scroll, bool_ get_name);
+bool_ artifact_scroll();
diff --git a/src/randart_gen_type.hpp b/src/randart_gen_type.hpp
new file mode 100644
index 00000000..09aedcd9
--- /dev/null
+++ b/src/randart_gen_type.hpp
@@ -0,0 +1,9 @@
+#pragma once
+
+struct randart_gen_type
+{
+ int chance; /* Chance to have that number of powers */
+ int dd;
+ int ds;
+ int plus; /* xdy+plus power */
+};
diff --git a/src/randart_part_type.hpp b/src/randart_part_type.hpp
new file mode 100644
index 00000000..5a4ca329
--- /dev/null
+++ b/src/randart_part_type.hpp
@@ -0,0 +1,44 @@
+#pragma once
+
+#include "ego_flag_set.hpp"
+#include "h-basic.h"
+#include "object_flag_set.hpp"
+
+#include <vector>
+
+/**
+ * Random artifact part descriptor.
+ */
+struct randart_part_type
+{
+public:
+ struct kind_filter_t {
+ byte tval;
+ byte min_sval;
+ byte max_sval;
+ };
+
+ std::vector<kind_filter_t> kind_filter;
+
+ byte level = 0; /* Minimum level */
+ byte rarity = 0; /* Object rarity */
+ byte mrarity = 0; /* Object rarity */
+
+ s16b max_to_h = 0; /* Maximum to-hit bonus */
+ s16b max_to_d = 0; /* Maximum to-dam bonus */
+ s16b max_to_a = 0; /* Maximum to-ac bonus */
+
+ s32b max_pval = 0; /* Maximum pval */
+
+ s32b value = 0; /* power value */
+ s16b max = 0; /* Number of time it can appear on a single item */
+
+ object_flag_set flags; /* Ego item flags */
+
+ ego_flag_set fego; /* Ego flags */
+
+ object_flag_set aflags; /* Antagonistic ego item flags */
+
+ s16b power = -1; /* Power granted(if any) */
+
+};
diff --git a/src/random_artifact.hpp b/src/random_artifact.hpp
new file mode 100644
index 00000000..618f1102
--- /dev/null
+++ b/src/random_artifact.hpp
@@ -0,0 +1,20 @@
+#pragma once
+
+#include "h-basic.h"
+
+#include <string>
+
+/**
+ * Random artifact descriptor.
+ */
+struct random_artifact
+{
+ std::string name_full; /* Full name for the artifact */
+ std::string name_short; /* Un-Id'd name */
+ byte level; /* Level of the artifact */
+ byte attr; /* Color that is used on the screen */
+ u32b cost; /* Object's value */
+ byte activation; /* Activation. */
+ s16b timeout; /* Timeout. */
+ byte generated; /* Does it exist already? */
+};
diff --git a/src/random_quest.hpp b/src/random_quest.hpp
new file mode 100644
index 00000000..9e3c6e10
--- /dev/null
+++ b/src/random_quest.hpp
@@ -0,0 +1,10 @@
+#pragma once
+
+#include "h-basic.h"
+
+struct random_quest
+{
+ byte type; /* Type/number of monsters to kill(0 = no quest) */
+ s16b r_idx; /* Monsters to crush */
+ bool done; /* Done? */
+};
diff --git a/src/random_spell.hpp b/src/random_spell.hpp
new file mode 100644
index 00000000..f02b9848
--- /dev/null
+++ b/src/random_spell.hpp
@@ -0,0 +1,20 @@
+#pragma once
+
+#include "h-basic.h"
+#include <string>
+
+/**
+ * A structure to describe the random spells of the Power Mages
+ */
+struct random_spell
+{
+ s16b mana = 0; /* Mana cost */
+ s16b fail = 0; /* Failure rate */
+ u32b proj_flags = 0; /* Project function flags */
+ byte GF = 0; /* Type of the projection */
+ byte radius = 0;
+ byte dam_sides = 0;
+ byte dam_dice = 0;
+ byte level = 0; /* Level needed */
+ bool untried = true; /* Is the spell was tried? */
+};
diff --git a/src/random_spell_fwd.hpp b/src/random_spell_fwd.hpp
new file mode 100644
index 00000000..ee559c31
--- /dev/null
+++ b/src/random_spell_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct random_spell;
diff --git a/src/range.cc b/src/range.cc
new file mode 100644
index 00000000..7bd407c7
--- /dev/null
+++ b/src/range.cc
@@ -0,0 +1,11 @@
+#include "range.hpp"
+
+#include <cassert>
+
+void range_init(range_type *range, s32b min, s32b max)
+{
+ assert(range != NULL);
+
+ range->min = min;
+ range->max = max;
+}
diff --git a/src/range.hpp b/src/range.hpp
new file mode 100644
index 00000000..3c185ba6
--- /dev/null
+++ b/src/range.hpp
@@ -0,0 +1,15 @@
+#pragma once
+
+#include "range_fwd.hpp"
+#include "h-basic.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.hpp b/src/range_fwd.hpp
new file mode 100644
index 00000000..b5eef3fa
--- /dev/null
+++ b/src/range_fwd.hpp
@@ -0,0 +1,4 @@
+#pragma once
+
+typedef struct range_type range_type;
+struct range_type;
diff --git a/src/readdib.c b/src/readdib.c
deleted file mode 100644
index 294c2702..00000000
--- a/src/readdib.c
+++ /dev/null
@@ -1,342 +0,0 @@
-/* File: readbits.c */
-
-/*
- * This package provides a routine to read a DIB file and set up the
- * device dependent version of the image.
- *
- * This file has been modified for use with "Angband 2.8.2"
- *
- * COPYRIGHT:
- *
- * (C) Copyright Microsoft Corp. 1993. All rights reserved.
- *
- * You have a royalty-free right to use, modify, reproduce and
- * distribute the Sample Files (and/or any modified version) in
- * any way you find useful, provided that you agree that
- * Microsoft has no warranty obligations or liability for any
- * Sample Application Files which are modified.
- */
-
-#ifdef WINDOWS
-
-#include <windows.h>
-
-#include "readdib.h"
-
-
-/*
- * Extract the "WIN32" flag from the compiler
- */
-#if defined(__WIN32__) || defined(__WINNT__) || defined(__NT__)
-# ifndef WIN32
-# define WIN32
-# endif
-#endif
-
-/*
- * Make sure "huge" is legal XXX XXX XXX
- */
-#undef huge
-#ifdef WIN32
-# define huge /* oops */
-#endif
-
-
-/*
- * Number of bytes to be read during each read operation
- */
-#define MAXREAD 32768
-
-/*
- * Private routine to read more than 64K at a time
- *
- * Reads data in steps of 32k till all the data has been read.
- *
- * Returns number of bytes requested, or zero if something went wrong.
- */
-static DWORD PASCAL lread(int fh, VOID far *pv, DWORD ul)
-{
- DWORD ulT = ul;
- BYTE huge *hp = pv;
-
- while (ul > (DWORD)MAXREAD)
- {
- if (_lread(fh, (LPSTR)hp, (WORD)MAXREAD) != MAXREAD)
- return 0;
- ul -= MAXREAD;
- hp += MAXREAD;
- }
- if (_lread(fh, (LPSTR)hp, (WORD)ul) != (WORD)ul)
- return 0;
- return ulT;
-}
-
-
-/*
- * Given a BITMAPINFOHEADER, create a palette based on the color table.
- *
- * Returns the handle of a palette, or zero if something went wrong.
- */
-static HPALETTE PASCAL NEAR MakeDIBPalette(LPBITMAPINFOHEADER lpInfo)
-{
- NPLOGPALETTE npPal;
- RGBQUAD far *lpRGB;
- HPALETTE hLogPal;
- WORD i;
-
- /*
- * since biClrUsed field was filled during the loading of the DIB,
- * we know it contains the number of colors in the color table.
- */
- if (lpInfo->biClrUsed)
- {
- npPal = (NPLOGPALETTE)LocalAlloc(LMEM_FIXED, sizeof(LOGPALETTE) +
- (WORD)lpInfo->biClrUsed * sizeof(PALETTEENTRY));
- if (!npPal)
- return (FALSE);
-
- npPal->palVersion = 0x300;
- npPal->palNumEntries = (WORD)lpInfo->biClrUsed;
-
- /* get pointer to the color table */
- lpRGB = (RGBQUAD FAR *)((LPSTR)lpInfo + lpInfo->biSize);
-
- /* copy colors from the color table to the LogPalette structure */
- for (i = 0; i < lpInfo->biClrUsed; i++, lpRGB++)
- {
- npPal->palPalEntry[i].peRed = lpRGB->rgbRed;
- npPal->palPalEntry[i].peGreen = lpRGB->rgbGreen;
- npPal->palPalEntry[i].peBlue = lpRGB->rgbBlue;
- npPal->palPalEntry[i].peFlags = PC_NOCOLLAPSE;
- }
-
- hLogPal = CreatePalette((LPLOGPALETTE)npPal);
- LocalFree((HANDLE)npPal);
- return (hLogPal);
- }
-
- /*
- * 24-bit DIB with no color table. return default palette. Another
- * option would be to create a 256 color "rainbow" palette to provide
- * some good color choices.
- */
- else
- {
- return (GetStockObject(DEFAULT_PALETTE));
- }
-}
-
-
-/*
- * Given a DIB, create a bitmap and corresponding palette to be used for a
- * device-dependent representation of the image.
- *
- * Returns TRUE on success (phPal and phBitmap are filled with appropriate
- * handles. Caller is responsible for freeing objects) and FALSE on failure
- * (unable to create objects, both pointer are invalid).
- */
-static BOOL NEAR PASCAL MakeBitmapAndPalette(HDC hDC, HANDLE hDIB,
- HPALETTE * phPal, HBITMAP * phBitmap)
-{
- LPBITMAPINFOHEADER lpInfo;
- BOOL result = FALSE;
- HBITMAP hBitmap;
- HPALETTE hPalette, hOldPal;
- LPSTR lpBits;
-
- lpInfo = (LPBITMAPINFOHEADER) GlobalLock(hDIB);
- if ((hPalette = MakeDIBPalette(lpInfo)) != 0)
- {
- /* Need to realize palette for converting DIB to bitmap. */
- hOldPal = SelectPalette(hDC, hPalette, TRUE);
- RealizePalette(hDC);
-
- lpBits = ((LPSTR)lpInfo + (WORD)lpInfo->biSize +
- (WORD)lpInfo->biClrUsed * sizeof(RGBQUAD));
- hBitmap = CreateDIBitmap(hDC, lpInfo, CBM_INIT, lpBits,
- (LPBITMAPINFO)lpInfo, DIB_RGB_COLORS);
-
- SelectPalette(hDC, hOldPal, TRUE);
- RealizePalette(hDC);
-
- if (!hBitmap)
- {
- DeleteObject(hPalette);
- }
- else
- {
- *phBitmap = hBitmap;
- *phPal = hPalette;
- result = TRUE;
- }
- }
- return (result);
-}
-
-
-
-/*
- * Reads a DIB from a file, obtains a handle to its BITMAPINFO struct, and
- * loads the DIB. Once the DIB is loaded, the function also creates a bitmap
- * and palette out of the DIB for a device-dependent form.
- *
- * Returns TRUE if the DIB is loaded and the bitmap/palette created, in which
- * case, the DIBINIT structure pointed to by pInfo is filled with the appropriate
- * handles, and FALSE if something went wrong.
- */
-BOOL ReadDIB(HWND hWnd, LPSTR lpFileName, DIBINIT *pInfo)
-{
- unsigned fh;
- LPBITMAPINFOHEADER lpbi;
- OFSTRUCT of;
- BITMAPFILEHEADER bf;
- WORD nNumColors;
- BOOL result = FALSE;
- char str[128];
- WORD offBits;
- HDC hDC;
- BOOL bCoreHead = FALSE;
-
- /* Open the file and get a handle to it's BITMAPINFO */
- fh = OpenFile(lpFileName, &of, OF_READ);
- if (fh == -1)
- {
- wsprintf(str, "Can't open file '%ls'", (LPSTR)lpFileName);
- MessageBox(NULL, str, "Error", MB_ICONSTOP | MB_OK);
- return (FALSE);
- }
-
- pInfo->hDIB = GlobalAlloc(GHND, (DWORD)(sizeof(BITMAPINFOHEADER) +
- 256 * sizeof(RGBQUAD)));
-
- if (!pInfo->hDIB)
- return (FALSE);
-
- lpbi = (LPBITMAPINFOHEADER)GlobalLock(pInfo->hDIB);
-
- /* read the BITMAPFILEHEADER */
- if (sizeof (bf) != _lread(fh, (LPSTR)&bf, sizeof(bf)))
- goto ErrExit;
-
- /* 'BM' */
- if (bf.bfType != 0x4d42)
- goto ErrExit;
-
- if (sizeof(BITMAPCOREHEADER) != _lread(fh, (LPSTR)lpbi, sizeof(BITMAPCOREHEADER)))
- goto ErrExit;
-
- if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
- {
- lpbi->biSize = sizeof(BITMAPINFOHEADER);
- lpbi->biBitCount = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount;
- lpbi->biPlanes = ((LPBITMAPCOREHEADER)lpbi)->bcPlanes;
- lpbi->biHeight = ((LPBITMAPCOREHEADER)lpbi)->bcHeight;
- lpbi->biWidth = ((LPBITMAPCOREHEADER)lpbi)->bcWidth;
- bCoreHead = TRUE;
- }
- else
- {
- /* get to the start of the header and read INFOHEADER */
- _llseek(fh, sizeof(BITMAPFILEHEADER), SEEK_SET);
- if (sizeof(BITMAPINFOHEADER) != _lread(fh, (LPSTR)lpbi, sizeof(BITMAPINFOHEADER)))
- goto ErrExit;
- }
-
- if (!(nNumColors = (WORD)lpbi->biClrUsed))
- {
- /* no color table for 24-bit, default size otherwise */
- if (lpbi->biBitCount != 24)
- nNumColors = 1 << lpbi->biBitCount;
- }
-
- /* fill in some default values if they are zero */
- if (lpbi->biClrUsed == 0)
- lpbi->biClrUsed = nNumColors;
-
- if (lpbi->biSizeImage == 0)
- {
- lpbi->biSizeImage = (((((lpbi->biWidth * (DWORD)lpbi->biBitCount) + 31) & ~31) >> 3)
- * lpbi->biHeight);
- }
-
- /* otherwise wouldn't work with 16 color bitmaps -- S.K. */
- else if ((nNumColors == 16) && (lpbi->biSizeImage > bf.bfSize))
- {
- lpbi->biSizeImage /= 2;
- }
-
- /* get a proper-sized buffer for header, color table and bits */
- GlobalUnlock(pInfo->hDIB);
- pInfo->hDIB = GlobalReAlloc(pInfo->hDIB, lpbi->biSize +
- nNumColors * sizeof(RGBQUAD) +
- lpbi->biSizeImage, 0);
-
- /* can't resize buffer for loading */
- if (!pInfo->hDIB)
- goto ErrExit2;
-
- lpbi = (LPBITMAPINFOHEADER)GlobalLock(pInfo->hDIB);
-
- /* read the color table */
- if (!bCoreHead)
- {
- _lread(fh, (LPSTR)(lpbi) + lpbi->biSize, nNumColors * sizeof(RGBQUAD));
- }
- else
- {
- signed int i;
- RGBQUAD FAR *pQuad;
- RGBTRIPLE FAR *pTriple;
-
- _lread(fh, (LPSTR)(lpbi) + lpbi->biSize, nNumColors * sizeof(RGBTRIPLE));
-
- pQuad = (RGBQUAD FAR *)((LPSTR)lpbi + lpbi->biSize);
- pTriple = (RGBTRIPLE FAR *) pQuad;
- for (i = nNumColors - 1; i >= 0; i--)
- {
- pQuad[i].rgbRed = pTriple[i].rgbtRed;
- pQuad[i].rgbBlue = pTriple[i].rgbtBlue;
- pQuad[i].rgbGreen = pTriple[i].rgbtGreen;
- pQuad[i].rgbReserved = 0;
- }
- }
-
- /* offset to the bits from start of DIB header */
- offBits = (WORD)lpbi->biSize + nNumColors * sizeof(RGBQUAD);
-
- if (bf.bfOffBits != 0L)
- {
- _llseek(fh, bf.bfOffBits, SEEK_SET);
- }
-
- /* Use local version of '_lread()' above */
- if (lpbi->biSizeImage == lread(fh, (LPSTR)lpbi + offBits, lpbi->biSizeImage))
- {
- GlobalUnlock(pInfo->hDIB);
-
- hDC = GetDC(hWnd);
- if (!MakeBitmapAndPalette(hDC, pInfo->hDIB, &(pInfo->hPalette),
- &(pInfo->hBitmap)))
- {
- ReleaseDC(hWnd, hDC);
- goto ErrExit2;
- }
- else
- {
- ReleaseDC(hWnd, hDC);
- result = TRUE;
- }
- }
- else
- {
-ErrExit:
- GlobalUnlock(pInfo->hDIB);
-ErrExit2:
- GlobalFree(pInfo->hDIB);
- }
-
- _lclose(fh);
- return (result);
-}
-
-#endif
diff --git a/src/readdib.h b/src/readdib.h
deleted file mode 100644
index c6402b50..00000000
--- a/src/readdib.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* File: readdib.h */
-
-/*
- * This file has been modified for use with "Angband 2.8.2"
- *
- * Copyright 1991 Microsoft Corporation. All rights reserved.
- */
-
-/*
- * Information about a bitmap
- */
-typedef struct {
- HANDLE hDIB;
- HANDLE hBitmap;
- HANDLE hPalette;
- BYTE CellWidth;
- BYTE CellHeight;
-} DIBINIT;
-
-/* Read a DIB from a file */
-BOOL ReadDIB(HWND, LPSTR, DIBINIT *);
diff --git a/src/rule_type.hpp b/src/rule_type.hpp
new file mode 100644
index 00000000..b88ce7bf
--- /dev/null
+++ b/src/rule_type.hpp
@@ -0,0 +1,17 @@
+#pragma once
+
+#include "h-basic.h"
+#include "monster_race_flag_set.hpp"
+#include "monster_spell_flag_set.hpp"
+
+/* Define monster generation rules */
+struct rule_type
+{
+ byte mode = 0; /* Mode of combination of the monster flags */
+ byte percent = 0; /* Percent of monsters affected by the rule */
+
+ monster_race_flag_set mflags; /* The monster flags that are allowed */
+ monster_spell_flag_set mspells; /* Monster spells the are allowed */
+
+ char r_char[5] = { 0 }; /* Monster race allowed */
+};
diff --git a/src/school_book.hpp b/src/school_book.hpp
new file mode 100644
index 00000000..51d3e6a7
--- /dev/null
+++ b/src/school_book.hpp
@@ -0,0 +1,15 @@
+#pragma once
+
+#include "h-basic.h"
+
+#include <vector>
+
+/**
+ * School book.
+ */
+struct school_book {
+ /**
+ * Indexes of all the spells in the book.
+ */
+ std::vector<s32b> spell_idxs;
+};
diff --git a/src/school_book_fwd.hpp b/src/school_book_fwd.hpp
new file mode 100644
index 00000000..46363da6
--- /dev/null
+++ b/src/school_book_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct school_book;
diff --git a/src/school_type.hpp b/src/school_type.hpp
new file mode 100644
index 00000000..7a5702b4
--- /dev/null
+++ b/src/school_type.hpp
@@ -0,0 +1,21 @@
+#pragma once
+
+#include "h-basic.h"
+#include "deity_type_fwd.hpp"
+
+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? */
+
+ struct school_provider_list *providers; /* List of secondary providers of this school */
+};
diff --git a/src/school_type_fwd.hpp b/src/school_type_fwd.hpp
new file mode 100644
index 00000000..dea0d3b4
--- /dev/null
+++ b/src/school_type_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct school_type;
diff --git a/src/script.c b/src/script.c
deleted file mode 100644
index 89c9ff3b..00000000
--- a/src/script.c
+++ /dev/null
@@ -1,535 +0,0 @@
-/* File: script.c */
-
-/* Purpose: scripting in lua */
-
-/*
- * Copyright (c) 2001 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 "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_quest_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_quest_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);
-
- /* 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 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 */
- max = exec_lua("return __corruptions_max");
- init_corruptions(max);
-}
-
-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/seed.cc b/src/seed.cc
new file mode 100644
index 00000000..0550c769
--- /dev/null
+++ b/src/seed.cc
@@ -0,0 +1,53 @@
+#include "seed.hpp"
+
+#include <random>
+
+seed_t seed_t::system()
+{
+ seed_t seed;
+ // Use system's random device for seeding.
+ std::random_device random_device;
+ std::uniform_int_distribution<std::uint8_t> distribution;
+ // Extract the number of bytes we need.
+ for (std::size_t i = 0; i < n_bytes; i++)
+ {
+ seed.m_data[i] = distribution(random_device);
+ }
+ // Done
+ return seed;
+}
+
+seed_t seed_t::from_bytes(std::uint8_t bytes[n_bytes])
+{
+ seed_t seed;
+ // Copy
+ for (std::size_t i = 0; i < n_bytes; i++)
+ {
+ seed.m_data[i] = bytes[i];
+ }
+ // Done
+ return seed;
+}
+
+void seed_t::to_bytes(std::uint8_t bytes[n_bytes]) const
+{
+ // Copy
+ for (std::size_t i = 0; i < n_bytes; i++)
+ {
+ bytes[i] = m_data[i];
+ }
+}
+void seed_t::to_uint32(std::uint32_t seed_seq_data[n_uint32]) const
+{
+ for (std::size_t i = 0; i < n_uint32; i++)
+ {
+ // Position in the byte-oriented data.
+ std::size_t p = 4 * i;
+ // Pack m_data[p + 0], ..., m_data[p + 3] into a single uint32_t
+ seed_seq_data[i] = 0;
+ seed_seq_data[i] |= (uint32_t(m_data[p + 0]) << (0 * 8));
+ seed_seq_data[i] |= (uint32_t(m_data[p + 1]) << (1 * 8));
+ seed_seq_data[i] |= (uint32_t(m_data[p + 2]) << (2 * 8));
+ seed_seq_data[i] |= (uint32_t(m_data[p + 3]) << (3 * 8));
+ }
+}
diff --git a/src/seed.hpp b/src/seed.hpp
new file mode 100644
index 00000000..91ec7eba
--- /dev/null
+++ b/src/seed.hpp
@@ -0,0 +1,51 @@
+#pragma once
+
+#include <array>
+#include <cstdint>
+
+class seed_t {
+
+public:
+ // Number of seed bytes.
+ static constexpr std::size_t n_bytes = 64;
+
+ // Sanity check; we're relying on converting to uint32_t elsewhere,
+ // so let's just keep it as easy as possible.
+ static_assert(n_bytes % 4 == 0, "n_bytes must be multiple of 4");
+
+ // Number of uint32_t's required to store the seed.
+ static constexpr std::size_t n_uint32 = n_bytes / 4;
+
+private:
+ std::array<std::uint8_t, n_bytes> m_data;
+
+ // Default constructor is private. Use the static
+ // factory functions instead.
+ seed_t()
+ {
+ // Factory functions do explicit initialization.
+ };
+
+public:
+
+ /**
+ * Create a seed from system entropy.
+ */
+ static seed_t system();
+
+ /**
+ * Create a seed from the given bytes.
+ */
+ static seed_t from_bytes(std::uint8_t bytes[n_bytes]);
+
+ /**
+ * Convert seed to bytes.
+ */
+ void to_bytes(std::uint8_t bytes[n_bytes]) const;
+
+ /**
+ * Convert seed to uint32_t's suitable for seed_seq.
+ */
+ void to_uint32(std::uint32_t seed_seq_data[n_uint32]) const;
+
+};
diff --git a/src/seed_fwd.hpp b/src/seed_fwd.hpp
new file mode 100644
index 00000000..291a6063
--- /dev/null
+++ b/src/seed_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+class seed_t;
diff --git a/src/set_component.hpp b/src/set_component.hpp
new file mode 100644
index 00000000..18dc4d57
--- /dev/null
+++ b/src/set_component.hpp
@@ -0,0 +1,16 @@
+#pragma once
+
+#include "h-basic.h"
+#include "object_flag_set.hpp"
+
+#include <array>
+#include <cstdint>
+
+constexpr std::size_t SET_MAX_SIZE = 6;
+
+struct set_component {
+ bool_ present = FALSE; /* Is it being worn? */
+ s16b a_idx = 0; /* What artifact? */
+ std::array<s16b , SET_MAX_SIZE> pval; /* Pval for each combination */
+ std::array<object_flag_set, SET_MAX_SIZE> flags; /* Flags */
+};
diff --git a/src/set_type.hpp b/src/set_type.hpp
new file mode 100644
index 00000000..bf13c932
--- /dev/null
+++ b/src/set_type.hpp
@@ -0,0 +1,20 @@
+#pragma once
+
+#include <array>
+#include <string>
+
+#include "set_component.hpp"
+
+/**
+ * Item set descriptor and runtime information.
+ */
+struct set_type
+{
+ std::string name; /* Name */
+ std::string desc; /* Desc */
+
+ byte num = 0; /* Number of artifacts used */
+ byte num_use = 0; /* Number actually worn */
+
+ std::array<set_component, SET_MAX_SIZE> arts;
+};
diff --git a/src/skill_descriptor.hpp b/src/skill_descriptor.hpp
new file mode 100644
index 00000000..8d9de004
--- /dev/null
+++ b/src/skill_descriptor.hpp
@@ -0,0 +1,37 @@
+#pragma once
+
+#include "h-basic.h"
+#include "skill_flag_set.hpp"
+#include "skills_defs.hpp"
+
+#include <vector>
+#include <tuple>
+
+/**
+ * Skill descriptor.
+ */
+struct skill_descriptor {
+
+ std::string name; /* Name */
+ std::string desc; /* Description */
+
+ std::string action_desc; /* Action Description */
+ s16b action_mkey = 0; /* Action do to */
+
+ std::vector<std::size_t> excludes; /* List of skills that this skill excludes;
+ any skill points assigned completely nullify
+ the listed skills */
+
+ std::vector<std::tuple<std::size_t, int>> increases;
+ /* List of skills the this skill increases,
+ along with the modifier that gets applied.
+ The first tuple element is the skill index. */
+
+ s16b father = 0; /* Father in the skill tree */
+ s16b order = 0; /* Order in the tree */
+
+ byte random_gain_chance = 100; /* Chance to gain from Lost Sword quest; if applicable */
+
+ skill_flag_set flags; /* Skill flags */
+
+};
diff --git a/src/skill_flag.hpp b/src/skill_flag.hpp
new file mode 100644
index 00000000..15c6de9c
--- /dev/null
+++ b/src/skill_flag.hpp
@@ -0,0 +1,12 @@
+#pragma once
+
+#include "skill_flag_set.hpp"
+#include <boost/preprocessor/cat.hpp>
+
+//
+// Define flag set for each flag.
+//
+#define SKF(tier, index, name) \
+ DECLARE_FLAG(skill_flag_set, BOOST_PP_CAT(SKF_,name), tier, index)
+#include "skill_flag_list.hpp"
+#undef SKF
diff --git a/src/skill_flag_list.hpp b/src/skill_flag_list.hpp
new file mode 100644
index 00000000..49cdc045
--- /dev/null
+++ b/src/skill_flag_list.hpp
@@ -0,0 +1,9 @@
+/**
+ * X-macro list of all the skill flags
+ */
+
+/* SKF(<tier>, <index>, <name>) */
+
+SKF(1, 0, HIDDEN ) /* Starts hidden */
+SKF(1, 1, AUTO_HIDE ) /* Tries to rehide at calc_bonus */
+SKF(1, 2, RANDOM_GAIN) /* Can be gained through Lost Sword quest */
diff --git a/src/skill_flag_set.hpp b/src/skill_flag_set.hpp
new file mode 100644
index 00000000..a2768b70
--- /dev/null
+++ b/src/skill_flag_set.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "flag_set.hpp"
+
+constexpr std::size_t SKF_MAX_TIERS = 1;
+
+typedef flag_set<SKF_MAX_TIERS> skill_flag_set;
diff --git a/src/skill_modifier.hpp b/src/skill_modifier.hpp
new file mode 100644
index 00000000..e4bf4ce9
--- /dev/null
+++ b/src/skill_modifier.hpp
@@ -0,0 +1,12 @@
+#pragma once
+
+#include "h-basic.h"
+
+struct skill_modifier {
+
+ char basem = '\0';
+ u32b base = 0;
+ char modm = '\0';
+ s16b mod = 0;
+
+};
diff --git a/src/skill_modifiers.hpp b/src/skill_modifiers.hpp
new file mode 100644
index 00000000..5e90b000
--- /dev/null
+++ b/src/skill_modifiers.hpp
@@ -0,0 +1,17 @@
+#pragma once
+
+#include "h-basic.h"
+#include "skills_defs.hpp"
+#include "skill_modifier.hpp"
+
+#include <vector>
+
+struct skill_modifiers
+{
+ /**
+ * Skill modifiers indexed by skill. Note that this vector
+ * may be shorter than the s_descriptors vector.
+ */
+ std::vector<skill_modifier> modifiers;
+
+};
diff --git a/src/skill_modifiers_fwd.hpp b/src/skill_modifiers_fwd.hpp
new file mode 100644
index 00000000..18f692bd
--- /dev/null
+++ b/src/skill_modifiers_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct skill_modifiers;
diff --git a/src/skill_type.hpp b/src/skill_type.hpp
new file mode 100644
index 00000000..c26d8649
--- /dev/null
+++ b/src/skill_type.hpp
@@ -0,0 +1,32 @@
+#pragma once
+
+#include "h-basic.h"
+#include "skill_flag_set.hpp"
+#include "skills_defs.hpp"
+#include "skill_descriptor.hpp"
+
+/**
+ * Skill runtime data.
+ */
+struct skill_type
+{
+ /**
+ * Current value.
+ */
+ s32b value = 0;
+
+ /**
+ * Current modifier, i.e. how much value 1 skill point gives.
+ */
+ s32b mod = 0;
+
+ /**
+ * Is the branch developed?
+ */
+ bool dev = false;
+
+ /**
+ * Is the skill hidden?
+ */
+ bool hidden = false;
+};
diff --git a/src/skills.c b/src/skills.c
deleted file mode 100644
index 36b4f585..00000000
--- a/src/skills.c
+++ /dev/null
@@ -1,1661 +0,0 @@
-/* File: skills.c */
-
-/* Purpose: player skills */
-
-/*
- * Copyright (c) 2001 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"
-
-
-/*
- * Advance the skill point of the skill specified by i and
- * modify related skills
- */
-void increase_skill(int i, s16b *invest)
-{
- s32b max_skill_overage;
-
- /* No skill points to be allocated */
- if (!p_ptr->skill_points) return;
-
- /* The skill cannot be increased */
- if (!s_info[i].mod) return;
-
- /* The skill is already maxed */
- 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);
- if (((s_info[i].value + s_info[i].mod) / SKILL_STEP) >= (p_ptr->lev + max_skill_overage + 1))
- {
- int hgt, wid;
-
- 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));
- return;
- }
-
- /* Spend an unallocated skill point */
- p_ptr->skill_points--;
-
- /* Increase the skill */
- s_info[i].value += s_info[i].mod;
- invest[i]++;
-}
-
-
-/*
- * Descrease the skill point of the skill specified by i and
- * modify related skills
- */
-void decrease_skill(int i, s16b *invest)
-{
- /* Cannot decrease more */
- if (!invest[i]) return;
-
- /* The skill cannot be decreased */
- if (!s_info[i].mod) return;
-
- /* The skill already has minimal value */
- if (!s_info[i].value) return;
-
- /* Free a skill point */
- p_ptr->skill_points++;
-
- /* Decrease the skill */
- s_info[i].value -= s_info[i].mod;
- invest[i]--;
-}
-
-
-/*
- * Given the name of a skill, returns skill index or -1 if no
- * such skill is found
- */
-s16b find_skill(cptr name)
-{
- u16b i;
-
- /* Scan skill list */
- for (i = 1; i < max_s_idx; i++)
- {
- /* The name matches */
- if (streq(s_info[i].name + s_name, name)) return (i);
- }
-
- /* No match found */
- return ( -1);
-}
-s16b find_skill_i(cptr name)
-{
- u16b i;
-
- /* Scan skill list */
- for (i = 1; i < max_s_idx; i++)
- {
- /* The name matches */
- if (0 == stricmp(s_info[i].name + s_name, name)) return (i);
- }
-
- /* No match found */
- return ( -1);
-}
-
-
-/*
- *
- */
-s16b get_skill(int skill)
-{
- return (s_info[skill].value / SKILL_STEP);
-}
-
-
-/*
- * Return "scale" (a misnomer -- this is max value) * (current skill value)
- * / (max skill value)
- */
-s16b get_skill_scale(int skill, u32b scale)
-{
- s32b temp;
-
- /*
- * SKILL_STEP shouldn't matter here because the second parameter is
- * relatively small (the largest one being somewhere around 200),
- * AND because we could have used much simpler 0--50 if the ability
- * progression were only possible at step boundaries.
- *
- * Because I'm not at all certain about my interpretation of the mysterious
- * formula given above, I verified this works the same by using a tiny
- * scheme program... -- pelpel
- */
- temp = scale * s_info[skill].value;
-
- return (temp / SKILL_MAX);
-}
-
-
-/*
- *
- */
-int get_idx(int i)
-{
- int j;
-
- for (j = 1; j < max_s_idx; j++)
- {
- if (s_info[j].order == i)
- return (j);
- }
- return (0);
-}
-
-static bool_ is_known(int s_idx)
-{
- int i;
-
- if (wizard) return TRUE;
- if (s_info[s_idx].value || s_info[s_idx].mod) return TRUE;
-
- for (i = 0; i < max_s_idx; i++)
- {
- /* It is our child, if we don't know it we continue to search, if we know it it is enough*/
- if (s_info[i].father == s_idx)
- {
- if (is_known(i))
- return TRUE;
- }
- }
-
- /* Ok know none */
- return FALSE;
-}
-
-/*
- *
- */
-void init_table_aux(int table[MAX_SKILLS][2], int *idx, int father, int lev,
- bool_ full)
-{
- int j, i;
-
- for (j = 1; j < max_s_idx; j++)
- {
- i = get_idx(j);
- if (s_info[i].father != father) continue;
- if (s_info[i].hidden) continue;
- if (!is_known(i)) continue;
-
- table[*idx][0] = i;
- table[*idx][1] = lev;
- (*idx)++;
- if (s_info[i].dev || full) init_table_aux(table, idx, i, lev + 1, full);
- }
-}
-
-
-void init_table(int table[MAX_SKILLS][2], int *max, bool_ full)
-{
- *max = 0;
- init_table_aux(table, max, -1, 0, full);
-}
-
-
-bool_ has_child(int sel)
-{
- int i;
-
- for (i = 1; i < max_s_idx; i++)
- {
- if ((s_info[i].father == sel) && (is_known(i)))
- return (TRUE);
- }
- return (FALSE);
-}
-
-
-/*
- * Dump the skill tree
- */
-void dump_skills(FILE *fff)
-{
- int i, j, max = 0;
- int table[MAX_SKILLS][2];
- char buf[80];
-
- init_table(table, &max, TRUE);
-
- fprintf(fff, "\nSkills (points left: %d)", p_ptr->skill_points);
-
- for (j = 0; j < max; j++)
- {
- int z;
-
- i = table[j][0];
-
- if ((s_info[i].value == 0) && (i != SKILL_MISC))
- {
- if (s_info[i].mod == 0) continue;
- }
-
- sprintf(buf, "\n");
-
- for (z = 0; z < table[j][1]; z++) strcat(buf, " ");
-
- if (!has_child(i))
- {
- strcat(buf, format(" . %s", s_info[i].name + s_name));
- }
- else
- {
- strcat(buf, format(" - %s", s_info[i].name + s_name));
- }
-
- fprintf(fff, "%-49s%s%06.3f [%05.3f]",
- buf, s_info[i].value < 0 ? "-" : " ",
- ((double) ABS(s_info[i].value)) / SKILL_STEP,
- ((double) s_info[i].mod) / 1000);
- }
-
- fprintf(fff, "\n");
-}
-
-
-/*
- * Draw the skill tree
- */
-void print_skills(int table[MAX_SKILLS][2], int max, int sel, int start)
-{
- int i, j;
- int wid, hgt;
- cptr keys;
-
- Term_clear();
- Term_get_size(&wid, &hgt);
-
- c_prt(TERM_WHITE, format("%s Skills Screen", game_module), 0, 28);
- keys = format("#BEnter#W to develop a branch, #Bup#W/#Bdown#W to move, #Bright#W/#Bleft#W to modify, #B?#W for help");
- display_message(0, 1, strlen(keys), TERM_WHITE, keys);
- c_prt((p_ptr->skill_points) ? TERM_L_BLUE : TERM_L_RED,
- format("Skill points left: %d", p_ptr->skill_points), 2, 0);
- print_desc_aux(s_info[table[sel][0]].desc + s_text, 3, 0);
-
- for (j = start; j < start + (hgt - 7); j++)
- {
- byte color = TERM_WHITE;
- char deb = ' ', end = ' ';
-
- if (j >= max) break;
-
- i = table[j][0];
-
- if ((s_info[i].value == 0) && (i != SKILL_MISC))
- {
- if (s_info[i].mod == 0) color = TERM_L_DARK;
- else color = TERM_ORANGE;
- }
- else if (s_info[i].value == SKILL_MAX) color = TERM_L_BLUE;
- if (s_info[i].hidden) color = TERM_L_RED;
- if (j == sel)
- {
- color = TERM_L_GREEN;
- deb = '[';
- end = ']';
- }
- if (!has_child(i))
- {
- c_prt(color, format("%c.%c%s", deb, end, s_info[i].name + s_name),
- j + 7 - start, table[j][1] * 4);
- }
- else if (s_info[i].dev)
- {
- c_prt(color, format("%c-%c%s", deb, end, s_info[i].name + s_name),
- j + 7 - start, table[j][1] * 4);
- }
- else
- {
- c_prt(color, format("%c+%c%s", deb, end, s_info[i].name + s_name),
- j + 7 - start, table[j][1] * 4);
- }
- c_prt(color,
- format("%s%02ld.%03ld [%01d.%03d]",
- s_info[i].value < 0 ? "-" : " ",
- ABS(s_info[i].value) / SKILL_STEP,
- ABS(s_info[i].value) % SKILL_STEP,
- ABS(s_info[i].mod) / 1000,
- ABS(s_info[i].mod) % 1000),
- j + 7 - start, 60);
- }
-}
-
-/*
- * Checks various stuff to do when skills change, like new spells, ...
- */
-void recalc_skills(bool_ init)
-{
- static int thaum_level = 0;
-
- /* TODO: This should be a hook in ToME's lua */
- if (init)
- {
- thaum_level = get_skill_scale(SKILL_THAUMATURGY, 100);
- }
- else
- {
- int thaum_gain = 0;
-
- /* Gain thaum spells */
- while (thaum_level < get_skill_scale(SKILL_THAUMATURGY, 100))
- {
- if (spell_num == MAX_SPELLS) break;
- thaum_level++;
- generate_spell((thaum_level + 1) / 2);
- thaum_gain++;
- }
- if (thaum_gain)
- {
- if (thaum_gain == 1)
- msg_print("You have gained one new thaumaturgy spell.");
- else
- msg_format("You have gained %d new thaumaturgy spells.", thaum_gain);
- }
-
- process_hooks(HOOK_RECALC_SKILLS, "()");
-
- /* Update stuffs */
- p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS | PU_POWERS |
- PU_SANITY | PU_BODY);
-
- /* Redraw various info */
- p_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP);
- }
-}
-
-/*
- * Recalc the skill value
- */
-void recalc_skills_theory(s16b *invest, s32b *base_val, s32b *base_mod, s32b *bonus)
-{
- int i, j;
-
- /* First we assign the normal points */
- for (i = 0; i < max_s_idx; i++)
- {
- /* Calc the base */
- s_info[i].value = base_val[i] + (base_mod[i] * invest[i]) + bonus[i];
-
- /* It cannot exceed SKILL_MAX */
- if (s_info[i].value > SKILL_MAX) s_info[i].value = SKILL_MAX;
- }
-
- /* Then we modify related skills */
- for (i = 0; i < max_s_idx; i++)
- {
- for (j = 1; j < max_s_idx; j++)
- {
- /* Ignore self */
- if (j == i) continue;
-
- /* Exclusive skills */
- if ((s_info[i].action[j] == SKILL_EXCLUSIVE) && invest[i])
- {
- /* Turn it off */
- p_ptr->skill_points += invest[j];
- invest[j] = 0;
- s_info[j].value = 0;
- }
-
- /* Non-exclusive skills */
- else if (s_info[i].action[j])
- {
- /* Increase / decrease with a % */
- s32b val = s_info[j].value + (invest[i] * s_info[j].mod * s_info[i].action[j] / 100);
-
- /* It cannot exceed SKILL_MAX */
- if (val > SKILL_MAX) val = SKILL_MAX;
-
- /* Save the modified value */
- s_info[j].value = val;
- }
- }
- }
-}
-
-/*
- * Interreact with skills
- */
-void do_cmd_skill()
-{
- int sel = 0, start = 0, max;
- char c;
- int table[MAX_SKILLS][2];
- int i;
- int wid, hgt;
- s16b skill_points_save;
- s32b *skill_values_save;
- s32b *skill_mods_save;
- s16b *skill_rates_save;
- s16b *skill_invest;
- s32b *skill_bonus;
-
- recalc_skills(TRUE);
-
- /* Save the screen */
- screen_save();
-
- /* Allocate arrays to save skill values */
- C_MAKE(skill_values_save, MAX_SKILLS, s32b);
- C_MAKE(skill_mods_save, MAX_SKILLS, s32b);
- C_MAKE(skill_rates_save, MAX_SKILLS, s16b);
- C_MAKE(skill_invest, MAX_SKILLS, s16b);
- C_MAKE(skill_bonus, MAX_SKILLS, s32b);
-
- /* Save skill points */
- skill_points_save = p_ptr->skill_points;
-
- /* Save skill values */
- for (i = 0; i < max_s_idx; i++)
- {
- skill_type *s_ptr = &s_info[i];
-
- skill_values_save[i] = s_ptr->value;
- skill_mods_save[i] = s_ptr->mod;
- skill_rates_save[i] = s_ptr->rate;
- skill_invest[i] = 0;
- }
-
- /* Clear the screen */
- Term_clear();
-
- /* Initialise the skill list */
- init_table(table, &max, FALSE);
-
- while (TRUE)
- {
- Term_get_size(&wid, &hgt);
-
- /* Display list of skills */
- recalc_skills_theory(skill_invest, skill_values_save, skill_mods_save, skill_bonus);
- print_skills(table, max, sel, start);
-
- /* Wait for user input */
- c = inkey();
-
- /* Leave the skill screen */
- if (c == ESCAPE) break;
-
- /* Expand / collapse list of skills */
- else if (c == '\r')
- {
- if (s_info[table[sel][0]].dev) s_info[table[sel][0]].dev = FALSE;
- else s_info[table[sel][0]].dev = TRUE;
- init_table(table, &max, FALSE);
- }
-
- /* Next page */
- else if (c == 'n')
- {
- sel += (hgt - 7);
- if (sel >= max) sel = max - 1;
- }
-
- /* Previous page */
- else if (c == 'p')
- {
- sel -= (hgt - 7);
- if (sel < 0) sel = 0;
- }
-
- /* Select / increase a skill */
- else
- {
- int dir;
-
- /* Allow use of numpad / arrow keys / roguelike keys */
- dir = get_keymap_dir(c);
-
- /* Move cursor down */
- if (dir == 2) sel++;
-
- /* Move cursor up */
- if (dir == 8) sel--;
-
- /* Miscellaneous skills cannot be increased/decreased as a group */
- if (table[sel][0] == SKILL_MISC) continue;
-
- /* Increase the current skill */
- if (dir == 6) increase_skill(table[sel][0], skill_invest);
-
- /* Decrease the current skill */
- if (dir == 4) decrease_skill(table[sel][0], skill_invest);
-
- /* XXX XXX XXX Wizard mode commands outside of wizard2.c */
-
- /* Increase the skill */
- if (wizard && (c == '+')) skill_bonus[table[sel][0]] += SKILL_STEP;
-
- /* Decrease the 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));
- ;
-
- /* Handle boundaries and scrolling */
- if (sel < 0) sel = max - 1;
- if (sel >= max) sel = 0;
- if (sel < start) start = sel;
- if (sel >= start + (hgt - 7)) start = sel - (hgt - 7) + 1;
- }
- }
-
-
- /* Some skill points are spent */
- if (p_ptr->skill_points != skill_points_save)
- {
- /* Flush input as we ask an important and irreversible question */
- 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')
- {
- /* User declines -- restore the skill values before exiting */
-
- /* Restore skill points */
- p_ptr->skill_points = skill_points_save;
-
- /* Restore skill values */
- for (i = 0; i < max_s_idx; i++)
- {
- skill_type *s_ptr = &s_info[i];
-
- s_ptr->value = skill_values_save[i];
- s_ptr->mod = skill_mods_save[i];
- s_ptr->rate = skill_rates_save[i];
- }
- }
- }
-
-
- /* Free arrays to save skill values */
- C_FREE(skill_values_save, MAX_SKILLS, s32b);
- C_FREE(skill_mods_save, MAX_SKILLS, s32b);
- C_FREE(skill_rates_save, MAX_SKILLS, s16b);
- C_FREE(skill_invest, MAX_SKILLS, s16b);
- C_FREE(skill_bonus, MAX_SKILLS, s32b);
-
- /* Load the screen */
- screen_load();
-
- recalc_skills(FALSE);
-}
-
-
-
-/*
- * List of melee skills
- */
-s16b melee_skills[MAX_MELEE] =
-{
- SKILL_MASTERY,
- SKILL_HAND,
- SKILL_BEAR,
-};
-char *melee_names[MAX_MELEE] =
-{
- "Weapon combat",
- "Barehanded combat",
- "Bearform combat",
-};
-static bool_ melee_bool[MAX_MELEE];
-static int melee_num[MAX_MELEE];
-
-s16b get_melee_skill()
-{
- int i;
-
- for (i = 0; i < MAX_MELEE; i++)
- {
- if (p_ptr->melee_style == melee_skills[i])
- return (i);
- }
- return (0);
-}
-
-s16b get_melee_skills()
-{
- int i, j = 0;
-
- for (i = 0; i < MAX_MELEE; i++)
- {
- if ((s_info[melee_skills[i]].value > 0) && (!s_info[melee_skills[i]].hidden))
- {
- melee_bool[i] = TRUE;
- j++;
- }
- else
- melee_bool[i] = FALSE;
- }
-
- return (j);
-}
-
-static void choose_melee()
-{
- int i, j, z = 0;
- int force_drop = FALSE, style_unchanged = FALSE;
-
- character_icky = TRUE;
- Term_save();
- Term_clear();
-
- j = get_melee_skills();
- prt("Choose a melee style:", 0, 0);
- for (i = 0; i < MAX_MELEE; i++)
- {
- if (melee_bool[i])
- {
- prt(format("%c) %s", I2A(z), melee_names[i]), z + 1, 0);
- melee_num[z] = i;
- z++;
- }
- }
-
- while (TRUE)
- {
- char c = inkey();
-
- if (c == ESCAPE) break;
- if (A2I(c) < 0) continue;
- if (A2I(c) >= j) continue;
-
- for (i = 0, z = 0; z < A2I(c); i++)
- if (melee_bool[i]) z++;
-
- if (p_ptr->melee_style == melee_skills[melee_num[z]])
- {
- style_unchanged = TRUE;
- break;
- }
-
- for (i = INVEN_WIELD; p_ptr->body_parts[i - INVEN_WIELD] == INVEN_WIELD; i++)
- {
- if (p_ptr->inventory[i].k_idx)
- {
- if (cursed_p(&p_ptr->inventory[i]))
- {
- char name[80];
- object_desc(name, &p_ptr->inventory[i], 0, 0);
- msg_format("Hmmm, your %s seems to be cursed.", name);
- break;
- }
- else if (INVEN_PACK == inven_takeoff(i, 255, force_drop))
- {
- force_drop = TRUE;
- }
- }
- }
- p_ptr->melee_style = melee_skills[melee_num[z]];
- energy_use = 100;
- break;
- }
-
- /* Recalculate bonuses */
- p_ptr->update |= (PU_BONUS);
-
- /* Recalculate hitpoint */
- p_ptr->update |= (PU_HP);
-
- /* Redraw monster hitpoint */
- p_ptr->redraw |= (PR_MH);
-
- Term_load();
- character_icky = FALSE;
-
- if (style_unchanged)
- {
- msg_format("You are already using %s.", melee_names[melee_num[z]]);
- }
-}
-
-void select_default_melee()
-{
- int i;
-
- get_melee_skills();
- p_ptr->melee_style = SKILL_MASTERY;
- for (i = 0; i < MAX_MELEE; i++)
- {
- if (melee_bool[i])
- {
- p_ptr->melee_style = melee_skills[i];
- break;
- }
- }
-}
-
-/*
- * Print a batch of skills.
- */
-static void print_skill_batch(int *p, cptr *p_desc, int start, int max, bool_ mode)
-{
- char buff[80];
- int i = start, j = 0;
-
- if (mode) prt(format(" %-31s", "Name"), 1, 20);
-
- for (i = start; i < (start + 20); i++)
- {
- if (i >= max) break;
-
- if (p[i] > 0)
- sprintf(buff, " %c - %d) %-30s", I2A(j), p[i], p_desc[i]);
- else
- sprintf(buff, " %c - %d) %-30s", I2A(j), p[i], "Change melee style");
-
- if (mode) prt(buff, 2 + j, 20);
- j++;
- }
- if (mode) prt("", 2 + j, 20);
- prt(format("Select a skill (a-%c), @ to select by name, +/- to scroll:", I2A(j - 1)), 0, 0);
-}
-
-int do_cmd_activate_skill_aux()
-{
- char which;
- int max = 0, i, start = 0;
- int ret;
- bool_ mode = FALSE;
- int *p;
- cptr *p_desc;
-
- C_MAKE(p, max_s_idx + max_ab_idx, int);
- C_MAKE(p_desc, max_s_idx + max_ab_idx, cptr);
-
- /* Count the max */
-
- /* More than 1 melee skill ? */
- if (get_melee_skills() > 1)
- {
- p_desc[max] = "Change melee mode";
- p[max++] = 0;
- }
-
- for (i = 1; i < max_s_idx; i++)
- {
- if (s_info[i].action_mkey && s_info[i].value && ((!s_info[i].hidden) || (i == SKILL_LEARN)))
- {
- int j;
- bool_ next = FALSE;
-
- /* Already got it ? */
- for (j = 0; j < max; j++)
- {
- if (s_info[i].action_mkey == p[j])
- {
- next = TRUE;
- break;
- }
- }
- if (next) continue;
-
- p_desc[max] = s_text + s_info[i].action_desc;
- p[max++] = s_info[i].action_mkey;
- }
- }
-
- for (i = 0; i < max_ab_idx; i++)
- {
- if (ab_info[i].action_mkey && ab_info[i].acquired)
- {
- int j;
- bool_ next = FALSE;
-
- /* Already got it ? */
- for (j = 0; j < max; j++)
- {
- if (ab_info[i].action_mkey == p[j])
- {
- next = TRUE;
- break;
- }
- }
- if (next) continue;
-
- p_desc[max] = ab_text + ab_info[i].action_desc;
- p[max++] = ab_info[i].action_mkey;
- }
- }
-
- if (!max)
- {
- msg_print("You don't have any activable skills or abilities.");
- return -1;
- }
-
- character_icky = TRUE;
- Term_save();
-
- while (1)
- {
- print_skill_batch(p, p_desc, start, max, mode);
- which = inkey();
-
- if (which == ESCAPE)
- {
- ret = -1;
- break;
- }
- else if (which == '*' || which == '?' || which == ' ')
- {
- mode = (mode) ? FALSE : TRUE;
- Term_load();
- character_icky = FALSE;
- }
- else if (which == '+')
- {
- start += 20;
- if (start >= max) start -= 20;
- Term_load();
- character_icky = FALSE;
- }
- else if (which == '-')
- {
- start -= 20;
- if (start < 0) start += 20;
- Term_load();
- character_icky = FALSE;
- }
- else if (which == '@')
- {
- char buf[80];
-
- strcpy(buf, "Cast a spell");
- if (!get_string("Skill action? ", buf, 79))
- return FALSE;
-
- /* Find the skill it is related to */
- for (i = 0; i < max; i++)
- {
- if (!strcmp(buf, p_desc[i]))
- break;
- }
- if ((i < max))
- {
- ret = p[i];
- break;
- }
-
- }
- else
- {
- which = tolower(which);
- if (start + A2I(which) >= max)
- {
- bell();
- continue;
- }
- if (start + A2I(which) < 0)
- {
- bell();
- continue;
- }
-
- ret = p[start + A2I(which)];
- break;
- }
- }
- Term_load();
- character_icky = FALSE;
-
- C_FREE(p, max_s_idx + max_ab_idx, int);
- C_FREE(p_desc, max_s_idx + max_ab_idx, cptr);
-
- return ret;
-}
-
-/* Ask & execute a skill */
-void do_cmd_activate_skill()
-{
- int x_idx;
- bool_ push = TRUE;
-
- /* Get the skill, if available */
- if (repeat_pull(&x_idx))
- {
- push = FALSE;
- }
- else if (!command_arg) x_idx = do_cmd_activate_skill_aux();
- else
- {
- int i, j;
-
- x_idx = command_arg;
-
- /* Check validity */
- for (i = 1; i < max_s_idx; i++)
- {
- if (s_info[i].value && (s_info[i].action_mkey == x_idx))
- break;
- }
- for (j = 0; j < max_ab_idx; j++)
- {
- if (ab_info[j].acquired && (ab_info[j].action_mkey == x_idx))
- break;
- }
-
- if ((j == max_ab_idx) && (i == max_s_idx))
- {
- msg_print("Uh?");
- return;
- }
- }
-
- if (x_idx == -1) return;
-
- if (push) repeat_push(x_idx);
-
- if (!x_idx)
- {
- choose_melee();
- return;
- }
-
- /* Break goi/manashield */
- if (p_ptr->invuln)
- {
- set_invuln(0);
- }
- if (p_ptr->disrupt_shield)
- {
- set_disrupt_shield(0);
- }
-
- switch (x_idx)
- {
- case MKEY_ANTIMAGIC:
- do_cmd_unbeliever();
- break;
- case MKEY_MINDCRAFT:
- do_cmd_mindcraft();
- break;
- case MKEY_ALCHEMY:
- do_cmd_alchemist();
- break;
- case MKEY_MIMIC:
- do_cmd_mimic();
- break;
- case MKEY_POWER_MAGE:
- do_cmd_powermage();
- break;
- case MKEY_RUNE:
- do_cmd_runecrafter();
- break;
- case MKEY_FORGING:
- do_cmd_archer();
- break;
- case MKEY_INCARNATION:
- do_cmd_possessor();
- break;
- case MKEY_TELEKINESIS:
- do_cmd_portable_hole();
- break;
- case MKEY_BLADE:
- do_cmd_blade();
- break;
- case MKEY_SUMMON:
- do_cmd_summoner();
- break;
- case MKEY_NECRO:
- do_cmd_necromancer();
- break;
- case MKEY_SYMBIOTIC:
- do_cmd_symbiotic();
- break;
- case MKEY_TRAP:
- do_cmd_set_trap();
- break;
- case MKEY_STEAL:
- do_cmd_steal();
- break;
- case MKEY_DODGE:
- use_ability_blade();
- break;
- case MKEY_SCHOOL:
- cast_school_spell();
- break;
- case MKEY_COPY:
- do_cmd_copy_spell();
- break;
- case MKEY_BOULDER:
- do_cmd_create_boulder();
- break;
- case MKEY_COMPANION:
- if (get_skill(SKILL_LORE) >= 12)
- do_cmd_companion();
- else
- msg_print("You need a skill level of at least 12.");
- break;
- case MKEY_PIERCING:
- do_cmd_set_piercing();
- break;
- default:
- process_hooks(HOOK_MKEY, "(d)", x_idx);
- break;
- }
-}
-
-
-/* Which magic forbids non FA gloves */
-bool_ forbid_gloves()
-{
- if (get_skill(SKILL_SORCERY)) return (TRUE);
- if (get_skill(SKILL_MANA)) return (TRUE);
- if (get_skill(SKILL_FIRE)) return (TRUE);
- if (get_skill(SKILL_AIR)) return (TRUE);
- if (get_skill(SKILL_WATER)) return (TRUE);
- if (get_skill(SKILL_EARTH)) return (TRUE);
- if (get_skill(SKILL_THAUMATURGY)) return (TRUE);
- return (FALSE);
-}
-
-/* Which gods forbid edged weapons */
-bool_ forbid_non_blessed()
-{
- GOD(GOD_ERU) return (TRUE);
- return (FALSE);
-}
-
-
-/*
- * Gets the base value of a skill, given a race/class/...
- */
-void compute_skills(s32b *v, s32b *m, int i)
-{
- s32b value, mod;
-
- /***** general skills *****/
-
- /* If the skill correspond to the magic school lets pump them a bit */
- value = gen_skill_base[i];
- mod = gen_skill_mod[i];
-
- *v = modify_aux(*v,
- value, gen_skill_basem[i]);
- *m = modify_aux(*m,
- mod, gen_skill_modm[i]);
-
- /***** race skills *****/
-
- value = rp_ptr->skill_base[i];
- mod = rp_ptr->skill_mod[i];
-
- *v = modify_aux(*v,
- value, rp_ptr->skill_basem[i]);
- *m = modify_aux(*m,
- mod, rp_ptr->skill_modm[i]);
-
- /***** race mod skills *****/
-
- value = rmp_ptr->skill_base[i];
- mod = rmp_ptr->skill_mod[i];
-
- *v = modify_aux(*v,
- value, rmp_ptr->skill_basem[i]);
- *m = modify_aux(*m,
- mod, rmp_ptr->skill_modm[i]);
-
- /***** class skills *****/
-
- value = cp_ptr->skill_base[i];
- mod = cp_ptr->skill_mod[i];
-
- *v = modify_aux(*v,
- value, cp_ptr->skill_basem[i]);
- *m = modify_aux(*m,
- mod, cp_ptr->skill_modm[i]);
-
- /***** class spec skills *****/
-
- value = spp_ptr->skill_base[i];
- mod = spp_ptr->skill_mod[i];
-
- *v = modify_aux(*v,
- value, spp_ptr->skill_basem[i]);
- *m = modify_aux(*m,
- mod, spp_ptr->skill_modm[i]);
-}
-
-/*
- * Initialize a skill with given values
- */
-void init_skill(s32b value, s32b mod, int i)
-{
- s_info[i].value = value;
- s_info[i].mod = mod;
-
- if (s_info[i].flags1 & SKF1_HIDDEN)
- s_info[i].hidden = TRUE;
- else
- s_info[i].hidden = FALSE;
-}
-
-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;
-
- /* Check if some skills didn't influence other stuff */
- recalc_skills(TRUE);
-
- /* Grab the ones we can gain */
- max = 0;
- for (i = 0; i < max_s_idx; i++)
- {
- if (s_info[i].flags1 & SKF1_RANDOM_GAIN)
- available_skills[max++] = i;
- }
- available_skills[max++] = -1;
-
- /* Init */
- for (max = 0; max < MAX_SKILLS; max++)
- {
- used[max] = FALSE;
- }
-
- /* Count the number of available skills */
- while (available_skills[max_a] != -1) max_a++;
-
- /* Get LOST_SWORD_NSKILLS skills */
- for (max = 0; max < LOST_SWORD_NSKILLS; max++)
- {
- 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;
-
- if (s_ptr->mod)
- {
- if (s_ptr->mod < 300)
- {
- val[max] = 1000;
- mod[max] = 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;
- }
- else
- {
- val[max] = s_ptr->mod * 3;
- mod[max] = 0;
- }
- }
- else
- {
- mod[max] = 300;
- val[max] = 1000;
- }
- 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));
- }
-
- while (TRUE)
- {
- char last = 'a' + (LOST_SWORD_NSKILLS-1);
- char buf[80];
- sprintf(buf, "Choose a skill to learn(a-%c to choose, ESC to cancel)?", last);
- res = ask_menu(buf, (char **)items, LOST_SWORD_NSKILLS);
-
- /* Ok ? lets learn ! */
- if (res > -1)
- {
- skill_type *s_ptr;
- bool_ oppose = FALSE;
- int oppose_skill = -1;
-
- /* Check we don't oppose an existing skill */
- for (i = 0; i < max_s_idx; i++)
- {
- if ((s_info[i].action[skl[res]] == SKILL_EXCLUSIVE) &&
- (s_info[i].value != 0))
- {
- oppose = TRUE;
- oppose_skill = i;
- break;
- }
- }
-
- /* Ok we oppose, so be sure */
- if (oppose)
- {
- cptr msg;
-
- /*
- * Because this is SO critical a question, we must flush
- * input to prevent killing character off -- pelpel
- */
- flush();
-
- /* Prepare prompt */
- msg = format("This skill is mutually exclusive with "
- "at least %s, continue?",
- s_info[oppose_skill].name + s_name);
-
- /* The player rejected the choice */
- if (!get_check(msg)) continue;
- }
-
- s_ptr = &s_info[skl[res]];
- s_ptr->value += val[res];
- s_ptr->mod += mod[res];
- if (mod[res])
- {
- msg_format("You can now learn the %s skill.",
- s_ptr->name + s_name);
- }
- else
- {
- msg_format("Your knowledge of the %s skill increases.",
- s_ptr->name + s_name);
- }
- break;
- }
- }
-
- /* Free them ! */
- for (max = 0; max < LOST_SWORD_NSKILLS; max++)
- {
- string_free(items[max]);
- }
-
- /* Check if some skills didn't influence other stuff */
- recalc_skills(FALSE);
-}
-
-
-
-
-/**************************************** ABILITIES *****************************************/
-
-/*
- * Given the name of an ability, returns ability index or -1 if no
- * such ability is found
- */
-s16b find_ability(cptr name)
-{
- u16b i;
-
- /* Scan ability list */
- for (i = 0; i < max_ab_idx; i++)
- {
- /* The name matches */
- if (streq(ab_info[i].name + ab_name, name)) return (i);
- }
-
- /* No match found */
- return ( -1);
-}
-
-/*
- * Do the player have the ability
- */
-bool_ has_ability(int ab)
-{
- return ab_info[ab].acquired;
-}
-
-/* Do we meet the requirements */
-bool_ can_learn_ability(int ab)
-{
- ability_type *ab_ptr = &ab_info[ab];
- int i;
-
- if (ab_ptr->acquired)
- return FALSE;
-
- if (p_ptr->skill_points < ab_info[ab].cost)
- return FALSE;
-
- for (i = 0; i < 10; i++)
- {
- /* Must have skill level */
- if (ab_ptr->skills[i] > -1)
- {
- if (get_skill(ab_ptr->skills[i]) < ab_ptr->skill_levels[i])
- return FALSE;
- }
-
- /* Must have ability */
- if (ab_ptr->need_abilities[i] > -1)
- {
- if (!ab_info[ab_ptr->need_abilities[i]].acquired)
- return FALSE;
- }
-
- /* Must not have ability */
- if (ab_ptr->forbid_abilities[i] > -1)
- {
- if (ab_info[ab_ptr->forbid_abilities[i]].acquired)
- return FALSE;
- }
- }
-
- for (i = 0; i < 6; i++)
- {
- /* Must have stat */
- if (ab_ptr->stat[i] > -1)
- {
- if (p_ptr->stat_ind[i] < ab_ptr->stat[i] - 3)
- return FALSE;
- }
- }
-
- /* Do the script allow us? */
- if (process_hooks(HOOK_LEARN_ABILITY, "(d)", ab))
- return FALSE;
-
- return TRUE;
-}
-
-/* Learn an ability */
-void gain_ability(int ab)
-{
- int wid, hgt;
- Term_get_size(&wid, &hgt);
-
- if (!can_learn_ability(ab))
- {
- msg_box("You cannot learn this ability.", (int)(hgt / 2), (int)(wid / 2));
- return;
- }
-
- /* Flush input as we ask an important and irreversible question */
- 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')
- {
- return;
- }
-
- ab_info[ab].acquired = TRUE;
- p_ptr->skill_points -= ab_info[ab].cost;
-}
-
-/* helper function to generate a sorted table */
-static void add_sorted_ability(int *table, int *max, int ab)
-{
- int i;
-
- for (i = 0; i < *max; i++)
- {
- if (strcmp(ab_name + ab_info[ab].name, ab_name + ab_info[table[i]].name) < 0)
- {
- int z;
-
- /* Move all indexes up */
- for (z = *max; z > i; z--)
- {
- table[z] = table[z - 1];
- }
- break;
- }
- }
- table[i] = ab;
-
- (*max)++;
-}
-
-/*
- * Print the abilities list
- */
-void dump_abilities(FILE *fff)
-{
- int i, j;
- int *table;
- int max = 0;
-
- C_MAKE(table, max_ab_idx, int);
-
- /* Initialise the abilities list */
- for (i = 0; i < max_ab_idx; i++)
- {
- if (ab_info[i].name && has_ability(i))
- add_sorted_ability(table, &max, i);
- }
-
- if (max)
- {
- fprintf(fff, "\nAbilities");
-
- for (j = 0; j < max; j++)
- {
- i = table[j];
-
- fprintf(fff, "\n * %s", ab_info[i].name + ab_name);
- }
-
- fprintf(fff, "\n");
- }
-}
-
-/*
- * Draw the abilities list
- */
-void print_abilities(int table[], int max, int sel, int start)
-{
- int i, j;
- int wid, hgt;
- cptr keys;
-
- Term_clear();
- Term_get_size(&wid, &hgt);
-
- c_prt(TERM_WHITE, format("%s Abilities Screen", game_module), 0, 28);
- keys = format("#Bup#W/#Bdown#W to move, #Bright#W to buy, #B?#W for help");
- display_message(0, 1, strlen(keys), TERM_WHITE, keys);
- c_prt((p_ptr->skill_points) ? TERM_L_BLUE : TERM_L_RED,
- format("Skill points left: %d", p_ptr->skill_points), 2, 0);
-
- print_desc_aux(ab_info[table[sel]].desc + ab_text, 3, 0);
-
- for (j = start; j < start + (hgt - 7); j++)
- {
- byte color = TERM_WHITE;
- char deb = ' ', end = ' ';
-
- if (j >= max) break;
-
- i = table[j];
-
- if (ab_info[i].acquired)
- color = TERM_L_BLUE;
- else if (can_learn_ability(i))
- color = TERM_WHITE;
- else
- color = TERM_L_DARK;
-
-
- if (j == sel)
- {
- color = TERM_L_GREEN;
- deb = '[';
- end = ']';
- }
-
- c_prt(color, format("%c.%c%s", deb, end, ab_info[i].name + ab_name),
- j + 7 - start, 0);
-
- if (!ab_info[i].acquired)
- {
- c_prt(color, format("%d", ab_info[i].cost), j + 7 - start, 60);
- }
- else
- {
- c_prt(color, "Known", j + 7 - start, 60);
- }
- }
-}
-
-/*
- * Interreact with abilitiess
- */
-void do_cmd_ability()
-{
- int sel = 0, start = 0, max = 0;
- char c;
- int *table;
- int i;
- int wid, hgt;
-
- C_MAKE(table, max_ab_idx, int);
-
- /* Save the screen */
- screen_save();
-
- /* Clear the screen */
- Term_clear();
-
- /* Initialise the abilities list */
- for (i = 0; i < max_ab_idx; i++)
- {
-if (ab_info[i].name)
- add_sorted_ability(table, &max, i);
- }
-
- while (TRUE)
- {
- Term_get_size(&wid, &hgt);
-
- /* Display list of skills */
- print_abilities(table, max, sel, start);
-
- /* Wait for user input */
- c = inkey();
-
- /* Leave the skill screen */
- if (c == ESCAPE) break;
-
- /* Next page */
- else if (c == 'n')
- {
- sel += (hgt - 7);
- if (sel >= max) sel = max - 1;
- }
-
- /* Previous page */
- else if (c == 'p')
- {
- sel -= (hgt - 7);
- if (sel < 0) sel = 0;
- }
-
- /* Select / increase a skill */
- else
- {
- int dir;
-
- /* Allow use of numpad / arrow keys / roguelike keys */
- dir = get_keymap_dir(c);
-
- /* Move cursor down */
- if (dir == 2) sel++;
-
- /* Move cursor up */
- if (dir == 8) sel--;
-
- /* gain ability */
- if (dir == 6) gain_ability(table[sel]);
-
- /* XXX XXX XXX Wizard mode commands outside of wizard2.c */
-
- if (wizard && (c == '+')) ab_info[table[sel]].acquired = TRUE;
- 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));
- ;
-
- /* Handle boundaries and scrolling */
- if (sel < 0) sel = max - 1;
- if (sel >= max) sel = 0;
- if (sel < start) start = sel;
- if (sel >= start + (hgt - 7)) start = sel - (hgt - 7) + 1;
- }
- }
-
- /* Load the screen */
- screen_load();
-
- C_FREE(table, max_ab_idx, int);
-
- /* Update stuffs */
- p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS | PU_POWERS |
- PU_SANITY | PU_BODY);
-
- /* Redraw various info */
- p_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP);
-}
-
-/*
- * Apply abilities to be granted this level
- */
-void apply_level_abilities(int level)
-{
- int i;
-
- for (i = 0; i < 10; i++)
- {
- if (cp_ptr->abilities[i].level == level)
- {
- if ((level > 1) && (!ab_info[cp_ptr->abilities[i].ability].acquired))
- cmsg_format(TERM_L_GREEN, "You have learned the ability '%s'.", ab_name + ab_info[cp_ptr->abilities[i].ability].name);
- ab_info[cp_ptr->abilities[i].ability].acquired = TRUE;
- }
- if (spp_ptr->abilities[i].level == level)
- {
- if ((level > 1) && (!ab_info[spp_ptr->abilities[i].ability].acquired))
- cmsg_format(TERM_L_GREEN, "You have learned the ability '%s'.", ab_name + ab_info[spp_ptr->abilities[i].ability].name);
- ab_info[spp_ptr->abilities[i].ability].acquired = TRUE;
- }
- if (rp_ptr->abilities[i].level == level)
- {
- if ((level > 1) && (!ab_info[rp_ptr->abilities[i].ability].acquired))
- cmsg_format(TERM_L_GREEN, "You have learned the ability '%s'.", ab_name + ab_info[rp_ptr->abilities[i].ability].name);
- ab_info[rp_ptr->abilities[i].ability].acquired = TRUE;
- }
- if (rmp_ptr->abilities[i].level == level)
- {
- if ((level > 1) && (!ab_info[rmp_ptr->abilities[i].ability].acquired))
- cmsg_format(TERM_L_GREEN, "You have learned the ability '%s'.", ab_name + ab_info[rmp_ptr->abilities[i].ability].name);
- ab_info[rmp_ptr->abilities[i].ability].acquired = TRUE;
- }
- }
-}
diff --git a/src/skills.cc b/src/skills.cc
new file mode 100644
index 00000000..af5e46c7
--- /dev/null
+++ b/src/skills.cc
@@ -0,0 +1,1918 @@
+/*
+ * Copyright (c) 2001 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 "skills.hpp"
+
+#include "ability_type.hpp"
+#include "birth.hpp"
+#include "cmd2.hpp"
+#include "cmd3.hpp"
+#include "cmd5.hpp"
+#include "cmd7.hpp"
+#include "game.hpp"
+#include "gods.hpp"
+#include "help.hpp"
+#include "hooks.hpp"
+#include "lua_bind.hpp"
+#include "monster2.hpp"
+#include "monster3.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "player_class.hpp"
+#include "player_race.hpp"
+#include "player_race_mod.hpp"
+#include "player_spec.hpp"
+#include "player_type.hpp"
+#include "skill_flag.hpp"
+#include "skill_type.hpp"
+#include "spells1.hpp"
+#include "spells4.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "util.h"
+#include "variable.h"
+#include "variable.hpp"
+#include "xtra2.hpp"
+#include "z-rand.hpp"
+
+#include <algorithm>
+#include <boost/algorithm/string/predicate.hpp>
+#include <cassert>
+#include <cmath>
+#include <fmt/format.h>
+#include <memory>
+#include <vector>
+#include <tuple>
+
+using boost::algorithm::iequals;
+
+/*
+ * Advance the skill point of the skill specified by i and
+ * modify related skills
+ */
+static void increase_skill(int i, s16b *invest)
+{
+ auto &s_info = game->s_info;
+
+ s32b max_skill_overage;
+
+ /* No skill points to be allocated */
+ if (!p_ptr->skill_points) return;
+
+ /* The skill cannot be increased */
+ if (!s_info[i].mod) return;
+
+ /* The skill is already maxed */
+ if (s_info[i].value >= SKILL_MAX) return;
+
+ /* Cannot allocate more than player level + max_skill_overage levels */
+ 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))
+ {
+ msg_box_auto(
+ fmt::format(
+ "Cannot raise a skill value above {} + player level.",
+ max_skill_overage
+ ));
+ return;
+ }
+
+ /* Spend an unallocated skill point */
+ p_ptr->skill_points--;
+
+ /* Increase the skill */
+ s_info[i].value += s_info[i].mod;
+ invest[i]++;
+}
+
+
+/*
+ * Descrease the skill point of the skill specified by i and
+ * modify related skills
+ */
+static void decrease_skill(int i, s16b *invest)
+{
+ auto &s_info = game->s_info;
+
+ /* Cannot decrease more */
+ if (!invest[i]) return;
+
+ /* The skill cannot be decreased */
+ if (!s_info[i].mod) return;
+
+ /* The skill already has minimal value */
+ if (!s_info[i].value) return;
+
+ /* Free a skill point */
+ p_ptr->skill_points++;
+
+ /* Decrease the skill */
+ s_info[i].value -= s_info[i].mod;
+ invest[i]--;
+}
+
+
+/*
+ * Given the name of a skill, returns skill index or -1 if no
+ * such skill is found
+ */
+s16b find_skill(cptr needle)
+{
+ auto const &s_descriptors = game->edit_data.s_descriptors;
+
+ /* Scan skill list */
+ for (std::size_t i = 1; i < s_descriptors.size(); i++)
+ {
+ auto const &name = s_descriptors[i].name;
+ if (!name.empty() && (name == needle))
+ {
+ return i;
+ }
+ }
+
+ /* No match found */
+ return -1;
+}
+
+s16b find_skill_i(cptr needle)
+{
+ auto const &s_descriptors = game->edit_data.s_descriptors;
+
+ /* Scan skill list */
+ for (std::size_t i = 1; i < s_descriptors.size(); i++)
+ {
+ auto const &name = s_descriptors[i].name;
+ if (!name.empty() && iequals(name, needle))
+ {
+ return (i);
+ }
+ }
+
+ /* No match found */
+ return ( -1);
+}
+
+
+/*
+ *
+ */
+s16b get_skill(int skill)
+{
+ auto const &s_info = game->s_info;
+
+ return (s_info[skill].value / SKILL_STEP);
+}
+
+
+/*
+ * Return "scale" (a misnomer -- this is max value) * (current skill value)
+ * / (max skill value)
+ */
+s16b get_skill_scale(int skill, u32b scale)
+{
+ auto const &s_info = game->s_info;
+
+ /*
+ * SKILL_STEP shouldn't matter here because the second parameter is
+ * relatively small (the largest one being somewhere around 200),
+ * AND because we could have used much simpler 0--50 if the ability
+ * progression were only possible at step boundaries.
+ *
+ * Because I'm not at all certain about my interpretation of the mysterious
+ * formula given above, I verified this works the same by using a tiny
+ * scheme program... -- pelpel
+ */
+ s32b temp = scale * s_info[skill].value;
+
+ return (temp / SKILL_MAX);
+}
+
+static std::size_t get_idx(int i)
+{
+ auto const &s_descriptors = game->edit_data.s_descriptors;
+
+ for (std::size_t j = 1; j < s_descriptors.size(); j++)
+ {
+ if (s_descriptors[j].order == i)
+ {
+ return j;
+ }
+ }
+
+ return 0;
+}
+
+static bool_ is_known(int s_idx)
+{
+ auto const &s_descriptors = game->edit_data.s_descriptors;
+ auto const &s_info = game->s_info;
+
+ if (wizard) return TRUE;
+ if (s_info[s_idx].value || s_info[s_idx].mod) return TRUE;
+
+ for (std::size_t i = 0; i < s_descriptors.size(); i++)
+ {
+ /* It is our child, if we don't know it we continue to search, if we know it it is enough*/
+ if (s_descriptors[i].father == s_idx)
+ {
+ if (is_known(i))
+ return TRUE;
+ }
+ }
+
+ /* Ok know none */
+ return FALSE;
+}
+
+namespace { // anonymous
+
+struct skill_entry {
+ std::size_t skill_idx;
+ int indent_level;
+};
+
+}
+
+static void init_table_aux(std::vector<skill_entry> *table, int father, int lev, bool_ full)
+{
+ auto const &s_descriptors = game->edit_data.s_descriptors;
+ auto const &s_info = game->s_info;
+
+ for (std::size_t j = 1; j < s_descriptors.size(); j++)
+ {
+ std::size_t i = get_idx(j);
+
+ if (s_descriptors[i].father != father) continue;
+ if (s_info[i].hidden) continue;
+ if (!is_known(i)) continue;
+
+ skill_entry entry;
+ entry.skill_idx = i;
+ entry.indent_level = lev;
+ table->emplace_back(entry);
+
+ if (s_info[i].dev || full)
+ {
+ init_table_aux(table, i, lev + 1, full);
+ }
+ }
+}
+
+static void init_table(std::vector<skill_entry> *table, bool_ full)
+{
+ table->clear();
+ init_table_aux(table, -1, 0, full);
+}
+
+static bool has_child(int sel)
+{
+ auto const &s_descriptors = game->edit_data.s_descriptors;
+
+ for (std::size_t i = 1; i < s_descriptors.size(); i++)
+ {
+ if ((s_descriptors[i].father == sel) && is_known(i))
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+/*
+ * Dump the skill tree
+ */
+void dump_skills(FILE *fff)
+{
+ auto const &s_descriptors = game->edit_data.s_descriptors;
+ auto const &s_info = game->s_info;
+
+ char buf[80];
+
+ std::vector<skill_entry> table;
+ table.reserve(s_descriptors.size());
+ init_table(&table, TRUE);
+
+ fprintf(fff, "\nSkills (points left: %d)", p_ptr->skill_points);
+
+ for (auto const &entry: table)
+ {
+ std::size_t i = entry.skill_idx;
+ auto const &skill = s_info[i];
+ auto const &skill_name = s_descriptors[i].name;
+
+ if ((skill.value == 0) && (i != SKILL_MISC))
+ {
+ if (skill.mod == 0)
+ {
+ continue;
+ }
+ }
+
+ sprintf(buf, "\n");
+
+ for (int z = 0; z < entry.indent_level; z++)
+ {
+ strcat(buf, " ");
+ }
+
+ if (!has_child(i))
+ {
+ strcat(buf, format(" . %s", skill_name.c_str()));
+ }
+ else
+ {
+ strcat(buf, format(" - %s", skill_name.c_str()));
+ }
+
+ fprintf(fff, "%-49s%s%06.3f [%05.3f]",
+ buf, skill.value < 0 ? "-" : " ",
+ static_cast<double>(ABS(skill.value)) / SKILL_STEP,
+ static_cast<double>(skill.mod) / 1000);
+ }
+
+ fprintf(fff, "\n");
+}
+
+
+/*
+ * Draw the skill tree
+ */
+static void print_skills(std::vector<skill_entry> const &table, int sel, int start)
+{
+ auto const &s_descriptors = game->edit_data.s_descriptors;
+ auto const &s_info = game->s_info;
+
+ int j;
+ int wid, hgt;
+ cptr keys;
+
+ Term_clear();
+ Term_get_size(&wid, &hgt);
+
+ c_prt(TERM_WHITE, format("%s Skills Screen", game_module), 0, 28);
+ keys = format("#BEnter#W to develop a branch, #Bup#W/#Bdown#W to move, #Bright#W/#Bleft#W to modify, #B?#W for help");
+ display_message(0, 1, strlen(keys), TERM_WHITE, keys);
+ c_prt((p_ptr->skill_points) ? TERM_L_BLUE : TERM_L_RED,
+ format("Skill points left: %d", p_ptr->skill_points), 2, 0);
+ print_desc_aux(s_descriptors[table[sel].skill_idx].desc.c_str(), 3, 0);
+
+ for (j = start; j < start + (hgt - 7); j++)
+ {
+ byte color = TERM_WHITE;
+ char deb = ' ', end = ' ';
+
+ if (j >= static_cast<int>(table.size()))
+ {
+ break;
+ }
+
+ std::size_t i = table[j].skill_idx;
+ auto const &name = s_descriptors[i].name;
+ auto const &skill = s_info[i];
+
+ if ((skill.value == 0) && (i != SKILL_MISC))
+ {
+ if (skill.mod == 0)
+ {
+ color = TERM_L_DARK;
+ }
+ else
+ {
+ color = TERM_ORANGE;
+ }
+ }
+ else if (skill.value == SKILL_MAX)
+ {
+ color = TERM_L_BLUE;
+ }
+
+ if (skill.hidden)
+ {
+ color = TERM_L_RED;
+ }
+
+ if (j == sel)
+ {
+ color = TERM_L_GREEN;
+ deb = '[';
+ end = ']';
+ }
+
+ if (!has_child(i))
+ {
+ c_prt(color, format("%c.%c%s", deb, end, name.c_str()),
+ j + 7 - start, table[j].indent_level * 4);
+ }
+ else if (skill.dev)
+ {
+ c_prt(color, format("%c-%c%s", deb, end, name.c_str()),
+ j + 7 - start, table[j].indent_level * 4);
+ }
+ else
+ {
+ c_prt(color, format("%c+%c%s", deb, end, name.c_str()),
+ j + 7 - start, table[j].indent_level * 4);
+ }
+
+ c_prt(color,
+ format("%s%02ld.%03ld [%01d.%03d]",
+ skill.value < 0 ? "-" : " ",
+ ABS(skill.value) / SKILL_STEP,
+ ABS(skill.value) % SKILL_STEP,
+ ABS(skill.mod) / 1000,
+ ABS(skill.mod) % 1000),
+ j + 7 - start, 60);
+ }
+}
+
+/*
+ * Checks various stuff to do when skills change, like new spells, ...
+ */
+void recalc_skills(bool_ init)
+{
+ auto const &s_info = game->s_info;
+
+ static int thaum_level = 0;
+
+ /* TODO: This should be a hook in ToME's lua */
+ if (init)
+ {
+ thaum_level = get_skill_scale(SKILL_THAUMATURGY, 100);
+ }
+ else
+ {
+ auto const &random_spells = p_ptr->random_spells;
+
+ int thaum_gain = 0;
+
+ /* Gain thaum spells while there's more to be gained */
+ while ((thaum_level < get_skill_scale(SKILL_THAUMATURGY, 100)) &&
+ (random_spells.size() < MAX_SPELLS))
+ {
+ thaum_level++;
+ generate_spell((thaum_level + 1) / 2);
+ thaum_gain++;
+ }
+
+ if (thaum_gain)
+ {
+ if (thaum_gain == 1)
+ msg_print("You have gained one new thaumaturgy spell.");
+ else
+ 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_new(HOOK_RECALC_SKILLS, NULL, NULL);
+
+ /* Update stuffs */
+ p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS | PU_POWERS |
+ PU_SANITY | PU_BODY);
+
+ /* Redraw various info */
+ p_ptr->redraw |= (PR_WIPE | PR_FRAME | PR_MAP);
+ }
+}
+
+/*
+ * Recalc the skill value
+ */
+static void recalc_skills_theory(
+ std::vector<s16b> &invest,
+ std::vector<s32b> const &base_val,
+ std::vector<s32b> const &base_mod,
+ std::vector<s32b> const &bonus)
+{
+ auto const &s_descriptors = game->edit_data.s_descriptors;
+ auto &s_info = game->s_info;
+
+ /* First we assign the normal points */
+ for (std::size_t i = 0; i < s_descriptors.size(); i++)
+ {
+ /* Calc the base */
+ s_info[i].value = base_val[i] + (base_mod[i] * invest[i]) + bonus[i];
+
+ /* It cannot exceed SKILL_MAX */
+ if (s_info[i].value > SKILL_MAX)
+ {
+ s_info[i].value = SKILL_MAX;
+ }
+ }
+
+ /* Then we modify related skills */
+ for (std::size_t i = 0; i < s_descriptors.size(); i++)
+ {
+ auto const &s_descriptor = s_descriptors[i];
+
+ // Process all exlusions
+ if (invest[i])
+ {
+ for (auto exclude_si: s_descriptor.excludes)
+ {
+ // Give back skill points invested during this "session"
+ p_ptr->skill_points += invest[exclude_si];
+ invest[exclude_si] = 0;
+
+ // Turn it off
+ s_info[exclude_si].value = 0;
+ }
+ }
+
+ // Add any bonuses
+ for (auto const &increase: s_descriptor.increases)
+ {
+ auto increase_si = std::get<0>(increase);
+ auto increase_pct = std::get<1>(increase);
+
+ /* Increase/decrease by percentage */
+ s32b val = s_info[increase_si].value + (invest[i] * s_info[increase_si].mod * increase_pct / 100);
+
+ /* It cannot exceed SKILL_MAX */
+ if (val > SKILL_MAX)
+ {
+ val = SKILL_MAX;
+ }
+
+ /* Save the modified value */
+ s_info[increase_si].value = val;
+ }
+ }
+}
+
+/*
+ * Interreact with skills
+ */
+void do_cmd_skill()
+{
+ auto const &s_descriptors = game->edit_data.s_descriptors;
+ auto &s_info = game->s_info;
+
+ int sel = 0, start = 0;
+ char c;
+ int wid, hgt;
+ s16b skill_points_save;
+
+ recalc_skills(TRUE);
+
+ /* Save the screen */
+ screen_save();
+
+ /* Allocate arrays to save skill values and track assigned points */
+ std::vector<s32b> skill_values_save; skill_values_save.resize(s_descriptors.size(), 0);
+ std::vector<s32b> skill_mods_save; skill_mods_save.resize(s_descriptors.size(), 0);
+ std::vector<s16b> skill_invest; skill_invest.resize(s_descriptors.size(), 0);
+ std::vector<s32b> skill_bonus; skill_bonus.resize(s_descriptors.size(), 0);
+
+ /* Save skill points */
+ skill_points_save = p_ptr->skill_points;
+
+ /* Save skill values */
+ for (std::size_t i = 0; i < s_descriptors.size(); i++)
+ {
+ auto s_ptr = &s_info[i];
+ skill_values_save[i] = s_ptr->value;
+ skill_mods_save[i] = s_ptr->mod;
+ }
+
+ /* Clear the screen */
+ Term_clear();
+
+ /* Initialise the skill list */
+ std::vector<skill_entry> table;
+ table.reserve(s_descriptors.size());
+ init_table(&table, FALSE);
+
+ while (TRUE)
+ {
+ Term_get_size(&wid, &hgt);
+
+ /* Display list of skills */
+ recalc_skills_theory(skill_invest, skill_values_save, skill_mods_save, skill_bonus);
+ print_skills(table, sel, start);
+
+ /* Wait for user input */
+ c = inkey();
+
+ /* Leave the skill screen */
+ if (c == ESCAPE) break;
+
+ /* Expand / collapse list of skills */
+ else if (c == '\r')
+ {
+ // Toggle the selected skill
+ s_info[table[sel].skill_idx].dev = !s_info[table[sel].skill_idx].dev;
+ // Re-populate table
+ init_table(&table, FALSE);
+ }
+
+ /* Next page */
+ else if (c == 'n')
+ {
+ sel += (hgt - 7);
+
+ if (sel >= static_cast<int>(table.size()))
+ {
+ sel = table.size() - 1;
+ }
+ }
+
+ /* Previous page */
+ else if (c == 'p')
+ {
+ sel -= (hgt - 7);
+ if (sel < 0) sel = 0;
+ }
+
+ /* Select / increase a skill */
+ else
+ {
+ int dir;
+
+ /* Allow use of numpad / arrow keys / roguelike keys */
+ dir = get_keymap_dir(c);
+
+ /* Move cursor down */
+ if (dir == 2) sel++;
+
+ /* Move cursor up */
+ if (dir == 8) sel--;
+
+ /* Miscellaneous skills cannot be increased/decreased as a group */
+ if ((sel >= 0) && (sel < static_cast<int>(table.size())) && table[sel].skill_idx == SKILL_MISC) continue;
+
+ /* Increase the current skill */
+ if (dir == 6) increase_skill(table[sel].skill_idx, skill_invest.data());
+
+ /* Decrease the current skill */
+ if (dir == 4) decrease_skill(table[sel].skill_idx, skill_invest.data());
+
+ /* XXX XXX XXX Wizard mode commands outside of wizard2.c */
+
+ /* Increase the skill */
+ if (wizard && (c == '+')) skill_bonus[table[sel].skill_idx] += SKILL_STEP;
+
+ /* Decrease the skill */
+ if (wizard && (c == '-')) skill_bonus[table[sel].skill_idx] -= SKILL_STEP;
+
+ /* Contextual help */
+ if (c == '?')
+ {
+ help_skill(s_descriptors[table[sel].skill_idx].name);
+ }
+
+ /* Handle boundaries and scrolling */
+ if (sel < 0) sel = table.size() - 1;
+ if (sel >= static_cast<int>(table.size())) sel = 0;
+ if (sel < start) start = sel;
+ if (sel >= start + (hgt - 7)) start = sel - (hgt - 7) + 1;
+ }
+ }
+
+
+ /* Some skill points are spent */
+ if (p_ptr->skill_points != skill_points_save)
+ {
+ /* Flush input as we ask an important and irreversible question */
+ flush();
+
+ /* Ask we can commit the change */
+ if (msg_box_auto("Save and use these skill values? (y/n)") != 'y')
+ {
+ /* User declines -- restore the skill values before exiting */
+
+ /* Restore skill points */
+ p_ptr->skill_points = skill_points_save;
+
+ /* Restore skill values */
+ for (std::size_t i = 0; i < s_descriptors.size(); i++)
+ {
+ auto s_ptr = &s_info[i];
+ s_ptr->value = skill_values_save[i];
+ s_ptr->mod = skill_mods_save[i];
+ }
+ }
+ }
+
+ /* Load the screen */
+ screen_load();
+
+ recalc_skills(FALSE);
+}
+
+
+
+/*
+ * List of melee skills
+ */
+static s16b melee_skills[MAX_MELEE] =
+{
+ SKILL_MASTERY,
+ SKILL_HAND,
+ SKILL_BEAR,
+};
+static const char *melee_names[MAX_MELEE] =
+{
+ "Weapon combat",
+ "Barehanded combat",
+ "Bearform combat",
+};
+static bool_ melee_bool[MAX_MELEE];
+static int melee_num[MAX_MELEE];
+
+s16b get_melee_skill()
+{
+ int i;
+
+ for (i = 0; i < MAX_MELEE; i++)
+ {
+ if (p_ptr->melee_style == melee_skills[i])
+ return (i);
+ }
+ return (0);
+}
+
+cptr get_melee_name()
+{
+ return melee_names[get_melee_skill()];
+}
+
+s16b get_melee_skills()
+{
+ auto const &s_info = game->s_info;
+
+ int j = 0;
+
+ for (std::size_t i = 0; i < MAX_MELEE; i++)
+ {
+ if ((s_info[melee_skills[i]].value > 0) && (!s_info[melee_skills[i]].hidden))
+ {
+ melee_bool[i] = TRUE;
+ j++;
+ }
+ else
+ melee_bool[i] = FALSE;
+ }
+
+ return (j);
+}
+
+static void choose_melee()
+{
+ int i, j, z = 0;
+ int force_drop = FALSE, style_unchanged = FALSE;
+
+ character_icky = TRUE;
+ Term_save();
+ Term_clear();
+
+ j = get_melee_skills();
+ prt("Choose a melee style:", 0, 0);
+ for (i = 0; i < MAX_MELEE; i++)
+ {
+ if (melee_bool[i])
+ {
+ prt(format("%c) %s", I2A(z), melee_names[i]), z + 1, 0);
+ melee_num[z] = i;
+ z++;
+ }
+ }
+
+ while (TRUE)
+ {
+ char c = inkey();
+
+ if (c == ESCAPE) break;
+ if (A2I(c) < 0) continue;
+ if (A2I(c) >= j) continue;
+
+ for (i = 0, z = 0; z < A2I(c); i++)
+ if (melee_bool[i]) z++;
+
+ if (p_ptr->melee_style == melee_skills[melee_num[z]])
+ {
+ style_unchanged = TRUE;
+ break;
+ }
+
+ for (i = INVEN_WIELD; p_ptr->body_parts[i - INVEN_WIELD] == INVEN_WIELD; i++)
+ {
+ if (p_ptr->inventory[i].k_idx)
+ {
+ if (cursed_p(&p_ptr->inventory[i]))
+ {
+ char name[80];
+ object_desc(name, &p_ptr->inventory[i], 0, 0);
+ msg_format("Hmmm, your %s seems to be cursed.", name);
+ break;
+ }
+ else if (INVEN_PACK == inven_takeoff(i, 255, force_drop))
+ {
+ force_drop = TRUE;
+ }
+ }
+ }
+ p_ptr->melee_style = melee_skills[melee_num[z]];
+ energy_use = 100;
+ break;
+ }
+
+ /* Recalculate bonuses */
+ p_ptr->update |= (PU_BONUS);
+
+ /* Recalculate hitpoint */
+ p_ptr->update |= (PU_HP);
+
+ /* Redraw monster hitpoint */
+ p_ptr->redraw |= (PR_FRAME);
+
+ Term_load();
+ character_icky = FALSE;
+
+ if (style_unchanged)
+ {
+ msg_format("You are already using %s.", melee_names[melee_num[z]]);
+ }
+}
+
+void select_default_melee()
+{
+ int i;
+
+ get_melee_skills();
+ p_ptr->melee_style = SKILL_MASTERY;
+ for (i = 0; i < MAX_MELEE; i++)
+ {
+ if (melee_bool[i])
+ {
+ p_ptr->melee_style = melee_skills[i];
+ break;
+ }
+ }
+}
+
+/*
+ * Print a batch of skills.
+ */
+static void print_skill_batch(const std::vector<std::tuple<std::string, int>> &p, int start)
+{
+ char buff[80];
+ int j = 0;
+
+ prt(format(" %-31s", "Name"), 1, 20);
+
+ for (int i = start; i < (start + 20); i++)
+ {
+ if (static_cast<size_t>(i) >= p.size())
+ {
+ break;
+ }
+
+ sprintf(buff, " %c - %d) %-30s", I2A(j),
+ std::get<1>(p[i]),
+ std::get<0>(p[i]).c_str());
+
+ prt(buff, 2 + j, 20);
+ j++;
+ }
+ prt("", 2 + j, 20);
+ prt(format("Select a skill (a-%c), @ to select by name, +/- to scroll:", I2A(j - 1)), 0, 0);
+}
+
+static int do_cmd_activate_skill_aux()
+{
+ auto const &ab_info = game->edit_data.ab_info;
+ auto const &s_descriptors = game->edit_data.s_descriptors;
+ auto const &s_info = game->s_info;
+
+ char which;
+ int start = 0;
+ int ret;
+
+ std::vector<std::tuple<std::string,int>> p;
+
+ /* More than 1 melee skill ? */
+ if (get_melee_skills() > 1)
+ {
+ p.push_back(std::make_tuple("Change melee mode", 0));
+ }
+
+ for (size_t i = 1; i < s_descriptors.size(); i++)
+ {
+ if (s_descriptors[i].action_mkey && s_info[i].value && ((!s_info[i].hidden) || (i == SKILL_LEARN)))
+ {
+ bool_ next = FALSE;
+
+ /* Already got it ? */
+ for (size_t j = 0; j < p.size(); j++)
+ {
+ if (s_descriptors[i].action_mkey == std::get<1>(p[j]))
+ {
+ next = TRUE;
+ break;
+ }
+ }
+ if (next) continue;
+
+ p.push_back(std::make_tuple(s_descriptors[i].action_desc,
+ s_descriptors[i].action_mkey));
+ }
+ }
+
+ for (size_t i = 0; i < ab_info.size(); i++)
+ {
+ if (ab_info[i].action_mkey && p_ptr->has_ability(i))
+ {
+ bool_ next = FALSE;
+
+ /* Already got it ? */
+ for (size_t j = 0; j < p.size(); j++)
+ {
+ if (ab_info[i].action_mkey == std::get<1>(p[j]))
+ {
+ next = TRUE;
+ break;
+ }
+ }
+ if (next) continue;
+
+ p.push_back(std::make_tuple(ab_info[i].action_desc,
+ ab_info[i].action_mkey));
+ }
+ }
+
+ if (p.empty())
+ {
+ msg_print("You don't have any activable skills or abilities.");
+ return -1;
+ }
+
+ character_icky = TRUE;
+ Term_save();
+
+ while (1)
+ {
+ print_skill_batch(p, start);
+ which = inkey();
+
+ if (which == ESCAPE)
+ {
+ ret = -1;
+ break;
+ }
+ else if (which == '+')
+ {
+ start += 20;
+ if (static_cast<size_t>(start) >= p.size())
+ {
+ start -= 20;
+ }
+ Term_load();
+ character_icky = FALSE;
+ }
+ else if (which == '-')
+ {
+ start -= 20;
+ if (start < 0)
+ {
+ start += 20;
+ }
+ Term_load();
+ character_icky = FALSE;
+ }
+ else if (which == '@')
+ {
+ char buf[80];
+
+ strcpy(buf, "Cast a spell");
+ if (!get_string("Skill action? ", buf, 79))
+ return FALSE;
+
+ /* Find the skill it is related to */
+ size_t i = 0;
+ for (; i < p.size(); i++)
+ {
+ if (std::get<0>(p[i]) == buf)
+ {
+ break;
+ }
+ }
+
+ if (i < p.size())
+ {
+ ret = std::get<1>(p[i]);
+ break;
+ }
+ }
+ else
+ {
+ which = tolower(which);
+ if (start + A2I(which) >= static_cast<int>(p.size()))
+ {
+ bell();
+ continue;
+ }
+ if (start + A2I(which) < 0)
+ {
+ bell();
+ continue;
+ }
+
+ ret = std::get<1>(p[start + A2I(which)]);
+ break;
+ }
+ }
+ Term_load();
+ character_icky = FALSE;
+
+ return ret;
+}
+
+/* Ask & execute a skill */
+void do_cmd_activate_skill()
+{
+ auto const &ab_info = game->edit_data.ab_info;
+ auto const &s_descriptors = game->edit_data.s_descriptors;
+ auto const &s_info = game->s_info;
+
+ int x_idx;
+ bool_ push = TRUE;
+
+ /* Get the skill, if available */
+ if (repeat_pull(&x_idx))
+ {
+ push = FALSE;
+ }
+ else if (!command_arg)
+ {
+ x_idx = do_cmd_activate_skill_aux();
+ }
+ else
+ {
+ x_idx = command_arg;
+
+ /* Check validity */
+ std::size_t i;
+ for (i = 1; i < s_descriptors.size(); i++)
+ {
+ if (s_info[i].value && (s_descriptors[i].action_mkey == x_idx))
+ {
+ break;
+ }
+ }
+
+ std::size_t j;
+ for (j = 0; j < ab_info.size(); j++)
+ {
+ if (p_ptr->has_ability(j) && (ab_info[j].action_mkey == x_idx))
+ {
+ break;
+ }
+ }
+
+ if ((j == ab_info.size()) && (i == s_descriptors.size()))
+ {
+ msg_print("Uh?");
+ return;
+ }
+ }
+
+ if (x_idx == -1) return;
+
+ if (push) repeat_push(x_idx);
+
+ if (!x_idx)
+ {
+ choose_melee();
+ return;
+ }
+
+ /* Break goi/manashield */
+ if (p_ptr->invuln)
+ {
+ set_invuln(0);
+ }
+ if (p_ptr->disrupt_shield)
+ {
+ set_disrupt_shield(0);
+ }
+
+ switch (x_idx)
+ {
+ case MKEY_ANTIMAGIC:
+ do_cmd_unbeliever();
+ break;
+ case MKEY_MINDCRAFT:
+ do_cmd_mindcraft();
+ break;
+ case MKEY_MIMIC:
+ do_cmd_mimic();
+ break;
+ case MKEY_POWER_MAGE:
+ do_cmd_powermage();
+ break;
+ case MKEY_FORGING:
+ do_cmd_archer();
+ break;
+ case MKEY_INCARNATION:
+ do_cmd_possessor();
+ break;
+ case MKEY_SUMMON:
+ do_cmd_summoner();
+ break;
+ case MKEY_NECRO:
+ do_cmd_necromancer();
+ break;
+ case MKEY_SYMBIOTIC:
+ do_cmd_symbiotic();
+ break;
+ case MKEY_STEAL:
+ do_cmd_steal();
+ break;
+ case MKEY_DODGE:
+ use_ability_blade();
+ break;
+ case MKEY_SCHOOL:
+ cast_school_spell();
+ break;
+ case MKEY_COPY:
+ do_cmd_copy_spell();
+ break;
+ case MKEY_BOULDER:
+ do_cmd_create_boulder();
+ break;
+ case MKEY_COMPANION:
+ if (get_skill(SKILL_LORE) >= 12)
+ do_cmd_companion();
+ else
+ msg_print("You need a skill level of at least 12.");
+ break;
+ 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;
+ }
+ 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;
+ }
+ 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:
+ break;
+ }
+}
+
+
+/* Which magic forbids non FA gloves */
+bool_ forbid_gloves()
+{
+ if (get_skill(SKILL_SORCERY)) return (TRUE);
+ if (get_skill(SKILL_MANA)) return (TRUE);
+ if (get_skill(SKILL_FIRE)) return (TRUE);
+ if (get_skill(SKILL_AIR)) return (TRUE);
+ if (get_skill(SKILL_WATER)) return (TRUE);
+ if (get_skill(SKILL_EARTH)) return (TRUE);
+ if (get_skill(SKILL_THAUMATURGY)) return (TRUE);
+ return (FALSE);
+}
+
+/* Which gods forbid edged weapons */
+bool_ forbid_non_blessed()
+{
+ if (p_ptr->pgod == GOD_ERU) return (TRUE);
+ return (FALSE);
+}
+
+
+/*
+ * Augment skill value/modifier with the given skill_modifiers
+ */
+static void augment_skills(s32b *v, s32b *m, std::vector<skill_modifier> const &modifiers, std::size_t i)
+{
+ if (i < modifiers.size()) // Ignore if the skill has no modifiers.
+ {
+ auto const &s = modifiers[i];
+ *v = modify_aux(*v, s.base, s.basem);
+ *m = modify_aux(*m, s.mod, s.modm);
+ }
+}
+
+
+/*
+ * Gets the base value of a skill, given a race/class/...
+ */
+void compute_skills(s32b *v, s32b *m, std::size_t i)
+{
+ auto const &gen_skill = game->edit_data.gen_skill;
+
+ augment_skills(v, m, gen_skill.modifiers, i);
+ augment_skills(v, m, rp_ptr->skill_modifiers.modifiers, i);
+ augment_skills(v, m, rmp_ptr->skill_modifiers.modifiers, i);
+ augment_skills(v, m, cp_ptr->skill_modifiers.modifiers, i);
+ augment_skills(v, m, spp_ptr->skill_modifiers.modifiers, i);
+}
+
+/*
+ * Initialize a skill with given values
+ */
+void init_skill(s32b value, s32b mod, std::size_t i)
+{
+ auto const &s_descriptors = game->edit_data.s_descriptors;
+ auto &s_info = game->s_info;
+
+ s_info[i].value = value;
+ s_info[i].mod = mod;
+ s_info[i].hidden = (s_descriptors[i].flags & SKF_HIDDEN)
+ ? true
+ : false
+ ;
+}
+
+/*
+ * Perform weighted random shuffle according to the algorithm given in
+ * "Weighted Random Sampling" (2005, Efraimidis, Spirakis).
+ *
+ * @param weights is the vector of weights.
+ * @return an output vector of the same size as the input weights vector containing,
+ * in order of selection, the indices to select. For example, if you
+ * need to choose two items, you would use v[0], v[1] as the indices
+ * to pick.
+ */
+static std::vector<size_t> wrs(const std::vector<s32b> &unscaled_weights)
+{
+ const size_t n = unscaled_weights.size();
+
+ /* Rescale weights into unit interval for numerical stability */
+ std::vector<double> weights(unscaled_weights.size());
+ {
+ s32b scale = 0;
+ for (s32b weight: unscaled_weights)
+ {
+ scale += weight;
+ }
+
+ for (size_t i = 0; i < n; i++) {
+ weights[i] =
+ ((double) unscaled_weights[i]) /
+ ((double) scale);
+ }
+ }
+
+ /* Generate the keys and indexes to use for selection. This
+ is the only randomized portion of the algorithm. */
+ std::vector<std::tuple<double,size_t>> keys_and_indexes(unscaled_weights.size());
+ for (size_t i = 0; i < n; i++) {
+ /* Randomized keys according to the algorithm. */
+ double u = static_cast<double>(rand_int(100000)) / 100000;
+ double k = std::pow(u, 1/weights[i]);
+ /* Set up the key and index. We negate the k value
+ here so that keys will be sorted in descending
+ order rather than ascending order. */
+ keys_and_indexes[i] = std::make_tuple(-k, i);
+ }
+
+ /* Sort indexes according to keys. Since the keys have been
+ negated and we're using a lexicographical sort, we're
+ effectively sorting in descending order of key. */
+ std::sort(std::begin(keys_and_indexes),
+ std::end(keys_and_indexes));
+
+ /* Produce the output vector consisting of indexes only. */
+ std::vector<size_t> indexes;
+ for (auto const &key_and_index: keys_and_indexes) {
+ indexes.push_back(std::get<1>(key_and_index));
+ }
+ return indexes;
+}
+
+void do_get_new_skill()
+{
+ auto const &s_descriptors = game->edit_data.s_descriptors;
+ auto &s_info = game->s_info;
+
+ /* Check if some skills didn't influence other stuff */
+ recalc_skills(TRUE);
+
+ /* Grab the ones we can gain */
+ std::vector<size_t> available_skills;
+ available_skills.reserve(s_descriptors.size());
+ for (std::size_t i = 0; i < s_descriptors.size(); i++)
+ {
+ if (s_descriptors[i].flags & SKF_RANDOM_GAIN)
+ {
+ available_skills.push_back(i);
+ }
+ }
+
+ /* Perform the selection */
+ std::vector<s32b> weights;
+ for (std::size_t i = 0; i < available_skills.size(); i++)
+ {
+ weights.push_back(s_descriptors[available_skills[i]].random_gain_chance);
+ }
+
+ std::vector<size_t> indexes = wrs(weights);
+ assert(indexes.size() >= LOST_SWORD_NSKILLS);
+
+ /* Extract the information needed from the skills */
+ int skl[LOST_SWORD_NSKILLS];
+ s32b val[LOST_SWORD_NSKILLS];
+ s32b mod[LOST_SWORD_NSKILLS];
+ std::vector<std::string> items;
+ for (std::size_t i = 0; i < LOST_SWORD_NSKILLS; i++)
+ {
+ s32b s_idx = available_skills[indexes[i]];
+ auto s_ptr = &s_info[s_idx];
+
+ if (s_ptr->mod)
+ {
+ if (s_ptr->mod < 300)
+ {
+ val[i] = 1000;
+ mod[i] = 300 - s_ptr->mod;
+ }
+ else if (s_ptr->mod < 500)
+ {
+ val[i] = s_ptr->mod * 1;
+ mod[i] = 100;
+ if (mod[i] + s_ptr->mod > 500)
+ {
+ mod[i] = 500 - s_ptr->mod;
+ }
+ }
+ else
+ {
+ val[i] = s_ptr->mod * 3;
+ mod[i] = 0;
+ }
+ }
+ else
+ {
+ mod[i] = 300;
+ val[i] = 1000;
+ }
+
+ if (s_ptr->value + val[i] > SKILL_MAX)
+ {
+ val[i] = SKILL_MAX - s_ptr->value;
+ }
+
+ skl[i] = s_idx;
+ items.push_back(format("%-40s: +%02ld.%03ld value, +%01d.%03d modifier",
+ s_descriptors[s_idx].name.c_str(),
+ val[i] / SKILL_STEP,
+ val[i] % SKILL_STEP,
+ mod[i] / SKILL_STEP,
+ mod[i] % SKILL_STEP));
+ }
+
+ // Ask for a skill
+ while (TRUE)
+ {
+ char last = 'a' + (LOST_SWORD_NSKILLS-1);
+ char buf[80];
+ sprintf(buf, "Choose a skill to learn (a-%c to choose, ESC to cancel)?", last);
+ int res = ask_menu(buf, items);
+
+ /* Ok ? lets learn ! */
+ if (res > -1)
+ {
+ std::size_t chosen_skill = skl[res];
+
+ bool_ oppose = FALSE;
+ int oppose_skill = -1;
+
+ /* Check we don't oppose a skill the player already has */
+ for (std::size_t i = 0; i < s_descriptors.size(); i++)
+ {
+ auto const &s_descriptor = s_descriptors[i];
+
+ // Only bother if player has skill
+ if (s_info[i].value)
+ {
+ // Check if i'th skill opposes the chosen one.
+ auto found = std::find(
+ s_descriptor.excludes.begin(),
+ s_descriptor.excludes.end(),
+ chosen_skill);
+
+ if (found != s_descriptor.excludes.end())
+ {
+ oppose = TRUE;
+ oppose_skill = i;
+ break;
+ }
+ }
+ }
+
+ /* Ok we oppose, so be sure */
+ if (oppose)
+ {
+ cptr msg;
+
+ /*
+ * Because this is SO critical a question, we must flush
+ * input to prevent killing character off -- pelpel
+ */
+ flush();
+
+ /* Prepare prompt */
+ msg = format("This skill is mutually exclusive with "
+ "at least %s, continue?",
+ s_descriptors[oppose_skill].name.c_str());
+
+ /* The player rejected the choice; go back to prompt */
+ if (!get_check(msg))
+ {
+ continue;
+ }
+ }
+
+ auto const s_desc = &s_descriptors[chosen_skill];
+ auto const s_ptr = &s_info[chosen_skill];
+
+ s_ptr->value += val[res];
+ s_ptr->mod += mod[res];
+
+ if (mod[res])
+ {
+ msg_format("You can now learn the %s skill.",
+ s_desc->name.c_str());
+ }
+ else
+ {
+ msg_format("Your knowledge of the %s skill increases.",
+ s_desc->name.c_str());
+ }
+
+ break;
+ }
+ }
+
+ /* Check if some skills didn't influence other stuff */
+ recalc_skills(FALSE);
+}
+
+
+
+
+/**************************************** ABILITIES *****************************************/
+
+/*
+ * Given the name of an ability, returns ability index or -1 if no
+ * such ability is found
+ */
+s16b find_ability(cptr name)
+{
+ auto const &ab_info = game->edit_data.ab_info;
+
+ for (std::size_t i = 0; i < ab_info.size(); i++)
+ {
+ auto const &ab_name = ab_info[i].name;
+
+ if ((!ab_name.empty()) && (ab_name == name))
+ {
+ return (i);
+ }
+ }
+
+ /* No match found */
+ return ( -1);
+}
+
+/* Do we meet the requirements? */
+static bool can_learn_ability(int ab)
+{
+ auto const &ab_info = game->edit_data.ab_info;
+
+ auto ab_ptr = &ab_info[ab];
+
+ if (p_ptr->has_ability(ab))
+ {
+ return FALSE;
+ }
+
+ if (p_ptr->skill_points < ab_info[ab].cost)
+ {
+ return FALSE;
+ }
+
+ for (auto const &need_skill: ab_ptr->need_skills)
+ {
+ if (get_skill(need_skill.skill_idx) < need_skill.level)
+ {
+ return FALSE;
+ }
+ }
+
+ for (auto const &need_ability: ab_ptr->need_abilities)
+ {
+ if (!p_ptr->has_ability(need_ability))
+ {
+ return FALSE;
+ }
+ }
+
+ for (std::size_t i = 0; i < 6; i++)
+ {
+ /* Must have stat */
+ if (ab_ptr->stat[i] > -1)
+ {
+ if (p_ptr->stat_ind[i] < ab_ptr->stat[i] - 3)
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/* Learn an ability */
+static void gain_ability(int ab)
+{
+ auto const &ab_info = game->edit_data.ab_info;
+
+ if (!can_learn_ability(ab))
+ {
+ msg_box_auto("You cannot learn this ability.");
+ return;
+ }
+
+ /* Flush input as we ask an important and irreversible question */
+ flush();
+
+ /* Ask we can commit the change */
+ if (msg_box_auto("Learn this ability (this is permanent)? (y/n)") != 'y')
+ {
+ return;
+ }
+
+ p_ptr->gain_ability(ab);
+ p_ptr->skill_points -= ab_info[ab].cost;
+}
+
+static bool compare_abilities(std::size_t ab_idx1, std::size_t ab_idx2)
+{
+ auto const &ab_info = game->edit_data.ab_info;
+
+ return ab_info[ab_idx1].name < ab_info[ab_idx2].name;
+}
+
+/*
+ * Print the abilities list
+ */
+void dump_abilities(FILE *fff)
+{
+ auto const &ab_info = game->edit_data.ab_info;
+
+ // Find all abilities that the player has.
+ std::vector<std::size_t> table;
+ for (std::size_t i = 0; i < ab_info.size(); i++)
+ {
+ if ((!ab_info[i].name.empty()) && p_ptr->has_ability(i))
+ {
+ table.push_back(i);
+ }
+ }
+
+ // Sort
+ std::sort(std::begin(table),
+ std::end(table),
+ compare_abilities);
+
+ // Show
+ if (!table.empty())
+ {
+ fprintf(fff, "\nAbilities");
+
+ for (int i : table)
+ {
+ fprintf(fff, "\n * %s", ab_info[i].name.c_str());
+ }
+
+ fprintf(fff, "\n");
+ }
+}
+
+/*
+ * Draw the abilities list
+ */
+static void print_abilities(const std::vector<std::size_t> &table, int sel, int start)
+{
+ auto const &ab_info = game->edit_data.ab_info;
+
+ int i, j;
+ int wid, hgt;
+ cptr keys;
+
+ Term_clear();
+ Term_get_size(&wid, &hgt);
+
+ c_prt(TERM_WHITE, format("%s Abilities Screen", game_module), 0, 28);
+ keys = format("#Bup#W/#Bdown#W to move, #Bright#W to buy, #B?#W for help");
+ display_message(0, 1, strlen(keys), TERM_WHITE, keys);
+ c_prt((p_ptr->skill_points) ? TERM_L_BLUE : TERM_L_RED,
+ format("Skill points left: %d", p_ptr->skill_points), 2, 0);
+
+ print_desc_aux(ab_info[table[sel]].desc.c_str(), 3, 0);
+
+ for (j = start; j < start + (hgt - 7); j++)
+ {
+ byte color = TERM_WHITE;
+ char deb = ' ', end = ' ';
+
+ assert(j >= 0);
+ if (static_cast<size_t>(j) >= table.size())
+ {
+ break;
+ }
+
+ i = table[j];
+
+ if (p_ptr->has_ability(i))
+ {
+ color = TERM_L_BLUE;
+ }
+ else if (can_learn_ability(i))
+ {
+ color = TERM_WHITE;
+ }
+ else
+ {
+ color = TERM_L_DARK;
+ }
+
+
+ if (j == sel)
+ {
+ color = TERM_L_GREEN;
+ deb = '[';
+ end = ']';
+ }
+
+ c_prt(color, format("%c.%c%s", deb, end, ab_info[i].name.c_str()),
+ j + 7 - start, 0);
+
+ if (!p_ptr->has_ability(i))
+ {
+ c_prt(color, format("%d", ab_info[i].cost), j + 7 - start, 60);
+ }
+ else
+ {
+ c_prt(color, "Known", j + 7 - start, 60);
+ }
+ }
+}
+
+/*
+ * Interreact with abilities
+ */
+void do_cmd_ability()
+{
+ auto const &ab_info = game->edit_data.ab_info;
+
+ int sel = 0, start = 0;
+ char c;
+ int wid, hgt;
+
+ /* Save the screen */
+ screen_save();
+
+ /* Clear the screen */
+ Term_clear();
+
+ /* Initialise the abilities list */
+ std::vector<std::size_t> table;
+ for (std::size_t i = 0; i < ab_info.size(); i++)
+ {
+ if (!ab_info[i].name.empty())
+ {
+ table.push_back(i);
+ }
+ }
+
+ std::sort(std::begin(table),
+ std::end(table),
+ compare_abilities);
+
+ while (TRUE)
+ {
+ Term_get_size(&wid, &hgt);
+
+ /* Display list of skills */
+ print_abilities(table, sel, start);
+
+ /* Wait for user input */
+ c = inkey();
+
+ /* Leave the skill screen */
+ if (c == ESCAPE)
+ {
+ break;
+ }
+
+ /* Next page */
+ else if (c == 'n')
+ {
+ sel += (hgt - 7);
+ assert(sel >= 0);
+ if (static_cast<size_t>(sel) >= table.size())
+ {
+ sel = table.size() - 1;
+ }
+ }
+
+ /* Previous page */
+ else if (c == 'p')
+ {
+ sel -= (hgt - 7);
+ if (sel < 0) sel = 0;
+ }
+
+ /* Select / increase a skill */
+ else
+ {
+ int dir;
+
+ /* Allow use of numpad / arrow keys / roguelike keys */
+ dir = get_keymap_dir(c);
+
+ /* Move cursor down */
+ if (dir == 2) sel++;
+
+ /* Move cursor up */
+ if (dir == 8) sel--;
+
+ /* gain ability */
+ if (dir == 6) gain_ability(table[sel]);
+
+ /* Wizard mode allows any ability */
+ if (wizard && (c == '+'))
+ {
+ p_ptr->gain_ability(table[sel]);
+ }
+
+ if (wizard && (c == '-'))
+ {
+ p_ptr->lose_ability(table[sel]);
+ }
+
+ /* Contextual help */
+ if (c == '?')
+ {
+ help_ability(ab_info[table[sel]].name);
+ }
+
+ /* Handle boundaries and scrolling */
+ if (sel < 0)
+ {
+ sel = table.size() - 1;
+ }
+ if (static_cast<size_t>(sel) >= table.size())
+ {
+ sel = 0;
+ }
+ if (sel < start)
+ {
+ start = sel;
+ }
+ if (sel >= start + (hgt - 7))
+ {
+ start = sel - (hgt - 7) + 1;
+ }
+ }
+ }
+
+ /* Load the screen */
+ screen_load();
+
+ /* Update stuffs */
+ p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS | PU_POWERS |
+ PU_SANITY | PU_BODY);
+
+ /* Redraw various info */
+ p_ptr->redraw |= (PR_WIPE | PR_FRAME | PR_MAP);
+}
+
+/*
+ * Apply abilities to be granted this level
+ */
+void apply_level_abilities(int level)
+{
+ auto apply = [level](std::vector<player_race_ability_type> const &abilities) -> void
+ {
+ auto const &ab_info = game->edit_data.ab_info;
+
+ for (auto const &a: abilities)
+ {
+ if (a.level == level)
+ {
+ if ((level > 1) && (!p_ptr->has_ability(a.ability)))
+ {
+ cmsg_format(TERM_L_GREEN, "You have learned the ability '%s'.", ab_info[a.ability].name.c_str());
+ }
+
+ p_ptr->gain_ability(a.ability);
+ }
+ }
+ };
+
+ apply(cp_ptr->abilities);
+ apply(spp_ptr->abilities);
+ apply(rp_ptr->abilities);
+ apply(rmp_ptr->abilities);
+}
diff --git a/src/skills.hpp b/src/skills.hpp
new file mode 100644
index 00000000..8b1437d9
--- /dev/null
+++ b/src/skills.hpp
@@ -0,0 +1,28 @@
+#pragma once
+
+#include "h-basic.h"
+
+#include <cstddef>
+
+/* Skill functions */
+void dump_skills(FILE *fff);
+s16b find_skill(cptr name);
+s16b find_skill_i(cptr name);
+s16b get_skill(int skill);
+s16b get_skill_scale(int skill, u32b scale);
+void do_cmd_skill();
+void do_cmd_activate_skill();
+cptr get_melee_name();
+s16b get_melee_skills();
+s16b get_melee_skill();
+bool_ forbid_gloves();
+bool_ forbid_non_blessed();
+void compute_skills(s32b *v, s32b *m, std::size_t i);
+void select_default_melee();
+void do_get_new_skill();
+void init_skill(s32b value, s32b mod, std::size_t i);
+s16b find_ability(cptr name);
+void dump_abilities(FILE *fff);
+void do_cmd_ability();
+void apply_level_abilities(int level);
+void recalc_skills(bool_ init);
diff --git a/src/skills_defs.hpp b/src/skills_defs.hpp
new file mode 100644
index 00000000..9bf3c9ce
--- /dev/null
+++ b/src/skills_defs.hpp
@@ -0,0 +1,61 @@
+#pragma once
+
+/*
+ * Skill constants
+ */
+#define SKILL_CONVEYANCE 1
+#define SKILL_MANA 2
+#define SKILL_FIRE 3
+#define SKILL_AIR 4
+#define SKILL_WATER 5
+#define SKILL_NATURE 6
+#define SKILL_EARTH 7
+#define SKILL_SYMBIOTIC 8
+#define SKILL_MUSIC 9
+#define SKILL_DIVINATION 10
+#define SKILL_TEMPORAL 11
+#define SKILL_DRUID 12
+#define SKILL_DAEMON 13
+#define SKILL_META 14
+#define SKILL_MAGIC 15
+#define SKILL_COMBAT 16
+#define SKILL_MASTERY 17
+#define SKILL_SWORD 18
+#define SKILL_AXE 19
+#define SKILL_POLEARM 20
+#define SKILL_HAFTED 21
+#define SKILL_BACKSTAB 22
+#define SKILL_ARCHERY 23
+#define SKILL_SLING 24
+#define SKILL_BOW 25
+#define SKILL_XBOW 26
+#define SKILL_BOOMERANG 27
+#define SKILL_SPIRITUALITY 28
+#define SKILL_MINDCRAFT 29
+#define SKILL_MISC 30
+#define SKILL_NECROMANCY 31
+#define SKILL_MIMICRY 32
+#define SKILL_ANTIMAGIC 33
+/* XXX */
+#define SKILL_STEALTH 36
+/* XXX */
+#define SKILL_STEALING 40
+#define SKILL_SORCERY 41
+#define SKILL_HAND 42
+#define SKILL_THAUMATURGY 43
+#define SKILL_SUMMON 44
+#define SKILL_SPELL 45
+#define SKILL_DODGE 46
+#define SKILL_BEAR 47
+#define SKILL_LORE 48
+#define SKILL_PRESERVATION 49
+#define SKILL_POSSESSION 50
+#define SKILL_MIND 51
+#define SKILL_CRITS 52
+#define SKILL_PRAY 53
+#define SKILL_LEARN 54
+#define SKILL_UDUN 55
+#define SKILL_DEVICE 56
+#define SKILL_STUN 57
+#define SKILL_BOULDER 58
+#define SKILL_GEOMANCY 59
diff --git a/src/spell_type.cc b/src/spell_type.cc
new file mode 100644
index 00000000..6cf6e35b
--- /dev/null
+++ b/src/spell_type.cc
@@ -0,0 +1,433 @@
+#include "spell_type.hpp"
+
+#include "range.hpp"
+#include "device_allocation.hpp"
+#include "dice.hpp"
+#include "skills_defs.hpp"
+#include "spells4.hpp"
+#include "stats.hpp"
+
+#include <cassert>
+#include <vector>
+#include <string>
+#include <type_traits>
+
+#define SCHOOL_IDXS_MAX 3
+
+/**
+ * Spell type definition.
+ */
+struct spell_type
+{
+ cptr name; /* Name */
+ byte skill_level; /* Required level (to learn) */
+ std::vector<std::string> m_description; /* List of strings */
+
+ casting_result (*effect_func)(); /* Spell effect function */
+ const 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 */
+
+ enum 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 */
+ std::vector<device_allocation *> m_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;
+
+ size_t school_idxs_count;
+ s32b school_idxs[3];
+
+public:
+
+ spell_type(cptr _name)
+ : name(_name)
+ , skill_level(0)
+ , m_description()
+ , effect_func(nullptr)
+ , info_func(nullptr)
+ , lasting_func(nullptr)
+ , depend_func(nullptr)
+ , minimum_pval(0)
+ , casting_type(USE_SPELL_POINTS)
+ , casting_stat(0)
+ , castable_while_blind(FALSE)
+ , castable_while_confused(FALSE)
+ , device_charges({ 0, 0, 0 })
+ , m_device_allocation()
+ , random_type(-1)
+ , failure_rate(0)
+ , inertia_difficulty(-1)
+ , inertia_delay(-1)
+ , mana_range({ -1, -1 })
+ , school_idxs_count(0)
+ , school_idxs{ -1, -1, -1 }
+ {
+ }
+
+};
+
+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_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,
+ const char* (*info_func)(),
+ casting_result (*effect_func)())
+{
+ 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,
+ const char* (*info_func)(),
+ casting_result (*effect_func)(),
+ 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,
+ const char* (*info_func)(),
+ casting_result (*effect_func)())
+{
+ 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,
+ const char* (*info_func)(),
+ casting_result (*effect_func)())
+{
+ 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,
+ const char* (*info_func)(),
+ casting_result (*effect_func)())
+{
+ assert(spell != NULL);
+
+ spell_type_init_mage(spell,
+ NO_RANDOM,
+ SCHOOL_DEVICE,
+ info_func,
+ effect_func);
+}
+
+void spell_type_init_demonology(spell_type *spell,
+ const char* (*info_func)(),
+ casting_result (*effect_func)())
+{
+ spell_type_init_mage(spell,
+ NO_RANDOM,
+ SCHOOL_DEMON,
+ info_func,
+ effect_func);
+}
+
+void spell_type_init_geomancy(spell_type *spell,
+ const char* (*info_func)(),
+ casting_result (*effect_func)(),
+ 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_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);
+
+ spell->m_description.push_back(std::string(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);
+ spell->m_device_allocation.push_back(a);
+}
+
+spell_type *spell_type_new(cptr name)
+{
+ spell_type *spell = new spell_type(name);
+ assert(spell != NULL);
+ 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)
+{
+ assert(spell->effect_func != NULL);
+ return spell->effect_func();
+}
+
+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, std::function<void (std::string const &text)> callback)
+{
+ for (auto line: spell->m_description)
+ {
+ callback(line);
+ }
+}
+
+long spell_type_roll_charges(spell_type *spell)
+{
+ return dice_roll(&spell->device_charges);
+}
+
+device_allocation *spell_type_device_allocation(spell_type *spell, byte tval)
+{
+ for (auto device_allocation_ptr: spell->m_device_allocation)
+ {
+ if (device_allocation_ptr->tval == tval)
+ {
+ return device_allocation_ptr;
+ }
+ }
+
+ 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;
+}
+
+std::vector<s32b> const spell_type_get_schools(spell_type *spell)
+{
+ std::vector<s32b> school_idxs;
+ for (size_t i = 0; i < spell->school_idxs_count; i++)
+ {
+ school_idxs.push_back(spell->school_idxs[i]);
+ }
+ return school_idxs;
+}
+
+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.hpp b/src/spell_type.hpp
new file mode 100644
index 00000000..43758103
--- /dev/null
+++ b/src/spell_type.hpp
@@ -0,0 +1,86 @@
+#pragma once
+
+#include "spell_type_fwd.hpp"
+#include <vector>
+#include <string>
+#include <functional>
+#include "h-basic.h"
+#include "device_allocation_fwd.hpp"
+#include "range_fwd.hpp"
+
+/*
+ * Casting type
+ */
+enum casting_type { USE_SPELL_POINTS, USE_PIETY };
+
+/*
+ * Does the spell appear on spell random books?
+ */
+enum random_type { RANDOM, NO_RANDOM };
+
+/*
+ * Spell functions
+ */
+
+void spell_type_init_music(spell_type *spell,
+ s16b minimum_pval,
+ const char* (*info_func)(),
+ casting_result (*effect_func)());
+void spell_type_init_music_lasting(spell_type *spell,
+ s16b minimum_pval,
+ const char* (*info_func)(),
+ casting_result (*effect_func)(),
+ int (*lasting_func)());
+void spell_type_init_mage(spell_type *spell,
+ random_type random_type,
+ s32b school_idx,
+ const char* (*info_func)(),
+ casting_result (*effect_func)());
+void spell_type_init_priest(spell_type *spell,
+ s32b school_idx,
+ const char* (*info_func)(),
+ casting_result (*effect_func)());
+void spell_type_init_device(spell_type *spell,
+ const char* (*info_func)(),
+ casting_result (*effect_func)());
+void spell_type_init_demonology(spell_type *spell,
+ const char* (*info_func)(),
+ casting_result (*effect_func)());
+void spell_type_init_geomancy(spell_type *spell,
+ const char* (*info_func)(),
+ casting_result (*effect_func)(),
+ bool_ (*depend_func)());
+
+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, 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);
+cptr spell_type_name(spell_type *spell);
+int spell_type_skill_level(spell_type *spell);
+long spell_type_roll_charges(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);
+std::vector<s32b> const spell_type_get_schools(spell_type *spell);
+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);
+void spell_type_description_foreach(spell_type *spell, std::function<void (std::string const &text)>);
diff --git a/src/spell_type_fwd.hpp b/src/spell_type_fwd.hpp
new file mode 100644
index 00000000..a3b27d27
--- /dev/null
+++ b/src/spell_type_fwd.hpp
@@ -0,0 +1,16 @@
+#pragma once
+
+/*
+ * 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;
diff --git a/src/spellbinder.hpp b/src/spellbinder.hpp
new file mode 100644
index 00000000..078d9eac
--- /dev/null
+++ b/src/spellbinder.hpp
@@ -0,0 +1,21 @@
+#pragma once
+
+#include "h-basic.h"
+#include <vector>
+
+/**
+ * Spellbinder state
+ */
+struct spellbinder {
+
+ /**
+ * Bound spells.
+ */
+ std::vector<u32b> spell_idxs;
+
+ /**
+ * Trigger condition.
+ */
+ byte trigger = 0;
+
+};
diff --git a/src/spells.pkg b/src/spells.pkg
deleted file mode 100644
index e785de0d..00000000
--- a/src/spells.pkg
+++ /dev/null
@@ -1,2448 +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 MAX_GF */
-#define MAX_GF 111
-/** @} */
-
-/** @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_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
- * @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_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.
- * @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 void 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);
-
-/** @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);
-
-/** @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.
- */
-extern s16b power_max;
-
-/* 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;
-
- /** @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)
- */
- s16b level;
-};
-
-/** @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 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
- * @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);
-
-/** @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
- * @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, 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.
- * 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);
diff --git a/src/spells1.c b/src/spells1.cc
index 9bfc6fe2..4df1a7c6 100644
--- a/src/spells1.c
+++ b/src/spells1.cc
@@ -1,7 +1,3 @@
-/* File: spells1.c */
-
-/* Purpose: Spell code (part 1) */
-
/*
* Copyright (c) 1989 James E. Wilson, Robert A. Koeneke
*
@@ -10,7 +6,55 @@
* included in all such copies.
*/
-#include "angband.h"
+#include "spells1.hpp"
+
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "cmd1.hpp"
+#include "cmd3.hpp"
+#include "cmd5.hpp"
+#include "dungeon_flag.hpp"
+#include "dungeon_info_type.hpp"
+#include "files.hpp"
+#include "feature_flag.hpp"
+#include "feature_type.hpp"
+#include "game.hpp"
+#include "gods.hpp"
+#include "melee2.hpp"
+#include "monster2.hpp"
+#include "monster3.hpp"
+#include "monster_race.hpp"
+#include "monster_race_flag.hpp"
+#include "monster_spell_flag.hpp"
+#include "monster_type.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_flag.hpp"
+#include "object_kind.hpp"
+#include "options.hpp"
+#include "player_type.hpp"
+#include "skills.hpp"
+#include "spell_type.hpp"
+#include "spells2.hpp"
+#include "spells4.hpp"
+#include "spells5.hpp"
+#include "squeltch.hpp"
+#include "stats.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "util.h"
+#include "variable.hpp"
+#include "wizard2.hpp"
+#include "xtra1.hpp"
+#include "xtra2.hpp"
+#include "z-rand.hpp"
+
+#include <chrono>
+#include <fmt/format.h>
+#include <thread>
+
+using std::this_thread::sleep_for;
+using std::chrono::milliseconds;
/* 1/x chance of reducing stats (for elemental attacks) */
#define HURT_CHANCE 32
@@ -21,6 +65,24 @@
/* Maximum number of tries for teleporting */
#define MAX_TRIES 100
+/*
+ * Convert an "attr"/"char" pair into a "pict" (P)
+ */
+#define PICT(A,C) \
+ ((((u16b)(A)) << 8) | ((byte)(C)))
+
+/*
+ * Convert a "pict" (P) into an "attr" (A)
+ */
+#define PICT_A(P) \
+ ((byte)((P) >> 8))
+
+/*
+ * Convert a "pict" (P) into an "char" (C)
+ */
+#define PICT_C(P) \
+ ((char)((byte)(P)))
+
/*
* Helper function -- return a "nearby" race for polymorphing
@@ -29,12 +91,14 @@
*/
s16b poly_r_idx(int r_idx)
{
- monster_race *r_ptr = &r_info[r_idx];
+ auto const &r_info = game->edit_data.r_info;
+
+ auto r_ptr = &r_info[r_idx];
int i, r;
/* Hack -- Uniques never polymorph */
- if (r_ptr->flags1 & RF1_UNIQUE)
+ if (r_ptr->flags & RF_UNIQUE)
return (r_idx);
/* Pick a (possibly new) non-unique race */
@@ -50,7 +114,7 @@ s16b poly_r_idx(int r_idx)
r_ptr = &r_info[r];
/* Ignore unique monsters */
- if (r_ptr->flags1 & (RF1_UNIQUE)) continue;
+ if (r_ptr->flags & RF_UNIQUE) continue;
/* Use that index */
r_idx = r;
@@ -158,9 +222,6 @@ void teleport_player_directed(int rad, int dir)
}
- /* Sound */
- sound(SOUND_TELEPORT);
-
/* Move player */
teleport_player_to(y, x);
@@ -173,7 +234,7 @@ void teleport_player_directed(int rad, int dir)
if (c_ptr->feat == FEAT_SHOP)
{
/* Disturb */
- disturb(0, 0);
+ disturb();
/* Hack -- enter store */
command_new = '_';
@@ -190,13 +251,9 @@ void teleport_player_directed(int rad, int dir)
*/
void teleport_away(int m_idx, int dis)
{
- int ny = 0, nx = 0, oy, ox, d, i, min;
- int tries = 0;
-
bool_ look = TRUE;
monster_type *m_ptr = &m_list[m_idx];
- monster_race *r_ptr = race_inf(m_ptr);
if (p_ptr->resist_continuum)
{
@@ -208,13 +265,16 @@ void teleport_away(int m_idx, int dis)
if (!m_ptr->r_idx) return;
/* Save the old location */
- oy = m_ptr->fy;
- ox = m_ptr->fx;
+ const int oy = m_ptr->fy;
+ const int ox = m_ptr->fx;
/* Minimum distance */
- min = dis / 2;
+ int min = dis / 2;
/* Look until done */
+ int tries = 0;
+ int ny = 0;
+ int nx = 0;
while (look)
{
tries++;
@@ -223,14 +283,14 @@ void teleport_away(int m_idx, int dis)
if (dis > 200) dis = 200;
/* Try several locations */
- for (i = 0; i < 500; i++)
+ for (int i = 0; i < 500; i++)
{
/* Pick a (possibly illegal) location */
while (1)
{
ny = rand_spread(oy, dis);
nx = rand_spread(ox, dis);
- d = distance(oy, ox, ny, nx);
+ int d = distance(oy, ox, ny, nx);
if ((d >= min) && (d <= dis)) break;
}
@@ -249,7 +309,7 @@ void teleport_away(int m_idx, int dis)
(cave[ny][nx].feat <= FEAT_PATTERN_XTRA2)) continue;
/* No teleporting into vaults and such */
- if (!(p_ptr->inside_quest || p_ptr->inside_arena))
+ if (!(p_ptr->inside_quest))
if (cave[ny][nx].info & (CAVE_ICKY)) continue;
/* This grid looks good */
@@ -269,9 +329,6 @@ void teleport_away(int m_idx, int dis)
if (tries > MAX_TRIES) return;
}
- /* Sound */
- sound(SOUND_TPOTHER);
-
/* Update the new location */
cave[ny][nx].m_idx = m_idx;
last_teleportation_y = ny;
@@ -294,22 +351,21 @@ void teleport_away(int m_idx, int dis)
lite_spot(ny, nx);
/* Update monster light */
- if (r_ptr->flags9 & RF9_HAS_LITE) p_ptr->update |= (PU_MON_LITE);
+ auto const r_ptr = m_ptr->race();
+ if (r_ptr->flags & RF_HAS_LITE)
+ {
+ p_ptr->update |= (PU_MON_LITE);
+ }
}
/*
* Teleport monster next to the player
*/
-void teleport_to_player(int m_idx)
+static void teleport_to_player(int m_idx)
{
- int ny = 0, nx = 0, oy, ox, d, i, min;
- int dis = 2;
-
- bool_ look = TRUE;
-
monster_type *m_ptr = &m_list[m_idx];
- monster_race *r_ptr = race_inf(m_ptr);
+ auto const r_ptr = m_ptr->race();
int attempts = 500;
@@ -326,27 +382,33 @@ void teleport_to_player(int m_idx)
if (randint(100) > m_ptr->level) return;
/* Save the old location */
- oy = m_ptr->fy;
- ox = m_ptr->fx;
+ const int oy = m_ptr->fy;
+ const int ox = m_ptr->fx;
/* Minimum distance */
- min = dis / 2;
+ int dis = 2;
+ int min = dis / 2;
+
+ /* End destination */
+ int ny = 0;
+ int nx = 0;
/* Look until done */
+ bool_ look = TRUE;
while (look && --attempts)
{
/* Verify max distance */
if (dis > 200) dis = 200;
/* Try several locations */
- for (i = 0; i < 500; i++)
+ for (int i = 0; i < 500; i++)
{
/* Pick a (possibly illegal) location */
while (1)
{
ny = rand_spread(p_ptr->py, dis);
nx = rand_spread(p_ptr->px, dis);
- d = distance(p_ptr->py, p_ptr->px, ny, nx);
+ const int d = distance(p_ptr->py, p_ptr->px, ny, nx);
if ((d >= min) && (d <= dis)) break;
}
@@ -383,9 +445,6 @@ void teleport_to_player(int m_idx)
if (attempts < 1) return;
- /* Sound */
- sound(SOUND_TPOTHER);
-
/* Update the new location */
cave[ny][nx].m_idx = m_idx;
last_teleportation_y = ny;
@@ -408,7 +467,7 @@ void teleport_to_player(int m_idx)
lite_spot(ny, nx);
/* Update monster light */
- if (r_ptr->flags9 & RF9_HAS_LITE) p_ptr->update |= (PU_MON_LITE);
+ if (r_ptr->flags & RF_HAS_LITE) p_ptr->update |= (PU_MON_LITE);
}
@@ -447,7 +506,7 @@ void teleport_player(int dis)
return;
}
- if ((dungeon_flags2 & DF2_NO_TELEPORT) && (!teleport_player_bypass))
+ if ((dungeon_flags & DF_NO_TELEPORT) && (!teleport_player_bypass))
{
msg_print("No teleport on special levels...");
return;
@@ -505,9 +564,6 @@ void teleport_player(int dis)
if (tries > MAX_TRIES) return;
}
- /* Sound */
- sound(SOUND_TELEPORT);
-
/* Save the old location */
oy = p_ptr->py;
ox = p_ptr->px;
@@ -535,12 +591,9 @@ void teleport_player(int dis)
{
if (cave[oy + yy][ox + xx].m_idx)
{
- monster_race *r_ptr = race_inf(&m_list[cave[oy + yy][ox + xx].m_idx]);
+ auto const r_ptr = m_list[cave[oy + yy][ox + xx].m_idx].race();
- if ((r_ptr->flags6
- & RF6_TPORT) &&
- !(r_ptr->flags3
- & RF3_RES_TELE))
+ if ((r_ptr->spells & SF_TPORT) && !(r_ptr->flags & RF_RES_TELE))
/*
* The latter limitation is to avoid
* totally unkillable suckers...
@@ -568,8 +621,6 @@ void teleport_player(int dis)
/* Update the monsters */
p_ptr->update |= (PU_DISTANCE);
- /* Redraw trap detection status */
- p_ptr->redraw |= (PR_DTRAP);
/* Window stuff */
p_ptr->window |= (PW_OVERHEAD);
@@ -691,9 +742,6 @@ void teleport_monster_to(int m_idx, int ny, int nx)
}
}
- /* Sound */
- sound(SOUND_TPOTHER);
-
/* Save the old position */
oy = m_ptr->fy;
ox = m_ptr->fx;
@@ -739,7 +787,7 @@ void teleport_player_to(int ny, int nx)
return;
}
- if (dungeon_flags2 & DF2_NO_TELEPORT)
+ if (dungeon_flags & DF_NO_TELEPORT)
{
msg_print("No teleport on special levels...");
return;
@@ -770,9 +818,6 @@ void teleport_player_to(int ny, int nx)
}
}
- /* Sound */
- sound(SOUND_TELEPORT);
-
/* Save the old location */
oy = p_ptr->py;
ox = p_ptr->px;
@@ -798,9 +843,6 @@ void teleport_player_to(int ny, int nx)
/* Update the monsters */
p_ptr->update |= (PU_DISTANCE);
- /* Redraw trap detection status */
- p_ptr->redraw |= (PR_DTRAP);
-
/* Window stuff */
p_ptr->window |= (PW_OVERHEAD);
@@ -813,22 +855,22 @@ void teleport_player_to(int ny, int nx)
/*
* Teleport the player one level up or down (random when legal)
*/
-void teleport_player_level(void)
+void teleport_player_level()
{
/* No effect in arena or quest */
- if (p_ptr->inside_arena || p_ptr->inside_quest)
+ if (p_ptr->inside_quest)
{
msg_print("There is no effect.");
return;
}
- if (dungeon_flags2 & DF2_NO_TELEPORT)
+ if (dungeon_flags & DF_NO_TELEPORT)
{
msg_print("No teleport on special levels...");
return;
}
- if (dungeon_flags2 & DF2_NO_EASY_MOVE)
+ if (dungeon_flags & DF_NO_EASY_MOVE)
{
- msg_print("Some powerfull force prevents your from teleporting.");
+ msg_print("Some powerful force prevents your from teleporting.");
return;
}
@@ -898,9 +940,6 @@ void teleport_player_level(void)
/* Leaving */
p_ptr->leaving = TRUE;
}
-
- /* Sound */
- sound(SOUND_TPLEVEL);
}
@@ -935,10 +974,40 @@ void recall_player(int d, int f)
p_ptr->word_recall = 0;
msg_print("A tension leaves the air around you...");
}
- p_ptr->redraw |= (PR_DEPTH);
+ p_ptr->redraw |= (PR_FRAME);
}
+/*
+ * Check the gods
+ */
+static void project_check_gods(int typ)
+{
+ if (p_ptr->pgod == 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 == 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,99 +1057,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"))
- {
- /* Analyze */
- switch (type)
- {
- case GF_MISSILE:
- return (0x0F);
- case GF_ACID:
- return (0x04);
- case GF_ELEC:
- return (0x02);
- case GF_FIRE:
- return (0x00);
- case GF_COLD:
- return (0x01);
- case GF_POIS:
- return (0x03);
- case GF_UNBREATH:
- return (0x03);
- case GF_HOLY_FIRE:
- return (0x00);
- case GF_HELL_FIRE:
- return (0x00);
- case GF_MANA:
- return (0x0E);
- case GF_ARROW:
- return (0x0F);
- case GF_WATER:
- return (0x04);
- case GF_WAVE:
- return (0x04);
- case GF_NETHER:
- return (0x07);
- case GF_CHAOS:
- return (mh_attr(15));
- case GF_DISENCHANT:
- return (0x05);
- case GF_NEXUS:
- return (0x0C);
- case GF_CONFUSION:
- return (mh_attr(4));
- case GF_SOUND:
- return (0x09);
- case GF_SHARDS:
- return (0x08);
- case GF_FORCE:
- return (0x09);
- case GF_INERTIA:
- return (0x09);
- case GF_GRAVITY:
- return (0x09);
- case GF_TIME:
- return (0x09);
- case GF_LITE_WEAK:
- return (0x06);
- case GF_LITE:
- return (0x06);
- case GF_DARK_WEAK:
- return (0x07);
- case GF_DARK:
- return (0x07);
- case GF_PLASMA:
- return (0x0B);
- case GF_METEOR:
- return (0x00);
- case GF_ICE:
- return (0x01);
- case GF_ROCKET:
- return (0x0F);
- case GF_DEATH_RAY:
- return (0x07);
- case GF_NUKE:
- return (mh_attr(2));
- case GF_DISINTEGRATE:
- return (0x05);
- case GF_PSI:
- case GF_PSI_DRAIN:
- case GF_TELEKINESIS:
- case GF_DOMINATION:
- return (0x09);
- }
-
- }
-
- /* Normal tiles or ASCII */
- else
{
/* Analyze */
switch (type)
@@ -1161,6 +1137,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;
}
}
@@ -1219,16 +1200,18 @@ static u16b bolt_pict(int y, int x, int ny, int nx, int typ)
*/
void spellbinder_trigger()
{
- int i;
+ auto spellbinder = &p_ptr->spellbinder;
cmsg_print(TERM_L_GREEN, "The spellbinder is triggered!");
- for (i = 0; i < p_ptr->spellbinder_num; i++)
+
+ for (auto spell_idx: spellbinder->spell_idxs)
{
- 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]));
+ msg_format("Triggering spell %s.", spell_type_name(spell_at(spell_idx)));
+ lua_cast_school_spell(spell_idx, TRUE);
}
- p_ptr->spellbinder_num = 0;
- p_ptr->spellbinder_trigger = 0;
+
+ spellbinder->spell_idxs.clear();
+ spellbinder->trigger = 0;
}
@@ -1251,14 +1234,14 @@ void take_hit(int damage, cptr hit_from)
char death_message[80];
- int warning = (p_ptr->mhp * hitpoint_warn / 10);
+ int warning = (p_ptr->mhp * options->hitpoint_warn / 10);
int percent;
/* Paranoia */
if (death) return;
/* Disturb */
- disturb(1, 0);
+ disturb();
/* Apply "invulnerability" */
if (p_ptr->invuln && (damage < 9000))
@@ -1289,27 +1272,27 @@ void take_hit(int damage, cptr hit_from)
}
/* Display the mana */
- p_ptr->redraw |= (PR_MANA);
+ p_ptr->redraw |= (PR_FRAME);
}
/* Hurt the wielded monster if any */
if ((o_ptr->k_idx) && (magik(5 + get_skill(SKILL_SYMBIOTIC))) && (!carried_monster_hit))
{
- cptr sym_name = symbiote_name(TRUE);
+ auto sym_name = symbiote_name(true);
if (o_ptr->pval2 - damage <= 0)
{
cmsg_format(TERM_L_RED,
"%s dies from protecting you, you feel very sad...",
- sym_name);
+ sym_name.c_str());
inc_stack_size_ex(INVEN_CARRY, -1, OPTIMIZE, NO_DESCRIBE);
damage -= o_ptr->pval2;
o_ptr->pval2 = 0;
- p_ptr->redraw |= PR_MH;
+ p_ptr->redraw |= PR_FRAME;
}
else
{
- msg_format("%s takes the damage instead of you.", sym_name);
+ msg_format("%s takes the damage instead of you.", sym_name.c_str());
o_ptr->pval2 -= damage;
monster_take = TRUE;
}
@@ -1317,14 +1300,14 @@ void take_hit(int damage, cptr hit_from)
carried_monster_hit = FALSE;
/* Display the monster hitpoints */
- p_ptr->redraw |= (PR_MH);
+ p_ptr->redraw |= (PR_FRAME);
}
/* Hurt the player */
if (!monster_take) p_ptr->chp -= damage;
/* Display the hitpoints */
- p_ptr->redraw |= (PR_HP);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
@@ -1336,27 +1319,26 @@ void take_hit(int damage, cptr hit_from)
if (p_ptr->chp < 0)
{
/* Necromancers get a special treatment */
- if (((!has_ability(AB_UNDEAD_FORM)) || ((p_ptr->necro_extra & CLASS_UNDEAD))))
+ if (((!p_ptr->has_ability(AB_UNDEAD_FORM)) || ((p_ptr->necro_extra & CLASS_UNDEAD))))
{
- /* Sound */
- sound(SOUND_DEATH);
-
/* Hack -- Note death */
- if (!last_words)
+ if (!options->last_words)
{
cmsg_print(TERM_RED, "You die.");
msg_print(NULL);
}
else
{
- (void)get_rnd_line("death.txt", death_message);
+ get_rnd_line("death.txt", death_message);
cmsg_print(TERM_RED, death_message);
}
/* Note cause of death */
- (void)strcpy(died_from, hit_from);
-
- if (p_ptr->image) strcat(died_from, "(?)");
+ game->died_from = hit_from;
+ if (p_ptr->image)
+ {
+ game->died_from = "(?)";
+ }
/* Leaving */
p_ptr->leaving = TRUE;
@@ -1394,7 +1376,7 @@ void take_hit(int damage, cptr hit_from)
do_cmd_wiz_cure_all();
/* Display the hitpoints */
- p_ptr->redraw |= (PR_HP);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
@@ -1405,9 +1387,10 @@ void take_hit(int damage, cptr hit_from)
if (p_ptr->chp < warning)
{
/* Hack -- bell on first notice */
- if (alert_hitpoint && (old_chp > warning)) bell();
-
- sound(SOUND_WARN);
+ if (old_chp > warning)
+ {
+ bell();
+ }
/* Message */
if (p_ptr->necro_extra & CLASS_UNDEAD)
@@ -1421,29 +1404,34 @@ void take_hit(int damage, cptr hit_from)
percent = p_ptr->chp * 100 / p_ptr->mhp;
/* Check the spellbinder trigger */
- if (p_ptr->spellbinder_trigger == SPELLBINDER_HP75)
+ switch (p_ptr->spellbinder.trigger)
{
- /* Trigger ?! */
- if (percent <= 75)
- spellbinder_trigger();
- }
- else if (p_ptr->spellbinder_trigger == SPELLBINDER_HP50)
- {
- /* Trigger ?! */
- if (percent <= 50)
- spellbinder_trigger();
- }
- else if (p_ptr->spellbinder_trigger == SPELLBINDER_HP25)
- {
- /* Trigger ?! */
- if (percent <= 25)
- spellbinder_trigger();
+ case SPELLBINDER_HP75:
+ if (percent <= 75)
+ {
+ spellbinder_trigger();
+ }
+ break;
+
+ case SPELLBINDER_HP50:
+ if (percent <= 50)
+ {
+ spellbinder_trigger();
+ }
+ break;
+
+ case SPELLBINDER_HP25:
+ if (percent <= 25)
+ {
+ spellbinder_trigger();
+ }
+ break;
}
/* Melkor acn summon to help you */
if (percent < 25)
{
- PRAY_GOD(GOD_MELKOR)
+ if (praying_to(GOD_MELKOR))
{
int chance = p_ptr->grace / 500; /* * 100 / 50000; */
@@ -1472,8 +1460,10 @@ void take_hit(int damage, cptr hit_from)
}
}
- if (player_char_health)
+ if (options->player_char_health)
+ {
lite_spot(p_ptr->py, p_ptr->px);
+ }
}
@@ -1484,21 +1474,21 @@ void take_sanity_hit(int damage, cptr hit_from)
char death_message[80];
- int warning = (p_ptr->msane * hitpoint_warn / 10);
+ int warning = (p_ptr->msane * options->hitpoint_warn / 10);
/* Paranoia */
if (death) return;
/* Disturb */
- disturb(1, 0);
+ disturb();
/* Hurt the player */
p_ptr->csane -= damage;
/* Display the hitpoints */
- p_ptr->redraw |= (PR_SANITY);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
@@ -1506,26 +1496,25 @@ void take_sanity_hit(int damage, cptr hit_from)
/* Dead player */
if (p_ptr->csane < 0)
{
- /* Sound */
- sound(SOUND_DEATH);
-
/* Hack -- Note death */
cmsg_print(TERM_VIOLET, "You turn into an unthinking vegetable.");
- if (!last_words)
+ if (!options->last_words)
{
cmsg_print(TERM_RED, "You die.");
msg_print(NULL);
}
else
{
- (void)get_rnd_line("death.txt", death_message);
+ get_rnd_line("death.txt", death_message);
cmsg_print(TERM_RED, death_message);
}
/* Note cause of death */
- (void)strcpy(died_from, hit_from);
-
- if (p_ptr->image) strcat(died_from, "(?)");
+ game->died_from = hit_from;
+ if (p_ptr->image)
+ {
+ game->died_from = "(?)";
+ }
/* Leaving */
p_ptr->leaving = TRUE;
@@ -1546,9 +1535,10 @@ void take_sanity_hit(int damage, cptr hit_from)
if (p_ptr->csane < warning)
{
/* Hack -- bell on first notice */
- if (alert_hitpoint && (old_csane > warning)) bell();
-
- sound(SOUND_WARN);
+ if (old_csane > warning)
+ {
+ bell();
+ }
/* Message */
cmsg_print(TERM_RED, "*** LOW SANITY WARNING! ***");
@@ -1727,12 +1717,10 @@ static bool_ hates_cold(object_type *o_ptr)
*/
static int set_acid_destroy(object_type *o_ptr)
{
- u32b f1, f2, f3, f4, f5, esp;
-
if (!hates_acid(o_ptr)) return (FALSE);
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
- if (f3 & (TR3_IGNORE_ACID)) return (FALSE);
+ auto const f = object_flags(o_ptr);
+ if (f & TR_IGNORE_ACID) return (FALSE);
return (TRUE);
}
@@ -1742,12 +1730,10 @@ static int set_acid_destroy(object_type *o_ptr)
*/
static int set_elec_destroy(object_type *o_ptr)
{
- u32b f1, f2, f3, f4, f5, esp;
-
if (!hates_elec(o_ptr)) return (FALSE);
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
- if (f3 & (TR3_IGNORE_ELEC)) return (FALSE);
+ auto const f = object_flags(o_ptr);
+ if (f & TR_IGNORE_ELEC) return (FALSE);
return (TRUE);
}
@@ -1757,12 +1743,10 @@ static int set_elec_destroy(object_type *o_ptr)
*/
static int set_fire_destroy(object_type *o_ptr)
{
- u32b f1, f2, f3, f4, f5, esp;
-
if (!hates_fire(o_ptr)) return (FALSE);
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
- if (f3 & (TR3_IGNORE_FIRE)) return (FALSE);
+ auto const f = object_flags(o_ptr);
+ if (f & TR_IGNORE_FIRE) return (FALSE);
return (TRUE);
}
@@ -1772,12 +1756,10 @@ static int set_fire_destroy(object_type *o_ptr)
*/
static int set_cold_destroy(object_type *o_ptr)
{
- u32b f1, f2, f3, f4, f5, esp;
-
if (!hates_cold(o_ptr)) return (FALSE);
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
- if (f3 & (TR3_IGNORE_COLD)) return (FALSE);
+ auto const f = object_flags(o_ptr);
+ if (f & (TR_IGNORE_COLD)) return (FALSE);
return (TRUE);
}
@@ -1797,6 +1779,8 @@ typedef int (*inven_func)(object_type *);
*/
static int inven_damage(inven_func typ, int perc)
{
+ auto const &k_info = game->edit_data.k_info;
+
int i, j, k, amt;
object_type *o_ptr;
@@ -1816,7 +1800,7 @@ static int inven_damage(inven_func typ, int perc)
if (!o_ptr->k_idx) continue;
/* Hack -- for now, skip artifacts */
- if (artifact_p(o_ptr) || o_ptr->art_name) continue;
+ if (artifact_p(o_ptr)) continue;
/* Give this item slot a shot at death */
if ((*typ)(o_ptr))
@@ -1843,8 +1827,8 @@ static int inven_damage(inven_func typ, int perc)
/* Potions smash open */
if (k_info[o_ptr->k_idx].tval == TV_POTION)
- {
- (void)potion_smash_effect(0, p_ptr->py, p_ptr->px, o_ptr->sval);
+ {
+ potion_smash_effect(0, p_ptr->py, p_ptr->px, o_ptr->sval);
}
/*
@@ -1881,12 +1865,10 @@ static int inven_damage(inven_func typ, int perc)
*
* If any armor is damaged (or resists), the player takes less damage.
*/
-static int minus_ac(void)
+static int minus_ac()
{
object_type *o_ptr = NULL;
- u32b f1, f2, f3, f4, f5, esp;
-
char o_name[80];
@@ -1924,10 +1906,10 @@ static int minus_ac(void)
object_desc(o_name, o_ptr, FALSE, 0);
/* Extract the flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ auto const flags = object_flags(o_ptr);
/* Object resists */
- if (f3 & (TR3_IGNORE_ACID))
+ if (flags & TR_IGNORE_ACID)
{
msg_format("Your %s is unaffected!", o_name);
@@ -1967,7 +1949,7 @@ void acid_dam(int dam, cptr kb_str)
if ((!(p_ptr->oppose_acid || p_ptr->resist_acid)) &&
randint(HURT_CHANCE) == 1)
- (void) do_dec_stat(A_CHR, STAT_DEC_NORMAL);
+ do_dec_stat(A_CHR, STAT_DEC_NORMAL);
/* If any armor gets hit, defend the player */
if (minus_ac()) dam = (dam + 1) / 2;
@@ -1997,7 +1979,7 @@ void elec_dam(int dam, cptr kb_str)
if ((!(p_ptr->oppose_elec || p_ptr->resist_elec)) &&
randint(HURT_CHANCE) == 1)
- (void) do_dec_stat(A_DEX, STAT_DEC_NORMAL);
+ do_dec_stat(A_DEX, STAT_DEC_NORMAL);
/* Take damage */
take_hit(dam, kb_str);
@@ -2027,7 +2009,7 @@ void fire_dam(int dam, cptr kb_str)
if ((!(p_ptr->oppose_fire || p_ptr->resist_fire)) &&
randint(HURT_CHANCE) == 1)
- (void) do_dec_stat(A_STR, STAT_DEC_NORMAL);
+ do_dec_stat(A_STR, STAT_DEC_NORMAL);
/* Take damage */
@@ -2055,7 +2037,7 @@ void cold_dam(int dam, cptr kb_str)
if ((!(p_ptr->oppose_cold || p_ptr->resist_cold)) &&
randint(HURT_CHANCE) == 1)
- (void) do_dec_stat(A_STR, STAT_DEC_NORMAL);
+ do_dec_stat(A_STR, STAT_DEC_NORMAL);
/* Take damage */
take_hit(dam, kb_str);
@@ -2067,75 +2049,6 @@ void cold_dam(int dam, cptr kb_str)
-
-
-/*
- * Increases a stat by one randomized level -RAK-
- *
- * Note that this function (used by stat potions) now restores
- * the stat BEFORE increasing it.
- */
-bool_ inc_stat(int stat)
-{
- int value, gain;
-
- /* Then augment the current/max stat */
- value = p_ptr->stat_cur[stat];
-
- /* Cannot go above 18/100 */
- if (value < 18 + 100)
- {
- /* Gain one (sometimes two) points */
- if (value < 18)
- {
- gain = ((rand_int(100) < 75) ? 1 : 2);
- value += gain;
- }
-
- /* Gain 1/6 to 1/3 of distance to 18/100 */
- else if (value < 18 + 98)
- {
- /* Approximate gain value */
- gain = (((18 + 100) - value) / 2 + 3) / 2;
-
- /* Paranoia */
- if (gain < 1) gain = 1;
-
- /* Apply the bonus */
- value += randint(gain) + gain / 2;
-
- /* Maximal value */
- if (value > 18 + 99) value = 18 + 99;
- }
-
- /* Gain one point at a time */
- else
- {
- value++;
- }
-
- /* Save the new value */
- p_ptr->stat_cur[stat] = value;
-
- /* Bring up the maximum too */
- if (value > p_ptr->stat_max[stat])
- {
- p_ptr->stat_max[stat] = value;
- }
-
- /* Recalculate bonuses */
- p_ptr->update |= (PU_BONUS);
-
- /* Success */
- return (TRUE);
- }
-
- /* Nothing to gain */
- return (FALSE);
-}
-
-
-
/*
* Decreases a stat by an amount indended to vary from 0 to 100 percent.
*
@@ -2403,7 +2316,7 @@ bool_ apply_disenchant(int mode)
/* Artifacts have 71% chance to resist */
- if ((artifact_p(o_ptr) || o_ptr->art_name) && (rand_int(100) < 71))
+ if (artifact_p(o_ptr) && (rand_int(100) < 71))
{
/* Message */
msg_format("Your %s (%c) resist%s disenchantment!",
@@ -2443,7 +2356,7 @@ bool_ apply_disenchant(int mode)
}
-void corrupt_player(void)
+void corrupt_player()
{
int max1, cur1, max2, cur2, ii, jj;
@@ -2472,7 +2385,7 @@ static void apply_nexus(monster_type *m_ptr)
{
if (m_ptr == NULL) return;
- if (!(dungeon_flags2 & DF2_NO_TELEPORT))
+ if (!(dungeon_flags & DF_NO_TELEPORT))
{
switch (randint(7))
{
@@ -2633,13 +2546,14 @@ int get_mana_path_dir(int y, int x, int oy, int ox, int pdir, int mana)
* is defined as "MAX(dy,dx) + MIN(dy,dx)/2", which means that the player
* actually has an "octagon of projection" not a "circle of projection".
*
- * The path grids are saved into the grid array pointed to by "gp", and
- * there should be room for at least "range" grids in "gp". Note that
- * due to the way in which distance is calculated, this function normally
- * uses fewer than "range" grids for the projection path, so the result
- * of this function should never be compared directly to "range". Note
- * that the initial grid (y1,x1) is never saved into the grid array, not
- * even if the initial grid is also the final grid. XXX XXX XXX
+ * This function returns the coordinates of all the grids on the path.
+ * The returned vector will be empty if and only if (y1,x1) and (y2,x2) are
+ * equal. Note that due to the way in which distance is calculated, this
+ * function normally uses fewer than "range" grids for the projection
+ * path, so the size of the result of this function should never be
+ * compared directly to "range". Note that the initial grid (y1,x1) is
+ * never saved into the returned grid array, not even if the initial grid
+ * is also the final grid.
*
* The "flg" flags can be used to modify the behavior of this function.
*
@@ -2655,18 +2569,16 @@ int get_mana_path_dir(int y, int x, int oy, int ox, int pdir, int mana)
* This flag is non-trivial and has not yet been implemented, but could
* perhaps make use of the "vinfo" array (above). XXX XXX XXX
*
- * This function returns the number of grids (if any) in the path. This
- * function will return zero if and only if (y1,x1) and (y2,x2) are equal.
- *
* This algorithm is similar to, but slightly different from, the one used
* by "update_view_los()", and very different from the one used by "los()".
*/
-sint project_path(u16b *gp, int range, int y1, int x1, int y2, int x2, int flg)
+static std::vector<std::tuple<int, int>> project_path(unsigned int range, int y1, int x1, int y2, int x2, int flg)
{
int y, x, mana = 0, dir = 0;
- int n = 0;
- int k = 0;
+ /* Output grids */
+ std::vector<std::tuple<int, int>> gp;
+ gp.reserve(range + 10);
/* Absolute */
int ay, ax;
@@ -2685,7 +2597,10 @@ sint project_path(u16b *gp, int range, int y1, int x1, int y2, int x2, int flg)
/* No path necessary (or allowed) */
- if ((x1 == x2) && (y1 == y2)) return (0);
+ if ((x1 == x2) && (y1 == y2))
+ {
+ return gp;
+ }
/* Hack -- to make a bolt/beam/ball follow a mana path */
if (flg & PROJECT_MANA_PATH)
@@ -2704,23 +2619,33 @@ sint project_path(u16b *gp, int range, int y1, int x1, int y2, int x2, int flg)
while (1)
{
/* Save grid */
- gp[n++] = GRID(y, x);
+ gp.push_back(std::make_tuple(y, x));
/* Hack -- Check maximum range */
- if (n >= range + 10) return n;
+ if (gp.size() >= range + 10)
+ {
+ return gp;
+ }
/* Always stop at non-initial wall grids */
- if ((n > 0) && (!cave_sight_bold(y, x) || !cave_floor_bold(y, x))) return n;
+ if ((!cave_sight_bold(y, x) || !cave_floor_bold(y, x)))
+ {
+ return gp;
+ }
/* Sometimes stop at non-initial monsters/players */
- if (flg & (PROJECT_STOP))
+ if ((flg & (PROJECT_STOP)) && (cave[y][x].m_idx != 0))
{
- if ((n > 0) && (cave[y][x].m_idx != 0)) return n;
+ return gp;
}
/* Get the new direction */
dir = get_mana_path_dir(y, x, oy, ox, pdir, mana);
- if (dir == 5) return n;
+ if (dir == 5)
+ {
+ return gp;
+ }
+
oy = y;
ox = x;
y += ddy[dir];
@@ -2773,28 +2698,37 @@ sint project_path(u16b *gp, int range, int y1, int x1, int y2, int x2, int flg)
y = y1 + sy;
x = x1;
+ /* Counter for distance calculation */
+ int k = 0;
+
/* Create the projection path */
while (1)
{
/* Save grid */
- gp[n++] = GRID(y, x);
+ gp.push_back(std::make_tuple(y, x));
/* Hack -- Check maximum range */
- if ((n + (k >> 1)) >= range) break;
+ if ((gp.size() + (k >> 1)) >= range)
+ {
+ break;
+ }
/* Sometimes stop at destination grid */
- if (!(flg & (PROJECT_THRU)))
+ if (!(flg & (PROJECT_THRU)) && (x == x2) && (y == y2))
{
- if ((x == x2) && (y == y2)) break;
+ break;
}
/* Always stop at non-initial wall grids */
- if ((n > 0) && (!cave_sight_bold(y, x) || !cave_floor_bold(y, x)) && !(flg & PROJECT_WALL)) break;
+ if ((!cave_sight_bold(y, x) || !cave_floor_bold(y, x)) && !(flg & PROJECT_WALL))
+ {
+ break;
+ }
/* Sometimes stop at non-initial monsters/players */
- if (flg & (PROJECT_STOP))
+ if ((flg & (PROJECT_STOP)) && (cave[y][x].m_idx != 0))
{
- if ((n > 0) && (cave[y][x].m_idx != 0)) break;
+ break;
}
/* Slant */
@@ -2835,28 +2769,37 @@ sint project_path(u16b *gp, int range, int y1, int x1, int y2, int x2, int flg)
y = y1;
x = x1 + sx;
+ /* Counter for distance calculation */
+ int k = 0;
+
/* Create the projection path */
while (1)
{
/* Save grid */
- gp[n++] = GRID(y, x);
+ gp.push_back(std::make_tuple(y, x));
/* Hack -- Check maximum range */
- if ((n + (k >> 1)) >= range) break;
+ if ((gp.size() + (k >> 1)) >= range)
+ {
+ break;
+ }
/* Sometimes stop at destination grid */
- if (!(flg & (PROJECT_THRU)))
+ if (!(flg & (PROJECT_THRU)) && (x == x2) && (y == y2))
{
- if ((x == x2) && (y == y2)) break;
+ break;
}
/* Always stop at non-initial wall grids */
- if ((n > 0) && (!cave_sight_bold(y, x) || !cave_floor_bold(y, x)) && !(flg & PROJECT_WALL)) break;
+ if ((!cave_sight_bold(y, x) || !cave_floor_bold(y, x)) && !(flg & PROJECT_WALL))
+ {
+ break;
+ }
/* Sometimes stop at non-initial monsters/players */
- if (flg & (PROJECT_STOP))
+ if ((flg & (PROJECT_STOP)) && (cave[y][x].m_idx != 0))
{
- if ((n > 0) && (cave[y][x].m_idx != 0)) break;
+ break;
}
/* Slant */
@@ -2895,24 +2838,30 @@ sint project_path(u16b *gp, int range, int y1, int x1, int y2, int x2, int flg)
while (1)
{
/* Save grid */
- gp[n++] = GRID(y, x);
+ gp.push_back(std::make_tuple(y, x));
/* Hack -- Check maximum range */
- if ((n + (n >> 1)) >= range) break;
+ if ((gp.size() + (gp.size() >> 1)) >= range)
+ {
+ break;
+ }
/* Sometimes stop at destination grid */
- if (!(flg & (PROJECT_THRU)))
+ if (!(flg & (PROJECT_THRU)) && (x == x2) && (y == y2))
{
- if ((x == x2) && (y == y2)) break;
+ break;
}
/* Always stop at non-initial wall grids */
- if ((n > 0) && (!cave_sight_bold(y, x) || !cave_floor_bold(y, x)) && !(flg & PROJECT_WALL)) break;
+ if ((!cave_sight_bold(y, x) || !cave_floor_bold(y, x)) && !(flg & PROJECT_WALL))
+ {
+ break;
+ }
/* Sometimes stop at non-initial monsters/players */
- if (flg & (PROJECT_STOP))
+ if ((flg & (PROJECT_STOP)) && (cave[y][x].m_idx != 0))
{
- if ((n > 0) && (cave[y][x].m_idx != 0)) break;
+ break;
}
/* Advance (Y) */
@@ -2923,9 +2872,8 @@ sint project_path(u16b *gp, int range, int y1, int x1, int y2, int x2, int flg)
}
}
-
- /* Length */
- return (n);
+ /* Done */
+ return gp;
}
@@ -2958,6 +2906,7 @@ static int project_m_y;
static bool_ project_f(int who, int r, int y, int x, int dam, int typ)
{
cave_type *c_ptr = &cave[y][x];
+ auto const &f_info = game->edit_data.f_info;
bool_ obvious = FALSE;
@@ -2975,6 +2924,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)
{
@@ -3024,12 +2976,12 @@ static bool_ project_f(int who, int r, int y, int x, int dam, int typ)
* the conditional... -- pelpel
*/
if (!cave_plain_floor_bold(y, x) ||
- (f_info[cave[y][x].feat].flags1 & FF1_PERMANENT)) break;
+ (f_info[cave[y][x].feat].flags & FF_PERMANENT)) break;
/* Destination shouldn't be "interesting" either */
while (tries &&
(!cave_plain_floor_bold(y2, x2) ||
- (f_info[cave[y2][x2].feat].flags1 & FF1_PERMANENT)))
+ (f_info[cave[y2][x2].feat].flags & FF_PERMANENT)))
{
y2 = y1 = randint(cur_hgt) - 1;
x2 = x1 = randint(cur_wid) - 1;
@@ -3070,7 +3022,7 @@ static bool_ project_f(int who, int r, int y, int x, int dam, int typ)
case GF_HELL_FIRE:
{
/* "Permanent" features will stay */
- if ((f_info[c_ptr->feat].flags1 & FF1_PERMANENT)) break;
+ if ((f_info[c_ptr->feat].flags & FF_PERMANENT)) break;
/* Trees *will* burn */
if (c_ptr->feat == FEAT_TREES)
@@ -3109,7 +3061,7 @@ static bool_ project_f(int who, int r, int y, int x, int dam, int typ)
}
/* Floors can become ash or lava (chance == 25%) */
- else if (f_info[c_ptr->feat].flags1 & FF1_FLOOR)
+ else if (f_info[c_ptr->feat].flags & FF_FLOOR)
{
int k = rand_int(100);
@@ -3156,7 +3108,7 @@ static bool_ project_f(int who, int r, int y, int x, int dam, int typ)
int k;
/* "Permanent" features will stay */
- if ((f_info[c_ptr->feat].flags1 & FF1_PERMANENT)) break;
+ if ((f_info[c_ptr->feat].flags & FF_PERMANENT)) break;
/* Needs more than 30 damage */
if (dam < 30) break;
@@ -3225,7 +3177,7 @@ static bool_ project_f(int who, int r, int y, int x, int dam, int typ)
case GF_NUKE:
{
/* "Permanent" features will stay */
- if ((f_info[c_ptr->feat].flags1 & FF1_PERMANENT)) break;
+ if ((f_info[c_ptr->feat].flags & FF_PERMANENT)) break;
if ((c_ptr->feat == FEAT_TREES) ||
(c_ptr->feat == FEAT_SMALL_TREES))
@@ -3245,11 +3197,11 @@ static bool_ project_f(int who, int r, int y, int x, int dam, int typ)
case GF_DISINTEGRATE:
{
/* "Permanent" features will stay */
- if ((f_info[c_ptr->feat].flags1 & FF1_PERMANENT)) break;
+ if ((f_info[c_ptr->feat].flags & FF_PERMANENT)) break;
if (((c_ptr->feat == FEAT_TREES) ||
(c_ptr->feat == FEAT_SMALL_TREES) ||
- (f_info[c_ptr->feat].flags1 & FF1_FLOOR)) &&
+ (f_info[c_ptr->feat].flags & FF_FLOOR)) &&
(rand_int(100) < 30))
{
/* Flow change */
@@ -3270,71 +3222,12 @@ static bool_ project_f(int who, int r, int y, int x, int dam, int typ)
break;
}
- /* Destroy Traps (and Locks) */
- case GF_KILL_TRAP:
- {
- /* Destroy normal traps and disarm monster traps */
- if ((c_ptr->t_idx != 0) || (c_ptr->feat == FEAT_MON_TRAP))
- {
- /* Check line of sight */
- if (player_has_los_bold(y, x))
- {
- msg_print("There is a bright flash of light!");
- obvious = TRUE;
- }
-
- /* Forget the trap */
- c_ptr->info &= ~(CAVE_MARK | CAVE_TRDT);
-
- /* Destroy normal traps */
- c_ptr->t_idx = 0;
-
- /* Disarm monster traps */
- if (c_ptr->feat == FEAT_MON_TRAP)
- {
- c_ptr->special = c_ptr->special2 = 0;
-
- /* Remove the feature */
- if (!(f_info[c_ptr->feat].flags1 & FF1_PERMANENT))
- place_floor_convert_glass(y, x);
- }
-
- /* Hack -- Force redraw */
- note_spot(y, x);
- lite_spot(y, x);
- }
-
- /* Secret / Locked doors are found and unlocked */
- else if ((c_ptr->feat == FEAT_SECRET) ||
- ((c_ptr->feat >= FEAT_DOOR_HEAD + 0x01) &&
- (c_ptr->feat <= FEAT_DOOR_HEAD + 0x07)))
- {
-
- /* Check line of sound */
- if (player_has_los_bold(y, x))
- {
- msg_print("Click!");
- obvious = TRUE;
- }
-
- /* Remove feature mimic */
- cave[y][x].mimic = 0;
-
- /* Unlock the door */
- cave_set_feat(y, x, FEAT_DOOR_HEAD + 0x00);
- }
-
- break;
- }
-
- /* Destroy Doors (and traps) */
+ /* Destroy Doors */
case GF_KILL_DOOR:
{
- /* Destroy all doors and traps, and disarm monster traps */
+ /* Destroy all doors */
if ((c_ptr->feat == FEAT_OPEN) ||
(c_ptr->feat == FEAT_BROKEN) ||
- (c_ptr->t_idx != 0) ||
- (c_ptr->feat == FEAT_MON_TRAP) ||
((c_ptr->feat >= FEAT_DOOR_HEAD) &&
(c_ptr->feat <= FEAT_DOOR_TAIL)))
{
@@ -3355,17 +3248,10 @@ static bool_ project_f(int who, int r, int y, int x, int dam, int typ)
}
/* Forget the door */
- c_ptr->info &= ~(CAVE_MARK | CAVE_TRDT);
-
- /* Remove normal traps */
- c_ptr->t_idx = 0;
-
- /* Disarm monster traps */
- if (c_ptr->feat == FEAT_MON_TRAP)
- c_ptr->special = c_ptr->special2 = 0;
+ c_ptr->info &= ~(CAVE_MARK);
/* Remove the feature */
- if (!(f_info[c_ptr->feat].flags1 & FF1_PERMANENT))
+ if (!(f_info[c_ptr->feat].flags & FF_PERMANENT))
place_floor_convert_glass(y, x);
/* Hack -- Force redraw */
@@ -3406,7 +3292,7 @@ static bool_ project_f(int who, int r, int y, int x, int dam, int typ)
if (cave_floor_bold(y, x)) break;
/* "Permanent" features will stay */
- if ((f_info[c_ptr->feat].flags1 & FF1_PERMANENT)) break;
+ if ((f_info[c_ptr->feat].flags & FF_PERMANENT)) break;
/* Granite -- How about other wall types? */
if ((c_ptr->feat >= FEAT_WALL_EXTRA) &&
@@ -3534,7 +3420,7 @@ static bool_ project_f(int who, int r, int y, int x, int dam, int typ)
/* Require a "naked" floor grid */
if (!cave_clean_bold(y, x)) break;
- if ((f_info[c_ptr->feat].flags1 & FF1_PERMANENT)) break;
+ if ((f_info[c_ptr->feat].flags & FF_PERMANENT)) break;
/* Create a closed door */
cave_set_feat(y, x, FEAT_DOOR_HEAD + 0x00);
@@ -3548,25 +3434,12 @@ static bool_ project_f(int who, int r, int y, int x, int dam, int typ)
break;
}
- /* Make traps */
- case GF_MAKE_TRAP:
- {
- /* Require a "naked" floor grid */
- if (!cave_clean_bold(y, x)) break;
-
- /* Place a trap */
- place_trap(y, x);
-
- break;
- }
-
-
case GF_MAKE_GLYPH:
{
/* Require a "naked" floor grid */
if (!cave_clean_bold(y, x)) break;
- if ((f_info[c_ptr->feat].flags1 & FF1_PERMANENT)) break;
+ if ((f_info[c_ptr->feat].flags & FF_PERMANENT)) break;
cave_set_feat(y, x, FEAT_GLYPH);
@@ -3582,8 +3455,8 @@ static bool_ project_f(int who, int r, int y, int x, int dam, int typ)
/* Require a "naked" floor grid */
if (!cave_clean_bold(y, x)) break;
- if ((f_info[c_ptr->feat].flags1 & FF1_PERMANENT)) break;
- if (!(f_info[c_ptr->feat].flags1 & FF1_FLOOR)) break;
+ if ((f_info[c_ptr->feat].flags & FF_PERMANENT)) break;
+ if (!(f_info[c_ptr->feat].flags & FF_FLOOR)) break;
/* Place a wall */
cave_set_feat(y, x, FEAT_WALL_EXTRA);
@@ -3626,7 +3499,7 @@ static bool_ project_f(int who, int r, int y, int x, int dam, int typ)
case GF_LAVA_FLOW:
{
- if ((f_info[c_ptr->feat].flags1 & FF1_PERMANENT)) break;
+ if ((f_info[c_ptr->feat].flags & FF_PERMANENT)) break;
/* Shallow Lava */
if (dam == 1)
@@ -3740,7 +3613,7 @@ static bool_ project_f(int who, int r, int y, int x, int dam, int typ)
/* Delete the monster (if any) */
delete_monster(y, x);
- if ((f_info[c_ptr->feat].flags1 & FF1_PERMANENT)) break;
+ if ((f_info[c_ptr->feat].flags & FF_PERMANENT)) break;
/* Destroy "valid" grids */
if (cave_valid_bold(y, x))
@@ -3793,16 +3666,20 @@ 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)) {
+ geomancy_random_wall(y, x);
}
break;
}
+
+ case GF_ELEMENTAL_GROWTH:
+ {
+ geomancy_random_floor(y, x, FALSE);
+ break;
+ }
}
/* Hack -- Affect player */
@@ -3815,7 +3692,7 @@ static bool_ project_f(int who, int r, int y, int x, int dam, int typ)
if (!p_ptr->resist_blind && !p_ptr->resist_lite)
{
/* Become blind */
- (void)set_blind(p_ptr->blind + 10 + randint(10));
+ set_blind(p_ptr->blind + 10 + randint(10));
}
}
@@ -3859,14 +3736,13 @@ static int raise_ego[MAX_RAISE] =
*/
static bool_ project_o(int who, int r, int y, int x, int dam, int typ)
{
- cave_type *c_ptr = &cave[y][x];
+ auto const &r_info = game->edit_data.r_info;
+ auto const &k_info = game->edit_data.k_info;
- s16b this_o_idx, next_o_idx = 0;
+ cave_type *c_ptr = &cave[y][x];
bool_ obvious = FALSE;
- u32b f1, f2, f3, f4, f5, esp;
-
char o_name[80];
int o_sval = 0;
@@ -3879,12 +3755,15 @@ 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);
+
+ /* Copy list of objects since we may destroy during iteration */
+ auto const object_idxs(c_ptr->o_idxs);
/* Scan all objects in the grid */
- for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
+ for (auto const this_o_idx: object_idxs)
{
- object_type * o_ptr;
-
bool_ is_art = FALSE;
bool_ ignore = FALSE;
bool_ plural = FALSE;
@@ -3893,19 +3772,16 @@ static bool_ project_o(int who, int r, int y, int x, int dam, int typ)
cptr note_kill = NULL;
/* Acquire object */
- o_ptr = &o_list[this_o_idx];
-
- /* Acquire next object */
- next_o_idx = o_ptr->next_o_idx;
+ object_type * o_ptr = &o_list[this_o_idx];
/* Extract the flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ auto const flags = object_flags(o_ptr);
/* Get the "plural"-ness */
if (o_ptr->number > 1) plural = TRUE;
/* Check for artifact */
- if ((artifact_p(o_ptr) || o_ptr->art_name)) is_art = TRUE;
+ if (artifact_p(o_ptr)) is_art = TRUE;
/* Analyze the type */
switch (typ)
@@ -3915,10 +3791,11 @@ static bool_ project_o(int who, int r, int y, int x, int dam, int typ)
{
if (o_ptr->tval == TV_CORPSE)
{
- monster_race *r_ptr = &r_info[o_ptr->pval2];
- s32b dama, radius = 7;
+ auto r_ptr = &r_info[o_ptr->pval2];
+ s32b radius = 7;
+ s32b dama;
- if (r_ptr->flags1 & RF1_FORCE_MAXHP)
+ if (r_ptr->flags & RF_FORCE_MAXHP)
dama = maxroll(r_ptr->hdice, r_ptr->hside);
else
dama = damroll(r_ptr->hdice, r_ptr->hside);
@@ -3943,7 +3820,7 @@ static bool_ project_o(int who, int r, int y, int x, int dam, int typ)
{
do_kill = TRUE;
note_kill = (plural ? " melt!" : " melts!");
- if (f3 & (TR3_IGNORE_ACID)) ignore = TRUE;
+ if (flags & TR_IGNORE_ACID) ignore = TRUE;
}
break;
}
@@ -3955,7 +3832,7 @@ static bool_ project_o(int who, int r, int y, int x, int dam, int typ)
{
do_kill = TRUE;
note_kill = (plural ? " are destroyed!" : " is destroyed!");
- if (f3 & (TR3_IGNORE_ELEC)) ignore = TRUE;
+ if (flags & TR_IGNORE_ELEC) ignore = TRUE;
}
break;
}
@@ -3967,7 +3844,7 @@ static bool_ project_o(int who, int r, int y, int x, int dam, int typ)
{
do_kill = TRUE;
note_kill = (plural ? " burn up!" : " burns up!");
- if (f3 & (TR3_IGNORE_FIRE)) ignore = TRUE;
+ if (flags & TR_IGNORE_FIRE) ignore = TRUE;
}
break;
}
@@ -3979,7 +3856,7 @@ static bool_ project_o(int who, int r, int y, int x, int dam, int typ)
{
note_kill = (plural ? " shatter!" : " shatters!");
do_kill = TRUE;
- if (f3 & (TR3_IGNORE_COLD)) ignore = TRUE;
+ if (flags & TR_IGNORE_COLD) ignore = TRUE;
}
break;
}
@@ -3991,14 +3868,14 @@ static bool_ project_o(int who, int r, int y, int x, int dam, int typ)
{
do_kill = TRUE;
note_kill = (plural ? " burn up!" : " burns up!");
- if (f3 & (TR3_IGNORE_FIRE)) ignore = TRUE;
+ if (flags & TR_IGNORE_FIRE) ignore = TRUE;
}
if (hates_elec(o_ptr))
{
ignore = FALSE;
do_kill = TRUE;
note_kill = (plural ? " are destroyed!" : " is destroyed!");
- if (f3 & (TR3_IGNORE_ELEC)) ignore = TRUE;
+ if (flags & TR_IGNORE_ELEC) ignore = TRUE;
}
break;
}
@@ -4010,14 +3887,14 @@ static bool_ project_o(int who, int r, int y, int x, int dam, int typ)
{
do_kill = TRUE;
note_kill = (plural ? " burn up!" : " burns up!");
- if (f3 & (TR3_IGNORE_FIRE)) ignore = TRUE;
+ if (flags & TR_IGNORE_FIRE) ignore = TRUE;
}
if (hates_cold(o_ptr))
{
ignore = FALSE;
do_kill = TRUE;
note_kill = (plural ? " shatter!" : " shatters!");
- if (f3 & (TR3_IGNORE_COLD)) ignore = TRUE;
+ if (flags & TR_IGNORE_COLD) ignore = TRUE;
}
break;
}
@@ -4055,7 +3932,7 @@ static bool_ project_o(int who, int r, int y, int x, int dam, int typ)
{
do_kill = TRUE;
note_kill = (plural ? " are destroyed!" : " is destroyed!");
- if (f2 & (TR2_RES_CHAOS)) ignore = TRUE;
+ if (flags & TR_RES_CHAOS) ignore = TRUE;
break;
}
@@ -4072,7 +3949,6 @@ static bool_ project_o(int who, int r, int y, int x, int dam, int typ)
}
/* Unlock chests */
- case GF_KILL_TRAP:
case GF_KILL_DOOR:
{
/* Chests are noticed only if trapped or locked */
@@ -4108,20 +3984,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");
-
- /* Squelch ! */
- squeltch_grid();
-
- break;
- }
- case GF_IDENTIFY:
- {
- object_aware(o_ptr);
- 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_FULL);
/* Squelch ! */
squeltch_grid();
@@ -4145,7 +4008,7 @@ static bool_ project_o(int who, int r, int y, int x, int dam, int typ)
}
case GF_RAISE_DEMON:
{
- monster_race *r_ptr = &r_info[o_ptr->pval2];
+ auto r_ptr = &r_info[o_ptr->pval2];
cptr name;
if (o_ptr->tval != TV_CORPSE) break;
@@ -4173,15 +4036,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;
}
@@ -4225,7 +4080,7 @@ static bool_ project_o(int who, int r, int y, int x, int dam, int typ)
/* Potions produce effects when 'shattered' */
if (is_potion)
{
- (void)potion_smash_effect(who, y, x, o_sval);
+ potion_smash_effect(who, y, x, o_sval);
}
@@ -4307,12 +4162,8 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
monster_type *m_ptr = &m_list[c_ptr->m_idx];
- monster_race *r_ptr = race_inf(m_ptr);
-
char killer [80];
- cptr name = (r_name + r_ptr->name);
-
/* Is the monster "seen"? */
bool_ seen;
@@ -4385,21 +4236,27 @@ 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);
+ /* Get race information */
+ auto r_ptr = m_ptr->race();
+
/* Mega Gachk */
- if (r_ptr->flags2 & RF2_DEATH_ORB)
+ if (r_ptr->flags & RF_DEATH_ORB)
{
msg_format("%^s is immune to magic.", m_name);
return seen;
}
/* Some monsters get "destroyed" */
- if ((r_ptr->flags3 & (RF3_DEMON)) ||
- (r_ptr->flags3 & (RF3_UNDEAD)) ||
- (r_ptr->flags2 & (RF2_STUPID)) ||
- (r_ptr->flags3 & (RF3_NONLIVING)) ||
+ if ((r_ptr->flags & RF_DEMON) ||
+ (r_ptr->flags & RF_UNDEAD) ||
+ (r_ptr->flags & RF_STUPID) ||
+ (r_ptr->flags & RF_NONLIVING) ||
(strchr("Evg", r_ptr->d_char)))
{
/* Special note at death */
@@ -4427,51 +4284,50 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
case GF_JAM_DOOR:
case GF_RAISE:
case GF_RAISE_DEMON:
- case GF_IDENTIFY:
break; /* none of the above anger */
case GF_TRAP_DEMONSOUL:
- if (r_ptr->flags3 & RF3_DEMON)
+ if (r_ptr->flags & RF_DEMON)
get_angry = TRUE;
break;
case GF_KILL_WALL:
- if (r_ptr->flags3 & (RF3_HURT_ROCK))
+ if (r_ptr->flags & RF_HURT_ROCK)
get_angry = TRUE;
break;
case GF_HOLY_FIRE:
- if (!(r_ptr->flags3 & (RF3_GOOD)))
+ if (!(r_ptr->flags & RF_GOOD))
get_angry = TRUE;
break;
case GF_TURN_UNDEAD:
case GF_DISP_UNDEAD:
- if (r_ptr->flags3 & RF3_UNDEAD)
+ if (r_ptr->flags & RF_UNDEAD)
get_angry = TRUE;
break;
case GF_TURN_EVIL:
case GF_DISP_EVIL:
- if (r_ptr->flags3 & RF3_EVIL)
+ if (r_ptr->flags & RF_EVIL)
get_angry = TRUE;
break;
case GF_DISP_GOOD:
- if (r_ptr->flags3 & RF3_GOOD)
+ if (r_ptr->flags & RF_GOOD)
get_angry = TRUE;
break;
case GF_DISP_DEMON:
- if (r_ptr->flags3 & RF3_DEMON)
+ if (r_ptr->flags & RF_DEMON)
get_angry = TRUE;
break;
case GF_DISP_LIVING:
case GF_UNBREATH:
- if (!(r_ptr->flags3 & (RF3_UNDEAD)) &&
- !(r_ptr->flags3 & (RF3_NONLIVING)))
+ if (!(r_ptr->flags & RF_UNDEAD) &&
+ !(r_ptr->flags & RF_NONLIVING))
get_angry = TRUE;
break;
case GF_PSI:
case GF_PSI_DRAIN:
- if (!(r_ptr->flags2 & (RF2_EMPTY_MIND)))
+ if (!(r_ptr->flags & RF_EMPTY_MIND))
get_angry = TRUE;
break;
case GF_DOMINATION:
- if (!(r_ptr->flags3 & (RF3_NO_CONF)))
+ if (!(r_ptr->flags & RF_NO_CONF))
get_angry = TRUE;
break;
case GF_OLD_POLY:
@@ -4481,17 +4337,16 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
break;
case GF_LITE:
case GF_LITE_WEAK:
- if (r_ptr->flags3 & RF3_HURT_LITE)
+ if (r_ptr->flags & RF_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 */
@@ -4526,23 +4381,12 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
break;
}
- case GF_IDENTIFY:
- {
- if (seen) obvious = TRUE;
-
- /* Probe */
- do_probe(c_ptr->m_idx);
-
- dam = 0;
- break;
- }
-
/* Death -- instant death */
case GF_DEATH:
{
if (seen) obvious = TRUE;
- if (r_ptr->r_flags1 & RF1_UNIQUE)
+ if (r_ptr->flags & RF_UNIQUE)
{
note = " resists.";
dam = 0;
@@ -4565,17 +4409,15 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
case GF_ACID:
{
if (seen) obvious = TRUE;
- if (r_ptr->flags9 & (RF9_SUSCEP_ACID))
+ if (r_ptr->flags & RF_SUSCEP_ACID)
{
note = " is hit hard.";
dam *= 3;
- if (seen) r_ptr->r_flags9 |= (RF9_SUSCEP_ACID);
}
- if (r_ptr->flags3 & (RF3_IM_ACID))
+ if (r_ptr->flags & RF_IM_ACID)
{
note = " resists a lot.";
dam /= 9;
- if (seen) r_ptr->r_flags3 |= (RF3_IM_ACID);
}
break;
}
@@ -4584,17 +4426,15 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
case GF_ELEC:
{
if (seen) obvious = TRUE;
- if (r_ptr->flags9 & (RF9_SUSCEP_ELEC))
+ if (r_ptr->flags & RF_SUSCEP_ELEC)
{
note = " is hit hard.";
dam *= 3;
- if (seen) r_ptr->r_flags9 |= (RF9_SUSCEP_ELEC);
}
- if (r_ptr->flags3 & (RF3_IM_ELEC))
+ if (r_ptr->flags & RF_IM_ELEC)
{
note = " resists a lot.";
dam /= 9;
- if (seen) r_ptr->r_flags3 |= (RF3_IM_ELEC);
}
break;
}
@@ -4603,17 +4443,15 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
case GF_FIRE:
{
if (seen) obvious = TRUE;
- if (r_ptr->flags3 & (RF3_SUSCEP_FIRE))
+ if (r_ptr->flags & RF_SUSCEP_FIRE)
{
note = " is hit hard.";
dam *= 3;
- if (seen) r_ptr->r_flags3 |= (RF3_SUSCEP_FIRE);
}
- if (r_ptr->flags3 & (RF3_IM_FIRE))
+ if (r_ptr->flags & RF_IM_FIRE)
{
note = " resists a lot.";
dam /= 9;
- if (seen) r_ptr->r_flags3 |= (RF3_IM_FIRE);
}
break;
}
@@ -4622,17 +4460,15 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
case GF_COLD:
{
if (seen) obvious = TRUE;
- if (r_ptr->flags3 & (RF3_SUSCEP_COLD))
+ if (r_ptr->flags & RF_SUSCEP_COLD)
{
note = " is hit hard.";
dam *= 3;
- if (seen) r_ptr->r_flags3 |= (RF3_SUSCEP_COLD);
}
- if (r_ptr->flags3 & (RF3_IM_COLD))
+ if (r_ptr->flags & RF_IM_COLD)
{
note = " resists a lot.";
dam /= 9;
- if (seen) r_ptr->r_flags3 |= (RF3_IM_COLD);
}
break;
}
@@ -4642,19 +4478,17 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
{
if (seen) obvious = TRUE;
if (magik(25)) do_pois = (10 + randint(11) + r) / (r + 1);
- if (r_ptr->flags9 & (RF9_SUSCEP_POIS))
+ if (r_ptr->flags & RF_SUSCEP_POIS)
{
note = " is hit hard.";
dam *= 3;
do_pois *= 2;
- if (seen) r_ptr->r_flags9 |= (RF9_SUSCEP_POIS);
}
- if (r_ptr->flags3 & (RF3_IM_POIS))
+ if (r_ptr->flags & RF_IM_POIS)
{
note = " resists a lot.";
dam /= 9;
do_pois = 0;
- if (seen) r_ptr->r_flags3 |= (RF3_IM_POIS);
}
break;
}
@@ -4665,7 +4499,7 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
{
if (seen) obvious = TRUE;
if (magik(15)) do_pois = (10 + randint(11) + r) / (r + 1);
- if ((r_ptr->flags3 & (RF3_NONLIVING)) || (r_ptr->flags3 & (RF3_UNDEAD)))
+ if ((r_ptr->flags & RF_NONLIVING) || (r_ptr->flags & RF_UNDEAD))
{
note = " is immune.";
dam = 0;
@@ -4679,12 +4513,11 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
{
if (seen) obvious = TRUE;
- if (r_ptr->flags3 & (RF3_IM_POIS))
+ if (r_ptr->flags & RF_IM_POIS)
{
note = " resists.";
dam *= 3;
dam /= (randint(6) + 6);
- if (seen) r_ptr->r_flags3 |= (RF3_IM_POIS);
}
else if (randint(3) == 1) do_poly = TRUE;
break;
@@ -4694,11 +4527,10 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
case GF_HELL_FIRE:
{
if (seen) obvious = TRUE;
- if (r_ptr->flags3 & (RF3_EVIL))
+ if (r_ptr->flags & RF_EVIL)
{
dam *= 2;
note = " is hit hard.";
- if (seen) r_ptr->r_flags3 |= (RF3_EVIL);
}
break;
}
@@ -4707,17 +4539,15 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
case GF_HOLY_FIRE:
{
if (seen) obvious = TRUE;
- if (r_ptr->flags3 & (RF3_GOOD))
+ if (r_ptr->flags & RF_GOOD)
{
dam = 0;
note = " is immune.";
- if (seen) r_ptr->r_flags3 |= (RF3_GOOD);
}
- else if (r_ptr->flags3 & (RF3_EVIL))
+ else if (r_ptr->flags & RF_EVIL)
{
dam *= 2;
note = " is hit hard.";
- if (seen) r_ptr->r_flags3 |= (RF3_EVIL);
}
else
{
@@ -4739,13 +4569,11 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
case GF_PLASMA:
{
if (seen) obvious = TRUE;
- if (r_ptr->flags3 & (RF3_RES_PLAS))
+ if (r_ptr->flags & RF_RES_PLAS)
{
note = " resists.";
dam *= 3;
dam /= (randint(6) + 6);
- if (seen)
- r_ptr->r_flags3 |= (RF3_RES_PLAS);
}
break;
}
@@ -4754,25 +4582,21 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
case GF_NETHER:
{
if (seen) obvious = TRUE;
- if (r_ptr->flags3 & (RF3_UNDEAD))
+ if (r_ptr->flags & RF_UNDEAD)
{
note = " is immune.";
dam = 0;
- if (seen) r_ptr->r_flags3 |= (RF3_UNDEAD);
}
- else if (r_ptr->flags3 & (RF3_RES_NETH))
+ else if (r_ptr->flags & RF_RES_NETH)
{
note = " resists.";
dam *= 3;
dam /= (randint(6) + 6);
-
- if (seen) r_ptr->r_flags3 |= (RF3_RES_NETH);
}
- else if (r_ptr->flags3 & (RF3_EVIL))
+ else if (r_ptr->flags & RF_EVIL)
{
dam /= 2;
note = " resists somewhat.";
- if (seen) r_ptr->r_flags3 |= (RF3_EVIL);
}
break;
}
@@ -4782,18 +4606,17 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
{
if (seen) obvious = TRUE;
if ((r_ptr->d_char == 'E') &&
- (prefix(name, "W") ||
- (strstr((r_name + r_ptr->name), "Unmaker"))))
+ (prefix(r_ptr->name, "W") ||
+ (strstr(r_ptr->name, "Unmaker"))))
{
note = " is immune.";
dam = 0;
}
- else if (r_ptr->flags3 & (RF3_RES_WATE))
+ else if (r_ptr->flags & RF_RES_WATE)
{
note = " resists.";
dam *= 3;
dam /= (randint(6) + 6);
- if (seen) r_ptr->r_flags3 |= (RF3_RES_WATE);
}
break;
}
@@ -4803,18 +4626,17 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
{
if (seen) obvious = TRUE;
if ((r_ptr->d_char == 'E') &&
- (prefix(name, "W") ||
- (strstr((r_name + r_ptr->name), "Unmaker"))))
+ (prefix(r_ptr->name, "W") ||
+ (strstr(r_ptr->name, "Unmaker"))))
{
note = " is immune.";
dam = 0;
}
- else if (r_ptr->flags3 & (RF3_RES_WATE))
+ else if (r_ptr->flags & RF_RES_WATE)
{
note = " resists.";
dam *= 3;
dam /= (randint(6) + 6);
- if (seen) r_ptr->r_flags3 |= (RF3_RES_WATE);
}
if (who == 0)
@@ -4898,8 +4720,8 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
if (seen) obvious = TRUE;
do_poly = TRUE;
do_conf = (5 + randint(11) + r) / (r + 1);
- if ((r_ptr->flags4 & (RF4_BR_CHAO)) ||
- ((r_ptr->flags3 & (RF3_DEMON)) && (randint(3) == 1)))
+ if ((r_ptr->spells & SF_BR_CHAO) ||
+ ((r_ptr->flags & RF_DEMON) && (randint(3) == 1)))
{
note = " resists.";
dam *= 3;
@@ -4914,7 +4736,7 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
{
if (seen) obvious = TRUE;
if (magik(33)) do_cut = (10 + randint(15) + r) / (r + 1);
- if (r_ptr->flags4 & (RF4_BR_SHAR))
+ if (r_ptr->spells & SF_BR_SHAR)
{
note = " resists.";
dam *= 3;
@@ -4930,7 +4752,7 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
if (seen) obvious = TRUE;
if (magik(12)) do_cut = (10 + randint(15) + r) / (r + 1);
- if (r_ptr->flags4 & (RF4_BR_SHAR))
+ if (r_ptr->spells & SF_BR_SHAR)
{
note = " resists somewhat.";
dam /= 2;
@@ -4951,7 +4773,7 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
}
else
do_stun = (10 + randint(15) + r) / (r + 1);
- if (r_ptr->flags4 & (RF4_BR_SOUN))
+ if (r_ptr->spells & SF_BR_SOUN)
{
note = " resists.";
dam *= 2;
@@ -4965,13 +4787,13 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
{
if (seen) obvious = TRUE;
do_conf = (10 + randint(15) + r) / (r + 1);
- if (r_ptr->flags4 & (RF4_BR_CONF))
+ if (r_ptr->spells & SF_BR_CONF)
{
note = " resists.";
dam *= 2;
dam /= (randint(6) + 6);
}
- else if (r_ptr->flags3 & (RF3_NO_CONF))
+ else if (r_ptr->flags & RF_NO_CONF)
{
note = " resists somewhat.";
dam /= 2;
@@ -4983,12 +4805,11 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
case GF_DISENCHANT:
{
if (seen) obvious = TRUE;
- if (r_ptr->flags3 & (RF3_RES_DISE))
+ if (r_ptr->flags & RF_RES_DISE)
{
note = " resists.";
dam *= 3;
dam /= (randint(6) + 6);
- if (seen) r_ptr->r_flags3 |= (RF3_RES_DISE);
}
break;
}
@@ -4997,12 +4818,11 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
case GF_NEXUS:
{
if (seen) obvious = TRUE;
- if (r_ptr->flags3 & (RF3_RES_NEXU))
+ if (r_ptr->flags & RF_RES_NEXU)
{
note = " resists.";
dam *= 3;
dam /= (randint(6) + 6);
- if (seen) r_ptr->r_flags3 |= (RF3_RES_NEXU);
}
break;
}
@@ -5095,7 +4915,7 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
/* --hack-- Only stun if a monster fired it */
else do_stun = (randint(15) + r) / (r + 1);
- if (r_ptr->flags4 & (RF4_BR_WALL))
+ if (r_ptr->spells & SF_BR_WALL)
{
note = " resists.";
dam *= 3;
@@ -5108,7 +4928,7 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
case GF_INERTIA:
{
if (seen) obvious = TRUE;
- if (r_ptr->flags4 & (RF4_BR_INER))
+ if (r_ptr->spells & SF_BR_INER)
{
note = " resists.";
dam *= 3;
@@ -5135,7 +4955,7 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
case GF_TIME:
{
if (seen) obvious = TRUE;
- if (r_ptr->flags4 & (RF4_BR_TIME))
+ if (r_ptr->spells & SF_BR_TIME)
{
note = " resists.";
dam *= 3;
@@ -5151,17 +4971,15 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
if (seen) obvious = TRUE;
- if (r_ptr->flags3 & (RF3_RES_TELE))
+ if (r_ptr->flags & RF_RES_TELE)
{
- if (r_ptr->flags1 & (RF1_UNIQUE))
+ if (r_ptr->flags & RF_UNIQUE)
{
- if (seen) r_ptr->r_flags3 |= RF3_RES_TELE;
note = " is unaffected!";
resist_tele = TRUE;
}
else if (m_ptr->level > randint(100))
{
- if (seen) r_ptr->r_flags3 |= RF3_RES_TELE;
note = " resists!";
resist_tele = TRUE;
}
@@ -5170,7 +4988,7 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
if (!resist_tele) do_dist = 10;
else do_dist = 0;
- if (r_ptr->flags4 & (RF4_BR_GRAV))
+ if (r_ptr->spells & SF_BR_GRAV)
{
note = " resists.";
dam *= 3;
@@ -5181,7 +4999,7 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
{
/* 1. slowness */
/* Powerful monsters can resist */
- if ((r_ptr->flags1 & (RF1_UNIQUE)) ||
+ if ((r_ptr->flags & RF_UNIQUE) ||
(m_ptr->level > randint((dam - 10) < 1 ? 1 : (dam - 10)) + 10))
{
obvious = FALSE;
@@ -5197,7 +5015,7 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
do_stun = damroll((p_ptr->lev / 10) + 3 , (dam)) + 1;
/* Attempt a saving throw */
- if ((r_ptr->flags1 & (RF1_UNIQUE)) ||
+ if ((r_ptr->flags & RF_UNIQUE) ||
(m_ptr->level > randint((dam - 10) < 1 ? 1 : (dam - 10)) + 10))
{
/* Resist */
@@ -5222,15 +5040,14 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
case GF_DISINTEGRATE:
{
if (seen) obvious = TRUE;
- if (r_ptr->flags3 & (RF3_HURT_ROCK))
+ if (r_ptr->flags & RF_HURT_ROCK)
{
- if (seen) r_ptr->r_flags3 |= (RF3_HURT_ROCK);
note = " loses some skin!";
note_dies = " evaporates!";
dam *= 2;
}
- if (r_ptr->flags1 & RF1_UNIQUE)
+ if (r_ptr->flags & RF_UNIQUE)
{
if (rand_int(m_ptr->level + 10) > rand_int(p_ptr->lev))
{
@@ -5243,7 +5060,7 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
case GF_FEAR:
{
- if (r_ptr->flags3 & (RF3_NO_FEAR))
+ if (r_ptr->flags & RF_NO_FEAR)
note = " is unaffected.";
else
set_afraid(p_ptr->afraid + (dam / 2) + randint(dam / 2));
@@ -5256,14 +5073,14 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
case GF_PSI:
{
if (seen) obvious = TRUE;
- if (r_ptr->flags2 & RF2_EMPTY_MIND)
+ if (r_ptr->flags & RF_EMPTY_MIND)
{
dam = 0;
note = " is immune!";
}
- else if ((r_ptr->flags2 & RF2_STUPID) ||
- (r_ptr->flags2 & RF2_WEIRD_MIND) ||
- (r_ptr->flags3 & RF3_ANIMAL) ||
+ else if ((r_ptr->flags & RF_STUPID) ||
+ (r_ptr->flags & RF_WEIRD_MIND) ||
+ (r_ptr->flags & RF_ANIMAL) ||
(m_ptr->level > randint(3 * dam)))
{
dam /= 3;
@@ -5271,8 +5088,8 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
/* Powerful demons & undead can turn a mindcrafter's
* attacks back on them */
- if (((r_ptr->flags3 & RF3_UNDEAD) ||
- (r_ptr->flags3 & RF3_DEMON)) &&
+ if (((r_ptr->flags & RF_UNDEAD) ||
+ (r_ptr->flags & RF_DEMON)) &&
(m_ptr->level > p_ptr->lev / 2) &&
(randint(2) == 1))
{
@@ -5301,7 +5118,7 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
break;
case 3:
{
- if (r_ptr->flags3 & (RF3_NO_FEAR))
+ if (r_ptr->flags & RF_NO_FEAR)
note = " is unaffected.";
else
set_afraid(p_ptr->afraid + 3 + randint(dam));
@@ -5309,7 +5126,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));
+ set_paralyzed(randint(dam));
break;
}
}
@@ -5344,14 +5161,14 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
case GF_PSI_DRAIN:
{
if (seen) obvious = TRUE;
- if (r_ptr->flags2 & RF2_EMPTY_MIND)
+ if (r_ptr->flags & RF_EMPTY_MIND)
{
dam = 0;
note = " is immune!";
}
- else if ((r_ptr->flags2 & RF2_STUPID) ||
- (r_ptr->flags2 & RF2_WEIRD_MIND) ||
- (r_ptr->flags3 & RF3_ANIMAL) ||
+ else if ((r_ptr->flags & RF_STUPID) ||
+ (r_ptr->flags & RF_WEIRD_MIND) ||
+ (r_ptr->flags & RF_ANIMAL) ||
(m_ptr->level > randint(3 * dam)))
{
dam /= 3;
@@ -5361,8 +5178,8 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
* Powerful demons & undead can turn a mindcrafter's
* attacks back on them
*/
- if (((r_ptr->flags3 & RF3_UNDEAD) ||
- (r_ptr->flags3 & RF3_DEMON)) &&
+ if (((r_ptr->flags & RF_UNDEAD) ||
+ (r_ptr->flags & RF_DEMON)) &&
(m_ptr->level > p_ptr->lev / 2) &&
(randint(2) == 1))
{
@@ -5380,7 +5197,7 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
monster_desc(killer, m_ptr, 0x88);
msg_print("Your psychic energy is drained!");
p_ptr->csp = MAX(0, p_ptr->csp - damroll(5, dam) / 2);
- p_ptr->redraw |= PR_MANA;
+ p_ptr->redraw |= PR_FRAME;
take_hit(dam, killer); /* has already been /3 */
}
dam = 0;
@@ -5393,7 +5210,7 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
m_name, (seen ? "'s" : "s"));
b = MIN(p_ptr->msp, p_ptr->csp + b);
p_ptr->csp = b;
- p_ptr->redraw |= PR_MANA;
+ p_ptr->redraw |= PR_FRAME;
}
note_dies = " collapses, a mindless husk.";
@@ -5408,7 +5225,7 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
do_stun = damroll((p_ptr->lev / 10) + 3 , (dam)) + 1;
/* Attempt a saving throw */
- if ((r_ptr->flags1 & (RF1_UNIQUE)) ||
+ if ((r_ptr->flags & RF_UNIQUE) ||
(m_ptr->level > 5 + randint(dam)))
{
/* Resist */
@@ -5432,16 +5249,10 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
if (seen) obvious = TRUE;
/* Attempt a saving throw */
- if ((r_ptr->flags1 & (RF1_UNIQUE)) ||
- (r_ptr->flags3 & (RF3_NO_CONF)) ||
+ if ((r_ptr->flags & RF_UNIQUE) ||
+ (r_ptr->flags & RF_NO_CONF) ||
(m_ptr->level > randint((dam - 10) < 1 ? 1 : (dam - 10)) + 10))
{
- /* Memorize a flag */
- if (r_ptr->flags3 & (RF3_NO_CONF))
- {
- if (seen) r_ptr->r_flags3 |= (RF3_NO_CONF);
- }
-
/* Resist */
do_conf = 0;
@@ -5449,8 +5260,8 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
* Powerful demons & undead can turn a mindcrafter's
* attacks back on them
*/
- if (((r_ptr->flags3 & RF3_UNDEAD) ||
- (r_ptr->flags3 & RF3_DEMON)) &&
+ if (((r_ptr->flags & RF_UNDEAD) ||
+ (r_ptr->flags & RF_DEMON)) &&
(m_ptr->level > p_ptr->lev / 2) &&
(randint(2) == 1))
{
@@ -5475,7 +5286,7 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
break;
default:
{
- if (r_ptr->flags3 & (RF3_NO_FEAR))
+ if (r_ptr->flags & RF_NO_FEAR)
note = " is unaffected.";
else
set_afraid(p_ptr->afraid + dam);
@@ -5496,7 +5307,7 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
{
note = " is in your thrall!";
m_ptr->status = MSTATUS_PET;
- if ((r_ptr->flags3 & RF3_ANIMAL) && (!(r_ptr->flags3 & RF3_EVIL)))
+ if ((r_ptr->flags & RF_ANIMAL) && (!(r_ptr->flags & RF_EVIL)))
inc_piety(GOD_YAVANNA, m_ptr->level * 2);
}
else
@@ -5528,19 +5339,17 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
if (seen) obvious = TRUE;
do_stun = (randint(15) + 1) / (r + 1);
if (magik(33)) do_cut = (10 + randint(15) + r) / (r + 1);
- if (r_ptr->flags3 & (RF3_SUSCEP_COLD))
+ if (r_ptr->flags & RF_SUSCEP_COLD)
{
note = " is hit hard.";
dam *= 3;
do_cut *= 2;
- if (seen) r_ptr->r_flags3 |= (RF3_SUSCEP_COLD);
}
- if (r_ptr->flags3 & (RF3_IM_COLD))
+ if (r_ptr->flags & RF_IM_COLD)
{
note = " resists a lot.";
dam /= 9;
do_cut = 0;
- if (seen) r_ptr->r_flags3 |= (RF3_IM_COLD);
}
break;
}
@@ -5551,20 +5360,11 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
{
if (seen) obvious = TRUE;
- if ((r_ptr->flags3 & (RF3_UNDEAD)) ||
- (r_ptr->flags3 & (RF3_DEMON)) ||
- (r_ptr->flags3 & (RF3_NONLIVING)) ||
+ if ((r_ptr->flags & RF_UNDEAD) ||
+ (r_ptr->flags & RF_DEMON) ||
+ (r_ptr->flags & RF_NONLIVING) ||
(strchr("Egv", r_ptr->d_char)))
{
- if (r_ptr->flags3 & (RF3_UNDEAD))
- {
- if (seen) r_ptr->r_flags3 |= (RF3_UNDEAD);
- }
- if (r_ptr->flags3 & (RF3_DEMON))
- {
- if (seen) r_ptr->r_flags3 |= (RF3_DEMON);
- }
-
note = " is unaffected!";
obvious = FALSE;
dam = 0;
@@ -5577,19 +5377,14 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
case GF_DEATH_RAY:
{
if (seen) obvious = TRUE;
- if ((r_ptr->flags3 & (RF3_UNDEAD)) ||
- (r_ptr->flags3 & (RF3_NONLIVING)))
+ if ((r_ptr->flags & RF_UNDEAD) ||
+ (r_ptr->flags & RF_NONLIVING))
{
- if (r_ptr->flags3 & (RF3_UNDEAD))
- {
- if (seen) r_ptr->r_flags3 |= (RF3_UNDEAD);
- }
-
note = " is immune.";
obvious = FALSE;
dam = 0;
}
- else if (((r_ptr->flags1 & (RF1_UNIQUE)) &&
+ else if (((r_ptr->flags & RF_UNIQUE) &&
(randint(888) != 666)) ||
(((m_ptr->level + randint(20)) > randint((dam) + randint(10))) &&
randint(100) != 66 ))
@@ -5613,7 +5408,7 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
do_poly = TRUE;
/* Powerful monsters can resist */
- if ((r_ptr->flags1 & RF1_UNIQUE) ||
+ if ((r_ptr->flags & RF_UNIQUE) ||
(m_ptr->mflag & MFLAG_QUEST) ||
(m_ptr->level > randint((dam - 10) < 1 ? 1 : (dam - 10)) + 10))
{
@@ -5672,7 +5467,7 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
if (m_ptr->hp > m_ptr->maxhp) m_ptr->hp = m_ptr->maxhp;
/* Redraw (later) if needed */
- if (health_who == c_ptr->m_idx) p_ptr->redraw |= (PR_HEALTH);
+ if (health_who == c_ptr->m_idx) p_ptr->redraw |= (PR_FRAME);
/* Message */
note = " looks healthier.";
@@ -5704,7 +5499,7 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
if (seen) obvious = TRUE;
/* Powerful monsters can resist */
- if ((r_ptr->flags1 & (RF1_UNIQUE)) ||
+ if ((r_ptr->flags & RF_UNIQUE) ||
(m_ptr->level > randint((dam - 10) < 1 ? 1 : (dam - 10)) + 10))
{
note = " is unaffected!";
@@ -5730,15 +5525,9 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
if (seen) obvious = TRUE;
/* Attempt a saving throw */
- if ((r_ptr->flags3 & (RF3_NO_SLEEP)) ||
+ if ((r_ptr->flags & RF_NO_SLEEP) ||
(m_ptr->level > randint((dam - 10) < 1 ? 1 : (dam - 10)) + 10))
{
- /* Memorize a flag */
- if (r_ptr->flags3 & (RF3_NO_SLEEP))
- {
- if (seen) r_ptr->r_flags3 |= (RF3_NO_SLEEP);
- }
-
/* No obvious effect */
note = " is unaffected!";
obvious = FALSE;
@@ -5762,7 +5551,7 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
if (seen) obvious = TRUE;
/* Attempt a saving throw */
- if ((r_ptr->flags1 & (RF1_UNIQUE)) ||
+ if ((r_ptr->flags & RF_UNIQUE) ||
(m_ptr->level > randint((dam - 10) < 1 ? 1 : (dam - 10)) + 10))
{
note = " is unaffected!";
@@ -5789,15 +5578,9 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
/* Attempt a saving throw */
if ((m_ptr->mflag & MFLAG_QUEST) ||
- (r_ptr->flags3 & RF3_NO_CONF) ||
+ (r_ptr->flags & RF_NO_CONF) ||
(m_ptr->level > randint((dam - 10) < 1 ? 1 : (dam - 10)) + 5))
{
- /* Memorize a flag */
- if (r_ptr->flags3 & (RF3_NO_CONF))
- {
- if (seen) r_ptr->r_flags3 |= (RF3_NO_CONF);
- }
-
/* Resist */
/* No obvious effect */
note = " is unaffected!";
@@ -5813,7 +5596,7 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
{
note = " suddenly seems friendly!";
m_ptr->status = MSTATUS_FRIEND;
- if ((r_ptr->flags3 & RF3_ANIMAL) && (!(r_ptr->flags3 & RF3_EVIL)))
+ if ((r_ptr->flags & RF_ANIMAL) && (!(r_ptr->flags & RF_EVIL)))
inc_piety(GOD_YAVANNA, m_ptr->level * 2);
}
}
@@ -5832,15 +5615,9 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
/* Attempt a saving throw */
if ((m_ptr->mflag & MFLAG_QUEST) ||
- (r_ptr->flags3 & RF3_NO_CONF) ||
+ (r_ptr->flags & RF_NO_CONF) ||
(m_ptr->level > randint((dam - 10) < 1 ? 1 : (dam - 10)) + 5))
{
- /* Memorize a flag */
- if (r_ptr->flags3 & (RF3_NO_CONF))
- {
- if (seen) r_ptr->r_flags3 |= (RF3_NO_CONF);
- }
-
/* Resist */
/* No obvious effect */
note = " is unaffected!";
@@ -5858,7 +5635,7 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
if (can_create_companion()) m_ptr->status = MSTATUS_COMPANION;
else m_ptr->status = MSTATUS_PET;
- if ((r_ptr->flags3 & RF3_ANIMAL) && (!(r_ptr->flags3 & RF3_EVIL)))
+ if ((r_ptr->flags & RF_ANIMAL) && (!(r_ptr->flags & RF_EVIL)))
inc_piety(GOD_YAVANNA, m_ptr->level * 2);
}
}
@@ -5874,9 +5651,9 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
if (seen) obvious = TRUE;
/* Attempt a saving throw */
- if ((r_ptr->flags1 & RF1_UNIQUE) ||
+ if ((r_ptr->flags & RF_UNIQUE) ||
(m_ptr->mflag & MFLAG_QUEST) ||
- (!(r_ptr->flags3 & RF3_UNDEAD)) ||
+ (!(r_ptr->flags & RF_UNDEAD)) ||
(m_ptr->level > randint((dam - 10) < 1 ? 1 : (dam - 10)) + 10))
{
/* Resist */
@@ -5905,9 +5682,9 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
if (seen) obvious = TRUE;
/* Attempt a saving throw */
- if ((r_ptr->flags1 & RF1_UNIQUE) ||
+ if ((r_ptr->flags & RF_UNIQUE) ||
(m_ptr->mflag & MFLAG_QUEST) ||
- (!(r_ptr->flags1 & RF1_NEVER_MOVE)) ||
+ (!(r_ptr->flags & RF_NEVER_MOVE)) ||
(m_ptr->level > randint((dam - 10) < 1 ? 1 : (dam - 10)) + 10))
{
/* Resist */
@@ -5936,18 +5713,12 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
if (seen) obvious = TRUE;
/* Attempt a saving throw */
- if ((r_ptr->flags1 & (RF1_UNIQUE)) ||
+ if ((r_ptr->flags & RF_UNIQUE) ||
(m_ptr->mflag & MFLAG_QUEST) ||
- (!(r_ptr->flags3 & (RF3_ANIMAL))) ||
- (r_ptr->flags3 & (RF3_NO_CONF)) ||
+ (!(r_ptr->flags & RF_ANIMAL)) ||
+ (r_ptr->flags & RF_NO_CONF) ||
(m_ptr->level > randint((dam - 10) < 1 ? 1 : (dam - 10)) + 10))
{
- /* Memorize a flag */
- if (r_ptr->flags3 & (RF3_NO_CONF))
- {
- if (seen) r_ptr->r_flags3 |= (RF3_NO_CONF);
- }
-
/* Resist */
/* No obvious effect */
note = " is unaffected!";
@@ -5975,17 +5746,11 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
if (seen) obvious = TRUE;
/* Attempt a saving throw */
- if ((r_ptr->flags1 & (RF1_UNIQUE)) ||
+ if ((r_ptr->flags & RF_UNIQUE) ||
(m_ptr->mflag & MFLAG_QUEST) ||
- (!(r_ptr->flags3 & (RF3_DEMON))) ||
+ (!(r_ptr->flags & RF_DEMON)) ||
(m_ptr->level > randint((dam - 10) < 1 ? 1 : (dam - 10)) + 10))
{
- /* Memorize a flag */
- if (r_ptr->flags3 & (RF3_NO_CONF))
- {
- if (seen) r_ptr->r_flags3 |= (RF3_NO_CONF);
- }
-
/* Resist */
/* No obvious effect */
note = " is unaffected!";
@@ -6015,15 +5780,9 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
do_conf = damroll(3, (dam / 2)) + 1;
/* Attempt a saving throw */
- if ((r_ptr->flags3 & (RF3_NO_CONF)) ||
+ if ((r_ptr->flags & RF_NO_CONF) ||
(m_ptr->level > randint((dam - 10) < 1 ? 1 : (dam - 10)) + 10))
{
- /* Memorize a flag */
- if (r_ptr->flags3 & (RF3_NO_CONF))
- {
- if (seen) r_ptr->r_flags3 |= (RF3_NO_CONF);
- }
-
/* Resist */
do_conf = 0;
@@ -6068,15 +5827,9 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
do_conf = damroll(3, (dam / 2)) + 1;
/* Attempt a saving throw */
- if ((r_ptr->flags3 & (RF3_NO_CONF)) ||
+ if ((r_ptr->flags & RF_NO_CONF) ||
(m_ptr->level > randint((dam - 10) < 1 ? 1 : (dam - 10)) + 10))
{
- /* Memorize a flag */
- if (r_ptr->flags3 & (RF3_NO_CONF))
- {
- if (seen) r_ptr->r_flags3 |= (RF3_NO_CONF);
- }
-
/* Resist */
do_conf = 0;
@@ -6114,7 +5867,7 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
do_stun = damroll((p_ptr->lev / 10) + 3 , (dam)) + 1;
/* Attempt a saving throw */
- if ((r_ptr->flags1 & (RF1_UNIQUE)) ||
+ if ((r_ptr->flags & RF_UNIQUE) ||
(m_ptr->level > randint((dam - 10) < 1 ? 1 : (dam - 10)) + 10))
{
/* Resist */
@@ -6126,7 +5879,7 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
}
/* Non_living resists */
- if (r_ptr->flags3 & (RF3_NONLIVING))
+ if (r_ptr->flags & RF_NONLIVING)
{
/* Resist */
do_stun = 0;
@@ -6148,15 +5901,9 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
do_conf = damroll(3, (dam / 2)) + 1;
/* Attempt a saving throw */
- if ((r_ptr->flags3 & (RF3_NO_CONF)) ||
+ if ((r_ptr->flags & RF_NO_CONF) ||
(m_ptr->level > randint((dam - 10) < 1 ? 1 : (dam - 10)) + 10))
{
- /* Memorize a flag */
- if (r_ptr->flags3 & (RF3_NO_CONF))
- {
- if (seen) r_ptr->r_flags3 |= (RF3_NO_CONF);
- }
-
/* Resist */
do_conf = 0;
@@ -6185,14 +5932,11 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
case GF_LITE_WEAK:
{
/* Hurt by light */
- if (r_ptr->flags3 & (RF3_HURT_LITE))
+ if (r_ptr->flags & RF_HURT_LITE)
{
/* Obvious effect */
if (seen) obvious = TRUE;
- /* Memorize the effects */
- if (seen) r_ptr->r_flags3 |= (RF3_HURT_LITE);
-
/* Special effect */
note = " cringes from the light!";
note_dies = " shrivels away in the light!";
@@ -6214,15 +5958,14 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
case GF_LITE:
{
if (seen) obvious = TRUE;
- if (r_ptr->flags4 & (RF4_BR_LITE))
+ if (r_ptr->spells & SF_BR_LITE)
{
note = " resists.";
dam *= 2;
dam /= (randint(6) + 6);
}
- else if (r_ptr->flags3 & (RF3_HURT_LITE))
+ else if (r_ptr->flags & RF_HURT_LITE)
{
- if (seen) r_ptr->r_flags3 |= (RF3_HURT_LITE);
note = " cringes from the light!";
note_dies = " shrivels away in the light!";
dam *= 2;
@@ -6237,9 +5980,9 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
if (seen) obvious = TRUE;
/* Likes darkness... */
- if ((r_ptr->flags4 & (RF4_BR_DARK)) ||
- (r_ptr->flags3 & RF3_ORC) ||
- (r_ptr->flags3 & RF3_HURT_LITE))
+ if ((r_ptr->spells & SF_BR_DARK) ||
+ (r_ptr->flags & RF_ORC) ||
+ (r_ptr->flags & RF_HURT_LITE))
{
note = " resists.";
dam *= 2;
@@ -6253,14 +5996,11 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
case GF_KILL_WALL:
{
/* Hurt by rock remover */
- if (r_ptr->flags3 & (RF3_HURT_ROCK))
+ if (r_ptr->flags & RF_HURT_ROCK)
{
/* Notice effect */
if (seen) obvious = TRUE;
- /* Memorize the effects */
- if (seen) r_ptr->r_flags3 |= (RF3_HURT_ROCK);
-
/* Cute little message */
note = " loses some skin!";
note_dies = " dissolves!";
@@ -6281,23 +6021,21 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
case GF_AWAY_UNDEAD:
{
- if (dungeon_flags2 & DF2_NO_TELEPORT) break; /* No teleport on special levels */
+ if (dungeon_flags & DF_NO_TELEPORT) break; /* No teleport on special levels */
/* Only affect undead */
- if (r_ptr->flags3 & (RF3_UNDEAD))
+ if (r_ptr->flags & RF_UNDEAD)
{
bool_ resists_tele = FALSE;
- if (r_ptr->flags3 & (RF3_RES_TELE))
+ if (r_ptr->flags & RF_RES_TELE)
{
- if (r_ptr->flags1 & (RF1_UNIQUE))
+ if (r_ptr->flags & RF_UNIQUE)
{
- if (seen) r_ptr->r_flags3 |= RF3_RES_TELE;
note = " is unaffected!";
resists_tele = TRUE;
}
else if (m_ptr->level > randint(100))
{
- if (seen) r_ptr->r_flags3 |= RF3_RES_TELE;
note = " resists!";
resists_tele = TRUE;
}
@@ -6306,7 +6044,6 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
if (!resists_tele)
{
if (seen) obvious = TRUE;
- if (seen) r_ptr->r_flags3 |= (RF3_UNDEAD);
do_dist = dam;
}
}
@@ -6327,23 +6064,21 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
/* Teleport evil (Use "dam" as "power") */
case GF_AWAY_EVIL:
{
- if (dungeon_flags2 & DF2_NO_TELEPORT) break; /* No teleport on special levels */
+ if (dungeon_flags & DF_NO_TELEPORT) break; /* No teleport on special levels */
/* Only affect evil */
- if (r_ptr->flags3 & (RF3_EVIL))
+ if (r_ptr->flags & RF_EVIL)
{
bool_ resists_tele = FALSE;
- if (r_ptr->flags3 & (RF3_RES_TELE))
+ if (r_ptr->flags & RF_RES_TELE)
{
- if (r_ptr->flags1 & (RF1_UNIQUE))
+ if (r_ptr->flags & RF_UNIQUE)
{
- if (seen) r_ptr->r_flags3 |= RF3_RES_TELE;
note = " is unaffected!";
resists_tele = TRUE;
}
else if (m_ptr->level > randint(100))
{
- if (seen) r_ptr->r_flags3 |= RF3_RES_TELE;
note = " resists!";
resists_tele = TRUE;
}
@@ -6352,7 +6087,6 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
if (!resists_tele)
{
if (seen) obvious = TRUE;
- if (seen) r_ptr->r_flags3 |= (RF3_EVIL);
do_dist = dam;
}
}
@@ -6375,18 +6109,16 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
{
bool_ resists_tele = FALSE;
- if (dungeon_flags2 & DF2_NO_TELEPORT) break; /* No teleport on special levels */
- if (r_ptr->flags3 & (RF3_RES_TELE))
+ if (dungeon_flags & DF_NO_TELEPORT) break; /* No teleport on special levels */
+ if (r_ptr->flags & RF_RES_TELE)
{
- if (r_ptr->flags1 & (RF1_UNIQUE))
+ if (r_ptr->flags & RF_UNIQUE)
{
- if (seen) r_ptr->r_flags3 |= RF3_RES_TELE;
note = " is unaffected!";
resists_tele = TRUE;
}
else if (m_ptr->level > randint(100))
{
- if (seen) r_ptr->r_flags3 |= RF3_RES_TELE;
note = " resists!";
resists_tele = TRUE;
}
@@ -6411,11 +6143,8 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
case GF_TURN_UNDEAD:
{
/* Only affect undead */
- if (r_ptr->flags3 & (RF3_UNDEAD))
+ if (r_ptr->flags & RF_UNDEAD)
{
- /* Learn about type */
- if (seen) r_ptr->r_flags3 |= (RF3_UNDEAD);
-
/* Obvious */
if (seen) obvious = TRUE;
@@ -6449,11 +6178,8 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
case GF_TURN_EVIL:
{
/* Only affect evil */
- if (r_ptr->flags3 & (RF3_EVIL))
+ if (r_ptr->flags & RF_EVIL)
{
- /* Learn about type */
- if (seen) r_ptr->r_flags3 |= (RF3_EVIL);
-
/* Obvious */
if (seen) obvious = TRUE;
@@ -6493,8 +6219,8 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
do_fear = damroll(3, (dam / 2)) + 1;
/* Attempt a saving throw */
- if ((r_ptr->flags1 & (RF1_UNIQUE)) ||
- (r_ptr->flags3 & (RF3_NO_FEAR)) ||
+ if ((r_ptr->flags & RF_UNIQUE) ||
+ (r_ptr->flags & RF_NO_FEAR) ||
(m_ptr->level > randint((dam - 10) < 1 ? 1 : (dam - 10)) + 10))
{
/* No obvious effect */
@@ -6513,11 +6239,8 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
case GF_DISP_UNDEAD:
{
/* Only affect undead */
- if (r_ptr->flags3 & (RF3_UNDEAD))
+ if (r_ptr->flags & RF_UNDEAD)
{
- /* Learn about type */
- if (seen) r_ptr->r_flags3 |= (RF3_UNDEAD);
-
/* Obvious */
if (seen) obvious = TRUE;
@@ -6544,11 +6267,8 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
case GF_DISP_EVIL:
{
/* Only affect evil */
- if (r_ptr->flags3 & (RF3_EVIL))
+ if (r_ptr->flags & RF_EVIL)
{
- /* Learn about type */
- if (seen) r_ptr->r_flags3 |= (RF3_EVIL);
-
/* Obvious */
if (seen) obvious = TRUE;
@@ -6574,11 +6294,8 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
case GF_DISP_GOOD:
{
/* Only affect good */
- if (r_ptr->flags3 & (RF3_GOOD))
+ if (r_ptr->flags & RF_GOOD)
{
- /* Learn about type */
- if (seen) r_ptr->r_flags3 |= (RF3_GOOD);
-
/* Obvious */
if (seen) obvious = TRUE;
@@ -6604,8 +6321,8 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
case GF_DISP_LIVING:
{
/* Only affect non-undead */
- if (!(r_ptr->flags3 & (RF3_UNDEAD)) &&
- !(r_ptr->flags3 & (RF3_NONLIVING)))
+ if (!(r_ptr->flags & RF_UNDEAD) &&
+ !(r_ptr->flags & RF_NONLIVING))
{
/* Obvious */
if (seen) obvious = TRUE;
@@ -6632,11 +6349,8 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
case GF_DISP_DEMON:
{
/* Only affect demons */
- if (r_ptr->flags3 & (RF3_DEMON))
+ if (r_ptr->flags & RF_DEMON)
{
- /* Learn about type */
- if (seen) r_ptr->r_flags3 |= (RF3_DEMON);
-
/* Obvious */
if (seen) obvious = TRUE;
@@ -6686,7 +6400,7 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
if (m_ptr->hp > m_ptr->maxhp) m_ptr->hp = m_ptr->maxhp;
/* Redraw (later) if needed */
- if (health_who == c_ptr->m_idx) p_ptr->redraw |= (PR_HEALTH);
+ if (health_who == c_ptr->m_idx) p_ptr->redraw |= (PR_FRAME);
/* Message */
note = " looks healthier.";
@@ -6702,9 +6416,9 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
if (seen) obvious = TRUE;
/* Check race */
- if ((r_ptr->flags1 & (RF1_UNIQUE)) ||
+ if ((r_ptr->flags & RF_UNIQUE) ||
(m_ptr->mflag & MFLAG_QUEST) ||
- (!(r_ptr->flags3 & (RF3_DEMON))))
+ (!(r_ptr->flags & RF_DEMON)))
{
/* No obvious effect */
note = " is unaffected!";
@@ -6721,7 +6435,7 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
object_prep(i_ptr, lookup_kind(TV_CORPSE, SV_CORPSE_CORPSE));
/* Unique corpses are unique */
- if (r_ptr->flags1 & RF1_UNIQUE)
+ if (r_ptr->flags & RF_UNIQUE)
{
object_aware(i_ptr);
i_ptr->name1 = 201;
@@ -6746,36 +6460,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->flags & RF_UNIQUE) && !(r_ptr->flags & RF_UNDEAD) && !(r_ptr->flags & RF_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;
}
@@ -6784,7 +6487,7 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
/* "Unique" monsters cannot be polymorphed */
- if (r_ptr->flags1 & (RF1_UNIQUE)) do_poly = FALSE;
+ if (r_ptr->flags & RF_UNIQUE) do_poly = FALSE;
/*
* "Quest" monsters cannot be polymorphed
@@ -6793,7 +6496,7 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
do_poly = FALSE;
/* "Unique" monsters can only be "killed" by the player unless they are player's friends */
- if ((r_ptr->flags1 & RF1_UNIQUE) && (m_ptr->status <= MSTATUS_NEUTRAL_P))
+ if ((r_ptr->flags & RF_UNIQUE) && (m_ptr->status <= MSTATUS_NEUTRAL_P))
{
/* Uniques may only be killed by the player */
if (who && (who != -2) && (dam > m_ptr->hp)) dam = m_ptr->hp;
@@ -6807,14 +6510,14 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
if ((who > 0) && (dam > m_ptr->hp)) dam = m_ptr->hp;
}
- if (do_pois && (!(r_ptr->flags3 & RF3_IM_POIS)) && (!(r_ptr->flags3 & RF4_BR_POIS)) && hurt_monster(m_ptr))
+ if (do_pois && (r_ptr->flags & RF_IM_POIS).empty() && (r_ptr->spells & SF_BR_POIS).empty() && hurt_monster(m_ptr))
{
if (m_ptr->poisoned) note = " is more poisoned.";
else note = " is poisoned.";
m_ptr->poisoned += do_pois;
}
- if (do_cut && (!(r_ptr->flags4 & RF4_BR_WALL)) && hurt_monster(m_ptr))
+ if (do_cut && (!(r_ptr->spells & SF_BR_WALL)) && hurt_monster(m_ptr))
{
if (m_ptr->bleeding) note = " bleeds more strongly.";
else note = " starts bleeding.";
@@ -6850,7 +6553,7 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
m_ptr = &m_list[c_ptr->m_idx];
/* Hack -- Get new race */
- r_ptr = race_inf(m_ptr);
+ r_ptr = m_ptr->race();
}
}
@@ -6947,8 +6650,8 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
/* Sound and Impact breathers never stun */
else if (do_stun &&
- !(r_ptr->flags4 & (RF4_BR_SOUN)) &&
- !(r_ptr->flags4 & (RF4_BR_WALL)) && hurt_monster(m_ptr))
+ !(r_ptr->spells & SF_BR_SOUN) &&
+ !(r_ptr->spells & SF_BR_WALL) && hurt_monster(m_ptr))
{
/* Obvious */
if (seen) obvious = TRUE;
@@ -6971,9 +6674,9 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
/* Confusion and Chaos breathers (and sleepers) never confuse */
else if (do_conf &&
- !(r_ptr->flags3 & (RF3_NO_CONF)) &&
- !(r_ptr->flags4 & (RF4_BR_CONF)) &&
- !(r_ptr->flags4 & (RF4_BR_CHAO)) && hurt_monster(m_ptr))
+ !(r_ptr->flags & RF_NO_CONF) &&
+ !(r_ptr->spells & SF_BR_CONF) &&
+ !(r_ptr->spells & SF_BR_CHAO) && hurt_monster(m_ptr))
{
/* Obvious */
if (seen) obvious = TRUE;
@@ -7053,9 +6756,6 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
/* Take note */
if ((fear || do_fear) && (m_ptr->ml))
{
- /* Sound */
- sound(SOUND_FLEE);
-
/* Message */
msg_format("%^s flees in terror!", m_name);
}
@@ -7094,10 +6794,6 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
}
-/* Is the spell unsafe for the player ? */
-bool_ unsafe = FALSE;
-
-
/*
* Helper function for "project()" below.
*
@@ -7119,6 +6815,10 @@ bool_ unsafe = FALSE;
*/
static bool_ project_p(int who, int r, int y, int x, int dam, int typ, int a_rad)
{
+ auto const &d_info = game->edit_data.d_info;
+ auto const &r_info = game->edit_data.r_info;
+ auto const &f_info = game->edit_data.f_info;
+
int k = 0, do_move = 0, a = 0, b = 0, x1 = 0, y1 = 0;
/* Hack -- assume obvious */
@@ -7147,7 +6847,7 @@ static bool_ project_p(int who, int r, int y, int x, int dam, int typ, int a_rad
if ((x != p_ptr->px) || (y != p_ptr->py)) return (FALSE);
/* Player cannot hurt himself */
- if ((!who) && (!unsafe)) return (FALSE);
+ if (!who) return (FALSE);
/* Bolt attack from a monster */
if ((!a_rad) && get_skill(SKILL_DODGE) && (who > 0))
@@ -7188,7 +6888,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();
return TRUE;
}
@@ -7203,9 +6903,6 @@ static bool_ project_p(int who, int r, int y, int x, int dam, int typ, int a_rad
/* If the player is blind, be more descriptive */
if (blind) fuzzy = TRUE;
- /* If the player is hit by a trap, be more descritive */
- if (who == -2) fuzzy = TRUE;
-
/* Did ``God'' do it? */
if (who == -99)
{
@@ -7221,13 +6918,11 @@ static bool_ project_p(int who, int r, int y, int x, int dam, int typ, int a_rad
/* Did the dungeon do it? */
if (who == -100)
{
- sprintf(killer, "%s",
- d_name + d_info[dungeon_type].name);
+ sprintf(killer, "%s", d_info[dungeon_type].name.c_str());
}
if (who == -101)
{
- sprintf(killer, "%s",
- f_name + f_info[cave[p_ptr->py][p_ptr->px].feat].name);
+ sprintf(killer, "%s", f_info[cave[p_ptr->py][p_ptr->px].feat].name);
}
if (who >= -1)
@@ -7242,12 +6937,6 @@ static bool_ project_p(int who, int r, int y, int x, int dam, int typ, int a_rad
monster_desc(killer, m_ptr, 0x88);
}
- if (who == -2)
- {
- sprintf(killer, "%s",
- t_name + t_info[cave[p_ptr->py][p_ptr->px].t_idx].name);
- }
-
/* Analyze the damage */
switch (typ)
{
@@ -7380,7 +7069,7 @@ static bool_ project_p(int who, int r, int y, int x, int dam, int typ, int a_rad
if (!p_ptr->resist_sound)
{
int k = (randint((dam > 40) ? 35 : (dam * 3 / 4 + 5)));
- (void)set_stun(p_ptr->stun + k);
+ set_stun(p_ptr->stun + k);
}
if (!(p_ptr->resist_fire ||
@@ -7465,11 +7154,11 @@ static bool_ project_p(int who, int r, int y, int x, int dam, int typ, int a_rad
}
if (!p_ptr->resist_conf)
{
- (void)set_confused(p_ptr->confused + rand_int(20) + 10);
+ set_confused(p_ptr->confused + rand_int(20) + 10);
}
if (!p_ptr->resist_chaos)
{
- (void)set_image(p_ptr->image + randint(10));
+ set_image(p_ptr->image + randint(10));
}
if (!p_ptr->resist_neth && !p_ptr->resist_chaos)
{
@@ -7508,7 +7197,7 @@ static bool_ project_p(int who, int r, int y, int x, int dam, int typ, int a_rad
}
else
{
- (void)set_cut(p_ptr->cut + dam);
+ set_cut(p_ptr->cut + dam);
}
if ((!p_ptr->resist_shard) || (randint(13) == 1))
@@ -7532,7 +7221,7 @@ static bool_ project_p(int who, int r, int y, int x, int dam, int typ, int a_rad
else
{
int k = (randint((dam > 90) ? 35 : (dam / 3 + 5)));
- (void)set_stun(p_ptr->stun + k);
+ set_stun(p_ptr->stun + k);
}
if ((!p_ptr->resist_sound) || (randint(13) == 1))
@@ -7555,7 +7244,7 @@ static bool_ project_p(int who, int r, int y, int x, int dam, int typ, int a_rad
}
if (!p_ptr->resist_conf)
{
- (void)set_confused(p_ptr->confused + randint(20) + 10);
+ set_confused(p_ptr->confused + randint(20) + 10);
}
take_hit(dam, killer);
break;
@@ -7572,7 +7261,7 @@ static bool_ project_p(int who, int r, int y, int x, int dam, int typ, int a_rad
}
else
{
- (void)apply_disenchant(0);
+ apply_disenchant(0);
}
take_hit(dam, killer);
break;
@@ -7601,7 +7290,7 @@ static bool_ project_p(int who, int r, int y, int x, int dam, int typ, int a_rad
if (fuzzy) msg_print("You are hit by kinetic force!");
if (!p_ptr->resist_sound)
{
- (void)set_stun(p_ptr->stun + randint(20));
+ set_stun(p_ptr->stun + randint(20));
/*
* If fired by player, try pushing monster.
* First get vector from player to monster.
@@ -7691,7 +7380,7 @@ static bool_ project_p(int who, int r, int y, int x, int dam, int typ, int a_rad
if (fuzzy) msg_print("There is an explosion!");
if (!p_ptr->resist_sound)
{
- (void)set_stun(p_ptr->stun + randint(20));
+ set_stun(p_ptr->stun + randint(20));
}
if (p_ptr->resist_shard)
{
@@ -7699,7 +7388,7 @@ static bool_ project_p(int who, int r, int y, int x, int dam, int typ, int a_rad
}
else
{
- (void)set_cut(p_ptr-> cut + ( dam / 2) );
+ set_cut(p_ptr-> cut + ( dam / 2) );
}
if ((!p_ptr->resist_shard) || (randint(12) == 1))
@@ -7715,7 +7404,7 @@ static bool_ project_p(int who, int r, int y, int x, int dam, int typ, int a_rad
case GF_INERTIA:
{
if (fuzzy) msg_print("You are hit by something slow!");
- (void)set_slow(p_ptr->slow + rand_int(4) + 4);
+ set_slow(p_ptr->slow + rand_int(4) + 4);
take_hit(dam, killer);
break;
}
@@ -7731,7 +7420,7 @@ static bool_ project_p(int who, int r, int y, int x, int dam, int typ, int a_rad
}
else if (!blind && !p_ptr->resist_blind)
{
- (void)set_blind(p_ptr->blind + randint(5) + 2);
+ set_blind(p_ptr->blind + randint(5) + 2);
}
if (p_ptr->sensible_lite)
{
@@ -7766,7 +7455,7 @@ static bool_ project_p(int who, int r, int y, int x, int dam, int typ, int a_rad
}
else if (!blind && !p_ptr->resist_blind)
{
- (void)set_blind(p_ptr->blind + randint(5) + 2);
+ set_blind(p_ptr->blind + randint(5) + 2);
}
if (p_ptr->wraith_form) hp_player(dam);
else take_hit(dam, killer);
@@ -7861,33 +7550,29 @@ static bool_ project_p(int who, int r, int y, int x, int dam, int typ, int a_rad
/* Gravity -- stun plus slowness plus teleport */
case GF_GRAVITY:
{
- if (dungeon_flags2 & DF2_NO_TELEPORT) break; /* No teleport on special levels */
+ if (dungeon_flags & DF_NO_TELEPORT) break; /* No teleport on special levels */
if (fuzzy) msg_print("You are hit by something heavy!");
msg_print("Gravity warps around you.");
- if (!unsafe)
- {
- teleport_player(5);
- if (!p_ptr->ffall)
- (void)set_slow(p_ptr->slow + rand_int(4) + 4);
- if (!(p_ptr->resist_sound || p_ptr->ffall))
- {
- int k = (randint((dam > 90) ? 35 : (dam / 3 + 5)));
- (void)set_stun(p_ptr->stun + k);
- }
- if (p_ptr->ffall)
- {
- dam = (dam * 2) / 3;
- }
- if ((!p_ptr->ffall) || (randint(13) == 1))
- {
- inven_damage(set_cold_destroy, 2);
- }
+ teleport_player(5);
+ if (!p_ptr->ffall)
+ set_slow(p_ptr->slow + rand_int(4) + 4);
+ if (!(p_ptr->resist_sound || p_ptr->ffall))
+ {
+ int k = (randint((dam > 90) ? 35 : (dam / 3 + 5)));
+ set_stun(p_ptr->stun + k);
+ }
+ if (p_ptr->ffall)
+ {
+ dam = (dam * 2) / 3;
+ }
- take_hit(dam, killer);
+ if ((!p_ptr->ffall) || (randint(13) == 1))
+ {
+ inven_damage(set_cold_destroy, 2);
}
- else
- teleport_player(dam);
+
+ take_hit(dam, killer);
break;
}
@@ -7902,7 +7587,7 @@ static bool_ project_p(int who, int r, int y, int x, int dam, int typ, int a_rad
case GF_OLD_HEAL:
{
if (fuzzy) msg_print("You are hit by something invigorating!");
- (void)hp_player(dam);
+ hp_player(dam);
dam = 0;
break;
}
@@ -7910,7 +7595,7 @@ static bool_ project_p(int who, int r, int y, int x, int dam, int typ, int a_rad
case GF_OLD_SPEED:
{
if (fuzzy) msg_print("You are hit by something!");
- (void)set_fast(p_ptr->fast + randint(5), 10);
+ set_fast(p_ptr->fast + randint(5), 10);
dam = 0;
break;
}
@@ -7918,7 +7603,7 @@ static bool_ project_p(int who, int r, int y, int x, int dam, int typ, int a_rad
case GF_OLD_SLOW:
{
if (fuzzy) msg_print("You are hit by something slow!");
- (void)set_slow(p_ptr->slow + rand_int(4) + 4);
+ set_slow(p_ptr->slow + rand_int(4) + 4);
break;
}
@@ -7926,7 +7611,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;
}
@@ -7960,11 +7645,11 @@ static bool_ project_p(int who, int r, int y, int x, int dam, int typ, int a_rad
cold_dam(dam, killer);
if (!p_ptr->resist_shard)
{
- (void)set_cut(p_ptr->cut + damroll(5, 8));
+ set_cut(p_ptr->cut + damroll(5, 8));
}
if (!p_ptr->resist_sound)
{
- (void)set_stun(p_ptr->stun + randint(15));
+ set_stun(p_ptr->stun + randint(15));
}
if ((!(p_ptr->resist_cold || p_ptr->oppose_cold)) || (randint(12) == 1))
@@ -7975,14 +7660,6 @@ static bool_ project_p(int who, int r, int y, int x, int dam, int typ, int a_rad
break;
}
- /* Knowledge */
- case GF_IDENTIFY:
- {
- if (fuzzy) msg_print("You are hit by pure knowledge!");
- self_knowledge(NULL);
- break;
- }
-
/* Psi -- ESP */
case GF_PSI:
{
@@ -7995,7 +7672,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;
}
@@ -8018,17 +7695,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;
}
}
@@ -8098,7 +7767,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();
/* Return "Anything seen?" */
@@ -8252,7 +7921,7 @@ static bool_ project_p(int who, int r, int y, int x, int dam, int typ, int a_rad
*/
bool_ project(int who, int rad, int y, int x, int dam, int typ, int flg)
{
- int i, t, dist;
+ int t, dist;
int y1, x1;
int y2, x2;
@@ -8261,7 +7930,7 @@ bool_ project(int who, int rad, int y, int x, int dam, int typ, int flg)
int y_saver, x_saver; /* For reflecting monsters */
- int msec = delay_factor * delay_factor * delay_factor;
+ auto const msec = options->delay_factor_ms();
/* Assume the player sees nothing */
bool_ notice = FALSE;
@@ -8275,11 +7944,8 @@ bool_ project(int who, int rad, int y, int x, int dam, int typ, int flg)
/* Is the player blind? */
bool_ blind = (p_ptr->blind ? TRUE : FALSE);
- /* Number of grids in the "path" */
- int path_n = 0;
-
/* Actual grids in the "path" */
- u16b path_g[1024];
+ std::vector<std::tuple<int, int>> path_g;
/* Number of grids in the "blast area" (including the "beam" path) */
int grids = 0;
@@ -8362,22 +8028,26 @@ bool_ project(int who, int rad, int y, int x, int dam, int typ, int flg)
/* Calculate the projection path */
if ((who == -101) || (who == -100))
- path_n = 0;
+ {
+ /* Leave path empty */
+ }
else
- path_n = project_path(path_g, MAX_RANGE, y1, x1, y2, x2, flg);
+ {
+ path_g = project_path(MAX_RANGE, y1, x1, y2, x2, flg);
+ }
/* Hack -- Handle stuff */
handle_stuff();
/* Project along the path */
- for (i = 0; i < path_n; ++i)
+ for (auto const &grid_yx: path_g)
{
int oy = y;
int ox = x;
- int ny = GRID_Y(path_g[i]);
- int nx = GRID_X(path_g[i]);
+ int ny = std::get<0>(grid_yx);
+ int nx = std::get<1>(grid_yx);
/* Hack -- Balls explode before reaching walls */
if (!cave_floor_bold(ny, nx) && (rad > 0)) break;
@@ -8415,10 +8085,16 @@ bool_ project(int who, int rad, int y, int x, int dam, int typ, int flg)
/* Visual effects */
print_rel(c, a, y, x);
move_cursor_relative(y, x);
- if (fresh_before) Term_fresh();
- Term_xtra(TERM_XTRA_DELAY, msec);
+ if (options->fresh_before)
+ {
+ Term_fresh();
+ }
+ sleep_for(milliseconds(msec));
lite_spot(y, x);
- if (fresh_before) Term_fresh();
+ if (options->fresh_before)
+ {
+ Term_fresh();
+ }
/* Display "beam" grids */
if (flg & (PROJECT_BEAM))
@@ -8442,7 +8118,7 @@ bool_ project(int who, int rad, int y, int x, int dam, int typ, int flg)
else if (visual)
{
/* Delay for consistency */
- Term_xtra(TERM_XTRA_DELAY, msec);
+ sleep_for(milliseconds(msec));
}
}
}
@@ -8523,7 +8199,7 @@ bool_ project(int who, int rad, int y, int x, int dam, int typ, int flg)
for (t = 0; t <= rad; t++)
{
/* Dump everything with this radius */
- for (i = gm[t]; i < gm[t + 1]; i++)
+ for (int i = gm[t]; i < gm[t + 1]; i++)
{
/* Extract the location */
y = gy[i];
@@ -8555,12 +8231,12 @@ bool_ project(int who, int rad, int y, int x, int dam, int typ, int flg)
move_cursor_relative(y2, x2);
/* Flush each "radius" seperately */
- if (fresh_before) Term_fresh();
+ if (options->fresh_before) Term_fresh();
/* Delay (efficiently) */
if (visual || drawn)
{
- Term_xtra(TERM_XTRA_DELAY, msec);
+ sleep_for(milliseconds(msec));
}
}
@@ -8568,7 +8244,7 @@ bool_ project(int who, int rad, int y, int x, int dam, int typ, int flg)
if (drawn)
{
/* Erase the explosion drawn above */
- for (i = 0; i < grids; i++)
+ for (int i = 0; i < grids; i++)
{
/* Extract the location */
y = gy[i];
@@ -8585,7 +8261,7 @@ bool_ project(int who, int rad, int y, int x, int dam, int typ, int flg)
move_cursor_relative(y2, x2);
/* Flush the explosion */
- if (fresh_before) Term_fresh();
+ if (options->fresh_before) Term_fresh();
}
}
@@ -8605,7 +8281,7 @@ bool_ project(int who, int rad, int y, int x, int dam, int typ, int flg)
}
/* Scan for features */
- for (i = 0; i < grids; i++)
+ for (int i = 0; i < grids; i++)
{
/* Hack -- Notice new "dist" values */
if (gm[dist + 1] == i) dist++;
@@ -8638,7 +8314,7 @@ bool_ project(int who, int rad, int y, int x, int dam, int typ, int flg)
dist = 0;
/* Scan for objects */
- for (i = 0; i < grids; i++)
+ for (int i = 0; i < grids; i++)
{
/* Hack -- Notice new "dist" values */
if (gm[dist + 1] == i) dist++;
@@ -8665,7 +8341,7 @@ bool_ project(int who, int rad, int y, int x, int dam, int typ, int flg)
dist = 0;
/* Scan for monsters */
- for (i = 0; i < grids; i++)
+ for (int i = 0; i < grids; i++)
{
/* Hack -- Notice new "dist" values */
if (gm[dist + 1] == i) dist++;
@@ -8681,9 +8357,9 @@ bool_ project(int who, int rad, int y, int x, int dam, int typ, int flg)
}
else
{
- monster_race *ref_ptr = race_inf(&m_list[cave[y][x].m_idx]);
+ auto ref_ptr = m_list[cave[y][x].m_idx].race();
- if ((ref_ptr->flags2 & (RF2_REFLECTING)) && (randint(10) != 1)
+ if ((ref_ptr->flags & RF_REFLECTING) && (randint(10) != 1)
&& (dist_hack > 1))
{
int t_y, t_x;
@@ -8709,7 +8385,6 @@ bool_ project(int who, int rad, int y, int x, int dam, int typ, int flg)
if (m_list[cave[y][x].m_idx].ml)
{
msg_print("The attack bounces!");
- ref_ptr->r_flags2 |= RF2_REFLECTING;
}
project(cave[y][x].m_idx, 0, t_y, t_x, dam, typ, flg);
@@ -8750,7 +8425,7 @@ bool_ project(int who, int rad, int y, int x, int dam, int typ, int flg)
dist = 0;
/* Scan for player */
- for (i = 0; i < grids; i++)
+ for (int i = 0; i < grids; i++)
{
/* Hack -- Notice new "dist" values */
if (gm[dist + 1] == i) dist++;
@@ -8836,7 +8511,6 @@ bool_ potion_smash_effect(int who, int y, int x, int o_sval)
case SV_POTION_AUGMENTATION:
case SV_POTION_ENLIGHTENMENT:
case SV_POTION_STAR_ENLIGHTENMENT:
- case SV_POTION_SELF_KNOWLEDGE:
case SV_POTION_EXPERIENCE:
case SV_POTION_RESISTANCE:
case SV_POTION_INVULNERABILITY:
@@ -8927,9 +8601,13 @@ bool_ potion_smash_effect(int who, int y, int x, int o_sval)
;
}
- (void) project(who, radius, y, x, dam, dt,
+ project(who, radius, y, x, dam, dt,
(PROJECT_JUMP | PROJECT_ITEM | PROJECT_KILL));
+ // Silence warning. We may want to introuce an actual implementation
+ // and I want to preserve the original "ident" values if we do so.
+ ident;
+
/* XXX those potions that explode need to become "known" */
return angry;
}
@@ -8983,7 +8661,7 @@ static const int attack_types[25] =
* Describe the attack using normal names.
*/
-void describe_attack_fully(int type, char* r)
+static void describe_attack_fully(int type, char* r)
{
switch (type)
{
@@ -9074,18 +8752,12 @@ void describe_attack_fully(int type, char* r)
case GF_KILL_DOOR:
strcpy(r, "door destruction");
break;
- case GF_KILL_TRAP:
- strcpy(r, "trap destruction");
- break;
case GF_STONE_WALL:
strcpy(r, "wall creation");
break;
case GF_MAKE_DOOR:
strcpy(r, "door creation");
break;
- case GF_MAKE_TRAP:
- strcpy(r, "trap creation");
- break;
case GF_DESTRUCTION:
strcpy(r, "destruction");
break;
@@ -9100,8 +8772,7 @@ void describe_attack_fully(int type, char* r)
* Give a randomly-generated spell a name.
* Note that it only describes the first effect!
*/
-
-static void name_spell(random_spell* s_ptr)
+std::string name_spell(random_spell const *s_ptr)
{
char buff[30];
cptr buff2 = "???";
@@ -9132,141 +8803,114 @@ static void name_spell(random_spell* s_ptr)
}
describe_attack_fully(s_ptr->GF, buff);
- strnfmt(s_ptr->name, 30, "%s - %s", buff2, buff);
+ return fmt::format("{:s} - {:s}", buff2, buff);
}
void generate_spell(int plev)
{
- random_spell* rspell;
- int dice, sides, chance, mana, power;
- bool_ destruc_gen = FALSE;
- bool_ simple_gen = TRUE;
- bool_ ball_desc = FALSE;
-
- if (spell_num == MAX_SPELLS) return;
-
- rspell = &random_spells[spell_num];
-
- power = rand_int(5);
-
- dice = plev / 2;
- sides = plev;
- mana = plev;
-
- /* Make the spell more or less powerful. */
- dice += power;
- sides += power;
- mana += (plev * power) / 15;
+ auto &random_spells = p_ptr->random_spells;
- /* Stay within reasonable bounds. */
- if (dice < 1) dice = 1;
+ assert(random_spells.size() < MAX_SPELLS);
- if (sides < 5) sides = 5;
+ bool destruc_gen = false;
+ bool simple_gen = true;
+ bool ball_desc = false;
- if (mana < 1) mana = 1;
+ // Calculate power, dice, etc.
+ int const power = rand_int(5);
+ int const dice = std::max(1, (plev / 2) + power);
+ int const sides = std::max(5, plev + power);
+ int const mana = std::max(1, plev + (plev * power) / 15);
- rspell->level = plev;
- rspell->mana = mana;
- rspell->untried = TRUE;
+ // Create spell
+ random_spell rspell;
+ rspell.level = plev;
+ rspell.mana = mana;
+ rspell.untried = true;
- /* Spells are always maximally destructive. */
- rspell->proj_flags = PROJECT_KILL | PROJECT_ITEM | PROJECT_GRID;
+ // Spells are always maximally destructive
+ rspell.proj_flags = PROJECT_KILL | PROJECT_ITEM | PROJECT_GRID;
- chance = randint(100);
+ // Roll the dice as to the "type" of spell
+ int chance = randint(100);
- /* Hack -- Always start with Magic Missile or derivative at lev. 1 */
+ // We always start with Magic Missile or derivative at level 1
if (plev == 1 || chance < 25)
{
- rspell->proj_flags |= PROJECT_STOP;
- /* Swap dice and sides for better damage */
- rspell->dam_dice = sides;
- rspell->dam_sides = dice;
- rspell->radius = 0;
+ // Swap dice and sides for better damage
+ rspell.proj_flags |= PROJECT_STOP;
+ rspell.dam_dice = sides;
+ rspell.dam_sides = dice;
+ rspell.radius = 0;
}
else if (chance < 50)
{
- rspell->proj_flags |= PROJECT_BEAM;
- rspell->dam_dice = dice;
- rspell->dam_sides = sides;
- rspell->radius = 0;
+ rspell.proj_flags |= PROJECT_BEAM;
+ rspell.dam_dice = dice;
+ rspell.dam_sides = sides;
+ rspell.radius = 0;
}
else if (chance < 76)
{
- rspell->proj_flags |= PROJECT_STOP;
- rspell->radius = dice / 3;
- rspell->dam_dice = dice;
- rspell->dam_sides = sides;
- ball_desc = TRUE;
+ rspell.proj_flags |= PROJECT_STOP;
+ rspell.radius = dice / 3;
+ rspell.dam_dice = dice;
+ rspell.dam_sides = sides;
+ ball_desc = true;
}
else if (chance < 83)
{
- rspell->proj_flags |= PROJECT_BLAST;
- rspell->radius = sides / 3;
- rspell->dam_dice = dice;
- rspell->dam_sides = sides;
+ rspell.proj_flags |= PROJECT_BLAST;
+ rspell.radius = sides / 3;
+ rspell.dam_dice = dice;
+ rspell.dam_sides = sides;
- destruc_gen = TRUE;
- simple_gen = FALSE;
+ destruc_gen = true;
+ simple_gen = false;
}
else if (chance < 90)
{
- rspell->proj_flags |= PROJECT_METEOR_SHOWER;
- /* Area effect spells do way less damage "per shot" */
- rspell->dam_dice = dice / 5;
- rspell->dam_sides = sides / 5;
- rspell->radius = sides / 3;
- if (rspell->radius < 4) rspell->radius = 4;
+ // Area effect spells do way less damage "per shot"
+ rspell.proj_flags |= PROJECT_METEOR_SHOWER;
+ rspell.dam_dice = dice / 5;
+ rspell.dam_sides = sides / 5;
+ rspell.radius = std::max(4, sides / 3);
- destruc_gen = TRUE;
+ destruc_gen = true;
}
else
{
- rspell->proj_flags |= PROJECT_VIEWABLE;
- /* View spells do less damage */
- rspell->dam_dice = dice;
- rspell->dam_sides = sides / 2;
+ // View spells do less damage
+ rspell.proj_flags |= PROJECT_VIEWABLE;
+ rspell.dam_dice = dice;
+ rspell.dam_sides = sides / 2;
}
- /* Both a destructive and a simple spell requested --
- * pick one or the other. */
+ // Both a destructive and a simple spell requested; pick one or the other
if (destruc_gen && simple_gen)
{
if (magik(25))
{
- simple_gen = FALSE;
+ simple_gen = false;
}
else
{
- destruc_gen = FALSE;
+ destruc_gen = false;
}
}
- /* Pick a simple spell */
+ // Choose the appropriate GF
if (simple_gen)
{
- rspell->GF = attack_types[rand_int(25)];
- }
- /* Pick a destructive spell */
- else
- {
- rspell->GF = destructive_attack_types[rand_int(10)];
- }
-
- /* Give the spell a name. */
- name_spell(rspell);
- if (ball_desc)
- {
- /* 30 character limit on the string! */
- sprintf(rspell->desc, "Dam: %d, Rad: %d, Pow: %d",
- sides, dice, power);
+ rspell.GF = attack_types[rand_int(25)];
}
else
{
- sprintf(rspell->desc, "Damage: %dd%d, Power: %d",
- dice, sides, power);
+ rspell.GF = destructive_attack_types[rand_int(10)];
}
- spell_num++;
+ // Add
+ random_spells.emplace_back(rspell);
}
/*
diff --git a/src/spells1.hpp b/src/spells1.hpp
new file mode 100644
index 00000000..ec8f2cc9
--- /dev/null
+++ b/src/spells1.hpp
@@ -0,0 +1,35 @@
+#pragma once
+
+#include <string>
+
+#include "h-basic.h"
+#include "random_spell_fwd.hpp"
+
+byte spell_color(int type);
+s16b poly_r_idx(int r_idx);
+void get_pos_player(int dis, int *ny, int *nx);
+extern bool_ teleport_player_bypass;
+void teleport_player_directed(int rad, int dir);
+void teleport_away(int m_idx, int dis);
+void teleport_player(int dis);
+void teleport_player_to(int ny, int nx);
+void teleport_monster_to(int m_idx, int ny, int nx);
+void teleport_player_level();
+void recall_player(int d, int f);
+void take_hit(int damage, cptr kb_str);
+void take_sanity_hit(int damage, cptr hit_from);
+void acid_dam(int dam, cptr kb_str);
+void elec_dam(int dam, cptr kb_str);
+void fire_dam(int dam, cptr kb_str);
+void cold_dam(int dam, cptr kb_str);
+bool_ dec_stat(int stat, int amount, int mode);
+bool_ res_stat(int stat, bool_ full);
+bool_ apply_disenchant(int mode);
+bool_ project_m(int who, int r, int y, int x, int dam, int typ);
+bool_ project(int who, int rad, int y, int x, int dam, int typ, int flg);
+bool_ potion_smash_effect(int who, int y, int x, int o_sval);
+void do_poly_self();
+void corrupt_player();
+std::string name_spell(random_spell const *);
+void generate_spell(int plev);
+s16b do_poly_monster(int y, int x);
diff --git a/src/spells2.c b/src/spells2.c
deleted file mode 100644
index 5467499c..00000000
--- a/src/spells2.c
+++ /dev/null
@@ -1,8076 +0,0 @@
-/* File: spells2.c */
-
-/* Purpose: Spell code (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"
-
-#define WEIRD_LUCK 12
-#define BIAS_LUCK 20
-/*
- * Bias luck needs to be higher than weird luck,
- * since it is usually tested several times...
- */
-
-void summon_dragon_riders();
-
-
-/*
- * Grow things
- */
-void grow_things(s16b type, int rad)
-{
- int a, i, j;
-
- for (a = 0; a < rad * rad + 11; a++)
- {
- i = (Rand_mod((rad * 2) + 1)-rad + Rand_mod((rad * 2) + 1)-rad) / 2;
- j = (Rand_mod((rad * 2) + 1)-rad + Rand_mod((rad * 2) + 1)-rad) / 2;
-
- if (!in_bounds(p_ptr->py + j, p_ptr->px + i)) continue;
- if (distance(p_ptr->py, p_ptr->px, p_ptr->py + j, p_ptr->px + i) > rad) continue;
-
- if (cave_clean_bold(p_ptr->py + j, p_ptr->px + i))
- {
- cave_set_feat(p_ptr->py + j, p_ptr->px + i, type);
- }
- }
-}
-
-/*
- * Grow trees
- */
-void grow_trees(int rad)
-{
- int a, i, j;
-
- for (a = 0; a < rad * rad + 11; a++)
- {
- i = (Rand_mod((rad * 2) + 1)-rad + Rand_mod((rad * 2) + 1)-rad) / 2;
- j = (Rand_mod((rad * 2) + 1)-rad + Rand_mod((rad * 2) + 1)-rad) / 2;
-
- if (!in_bounds(p_ptr->py + j, p_ptr->px + i)) continue;
- if (distance(p_ptr->py, p_ptr->px, p_ptr->py + j, p_ptr->px + i) > rad) continue;
-
- if (cave_clean_bold(p_ptr->py + j, p_ptr->px + i) && (f_info[cave[p_ptr->py][p_ptr->px].feat].flags1 & FF1_SUPPORT_GROWTH))
- {
- cave_set_feat(p_ptr->py + j, p_ptr->px + i, FEAT_TREES);
- }
- }
-}
-
-/*
- * Grow grass
- */
-void grow_grass(int rad)
-{
- int a, i, j;
-
- for (a = 0; a < rad * rad + 11; a++)
- {
- i = (Rand_mod((rad * 2) + 1)-rad + Rand_mod((rad * 2) + 1)-rad) / 2;
- j = (Rand_mod((rad * 2) + 1)-rad + Rand_mod((rad * 2) + 1)-rad) / 2;
-
- if (!in_bounds(p_ptr->py + j, p_ptr->px + i)) continue;
- if (distance(p_ptr->py, p_ptr->px, p_ptr->py + j, p_ptr->px + i) > rad) continue;
-
- if (cave_clean_bold(p_ptr->py + j, p_ptr->px + i) && (f_info[cave[p_ptr->py][p_ptr->px].feat].flags1 & FF1_SUPPORT_GROWTH))
- {
- cave_set_feat(p_ptr->py + j, p_ptr->px + i, FEAT_GRASS);
- }
- }
-}
-
-/*
- * Increase players hit points, notice effects
- */
-bool_ hp_player(int num)
-{
- bool_ dead = p_ptr->chp < 0;
-
- /* Healing needed */
- if (p_ptr->chp < p_ptr->mhp)
- {
- /* Gain hitpoints */
- p_ptr->chp += num;
-
- /* Enforce maximum */
- if ((p_ptr->chp >= p_ptr->mhp) ||
- /* prevent wrapping */
- (!dead && (p_ptr->chp < 0)))
- {
- p_ptr->chp = p_ptr->mhp;
- p_ptr->chp_frac = 0;
- }
-
- /* Redraw */
- p_ptr->redraw |= (PR_HP);
-
- /* Window stuff */
- p_ptr->window |= (PW_PLAYER);
-
- /* Heal 0-4 */
- if (num < 5)
- {
- msg_print("You feel a little better.");
- }
-
- /* Heal 5-14 */
- else if (num < 15)
- {
- msg_print("You feel better.");
- }
-
- /* Heal 15-34 */
- else if (num < 35)
- {
- msg_print("You feel much better.");
- }
-
- /* Heal 35+ */
- else
- {
- msg_print("You feel very good.");
- }
-
- /* Notice */
- return (TRUE);
- }
-
- /* Ignore */
- return (FALSE);
-}
-
-
-
-/*
- * Leave a "glyph of warding" which prevents monster movement
- */
-void warding_glyph(void)
-{
- /* XXX XXX XXX */
- if (!cave_clean_bold(p_ptr->py, p_ptr->px))
- {
- msg_print("The object resists the spell.");
- return;
- }
-
- /* Create a glyph */
- cave_set_feat(p_ptr->py, p_ptr->px, FEAT_GLYPH);
-}
-
-void explosive_rune(void)
-{
- /* XXX XXX XXX */
- if (!cave_clean_bold(p_ptr->py, p_ptr->px))
- {
- msg_print("The object resists the spell.");
- return;
- }
-
- /* Create a glyph */
- cave_set_feat(p_ptr->py, p_ptr->px, FEAT_MINOR_GLYPH);
-}
-
-
-
-/*
- * Array of stat "descriptions"
- */
-static cptr desc_stat_pos[] =
-{
- "strong",
- "smart",
- "wise",
- "dextrous",
- "healthy",
- "cute"
-};
-
-/*
- * Array of long descriptions of stat
- */
-
-static cptr long_desc_stat[] =
-{
- "strength",
- "intelligence",
- "wisdom",
- "dexterity",
- "constitution",
- "charisma"
-};
-
-/*
- * Array of stat "descriptions"
- */
-static cptr desc_stat_neg[] =
-{
- "weak",
- "stupid",
- "naive",
- "clumsy",
- "sickly",
- "ugly"
-};
-
-
-/*
- * Lose a "point"
- */
-bool_ do_dec_stat(int stat, int mode)
-{
- bool_ sust = FALSE;
-
- /* Access the "sustain" */
- switch (stat)
- {
- case A_STR:
- if (p_ptr->sustain_str) sust = TRUE;
- break;
- case A_INT:
- if (p_ptr->sustain_int) sust = TRUE;
- break;
- case A_WIS:
- if (p_ptr->sustain_wis) sust = TRUE;
- break;
- case A_DEX:
- if (p_ptr->sustain_dex) sust = TRUE;
- break;
- case A_CON:
- if (p_ptr->sustain_con) sust = TRUE;
- break;
- case A_CHR:
- if (p_ptr->sustain_chr) sust = TRUE;
- break;
- }
-
- /* Sustain */
- if (sust)
- {
- /* Message */
- msg_format("You feel %s for a moment, but the feeling passes.",
- desc_stat_neg[stat]);
-
- /* Notice effect */
- return (TRUE);
- }
-
- /* Attempt to reduce the stat */
- if (dec_stat(stat, 10, mode))
- {
- /* Message */
- msg_format("You feel very %s.", desc_stat_neg[stat]);
-
- /* Notice effect */
- return (TRUE);
- }
-
- /* Nothing obvious */
- return (FALSE);
-}
-
-
-/*
- * Restore lost "points" in a stat
- */
-bool_ do_res_stat(int stat, bool_ full)
-{
- /* Keep a copy of the current stat, so we can evaluate it if necessary */
- int cur_stat = p_ptr->stat_cur[stat];
-
- /* Attempt to increase */
- if (res_stat(stat, full))
- {
- /* Message, depending on whether we got stronger or weaker */
- if (cur_stat > p_ptr->stat_max[stat])
- {
- msg_format("You feel your %s boost drain away.", long_desc_stat[stat]);
- }
- else
- {
- msg_format("You feel less %s.", desc_stat_neg[stat]);
- }
-
- /* Notice */
- return (TRUE);
- }
-
- /* Nothing obvious */
- return (FALSE);
-}
-
-
-/*
- * Gain a "point" in a stat
- */
-bool_ do_inc_stat(int stat)
-{
- bool_ res;
-
- /* Restore strength */
- res = res_stat(stat, TRUE);
-
- /* Attempt to increase */
- if (inc_stat(stat))
- {
- /* Message */
- msg_format("Wow! You feel very %s!", desc_stat_pos[stat]);
-
- /* Notice */
- return (TRUE);
- }
-
- /* Restoration worked */
- if (res)
- {
- /* Message */
- msg_format("You feel less %s.", desc_stat_neg[stat]);
-
- /* Notice */
- return (TRUE);
- }
-
- /* Nothing obvious */
- return (FALSE);
-}
-
-
-
-/*
- * Identify everything being carried.
- * Done by a potion of "self knowledge".
- */
-void identify_pack(void)
-{
- int i;
-
- /* Simply identify and know every item */
- for (i = 0; i < INVEN_TOTAL; i++)
- {
- object_type *o_ptr = &p_ptr->inventory[i];
-
- /* Skip non-objects */
- if (!o_ptr->k_idx) continue;
-
- /* Aware and Known */
- object_aware(o_ptr);
- object_known(o_ptr);
-
- /* Process the appropriate hooks */
- process_hooks(HOOK_IDENTIFY, "(d,s)", i, "normal");
- }
-
- p_ptr->notice |= (PN_COMBINE | PN_REORDER);
- p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
-}
-
-/*
- * common portions of identify_fully and identify_pack_fully
- */
-static void make_item_fully_identified(object_type *o_ptr)
-{
- /* Identify it fully */
- object_aware(o_ptr);
- object_known(o_ptr);
-
- /* Mark the item as fully known */
- o_ptr->ident |= (IDENT_MENTAL);
-
- /* For those with alchemist skills, learn how to create it */
- alchemist_learn_object(o_ptr);
-}
-
-/*
- * Identify everything being carried.
- * Done by a potion of "self knowledge".
- */
-void identify_pack_fully(void)
-{
- int i;
-
- /* Simply identify and know every item */
- for (i = 0; i < INVEN_TOTAL; i++)
- {
- object_type *o_ptr = &p_ptr->inventory[i];
-
- /* Skip non-objects */
- if (!o_ptr->k_idx) continue;
-
- make_item_fully_identified(o_ptr);
-
- /* Process the appropriate hooks */
- process_hooks(HOOK_IDENTIFY, "(d,s)", i, "full");
- }
-
- p_ptr->update |= (PU_BONUS);
- p_ptr->notice |= (PN_COMBINE | PN_REORDER);
- p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
-}
-
-/*
- * Used by the "enchant" function (chance of failure)
- * (modified for Zangband, we need better stuff there...) -- TY
- */
-static int enchant_table[16] =
-{
- 0, 10, 50, 100, 200,
- 300, 400, 500, 650, 800,
- 950, 987, 993, 995, 998,
- 1000
-};
-
-bool_ remove_curse_object(object_type *o_ptr, bool_ all)
-{
- u32b f1, f2, f3, f4, f5, esp;
-
- /* Skip non-objects */
- if (!o_ptr->k_idx) return FALSE;
-
- /* Uncursed already */
- if (!cursed_p(o_ptr)) return FALSE;
-
- /* Extract the flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
-
- /* Heavily Cursed Items need a special spell */
- if (!all && (f3 & (TR3_HEAVY_CURSE))) return FALSE;
-
- /* Perma-Cursed Items can NEVER be uncursed */
- if (f3 & (TR3_PERMA_CURSE)) return FALSE;
-
- /* Uncurse it */
- o_ptr->ident &= ~(IDENT_CURSED);
-
- /* Hack -- Assume felt */
- o_ptr->ident |= (IDENT_SENSE);
-
- if (o_ptr->art_flags3 & (TR3_CURSED))
- o_ptr->art_flags3 &= ~(TR3_CURSED);
-
- if (o_ptr->art_flags3 & (TR3_HEAVY_CURSE))
- o_ptr->art_flags3 &= ~(TR3_HEAVY_CURSE);
-
- /* Take note */
- o_ptr->sense = SENSE_UNCURSED;
-
- /* Reverse the curse effect */
- /* jk - scrolls of *remove curse* have a 1 in (55-level chance to */
- /* reverse the curse effects - a ring of damage(-15) {cursed} then */
- /* becomes a ring of damage (+15) */
- /* this does not go for artifacts - a Sword of Mormegil +40,+60 would */
- /* be somewhat unbalancing */
- /* due to the nature of this procedure, it only works on cursed items */
- /* ie you get only one chance! */
- if ((randint(55-p_ptr->lev) == 1) && !artifact_p(o_ptr))
- {
- if (o_ptr->to_a < 0) o_ptr->to_a = -o_ptr->to_a;
- if (o_ptr->to_h < 0) o_ptr->to_h = -o_ptr->to_h;
- if (o_ptr->to_d < 0) o_ptr->to_d = -o_ptr->to_d;
- if (o_ptr->pval < 0) o_ptr->pval = -o_ptr->pval;
- }
-
- /* Recalculate the bonuses */
- p_ptr->update |= (PU_BONUS);
-
- /* Window stuff */
- p_ptr->window |= (PW_EQUIP);
-
- return TRUE;
-}
-
-/*
- * Removes curses from items in inventory
- *
- * Note that Items which are "Perma-Cursed" (The One Ring,
- * The Crown of Morgoth) can NEVER be uncursed.
- *
- * Note that if "all" is FALSE, then Items which are
- * "Heavy-Cursed" (Mormegil, Calris, and Weapons of Morgul)
- * will not be uncursed.
- */
-static int remove_curse_aux(int all)
-{
- int i, cnt = 0;
-
- /* Attempt to uncurse items being worn */
- for (i = 0; i < INVEN_TOTAL; i++)
- {
- object_type *o_ptr = &p_ptr->inventory[i];
-
- if (!remove_curse_object(o_ptr, all)) continue;
-
- /* Count the uncursings */
- cnt++;
- }
-
- /* Return "something uncursed" */
- return (cnt);
-}
-
-
-/*
- * Remove most curses
- */
-bool_ remove_curse(void)
-{
- return (remove_curse_aux(FALSE) ? TRUE : FALSE);
-}
-
-/*
- * Remove all curses
- */
-bool_ remove_all_curse(void)
-{
- return (remove_curse_aux(TRUE) ? TRUE : FALSE);
-}
-
-
-
-/*
- * Restores any drained experience
- */
-bool_ restore_level(void)
-{
- /* Restore experience */
- if (p_ptr->exp < p_ptr->max_exp)
- {
- /* Message */
- msg_print("You feel your life energies returning.");
-
- /* Restore the experience */
- p_ptr->exp = p_ptr->max_exp;
-
- /* Check the experience */
- check_experience();
-
- /* Did something */
- return (TRUE);
- }
-
- /* No effect */
- return (FALSE);
-}
-
-
-bool_ alchemy(void) /* Turns an object into gold, gain some of its value in a shop */
-{
- int item, amt = 1;
- int old_number;
- long price;
- bool_ force = FALSE;
- object_type *o_ptr;
- char o_name[80];
- char out_val[160];
-
- cptr q, s;
-
- /* Hack -- force destruction */
- if (command_arg > 0) force = TRUE;
-
- /* Get an item */
- q = "Turn which item to gold? ";
- s = "You have nothing to turn to gold.";
- if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return (FALSE);
-
- /* 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 FALSE;
- }
-
-
- /* 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 */
- sprintf(out_val, "Really turn %s to gold? ", o_name);
- if (!get_check(out_val)) return FALSE;
- }
- }
-
- /* Artifacts cannot be destroyed */
- if (artifact_p(o_ptr) || o_ptr->art_name)
- {
- byte feel = SENSE_SPECIAL;
-
- /* Message */
- msg_format("You fail to turn %s to gold!", 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 FALSE;
- }
-
- price = object_value_real(o_ptr);
-
- if (price <= 0)
- /* Message */
- msg_format("You turn %s to fool's gold.", o_name);
- else
- {
- price /= 3;
-
- if (amt > 1) price *= amt;
-
- msg_format("You turn %s to %ld coins worth of gold.", o_name, price);
- p_ptr->au += price;
-
- /* Redraw gold */
- p_ptr->redraw |= (PR_GOLD);
-
- /* Window stuff */
- p_ptr->window |= (PW_PLAYER);
-
- }
-
- /* Eliminate the item */
- inc_stack_size(item, -amt);
-
- return TRUE;
-}
-
-
-
-
-/*
- * 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
- *
- * It is now a lot more efficient. -BEN-
- *
- * See also "identify_fully()".
- *
- * XXX XXX XXX Use the "show_file()" method, perhaps.
- */
-void self_knowledge(FILE *fff)
-{
- int i = 0, j, k;
-
- u32b f1 = 0L, f2 = 0L, f3 = 0L, f4 = 0L, f5 = 0L, esp = 0L;
-
- int iter; /* Iterator for a loop */
-
- object_type *o_ptr;
-
- char Dummy[80];
-
- cptr info[200];
-
- strcpy (Dummy, "");
-
- /* Acquire item flags from equipment */
- for (k = INVEN_WIELD; k < INVEN_TOTAL; k++)
- {
- u32b t1, t2, t3, t4, t5, esp;
-
- o_ptr = &p_ptr->inventory[k];
-
- /* Skip non-objects */
- if (!o_ptr->k_idx) continue;
-
- /* Extract the flags */
- object_flags(o_ptr, &t1, &t2, &t3, &t4, &t5, &esp);
-
- /* Extract flags */
- f1 |= t1;
- f2 |= t2;
- f3 |= t3;
- }
-
- if (death)
- {
- static char buf[250];
-
- sprintf(buf, "You are dead, killed by %s %s.",
- died_from, describe_player_location());
- info[i++] = buf;
- }
-
- /* Racial powers... */
- if (p_ptr->body_monster != 0)
- {
- monster_race *r_ptr = &r_info[p_ptr->body_monster];
-
- if (r_ptr->flags1 & RF1_CHAR_CLEAR ||
- r_ptr->flags1 & RF1_ATTR_CLEAR)
- info[i++] = "You are transparent.";
- if ((r_ptr->flags1 & RF1_CHAR_MULTI) ||
- (r_ptr->flags2 & RF2_SHAPECHANGER))
- info[i++] = "Your form constantly changes.";
- if (r_ptr->flags1 & RF1_ATTR_MULTI)
- info[i++] = "Your color constantly changes.";
- if (r_ptr->flags1 & RF1_NEVER_BLOW)
- info[i++] = "You do not have a physical weapon.";
- if (r_ptr->flags1 & RF1_NEVER_MOVE)
- info[i++] = "You cannot move.";
- if ((r_ptr->flags1 & RF1_RAND_25) &&
- (r_ptr->flags1 & RF1_RAND_50))
- info[i++] = "You move extremely erratically.";
- else if (r_ptr->flags1 & RF1_RAND_50)
- info[i++] = "You move somewhat erratically.";
- else if (r_ptr->flags1 & RF1_RAND_25)
- info[i++] = "You move a bit erratically.";
- if (r_ptr->flags2 & RF2_STUPID)
- info[i++] = "You are very stupid (INT -4).";
- if (r_ptr->flags2 & RF2_SMART)
- info[i++] = "You are very smart (INT +4).";
- /* Not implemented */
- if (r_ptr->flags2 & RF2_CAN_SPEAK)
- info[i++] = "You can speak.";
- else
- info[i++] = "You cannot speak.";
- /* Not implemented */
- if (r_ptr->flags2 & RF2_COLD_BLOOD)
- info[i++] = "You are cold blooded.";
- /* Not implemented */
- if (r_ptr->flags2 & RF2_EMPTY_MIND)
- info[i++] = "You have an empty mind.";
- if (r_ptr->flags2 & RF2_WEIRD_MIND)
- info[i++] = "You have a weird mind.";
- if (r_ptr->flags4 & RF4_MULTIPLY)
- info[i++] = "You can multiply.";
- if (r_ptr->flags2 & RF2_POWERFUL)
- info[i++] = "You have strong breath.";
- /* Not implemented */
- if (r_ptr->flags2 & RF2_ELDRITCH_HORROR)
- info[i++] = "You are an eldritch horror.";
- if (r_ptr->flags2 & RF2_OPEN_DOOR)
- info[i++] = "You can open doors.";
- else
- info[i++] = "You cannot open doors.";
- if (r_ptr->flags2 & RF2_BASH_DOOR)
- info[i++] = "You can bash doors.";
- else
- info[i++] = "You cannot bash doors.";
- if (r_ptr->flags2 & RF2_PASS_WALL)
- info[i++] = "You can pass walls.";
- if (r_ptr->flags2 & RF2_KILL_WALL)
- info[i++] = "You destroy walls.";
- /* Not implemented */
- if (r_ptr->flags2 & RF2_MOVE_BODY)
- info[i++] = "You can move monsters.";
- /* Not implemented */
- if (r_ptr->flags3 & RF3_ORC)
- info[i++] = "You have orc blood in your veins.";
- /* Not implemented */
- else if (r_ptr->flags3 & RF3_TROLL)
- info[i++] = "You have troll blood in your veins.";
- /* Not implemented */
- else if (r_ptr->flags3 & RF3_GIANT)
- info[i++] = "You have giant blood in your veins.";
- /* Not implemented */
- else if (r_ptr->flags3 & RF3_DRAGON)
- info[i++] = "You have dragon blood in your veins.";
- /* Not implemented */
- else if (r_ptr->flags3 & RF3_DEMON)
- info[i++] = "You have demon blood in your veins.";
- /* Not implemented */
- else if (r_ptr->flags3 & RF3_UNDEAD)
- info[i++] = "You are an undead.";
- /* Not implemented */
- else if (r_ptr->flags3 & RF3_ANIMAL)
- info[i++] = "You are an animal.";
- /* Not implemented */
- else if (r_ptr->flags3 & RF3_THUNDERLORD)
- info[i++] = "You have thunderlord blood in your veins.";
- if (r_ptr->flags3 & RF3_EVIL)
- info[i++] = "You are inherently evil.";
- else if (r_ptr->flags3 & RF3_GOOD)
- info[i++] = "You are inherently good.";
- if (r_ptr->flags3 & RF3_AURA_COLD)
- info[i++] = "You are surrounded by a chilly aura.";
- /* Not implemented */
- if (r_ptr->flags3 & RF3_NONLIVING)
- info[i++] = "You are not living.";
- /* Not implemented */
- if (r_ptr->flags3 & RF3_HURT_LITE)
- info[i++] = "Your eyes are vulnerable to bright light.";
- /* Not implemented */
- if (r_ptr->flags3 & RF3_HURT_ROCK)
- info[i++] = "You can be hurt by rock remover.";
- if (r_ptr->flags3 & RF3_SUSCEP_FIRE)
- info[i++] = "You are vulnerable to fire.";
- if (r_ptr->flags3 & RF3_SUSCEP_COLD)
- info[i++] = "You are vulnerable to cold.";
- if (r_ptr->flags3 & RF3_RES_TELE)
- info[i++] = "You are resistant to teleportation.";
- if (r_ptr->flags3 & RF3_RES_NETH)
- info[i++] = "You are resistant to nether.";
- if (r_ptr->flags3 & RF3_RES_WATE)
- info[i++] = "You are resistant to water.";
- if (r_ptr->flags3 & RF3_RES_PLAS)
- info[i++] = "You are resistant to plasma.";
- if (r_ptr->flags3 & RF3_RES_WATE)
- info[i++] = "You are resistant to nexus.";
- if (r_ptr->flags3 & RF3_RES_DISE)
- info[i++] = "You are resistant to disease.";
- /* Not implemented */
- if (r_ptr->flags3 & RF3_NO_SLEEP)
- info[i++] = "You cannot be slept.";
- /* Not implemented */
- if (r_ptr->flags3 & RF3_UNIQUE_4)
- info[i++] = "You are a Nazgul.";
- if (r_ptr->flags3 & RF3_NO_FEAR)
- info[i++] = "You are immune to fear.";
- if (r_ptr->flags3 & RF3_NO_STUN)
- info[i++] = "You are immune to stun.";
- if (r_ptr->flags3 & RF3_NO_CONF)
- info[i++] = "You are immune to confusion.";
- if (r_ptr->flags3 & RF3_NO_SLEEP)
- info[i++] = "You are immune to sleep.";
-
- if (r_ptr->flags4 & RF4_SHRIEK)
- info[i++] = "You can aggravate monsters.";
- if (r_ptr->flags4 & RF4_ROCKET)
- info[i++] = "You can fire a rocket.";
- if (r_ptr->flags4 & RF4_ARROW_1)
- info[i++] = "You can fire a light arrow.";
- if (r_ptr->flags4 & RF4_ARROW_2)
- info[i++] = "You can fire a heavy arrow.";
- if (r_ptr->flags4 & RF4_ARROW_3)
- info[i++] = "You can fire a light missile.";
- if (r_ptr->flags4 & RF4_ARROW_4)
- info[i++] = "You can fire a heavy missile.";
- if (r_ptr->flags4 & RF4_BR_ACID)
- info[i++] = "You can breathe acid.";
- if (r_ptr->flags4 & RF4_BR_ELEC)
- info[i++] = "You can breathe electricity.";
- if (r_ptr->flags4 & RF4_BR_FIRE)
- info[i++] = "You can breathe fire.";
- if (r_ptr->flags4 & RF4_BR_COLD)
- info[i++] = "You can breathe cold.";
- if (r_ptr->flags4 & RF4_BR_POIS)
- info[i++] = "You can breathe poison.";
- if (r_ptr->flags4 & RF4_BR_NETH)
- info[i++] = "You can breathe nether.";
- if (r_ptr->flags4 & RF4_BR_LITE)
- info[i++] = "You can breathe light.";
- if (r_ptr->flags4 & RF4_BR_DARK)
- info[i++] = "You can breathe darkness.";
- if (r_ptr->flags4 & RF4_BR_CONF)
- info[i++] = "You can breathe confusion.";
- if (r_ptr->flags4 & RF4_BR_SOUN)
- info[i++] = "You can breathe sound.";
- if (r_ptr->flags4 & RF4_BR_CHAO)
- info[i++] = "You can breathe chaos.";
- if (r_ptr->flags4 & RF4_BR_DISE)
- info[i++] = "You can breathe disenchantment.";
- if (r_ptr->flags4 & RF4_BR_NEXU)
- info[i++] = "You can breathe nexus.";
- if (r_ptr->flags4 & RF4_BR_TIME)
- info[i++] = "You can breathe time.";
- if (r_ptr->flags4 & RF4_BR_INER)
- info[i++] = "You can breathe inertia.";
- if (r_ptr->flags4 & RF4_BR_GRAV)
- info[i++] = "You can breathe gravity.";
- if (r_ptr->flags4 & RF4_BR_SHAR)
- info[i++] = "You can breathe shards.";
- if (r_ptr->flags4 & RF4_BR_PLAS)
- info[i++] = "You can breathe plasma.";
- if (r_ptr->flags4 & RF4_BR_WALL)
- info[i++] = "You can breathe force.";
- if (r_ptr->flags4 & RF4_BR_MANA)
- info[i++] = "You can breathe mana.";
- if (r_ptr->flags4 & RF4_BR_NUKE)
- info[i++] = "You can breathe nuke.";
- if (r_ptr->flags4 & RF4_BR_DISI)
- info[i++] = "You can breathe disintegration.";
- if (r_ptr->flags5 & RF5_BA_ACID)
- info[i++] = "You can cast a ball of acid.";
- if (r_ptr->flags5 & RF5_BA_ELEC)
- info[i++] = "You can cast a ball of electricity.";
- if (r_ptr->flags5 & RF5_BA_FIRE)
- info[i++] = "You can cast a ball of fire.";
- if (r_ptr->flags5 & RF5_BA_COLD)
- info[i++] = "You can cast a ball of cold.";
- if (r_ptr->flags5 & RF5_BA_POIS)
- info[i++] = "You can cast a ball of poison.";
- if (r_ptr->flags5 & RF5_BA_NETH)
- info[i++] = "You can cast a ball of nether.";
- if (r_ptr->flags5 & RF5_BA_WATE)
- info[i++] = "You can cast a ball of water.";
- /* Not implemented */
- if (r_ptr->flags5 & RF5_DRAIN_MANA)
- info[i++] = "You can drain mana.";
- if (r_ptr->flags5 & RF5_MIND_BLAST)
- info[i++] = "You can cause mind blasting.";
- if (r_ptr->flags5 & RF5_BRAIN_SMASH)
- info[i++] = "You can cause brain smashing.";
- if (r_ptr->flags5 & RF5_CAUSE_1)
- info[i++] = "You can cause light wounds.";
- if (r_ptr->flags5 & RF5_CAUSE_2)
- info[i++] = "You can cause serious wounds.";
- if (r_ptr->flags5 & RF5_CAUSE_3)
- info[i++] = "You can cause critical wounds.";
- if (r_ptr->flags5 & RF5_CAUSE_4)
- info[i++] = "You can cause mortal wounds.";
- if (r_ptr->flags5 & RF5_BO_ACID)
- info[i++] = "You can cast a bolt of acid.";
- if (r_ptr->flags5 & RF5_BO_ELEC)
- info[i++] = "You can cast a bolt of electricity.";
- if (r_ptr->flags5 & RF5_BO_FIRE)
- info[i++] = "You can cast a bolt of fire.";
- if (r_ptr->flags5 & RF5_BO_COLD)
- info[i++] = "You can cast a bolt of cold.";
- if (r_ptr->flags5 & RF5_BO_POIS)
- info[i++] = "You can cast a bolt of poison.";
- if (r_ptr->flags5 & RF5_BO_NETH)
- info[i++] = "You can cast a bolt of nether.";
- if (r_ptr->flags5 & RF5_BO_WATE)
- info[i++] = "You can cast a bolt of water.";
- if (r_ptr->flags5 & RF5_BO_MANA)
- info[i++] = "You can cast a bolt of mana.";
- if (r_ptr->flags5 & RF5_BO_PLAS)
- info[i++] = "You can cast a bolt of plasma.";
- if (r_ptr->flags5 & RF5_BO_ICEE)
- info[i++] = "You can cast a bolt of ice.";
- if (r_ptr->flags5 & RF5_MISSILE)
- info[i++] = "You can cast magic missile.";
- if (r_ptr->flags5 & RF5_SCARE)
- info[i++] = "You can terrify.";
- if (r_ptr->flags5 & RF5_BLIND)
- info[i++] = "You can blind.";
- if (r_ptr->flags5 & RF5_CONF)
- info[i++] = "You can use confusion.";
- if (r_ptr->flags5 & RF5_SLOW)
- info[i++] = "You can cast slow.";
- if (r_ptr->flags5 & RF5_HOLD)
- info[i++] = "You can touch to paralyze.";
- if (r_ptr->flags6 & RF6_HASTE)
- info[i++] = "You can haste yourself.";
- if (r_ptr->flags6 & RF6_HAND_DOOM)
- info[i++] = "You can invoke Hand of Doom.";
- if (r_ptr->flags6 & RF6_HEAL)
- info[i++] = "You can heal yourself.";
- if (r_ptr->flags6 & RF6_BLINK)
- info[i++] = "You can blink.";
- if (r_ptr->flags6 & RF6_TPORT)
- info[i++] = "You can teleport.";
- if (r_ptr->flags6 & RF6_TELE_TO)
- info[i++] = "You can go between places.";
- if (r_ptr->flags6 & RF6_TELE_AWAY)
- info[i++] = "You can teleport away.";
- if (r_ptr->flags6 & RF6_TELE_LEVEL)
- info[i++] = "You can teleport level.";
- if (r_ptr->flags6 & RF6_DARKNESS)
- info[i++] = "You can create darkness.";
- if (r_ptr->flags6 & RF6_TRAPS)
- info[i++] = "You can create traps.";
- /* Not implemented */
- if (r_ptr->flags6 & RF6_FORGET)
- info[i++] = "You can fade memories.";
- if (r_ptr->flags6 & RF6_RAISE_DEAD)
- info[i++] = "You can Raise the Dead.";
- if (r_ptr->flags6 & RF6_S_BUG)
- info[i++] = "You can magically summon a Software Bugs.";
- if (r_ptr->flags6 & RF6_S_RNG)
- info[i++] = "You can magically summon the RNG.";
- if (r_ptr->flags6 & RF6_S_THUNDERLORD)
- info[i++] = "You can magically summon some Thunderlords.";
- if (r_ptr->flags6 & RF6_S_KIN)
- info[i++] = "You can magically summon some Kins.";
- if (r_ptr->flags6 & RF6_S_HI_DEMON)
- info[i++] = "You can magically summon greater demons.";
- if (r_ptr->flags6 & RF6_S_MONSTER)
- info[i++] = "You can magically summon a monster.";
- if (r_ptr->flags6 & RF6_S_MONSTERS)
- info[i++] = "You can magically summon monsters.";
- if (r_ptr->flags6 & RF6_S_ANT)
- info[i++] = "You can magically summon ants.";
- if (r_ptr->flags6 & RF6_S_SPIDER)
- info[i++] = "You can magically summon spiders.";
- if (r_ptr->flags6 & RF6_S_HOUND)
- info[i++] = "You can magically summon hounds.";
- if (r_ptr->flags6 & RF6_S_HYDRA)
- info[i++] = "You can magically summon hydras.";
- if (r_ptr->flags6 & RF6_S_ANGEL)
- info[i++] = "You can magically summon an angel.";
- if (r_ptr->flags6 & RF6_S_DEMON)
- info[i++] = "You can magically summon a demon.";
- if (r_ptr->flags6 & RF6_S_UNDEAD)
- info[i++] = "You can magically summon an undead.";
- if (r_ptr->flags6 & RF6_S_DRAGON)
- info[i++] = "You can magically summon a dragon.";
- if (r_ptr->flags6 & RF6_S_HI_UNDEAD)
- info[i++] = "You can magically summon greater undead.";
- if (r_ptr->flags6 & RF6_S_HI_DRAGON)
- info[i++] = "You can magically summon greater dragons.";
- if (r_ptr->flags6 & RF6_S_WRAITH)
- info[i++] = "You can magically summon a wraith.";
- /* Not implemented */
- if (r_ptr->flags6 & RF6_S_UNIQUE)
- info[i++] = "You can magically summon an unique monster.";
- /* Not implemented */
- if (r_ptr->flags7 & RF7_AQUATIC)
- info[i++] = "You are aquatic.";
- /* Not implemented */
- if (r_ptr->flags7 & RF7_CAN_SWIM)
- info[i++] = "You can swim.";
- /* Not implemented */
- if (r_ptr->flags7 & RF7_CAN_FLY)
- info[i++] = "You can fly.";
- if ((r_ptr->flags7 & RF7_MORTAL) == 0)
- info[i++] = "You are immortal.";
- /* Not implemented */
- if (r_ptr->flags7 & RF7_NAZGUL)
- info[i++] = "You are a Nazgul.";
-
- if (r_ptr->flags7 & RF7_SPIDER)
- info[i++] = "You are a spider.";
-
- if (r_ptr->flags8 & RF8_WILD_TOWN)
- info[i++] = "You appear in towns.";
- if (r_ptr->flags8 & RF8_WILD_SHORE)
- info[i++] = "You appear on the shore.";
- if (r_ptr->flags8 & RF8_WILD_OCEAN)
- info[i++] = "You appear in the ocean.";
- if (r_ptr->flags8 & RF8_WILD_WASTE)
- info[i++] = "You appear in the waste.";
- if (r_ptr->flags8 & RF8_WILD_WOOD)
- info[i++] = "You appear in woods.";
- if (r_ptr->flags8 & RF8_WILD_VOLCANO)
- info[i++] = "You appear in volcanos.";
- if (r_ptr->flags8 & RF8_WILD_MOUNTAIN)
- info[i++] = "You appear in the mountains.";
- if (r_ptr->flags8 & RF8_WILD_GRASS)
- info[i++] = "You appear in grassy areas.";
-
- if (r_ptr->flags9 & RF9_SUSCEP_ACID)
- info[i++] = "You are vulnerable to acid.";
- if (r_ptr->flags9 & RF9_SUSCEP_ELEC)
- info[i++] = "You are vulnerable to electricity.";
- if (r_ptr->flags9 & RF9_SUSCEP_POIS)
- info[i++] = "You are vulnerable to poison.";
- if (r_ptr->flags9 & RF9_KILL_TREES)
- info[i++] = "You can eat trees.";
- if (r_ptr->flags9 & RF9_WYRM_PROTECT)
- info[i++] = "You are protected by great wyrms of power.";
- }
-
- /* List powers */
- for (iter = 0; iter < power_max; iter++)
- {
- if (p_ptr->powers[iter])
- {
- info[i++] = powers_type[iter].desc_text;
- }
- }
-
- if (p_ptr->allow_one_death)
- {
- info[i++] = "The Blood of Life flows through your veins.";
- }
- if (p_ptr->blind)
- {
- info[i++] = "You cannot see.";
- }
- if (p_ptr->confused)
- {
- info[i++] = "You are confused.";
- }
- if (p_ptr->afraid)
- {
- info[i++] = "You are terrified.";
- }
- if (p_ptr->cut)
- {
- info[i++] = "You are bleeding.";
- }
- if (p_ptr->stun)
- {
- info[i++] = "You are stunned.";
- }
- if (p_ptr->poisoned)
- {
- info[i++] = "You are poisoned.";
- }
- if (p_ptr->image)
- {
- info[i++] = "You are hallucinating.";
- }
- if (p_ptr->aggravate)
- {
- info[i++] = "You aggravate monsters.";
- }
- if (p_ptr->teleport)
- {
- info[i++] = "Your position is very uncertain.";
- }
- if (p_ptr->blessed)
- {
- info[i++] = "You feel righteous.";
- }
- if (p_ptr->hero)
- {
- info[i++] = "You feel heroic.";
- }
- if (p_ptr->shero)
- {
- info[i++] = "You are in a battle rage.";
- }
- if (p_ptr->protevil)
- {
- info[i++] = "You are protected from evil.";
- }
- if (p_ptr->protgood)
- {
- info[i++] = "You are protected from good.";
- }
- if (p_ptr->shield)
- {
- info[i++] = "You are protected by a mystic shield.";
- }
- if (p_ptr->invuln)
- {
- info[i++] = "You are temporarily invulnerable.";
- }
- if (p_ptr->confusing)
- {
- info[i++] = "Your hands are glowing dull red.";
- }
- if (p_ptr->searching)
- {
- info[i++] = "You are looking around very carefully.";
- }
- if (p_ptr->new_spells)
- {
- info[i++] = "You can learn some spells/prayers.";
- }
- if (p_ptr->word_recall)
- {
- info[i++] = "You will soon be recalled.";
- }
- if (p_ptr->see_infra)
- {
- info[i++] = "Your eyes are sensitive to infrared light.";
- }
- if (p_ptr->see_inv)
- {
- info[i++] = "You can see invisible creatures.";
- }
- if (p_ptr->magical_breath)
- {
- info[i++] = "You can breathe without air.";
- }
- else if (p_ptr->water_breath)
- {
- info[i++] = "You can breathe underwater.";
- }
- if (p_ptr->ffall)
- {
- info[i++] = "You levitate just over the ground.";
- }
- if (p_ptr->climb)
- {
- info[i++] = "You can climb high mountains.";
- }
- if (p_ptr->free_act)
- {
- info[i++] = "You have free action.";
- }
- if (p_ptr->regenerate)
- {
- info[i++] = "You regenerate quickly.";
- }
- if (p_ptr->slow_digest)
- {
- info[i++] = "Your appetite is small.";
- }
- if (p_ptr->telepathy)
- {
- if (p_ptr->telepathy & ESP_ALL) info[i++] = "You have ESP.";
- else
- {
- if (p_ptr->telepathy & ESP_ORC) info[i++] = "You can sense the presence of orcs.";
- if (p_ptr->telepathy & ESP_TROLL) info[i++] = "You can sense the presence of trolls.";
- if (p_ptr->telepathy & ESP_DRAGON) info[i++] = "You can sense the presence of dragons.";
- if (p_ptr->telepathy & ESP_SPIDER) info[i++] = "You can sense the presence of spiders.";
- if (p_ptr->telepathy & ESP_GIANT) info[i++] = "You can sense the presence of giants.";
- if (p_ptr->telepathy & ESP_DEMON) info[i++] = "You can sense the presence of demons.";
- if (p_ptr->telepathy & ESP_UNDEAD) info[i++] = "You can sense presence of undead.";
- if (p_ptr->telepathy & ESP_EVIL) info[i++] = "You can sense the presence of evil beings.";
- if (p_ptr->telepathy & ESP_ANIMAL) info[i++] = "You can sense the presence of animals.";
- if (p_ptr->telepathy & ESP_THUNDERLORD) info[i++] = "You can sense the presence of thunderlords.";
- if (p_ptr->telepathy & ESP_GOOD) info[i++] = "You can sense the presence of good beings.";
- if (p_ptr->telepathy & ESP_NONLIVING) info[i++] = "You can sense the presence of non-living things.";
- if (p_ptr->telepathy & ESP_UNIQUE) info[i++] = "You can sense the presence of unique beings.";
- }
- }
- if (!luck( -100, 100))
- {
- info[i++] = "You have normal luck.";
- }
- else if (luck( -100, 100) < 0)
- {
- if (luck( -100, 100) < -90)
- {
- info[i++] = "You are incredibly unlucky.";
- }
- else if (luck( -100, 100) < -60)
- {
- info[i++] = "You are extremely unlucky.";
- }
- else if (luck( -100, 100) < -30)
- {
- info[i++] = "You are very unlucky.";
- }
- else
- {
- info[i++] = "You are unlucky.";
- }
- }
- else if (luck( -100, 100) > 0)
- {
- if (luck( -100, 100) > 90)
- {
- info[i++] = "You are incredibly lucky.";
- }
- else if (luck( -100, 100) > 60)
- {
- info[i++] = "You are extremely lucky.";
- }
- else if (luck( -100, 100) > 30)
- {
- info[i++] = "You are very lucky.";
- }
- else
- {
- info[i++] = "You are lucky.";
- }
- }
- if (p_ptr->auto_id)
- {
- info[i++] = "You know everything.";
- }
- if (p_ptr->hold_life)
- {
- info[i++] = "You have a firm hold on your life force.";
- }
- if (p_ptr->reflect)
- {
- info[i++] = "You reflect arrows and bolts.";
- }
- if (p_ptr->sh_fire)
- {
- info[i++] = "You are surrounded with a fiery aura.";
- }
- if (p_ptr->sh_elec)
- {
- info[i++] = "You are surrounded with electricity.";
- }
- if (p_ptr->antimagic)
- {
- info[i++] = "You are surrounded by an anti-magic field.";
- }
- if (p_ptr->anti_magic)
- {
- info[i++] = "You are surrounded by an anti-magic shell.";
- }
- if (p_ptr->wraith_form)
- {
- info[i++] = "You are incorporeal.";
- }
- if (p_ptr->anti_tele)
- {
- info[i++] = "You cannot teleport.";
- }
- if (p_ptr->lite)
- {
- info[i++] = "You are carrying a permanent light.";
- }
-
- if (p_ptr->immune_acid)
- {
- info[i++] = "You are completely immune to acid.";
- }
- else if ((p_ptr->resist_acid) && (p_ptr->oppose_acid))
- {
- info[i++] = "You resist acid exceptionally well.";
- }
- else if ((p_ptr->resist_acid) || (p_ptr->oppose_acid))
- {
- info[i++] = "You are resistant to acid.";
- }
-
- if (p_ptr->immune_elec)
- {
- info[i++] = "You are completely immune to lightning.";
- }
- else if ((p_ptr->resist_elec) && (p_ptr->oppose_elec))
- {
- info[i++] = "You resist lightning exceptionally well.";
- }
- else if ((p_ptr->resist_elec) || (p_ptr->oppose_elec))
- {
- info[i++] = "You are resistant to lightning.";
- }
-
- if (p_ptr->immune_fire)
- {
- info[i++] = "You are completely immune to fire.";
- }
- else if ((p_ptr->resist_fire) && (p_ptr->oppose_fire))
- {
- info[i++] = "You resist fire exceptionally well.";
- }
- else if ((p_ptr->resist_fire) || (p_ptr->oppose_fire))
- {
- info[i++] = "You are resistant to fire.";
- }
- else if (p_ptr->sensible_fire)
- {
- info[i++] = "You are very vulnerable to fire.";
- }
-
- if (p_ptr->immune_cold)
- {
- info[i++] = "You are completely immune to cold.";
- }
- else if ((p_ptr->resist_cold) && (p_ptr->oppose_cold))
- {
- info[i++] = "You resist cold exceptionally well.";
- }
- else if ((p_ptr->resist_cold) || (p_ptr->oppose_cold))
- {
- info[i++] = "You are resistant to cold.";
- }
-
- if ((p_ptr->resist_pois) && (p_ptr->oppose_pois))
- {
- info[i++] = "You resist poison exceptionally well.";
- }
- else if ((p_ptr->resist_pois) || (p_ptr->oppose_pois))
- {
- info[i++] = "You are resistant to poison.";
- }
-
- if (p_ptr->resist_lite)
- {
- info[i++] = "You are resistant to bright light.";
- }
- if (p_ptr->resist_dark)
- {
- info[i++] = "You are resistant to darkness.";
- }
- if (p_ptr->resist_conf)
- {
- info[i++] = "You are resistant to confusion.";
- }
- if (p_ptr->resist_sound)
- {
- info[i++] = "You are resistant to sonic attacks.";
- }
- if (p_ptr->resist_disen)
- {
- info[i++] = "You are resistant to disenchantment.";
- }
- if (p_ptr->resist_chaos)
- {
- info[i++] = "You are resistant to chaos.";
- }
- if (p_ptr->resist_shard)
- {
- info[i++] = "You are resistant to blasts of shards.";
- }
- if (p_ptr->resist_nexus)
- {
- info[i++] = "You are resistant to nexus attacks.";
- }
- if (p_ptr->immune_neth)
- {
- info[i++] = "You are immune to nether forces.";
- }
- else if (p_ptr->resist_neth)
- {
- info[i++] = "You are resistant to nether forces.";
- }
- if (p_ptr->resist_fear)
- {
- info[i++] = "You are completely fearless.";
- }
- if (p_ptr->resist_blind)
- {
- info[i++] = "Your eyes are resistant to blindness.";
- }
- if (p_ptr->resist_continuum)
- {
- info[i++] = "The space-time continuum cannot be disrupted near you.";
- }
-
- if (p_ptr->sustain_str)
- {
- info[i++] = "Your strength is sustained.";
- }
- if (p_ptr->sustain_int)
- {
- info[i++] = "Your intelligence is sustained.";
- }
- if (p_ptr->sustain_wis)
- {
- info[i++] = "Your wisdom is sustained.";
- }
- if (p_ptr->sustain_con)
- {
- info[i++] = "Your constitution is sustained.";
- }
- if (p_ptr->sustain_dex)
- {
- info[i++] = "Your dexterity is sustained.";
- }
- if (p_ptr->sustain_chr)
- {
- info[i++] = "Your charisma is sustained.";
- }
- if (p_ptr->black_breath)
- {
- info[i++] = "You suffer from Black Breath.";
- }
-
- if (f1 & (TR1_STR))
- {
- info[i++] = "Your strength is affected by your equipment.";
- }
- if (f1 & (TR1_INT))
- {
- info[i++] = "Your intelligence is affected by your equipment.";
- }
- if (f1 & (TR1_WIS))
- {
- info[i++] = "Your wisdom is affected by your equipment.";
- }
- if (f1 & (TR1_DEX))
- {
- info[i++] = "Your dexterity is affected by your equipment.";
- }
- if (f1 & (TR1_CON))
- {
- info[i++] = "Your constitution is affected by your equipment.";
- }
- if (f1 & (TR1_CHR))
- {
- info[i++] = "Your charisma is affected by your equipment.";
- }
-
- if (f1 & (TR1_STEALTH))
- {
- info[i++] = "Your stealth is affected by your equipment.";
- }
- if (f1 & (TR1_SEARCH))
- {
- info[i++] = "Your searching ability is affected by your equipment.";
- }
- if (f1 & (TR1_INFRA))
- {
- info[i++] = "Your infravision is affected by your equipment.";
- }
- if (f1 & (TR1_TUNNEL))
- {
- info[i++] = "Your digging ability is affected by your equipment.";
- }
- if (f1 & (TR1_SPEED))
- {
- info[i++] = "Your speed is affected by your equipment.";
- }
- if (f1 & (TR1_BLOWS))
- {
- info[i++] = "Your attack speed is affected by your equipment.";
- }
- if (f5 & (TR5_CRIT))
- {
- info[i++] = "Your ability to score critical hits is affected by your equipment.";
- }
-
-
- /* Access the current weapon */
- o_ptr = &p_ptr->inventory[INVEN_WIELD];
-
- /* Analyze the weapon */
- if (o_ptr->k_idx)
- {
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
-
- /* Indicate Blessing */
- if (f3 & (TR3_BLESSED))
- {
- info[i++] = "Your weapon has been blessed by the gods.";
- }
-
- if (f1 & (TR1_CHAOTIC))
- {
- info[i++] = "Your weapon is branded with the Sign of Chaos.";
- }
-
- /* Hack */
- if (f1 & (TR1_IMPACT))
- {
- info[i++] = "The impact of your weapon can cause earthquakes.";
- }
-
- if (f1 & (TR1_VORPAL))
- {
- info[i++] = "Your weapon is very sharp.";
- }
-
- if (f1 & (TR1_VAMPIRIC))
- {
- info[i++] = "Your weapon drains life from your foes.";
- }
-
- /* Special "Attack Bonuses" */
- if (f1 & (TR1_BRAND_ACID))
- {
- info[i++] = "Your weapon melts your foes.";
- }
- if (f1 & (TR1_BRAND_ELEC))
- {
- info[i++] = "Your weapon shocks your foes.";
- }
- if (f1 & (TR1_BRAND_FIRE))
- {
- info[i++] = "Your weapon burns your foes.";
- }
- if (f1 & (TR1_BRAND_COLD))
- {
- info[i++] = "Your weapon freezes your foes.";
- }
- if (f1 & (TR1_BRAND_POIS))
- {
- info[i++] = "Your weapon poisons your foes.";
- }
-
- /* Special "slay" flags */
- if (f1 & (TR1_SLAY_ANIMAL))
- {
- info[i++] = "Your weapon strikes at animals with extra force.";
- }
- if (f1 & (TR1_SLAY_EVIL))
- {
- info[i++] = "Your weapon strikes at evil with extra force.";
- }
- if (f1 & (TR1_SLAY_UNDEAD))
- {
- info[i++] = "Your weapon strikes at undead with holy wrath.";
- }
- if (f1 & (TR1_SLAY_DEMON))
- {
- info[i++] = "Your weapon strikes at demons with holy wrath.";
- }
- if (f1 & (TR1_SLAY_ORC))
- {
- info[i++] = "Your weapon is especially deadly against orcs.";
- }
- if (f1 & (TR1_SLAY_TROLL))
- {
- info[i++] = "Your weapon is especially deadly against trolls.";
- }
- if (f1 & (TR1_SLAY_GIANT))
- {
- info[i++] = "Your weapon is especially deadly against giants.";
- }
- if (f1 & (TR1_SLAY_DRAGON))
- {
- info[i++] = "Your weapon is especially deadly against dragons.";
- }
-
- /* Special "kill" flags */
- if (f1 & (TR1_KILL_DRAGON))
- {
- info[i++] = "Your weapon is a great bane of dragons.";
- }
- /* Special "kill" flags */
- if (f5 & (TR5_KILL_DEMON))
- {
- info[i++] = "Your weapon is a great bane of demons.";
- }
- /* Special "kill" flags */
- if (f5 & (TR5_KILL_UNDEAD))
- {
- info[i++] = "Your weapon is a great bane of undeads.";
- }
- }
-
- /* Print on screen or in a file ? */
- if (fff == NULL)
- {
- /* Save the screen */
- character_icky = TRUE;
- Term_save();
-
- /* Erase the screen */
- for (k = 1; k < 24; k++) prt("", k, 13);
-
- /* Label the information */
- prt(" Your Attributes:", 1, 15);
-
- /* We will print on top of the map (column 13) */
- for (k = 2, j = 0; j < i; j++)
- {
- /* Show the info */
- prt(info[j], k++, 15);
-
- /* Every 20 entries (lines 2 to 21), start over */
- if ((k == 22) && (j + 1 < i))
- {
- prt("-- more --", k, 15);
- inkey();
- for (; k > 2; k--) prt("", k, 15);
- }
- }
-
- /* Pause */
- prt("[Press any key to continue]", k, 13);
- inkey();
-
- /* Restore the screen */
- Term_load();
- character_icky = FALSE;
- }
- else
- {
- /* Label the information */
- fprintf(fff, " Your Attributes:\n");
-
- /* We will print on top of the map (column 13) */
- for (j = 0; j < i; j ++)
- {
- /* Show the info */
- fprintf(fff, "%s\n", info[j]);
- }
- }
-}
-
-
-static int report_magics_aux(int dur)
-{
- if (dur <= 5)
- {
- return 0;
- }
- else if (dur <= 10)
- {
- return 1;
- }
- else if (dur <= 20)
- {
- return 2;
- }
- else if (dur <= 50)
- {
- return 3;
- }
- else if (dur <= 100)
- {
- return 4;
- }
- else if (dur <= 200)
- {
- return 5;
- }
- else
- {
- return 6;
- }
-}
-
-static cptr report_magic_durations[] =
-{
- "for a short time",
- "for a little while",
- "for a while",
- "for a long while",
- "for a long time",
- "for a very long time",
- "for an incredibly long time",
- "until you hit a monster"
-};
-
-
-void report_magics(void)
-{
- int i = 0, j, k;
-
- char Dummy[80];
-
- cptr info[128];
- int info2[128];
-
- if (p_ptr->blind)
- {
- info2[i] = report_magics_aux(p_ptr->blind);
- info[i++] = "You cannot see";
- }
- if (p_ptr->confused)
- {
- info2[i] = report_magics_aux(p_ptr->confused);
- info[i++] = "You are confused";
- }
- if (p_ptr->afraid)
- {
- info2[i] = report_magics_aux(p_ptr->afraid);
- info[i++] = "You are terrified";
- }
- if (p_ptr->poisoned)
- {
- info2[i] = report_magics_aux(p_ptr->poisoned);
- info[i++] = "You are poisoned";
- }
- if (p_ptr->image)
- {
- info2[i] = report_magics_aux(p_ptr->image);
- info[i++] = "You are hallucinating";
- }
-
- if (p_ptr->blessed)
- {
- info2[i] = report_magics_aux(p_ptr->blessed);
- info[i++] = "You feel righteous";
- }
- if (p_ptr->hero)
- {
- info2[i] = report_magics_aux(p_ptr->hero);
- info[i++] = "You feel heroic";
- }
- if (p_ptr->shero)
- {
- info2[i] = report_magics_aux(p_ptr->shero);
- info[i++] = "You are in a battle rage";
- }
- if (p_ptr->protevil)
- {
- info2[i] = report_magics_aux(p_ptr->protevil);
- info[i++] = "You are protected from evil";
- }
- if (p_ptr->protgood)
- {
- info2[i] = report_magics_aux(p_ptr->protgood);
- info[i++] = "You are protected from good";
- }
- if (p_ptr->shield)
- {
- info2[i] = report_magics_aux(p_ptr->shield);
- info[i++] = "You are protected by a mystic shield";
- }
- if (p_ptr->invuln)
- {
- info2[i] = report_magics_aux(p_ptr->invuln);
- info[i++] = "You are invulnerable";
- }
- if (p_ptr->tim_wraith)
- {
- info2[i] = report_magics_aux(p_ptr->tim_wraith);
- info[i++] = "You are incorporeal";
- }
- if (p_ptr->confusing)
- {
- info2[i] = 7;
- info[i++] = "Your hands are glowing dull red.";
- }
- if (p_ptr->word_recall)
- {
- info2[i] = report_magics_aux(p_ptr->word_recall);
- info[i++] = "You waiting to be recalled";
- }
- if (p_ptr->oppose_acid)
- {
- info2[i] = report_magics_aux(p_ptr->oppose_acid);
- info[i++] = "You are resistant to acid";
- }
- if (p_ptr->oppose_elec)
- {
- info2[i] = report_magics_aux(p_ptr->oppose_elec);
- info[i++] = "You are resistant to lightning";
- }
- if (p_ptr->oppose_fire)
- {
- info2[i] = report_magics_aux(p_ptr->oppose_fire);
- info[i++] = "You are resistant to fire";
- }
- if (p_ptr->oppose_cold)
- {
- info2[i] = report_magics_aux(p_ptr->oppose_cold);
- info[i++] = "You are resistant to cold";
- }
- if (p_ptr->oppose_pois)
- {
- info2[i] = report_magics_aux(p_ptr->oppose_pois);
- info[i++] = "You are resistant to poison";
- }
-
- /* Save the screen */
- character_icky = TRUE;
- Term_save();
-
- /* Erase the screen */
- for (k = 1; k < 24; k++) prt("", k, 13);
-
- /* Label the information */
- prt(" Your Current Magic:", 1, 15);
-
- /* We will print on top of the map (column 13) */
- for (k = 2, j = 0; j < i; j++)
- {
- /* Show the info */
- sprintf( Dummy, "%s %s.", info[j],
- report_magic_durations[info2[j]] );
- prt(Dummy, k++, 15);
-
- /* Every 20 entries (lines 2 to 21), start over */
- if ((k == 22) && (j + 1 < i))
- {
- prt("-- more --", k, 15);
- inkey();
- for (; k > 2; k--) prt("", k, 15);
- }
- }
-
- /* Pause */
- prt("[Press any key to continue]", k, 13);
- inkey();
-
- /* Restore the screen */
- Term_load();
- character_icky = FALSE;
-}
-
-
-
-/*
- * Forget everything
- */
-bool_ lose_all_info(void)
-{
- int i;
-
- /* Forget info about objects */
- for (i = 0; i < INVEN_TOTAL; i++)
- {
- object_type *o_ptr = &p_ptr->inventory[i];
-
- /* Skip non-objects */
- if (!o_ptr->k_idx) continue;
-
- /* Allow "protection" by the MENTAL flag */
- if (o_ptr->ident & (IDENT_MENTAL)) continue;
-
- /* Remove sensing */
- o_ptr->sense = SENSE_NONE;
-
- /* Hack -- Clear the "empty" flag */
- o_ptr->ident &= ~(IDENT_EMPTY);
-
- /* Hack -- Clear the "known" flag */
- o_ptr->ident &= ~(IDENT_KNOWN);
-
- /* Hack -- Clear the "felt" flag */
- o_ptr->ident &= ~(IDENT_SENSE);
- }
-
- /* Recalculate bonuses */
- p_ptr->update |= (PU_BONUS);
-
- /* Combine / Reorder the pack (later) */
- p_ptr->notice |= (PN_COMBINE | PN_REORDER);
-
- /* Window stuff */
- p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
-
- /* Mega-Hack -- Forget the map */
- wiz_dark();
-
- /* It worked */
- return (TRUE);
-}
-
-
-
-
-/*
- * Detect all traps on current panel
- */
-bool_ detect_traps(int rad)
-{
- int x, y;
- bool_ detect = FALSE;
- cave_type *c_ptr;
-
-
- /* Scan the current panel */
- for (y = p_ptr->py - rad; y <= p_ptr->py + rad; y++)
- {
- for (x = p_ptr->px - rad; x <= p_ptr->px + rad; x++)
- {
- /* Reject locations outside of dungeon */
- if (!in_bounds(y, x)) continue;
-
- /* Reject those out of radius */
- if (distance(p_ptr->py, p_ptr->px, y, x) > rad) continue;
-
- /* Access the grid */
- c_ptr = &cave[y][x];
-
- /* mark as detected */
- c_ptr->info |= CAVE_DETECT;
-
- /* Detect invisible traps */
- if (c_ptr->t_idx != 0)
- {
- /* Hack -- Remember detected traps */
- c_ptr->info |= (CAVE_MARK);
-
- /* Pick a trap */
- pick_trap(y, x);
-
- /* Obvious */
- detect = TRUE;
- }
- }
- }
-
- /* Describe */
- if (detect)
- {
- msg_print("You sense the presence of traps!");
- }
-
- /*
- * This reveals un-identified trap detection items,
- * but so does leaving/entering trap-detected areas...
- * There are a couple of possible solutions:
- * (1) Immediately self-id such items (i.e. always returns TRUE)
- * (2) add another parameter to function which tells if unaware
- * item is used for trap detection, and if it is the case,
- * do two-pass scanning, first scanning for traps if an unaware
- * item is used and return FALSE there are none,
- * followed by current implementation --pelpel
- */
- p_ptr->redraw |= (PR_DTRAP);
-
- /* Result -- see my comment above -- pelpel */
- /* return (detect); */
- return (TRUE);
-}
-
-
-
-/*
- * Detect all doors on current panel
- */
-bool_ detect_doors(int rad)
-{
- int y, x;
-
- bool_ detect = FALSE;
-
- cave_type *c_ptr;
-
-
- /* Scan the panel */
- for (y = p_ptr->py - rad; y <= p_ptr->py + rad; y++)
- {
- for (x = p_ptr->px - rad; x <= p_ptr->px + rad; x++)
- {
- if (!in_bounds(y, x)) continue;
-
- if (distance(p_ptr->py, p_ptr->px, y, x) > rad) continue;
-
- c_ptr = &cave[y][x];
-
- /* Detect secret doors */
- if (c_ptr->feat == FEAT_SECRET)
- {
- /* Remove feature mimics */
- cave[y][x].mimic = 0;
-
- /* Pick a door XXX XXX XXX */
- cave_set_feat(y, x, FEAT_DOOR_HEAD + 0x00);
- }
-
- /* Detect doors */
- if (((c_ptr->feat >= FEAT_DOOR_HEAD) &&
- (c_ptr->feat <= FEAT_DOOR_TAIL)) ||
- ((c_ptr->feat == FEAT_OPEN) ||
- (c_ptr->feat == FEAT_BROKEN)))
- {
- /* Hack -- Memorize */
- c_ptr->info |= (CAVE_MARK);
-
- /* Reveal it */
- /* c_ptr->mimic = 0; */
-
- /* Redraw */
- lite_spot(y, x);
-
- /* Obvious */
- detect = TRUE;
- }
- }
- }
-
- /* Describe */
- if (detect)
- {
- msg_print("You sense the presence of doors!");
- }
-
- /* Result */
- return (detect);
-}
-
-
-/*
- * Detect all stairs on current panel
- */
-bool_ detect_stairs(int rad)
-{
- int y, x;
-
- bool_ detect = FALSE;
-
- cave_type *c_ptr;
-
-
- /* Scan the panel */
- for (y = p_ptr->py - rad; y <= p_ptr->py + rad; y++)
- {
- for (x = p_ptr->px - rad; x <= p_ptr->px + rad; x++)
- {
- if (!in_bounds(y, x)) continue;
-
- if (distance(p_ptr->py, p_ptr->px, y, x) > rad) continue;
-
- c_ptr = &cave[y][x];
-
- /* Detect stairs */
- if ((c_ptr->feat == FEAT_LESS) ||
- (c_ptr->feat == FEAT_MORE) ||
- (c_ptr->feat == FEAT_SHAFT_DOWN) ||
- (c_ptr->feat == FEAT_SHAFT_UP) ||
- (c_ptr->feat == FEAT_WAY_LESS) ||
- (c_ptr->feat == FEAT_WAY_MORE))
- {
- /* Hack -- Memorize */
- c_ptr->info |= (CAVE_MARK);
-
- /* Redraw */
- lite_spot(y, x);
-
- /* Obvious */
- detect = TRUE;
- }
- }
- }
-
- /* Describe */
- if (detect)
- {
- msg_print("You sense the presence of ways out of this area!");
- }
-
- /* Result */
- return (detect);
-}
-
-
-/*
- * Detect any treasure on the current panel
- */
-bool_ detect_treasure(int rad)
-{
- int y, x;
-
- bool_ detect = FALSE;
-
- cave_type *c_ptr;
-
-
- /* Scan the current panel */
- for (y = p_ptr->py - rad; y <= p_ptr->py + rad; y++)
- {
- for (x = p_ptr->px - rad; x <= p_ptr->px + rad; x++)
- {
- if (!in_bounds(y, x)) continue;
-
- if (distance(p_ptr->py, p_ptr->px, y, x) > rad) continue;
-
- c_ptr = &cave[y][x];
-
- /* Notice embedded gold */
- if ((c_ptr->feat == FEAT_MAGMA_H) ||
- (c_ptr->feat == FEAT_QUARTZ_H))
- {
- /* Expose the gold */
- cave_set_feat(y, x, c_ptr->feat + 0x02);
- }
- else if (c_ptr->feat == FEAT_SANDWALL_H)
- {
- /* Expose the gold */
- cave_set_feat(y, x, FEAT_SANDWALL_K);
- }
-
- /* Magma/Quartz + Known Gold */
- if ((c_ptr->feat == FEAT_MAGMA_K) ||
- (c_ptr->feat == FEAT_QUARTZ_K) ||
- (c_ptr->feat == FEAT_SANDWALL_K))
- {
- /* Hack -- Memorize */
- c_ptr->info |= (CAVE_MARK);
-
- /* Redraw */
- lite_spot(y, x);
-
- /* Detect */
- detect = TRUE;
- }
- }
- }
-
- /* Describe */
- if (detect)
- {
- msg_print("You sense the presence of buried treasure!");
- }
-
-
-
- /* Result */
- return (detect);
-}
-
-
-
-/*
- * Detect all "gold" objects on the current panel
- */
-bool_ hack_no_detect_message = FALSE;
-bool_ detect_objects_gold(int rad)
-{
- int i, y, x;
-
- bool_ detect = FALSE;
-
-
- /* Scan 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)
- {
- /* Access the monster */
- monster_type *m_ptr = &m_list[o_ptr->held_m_idx];
- monster_race *r_ptr = race_inf(m_ptr);
-
- if (!(r_ptr->flags9 & RF9_MIMIC)) continue;
- else
- {
- /* Location */
- y = m_ptr->fy;
- x = m_ptr->fx;
- }
- }
- else
- {
- /* Location */
- y = o_ptr->iy;
- x = o_ptr->ix;
- }
-
- /* Only detect nearby objects */
- if (distance(p_ptr->py, p_ptr->px, y, x) > rad) continue;
-
- /* Detect "gold" objects */
- if (o_ptr->tval == TV_GOLD)
- {
- /* Hack -- memorize it */
- o_ptr->marked = TRUE;
-
- /* Redraw */
- if (panel_contains(y, x)) lite_spot(y, x);
-
- /* Detect */
- detect = TRUE;
- }
- }
-
- /* Describe */
- if (detect && (!hack_no_detect_message))
- {
- msg_print("You sense the presence of treasure!");
- }
-
- if (detect_monsters_string("$", rad))
- {
- detect = TRUE;
- }
-
- /* Result */
- return (detect);
-}
-
-
-/*
- * Detect all "normal" objects on the current panel
- */
-bool_ detect_objects_normal(int rad)
-{
- int i, y, x;
-
- bool_ detect = FALSE;
-
-
- /* Scan 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)
- {
- /* Access the monster */
- monster_type *m_ptr = &m_list[o_ptr->held_m_idx];
- monster_race *r_ptr = race_inf(m_ptr);
-
- if (!(r_ptr->flags9 & RF9_MIMIC)) continue;
- else
- {
- /* Location */
- y = m_ptr->fy;
- x = m_ptr->fx;
- }
- }
- else
- {
- /* Location */
- y = o_ptr->iy;
- x = o_ptr->ix;
- }
-
- /* Only detect nearby objects */
- if (distance(p_ptr->py, p_ptr->px, y, x) > rad) continue;
-
- /* Detect "real" objects */
- if (o_ptr->tval != TV_GOLD)
- {
- /* Hack -- memorize it */
- o_ptr->marked = TRUE;
-
- /* Redraw */
- if (panel_contains(y, x)) lite_spot(y, x);
-
- /* Detect */
- detect = TRUE;
- }
- }
-
- /* Describe */
- if (detect && (!hack_no_detect_message))
- {
- msg_print("You sense the presence of objects!");
- }
-
- if (detect_monsters_string("!=?|", rad))
- {
- detect = TRUE;
- }
-
- /* Result */
- return (detect);
-}
-
-
-/*
- * Detect all "magic" objects on the current panel.
- *
- * 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.
- *
- * It can probably be argued that this function is now too powerful.
- */
-bool_ detect_objects_magic(int rad)
-{
- int i, y, x, tv;
-
- bool_ detect = FALSE;
-
-
- /* Scan 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)
- {
- /* Access the monster */
- monster_type *m_ptr = &m_list[o_ptr->held_m_idx];
- monster_race *r_ptr = race_inf(m_ptr);
-
- if (!(r_ptr->flags9 & RF9_MIMIC)) continue;
- else
- {
- /* Location */
- y = m_ptr->fy;
- x = m_ptr->fx;
- }
- }
- else
- {
- /* Location */
- y = o_ptr->iy;
- x = o_ptr->ix;
- }
-
- /* Only detect nearby objects */
- if (distance(p_ptr->py, p_ptr->px, y, x) > rad) continue;
-
- /* Examine the tval */
- tv = o_ptr->tval;
-
- /* Artifacts, misc magic items, or enchanted wearables */
- if (artifact_p(o_ptr) || ego_item_p(o_ptr) || o_ptr->art_name ||
- (tv == TV_AMULET) || (tv == TV_RING) || (tv == TV_BATERIE) ||
- (tv == TV_STAFF) || (tv == TV_WAND) || (tv == TV_ROD) || (tv == TV_ROD_MAIN) ||
- (tv == TV_SCROLL) || (tv == TV_POTION) || (tv == TV_POTION2) ||
- (tv == TV_DAEMON_BOOK) ||
- (tv == TV_SYMBIOTIC_BOOK) || (tv == TV_MUSIC_BOOK) ||
- ((o_ptr->to_a > 0) || (o_ptr->to_h + o_ptr->to_d > 0)))
- {
- /* Memorize the item */
- o_ptr->marked = TRUE;
-
- /* Redraw */
- if (panel_contains(y, x)) lite_spot(y, x);
-
- /* Detect */
- detect = TRUE;
- }
- }
-
- /* Describe */
- if (detect)
- {
- msg_print("You sense the presence of magic objects!");
- }
-
- /* Return result */
- return (detect);
-}
-
-
-/*
- * Detect all "normal" monsters on the current panel
- */
-bool_ detect_monsters_normal(int rad)
-{
- int i, y, x;
-
- bool_ flag = FALSE;
-
-
- /* Scan monsters */
- for (i = 1; i < m_max; i++)
- {
- monster_type *m_ptr = &m_list[i];
- monster_race *r_ptr = race_inf(m_ptr);
-
- /* Skip dead monsters */
- if (!m_ptr->r_idx) continue;
-
- /* Location */
- y = m_ptr->fy;
- x = m_ptr->fx;
-
- /* Only detect nearby monsters */
- if (m_ptr->cdis > rad) continue;
-
- /* Detect all non-invisible monsters */
- if ((!(r_ptr->flags2 & (RF2_INVISIBLE))) ||
- p_ptr->see_inv || p_ptr->tim_invis)
- {
- /* Repair visibility later */
- repair_monsters = TRUE;
-
- /* Hack -- Detect monster */
- m_ptr->mflag |= (MFLAG_MARK | MFLAG_SHOW);
-
- /* Hack -- See monster */
- m_ptr->ml = TRUE;
-
- /* Redraw */
- if (panel_contains(y, x)) lite_spot(y, x);
-
- /* Detect */
- flag = TRUE;
- }
- }
-
- /* Describe */
- if (flag)
- {
- /* Describe result */
- msg_print("You sense the presence of monsters!");
- }
-
- /* Result */
- return (flag);
-}
-
-
-/*
- * Detect all "invisible" monsters on current panel
- */
-bool_ detect_monsters_invis(int rad)
-{
- int i, y, x;
- bool_ flag = FALSE;
-
- /* Scan monsters */
- for (i = 1; i < m_max; i++)
- {
- monster_type *m_ptr = &m_list[i];
- monster_race *r_ptr = race_inf(m_ptr);
-
- /* Skip dead monsters */
- if (!m_ptr->r_idx) continue;
-
- /* Location */
- y = m_ptr->fy;
- x = m_ptr->fx;
-
- /* Only detect nearby monsters */
- if (m_ptr->cdis > rad) continue;
-
- /* Detect invisible monsters */
- if (r_ptr->flags2 & (RF2_INVISIBLE))
- {
- /* Take note that they are invisible */
- r_ptr->r_flags2 |= (RF2_INVISIBLE);
-
- /* Update monster recall window */
- if (monster_race_idx == m_ptr->r_idx)
- {
- /* Window stuff */
- p_ptr->window |= (PW_MONSTER);
- }
-
- /* Repair visibility later */
- repair_monsters = TRUE;
-
- /* Hack -- Detect monster */
- m_ptr->mflag |= (MFLAG_MARK | MFLAG_SHOW);
-
- /* Hack -- See monster */
- m_ptr->ml = TRUE;
-
- /* Redraw */
- if (panel_contains(y, x)) lite_spot(y, x);
-
- /* Detect */
- flag = TRUE;
- }
- }
-
- /* Describe */
- if (flag)
- {
- /* Describe result */
- msg_print("You sense the presence of invisible creatures!");
- }
-
- /* Result */
- return (flag);
-}
-
-
-
-/*
- * Detect all "evil" monsters on current panel
- */
-bool_ detect_monsters_evil(int rad)
-{
- int i, y, x;
- bool_ flag = FALSE;
-
-
- /* Scan monsters */
- for (i = 1; i < m_max; i++)
- {
- monster_type *m_ptr = &m_list[i];
- monster_race *r_ptr = race_inf(m_ptr);
-
- /* Skip dead monsters */
- if (!m_ptr->r_idx) continue;
-
- /* Location */
- y = m_ptr->fy;
- x = m_ptr->fx;
-
- /* Only detect nearby monsters */
- if (m_ptr->cdis > rad) continue;
-
- /* Detect evil monsters */
- if (r_ptr->flags3 & (RF3_EVIL))
- {
- /* Take note that they are evil */
- r_ptr->r_flags3 |= (RF3_EVIL);
-
- /* Update monster recall window */
- if (monster_race_idx == m_ptr->r_idx)
- {
- /* Window stuff */
- p_ptr->window |= (PW_MONSTER);
- }
-
- /* Repair visibility later */
- repair_monsters = TRUE;
-
- /* Hack -- Detect monster */
- m_ptr->mflag |= (MFLAG_MARK | MFLAG_SHOW);
-
- /* Hack -- See monster */
- m_ptr->ml = TRUE;
-
- /* Redraw */
- if (panel_contains(y, x)) lite_spot(y, x);
-
- /* Detect */
- flag = TRUE;
- }
- }
-
- /* Describe */
- if (flag)
- {
- /* Describe result */
- msg_print("You sense the presence of evil creatures!");
- }
-
- /* Result */
- return (flag);
-}
-
-
-
-
-/*
- * Detect all (string) monsters on current panel
- */
-bool_ detect_monsters_string(cptr chars, int rad)
-{
- int i, y, x;
- bool_ flag = FALSE;
-
-
- /* Scan monsters */
- for (i = 1; i < m_max; i++)
- {
- monster_type *m_ptr = &m_list[i];
- monster_race *r_ptr = race_inf(m_ptr);
-
- /* Skip dead monsters */
- if (!m_ptr->r_idx) continue;
-
- /* Location */
- y = m_ptr->fy;
- x = m_ptr->fx;
-
- /* Only detect nearby monsters */
- if (m_ptr->cdis > rad) continue;
-
- /* Detect evil monsters */
- if (strchr(chars, r_ptr->d_char))
- {
-
- /* Update monster recall window */
- if (monster_race_idx == m_ptr->r_idx)
- {
- /* Window stuff */
- p_ptr->window |= (PW_MONSTER);
- }
-
- /* Repair visibility later */
- repair_monsters = TRUE;
-
- /* Hack -- Detect monster */
- m_ptr->mflag |= (MFLAG_MARK | MFLAG_SHOW);
-
- /* Hack -- See monster */
- m_ptr->ml = TRUE;
-
- /* Redraw */
- if (panel_contains(y, x)) lite_spot(y, x);
-
- /* Detect */
- flag = TRUE;
- }
- }
-
- /* Describe */
- if (flag)
- {
- /* Describe result */
- msg_print("You sense the presence of monsters!");
- }
-
- /* Result */
- return (flag);
-}
-
-
-/*
- * A "generic" detect monsters routine, tagged to flags3
- */
-bool_ detect_monsters_xxx(u32b match_flag, int rad)
-{
- int i, y, x;
- bool_ flag = FALSE;
- cptr desc_monsters = "weird monsters";
-
-
- /* Scan monsters */
- for (i = 1; i < m_max; i++)
- {
- monster_type *m_ptr = &m_list[i];
- monster_race *r_ptr = race_inf(m_ptr);
-
- /* Skip dead monsters */
- if (!m_ptr->r_idx) continue;
-
- /* Location */
- y = m_ptr->fy;
- x = m_ptr->fx;
-
- /* Only detect nearby monsters */
- if (m_ptr->cdis > rad) continue;
-
- /* Detect evil monsters */
- if (r_ptr->flags3 & (match_flag))
- {
- /* Take note that they are something */
- r_ptr->r_flags3 |= (match_flag);
-
- /* Update monster recall window */
- if (monster_race_idx == m_ptr->r_idx)
- {
- /* Window stuff */
- p_ptr->window |= (PW_MONSTER);
- }
-
- /* Repair visibility later */
- repair_monsters = TRUE;
-
- /* Hack -- Detect monster */
- m_ptr->mflag |= (MFLAG_MARK | MFLAG_SHOW);
-
- /* Hack -- See monster */
- m_ptr->ml = TRUE;
-
- /* Redraw */
- if (panel_contains(y, x)) lite_spot(y, x);
-
- /* Detect */
- flag = TRUE;
- }
- }
-
- /* Describe */
- if (flag)
- {
- switch (match_flag)
- {
- case RF3_DEMON:
- desc_monsters = "demons";
- break;
- case RF3_UNDEAD:
- desc_monsters = "the undead";
- break;
- case RF3_GOOD:
- desc_monsters = "good";
- break;
- }
-
- /* Describe result */
- msg_format("You sense the presence of %s!", desc_monsters);
- msg_print(NULL);
- }
-
- /* Result */
- return (flag);
-}
-
-/* Detect good monsters */
-bool_ detect_monsters_good(int rad)
-{
- return (detect_monsters_xxx(RF3_GOOD, rad));
-}
-
-
-/*
- * Detect everything
- */
-bool_ detect_all(int rad)
-{
- bool_ detect = FALSE;
-
- /* Detect everything */
- if (detect_traps(rad)) detect = TRUE;
- if (detect_doors(rad)) detect = TRUE;
- if (detect_stairs(rad)) detect = TRUE;
- if (detect_treasure(rad)) detect = TRUE;
- if (detect_objects_gold(rad)) detect = TRUE;
- if (detect_objects_normal(rad)) detect = TRUE;
- if (detect_monsters_invis(rad)) detect = TRUE;
- if (detect_monsters_normal(rad)) detect = TRUE;
-
- /* Result */
- return (detect);
-}
-
-
-
-/*
- * Create stairs at the player location
- */
-void stair_creation(void)
-{
- /* XXX XXX XXX */
- if (!cave_valid_bold(p_ptr->py, p_ptr->px))
- {
- msg_print("The object resists the spell.");
- return;
- }
-
- if (dungeon_flags1 & DF1_FLAT)
- {
- msg_print("No stair creation in non dungeons...");
- return;
- }
-
- if (dungeon_flags2 & DF2_SPECIAL)
- {
- msg_print("No stair creation on special levels...");
- return;
- }
-
- /* XXX XXX XXX */
- delete_object(p_ptr->py, p_ptr->px);
-
- /* Create a staircase */
- if (p_ptr->inside_arena || p_ptr->inside_quest)
- {
- /* arena or quest */
- msg_print("There is no effect!");
- }
- else if (!dun_level)
- {
- /* Town/wilderness */
- cave_set_feat(p_ptr->py, p_ptr->px, FEAT_MORE);
- }
- else if (is_quest(dun_level) || (dun_level >= MAX_DEPTH - 1))
- {
- /* Quest level */
- cave_set_feat(p_ptr->py, p_ptr->px, FEAT_LESS);
- }
- else if (rand_int(100) < 50)
- {
- cave_set_feat(p_ptr->py, p_ptr->px, FEAT_MORE);
- }
- else
- {
- cave_set_feat(p_ptr->py, p_ptr->px, FEAT_LESS);
- }
-}
-
-
-
-
-/*
- * Hook to specify "weapon"
- */
-static bool_ item_tester_hook_weapon(object_type *o_ptr)
-{
- switch (o_ptr->tval)
- {
- case TV_MSTAFF:
- case TV_BOOMERANG:
- case TV_SWORD:
- case TV_AXE:
- case TV_HAFTED:
- case TV_POLEARM:
- case TV_BOW:
- case TV_BOLT:
- case TV_ARROW:
- case TV_SHOT:
- {
- return (TRUE);
- }
- case TV_DAEMON_BOOK:
- {
- switch (o_ptr->sval)
- {
- case SV_DEMONBLADE:
- {
- return (TRUE);
- }
- }
- }
- }
-
- return (FALSE);
-}
-
-
-/*
- * Hook to specify "armour"
- */
-bool_ item_tester_hook_armour(object_type *o_ptr)
-{
- switch (o_ptr->tval)
- {
- case TV_DRAG_ARMOR:
- case TV_HARD_ARMOR:
- case TV_SOFT_ARMOR:
- case TV_SHIELD:
- case TV_CLOAK:
- case TV_CROWN:
- case TV_HELM:
- case TV_BOOTS:
- case TV_GLOVES:
- {
- return (TRUE);
- }
- case TV_DAEMON_BOOK:
- {
- switch (o_ptr->sval)
- {
- case SV_DEMONHORN:
- case SV_DEMONSHIELD:
- {
- return (TRUE);
- }
- }
- }
- }
-
- return (FALSE);
-}
-
-
-/*
- * Check if an object is weapon or armour (but not arrow, bolt, or shot)
- */
-bool_ item_tester_hook_weapon_armour(object_type *o_ptr)
-{
- return (item_tester_hook_weapon(o_ptr) ||
- item_tester_hook_armour(o_ptr));
-}
-
-/*
- * Check if an object is artifactable
- */
-bool_ item_tester_hook_artifactable(object_type *o_ptr)
-{
- return ((item_tester_hook_weapon(o_ptr) ||
- item_tester_hook_armour(o_ptr) ||
- (o_ptr->tval == TV_DIGGING) ||
- (o_ptr->tval == TV_RING) || (o_ptr->tval == TV_AMULET))
- /* be nice: allow only normal items */
- && (!artifact_p(o_ptr)) && (!ego_item_p(o_ptr)));
-}
-
-
-/*
- * Enchants a plus onto an item. -RAK-
- *
- * Revamped! Now takes item pointer, number of times to try enchanting,
- * and a flag of what to try enchanting. Artifacts resist enchantment
- * some of the time, and successful enchantment to at least +0 might
- * break a curse on the item. -CFT-
- *
- * Note that an item can technically be enchanted all the way to +15 if
- * you wait a very, very, long time. Going from +9 to +10 only works
- * about 5% of the time, and from +10 to +11 only about 1% of the time.
- *
- * Note that this function can now be used on "piles" of items, and
- * the larger the pile, the lower the chance of success.
- */
-bool_ enchant(object_type *o_ptr, int n, int eflag)
-{
- int i, chance, prob;
- bool_ res = FALSE;
- bool_ a = (artifact_p(o_ptr) || o_ptr->art_name);
- u32b f1, f2, f3, f4, f5, esp;
-
-
- /* Extract the flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
-
- /* Large piles resist enchantment */
- prob = o_ptr->number * 100;
-
- /* Missiles are easy to enchant */
- if ((o_ptr->tval == TV_BOLT) ||
- (o_ptr->tval == TV_ARROW) ||
- (o_ptr->tval == TV_SHOT))
- {
- prob = prob / 20;
- }
-
- /* Try "n" times */
- for (i = 0; i < n; i++)
- {
- /* Hack -- Roll for pile resistance */
- if (rand_int(prob) >= 100) continue;
-
- /* Enchant to hit */
- if (eflag & (ENCH_TOHIT))
- {
- if (o_ptr->to_h < 0) chance = 0;
- else if (o_ptr->to_h > 15) chance = 1000;
- else chance = enchant_table[o_ptr->to_h];
-
- if ((randint(1000) > chance) && (!a || (rand_int(100) < 50)))
- {
- o_ptr->to_h++;
- res = TRUE;
-
- /* only when you get it above -1 -CFT */
- if (cursed_p(o_ptr) &&
- (!(f3 & (TR3_PERMA_CURSE))) &&
- (o_ptr->to_h >= 0) && (rand_int(100) < 25))
- {
- msg_print("The curse is broken!");
- o_ptr->ident &= ~(IDENT_CURSED);
- o_ptr->ident |= (IDENT_SENSE);
-
- if (o_ptr->art_flags3 & (TR3_CURSED))
- o_ptr->art_flags3 &= ~(TR3_CURSED);
- if (o_ptr->art_flags3 & (TR3_HEAVY_CURSE))
- o_ptr->art_flags3 &= ~(TR3_HEAVY_CURSE);
-
- o_ptr->sense = SENSE_UNCURSED;
- }
- }
- }
-
- /* Enchant to damage */
- if (eflag & (ENCH_TODAM))
- {
- if (o_ptr->to_d < 0) chance = 0;
- else if (o_ptr->to_d > 15) chance = 1000;
- else chance = enchant_table[o_ptr->to_d];
-
- if ((randint(1000) > chance) && (!a || (rand_int(100) < 50)))
- {
- o_ptr->to_d++;
- res = TRUE;
-
- /* only when you get it above -1 -CFT */
- if (cursed_p(o_ptr) &&
- (!(f3 & (TR3_PERMA_CURSE))) &&
- (o_ptr->to_d >= 0) && (rand_int(100) < 25))
- {
- msg_print("The curse is broken!");
- o_ptr->ident &= ~(IDENT_CURSED);
- o_ptr->ident |= (IDENT_SENSE);
-
- if (o_ptr->art_flags3 & (TR3_CURSED))
- o_ptr->art_flags3 &= ~(TR3_CURSED);
- if (o_ptr->art_flags3 & (TR3_HEAVY_CURSE))
- o_ptr->art_flags3 &= ~(TR3_HEAVY_CURSE);
-
- o_ptr->sense = SENSE_UNCURSED;
- }
- }
- }
-
-
- /* Enchant to damage */
- if (eflag & (ENCH_PVAL))
- {
- if (o_ptr->pval < 0) chance = 0;
- else if (o_ptr->pval > 6) chance = 1000;
- else chance = enchant_table[o_ptr->pval * 2];
-
- if ((randint(1000) > chance) && (!a || (rand_int(100) < 50)))
- {
- o_ptr->pval++;
- res = TRUE;
-
- /* only when you get it above -1 -CFT */
- if (cursed_p(o_ptr) &&
- (!(f3 & (TR3_PERMA_CURSE))) &&
- (o_ptr->pval >= 0) && (rand_int(100) < 25))
- {
- msg_print("The curse is broken!");
- o_ptr->ident &= ~(IDENT_CURSED);
- o_ptr->ident |= (IDENT_SENSE);
-
- if (o_ptr->art_flags3 & (TR3_CURSED))
- o_ptr->art_flags3 &= ~(TR3_CURSED);
- if (o_ptr->art_flags3 & (TR3_HEAVY_CURSE))
- o_ptr->art_flags3 &= ~(TR3_HEAVY_CURSE);
-
- o_ptr->sense = SENSE_UNCURSED;
- }
- }
- }
-
- /* Enchant to armor class */
- if (eflag & (ENCH_TOAC))
- {
- if (o_ptr->to_a < 0) chance = 0;
- else if (o_ptr->to_a > 15) chance = 1000;
- else chance = enchant_table[o_ptr->to_a];
-
- if ((randint(1000) > chance) && (!a || (rand_int(100) < 50)))
- {
- o_ptr->to_a++;
- res = TRUE;
-
- /* only when you get it above -1 -CFT */
- if (cursed_p(o_ptr) &&
- (!(f3 & (TR3_PERMA_CURSE))) &&
- (o_ptr->to_a >= 0) && (rand_int(100) < 25))
- {
- msg_print("The curse is broken!");
- o_ptr->ident &= ~(IDENT_CURSED);
- o_ptr->ident |= (IDENT_SENSE);
-
- if (o_ptr->art_flags3 & (TR3_CURSED))
- o_ptr->art_flags3 &= ~(TR3_CURSED);
- if (o_ptr->art_flags3 & (TR3_HEAVY_CURSE))
- o_ptr->art_flags3 &= ~(TR3_HEAVY_CURSE);
-
- o_ptr->sense = SENSE_UNCURSED;
- }
- }
- }
- }
-
- /* Failure */
- if (!res) return (FALSE);
-
- /* Recalculate bonuses */
- p_ptr->update |= (PU_BONUS);
-
- /* Combine / Reorder the pack (later) */
- p_ptr->notice |= (PN_COMBINE | PN_REORDER);
-
- /* Window stuff */
- p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
-
- /* Success */
- return (TRUE);
-}
-
-
-
-/*
- * Enchant an item (in the inventory or on the floor)
- * Note that "num_ac" requires armour, else weapon
- * Returns TRUE if attempted, FALSE if cancelled
- */
-bool_ enchant_spell(int num_hit, int num_dam, int num_ac, int num_pval)
-{
- int item;
- bool_ okay = FALSE;
- object_type *o_ptr;
- char o_name[80];
- cptr q, s;
-
-
- /* Assume enchant weapon */
- item_tester_hook = item_tester_hook_weapon;
-
- /* Enchant armor if requested */
- if (num_ac) item_tester_hook = item_tester_hook_armour;
-
- /* Get an item */
- q = "Enchant which item? ";
- s = "You have nothing to enchant.";
- if (!get_item(&item, q, s, (USE_EQUIP | USE_INVEN | USE_FLOOR))) return (FALSE);
-
- /* Get the item */
- o_ptr = get_object(item);
-
- /* Description */
- object_desc(o_name, o_ptr, FALSE, 0);
-
- /* Describe */
- msg_format("%s %s glow%s brightly!",
- ((item >= 0) ? "Your" : "The"), o_name,
- ((o_ptr->number > 1) ? "" : "s"));
-
- /* Enchant */
- if (enchant(o_ptr, num_hit, ENCH_TOHIT)) okay = TRUE;
- if (enchant(o_ptr, num_dam, ENCH_TODAM)) okay = TRUE;
- if (enchant(o_ptr, num_ac, ENCH_TOAC)) okay = TRUE;
- if (enchant(o_ptr, num_pval, ENCH_PVAL)) okay = TRUE;
-
- /* Failure */
- if (!okay)
- {
- /* Flush */
- if (flush_failure) flush();
-
- /* Message */
- msg_print("The enchantment failed.");
- }
-
- /* Something happened */
- return (TRUE);
-}
-
-void curse_artifact(object_type * o_ptr)
-{
- if (o_ptr->pval) o_ptr->pval = 0 - ((o_ptr->pval) + randint(4));
- if (o_ptr->to_a) o_ptr->to_a = 0 - ((o_ptr->to_a) + randint(4));
- if (o_ptr->to_h) o_ptr->to_h = 0 - ((o_ptr->to_h) + randint(4));
- if (o_ptr->to_d) o_ptr->to_d = 0 - ((o_ptr->to_d) + randint(4));
- o_ptr->art_flags3 |= ( TR3_HEAVY_CURSE | TR3_CURSED );
- if (randint(3) == 1) o_ptr-> art_flags3 |= TR3_TY_CURSE;
- if (randint(2) == 1) o_ptr-> art_flags3 |= TR3_AGGRAVATE;
- if (randint(3) == 1) o_ptr-> art_flags3 |= TR3_DRAIN_EXP;
- if (randint(3) == 1) o_ptr-> art_flags4 |= TR4_BLACK_BREATH;
- if (randint(2) == 1) o_ptr-> art_flags3 |= TR3_TELEPORT;
- else if (randint(3) == 1) o_ptr->art_flags3 |= TR3_NO_TELE;
- o_ptr->ident |= IDENT_CURSED;
-}
-
-
-/*
- * Should be merged with randart code.
- * looks like BASIC coder's work...
- */
-void random_plus(object_type * o_ptr, bool_ is_scroll)
-{
- int this_type = (o_ptr->tval < TV_BOOTS ? 23 : 19);
-
- if (artifact_bias == BIAS_WARRIOR)
- {
- if (!(o_ptr->art_flags1 & TR1_STR))
- {
- o_ptr->art_flags1 |= TR1_STR;
- if (randint(2) == 1) return ; /* 50% chance of being a "free" power */
- }
-
- if (!(o_ptr->art_flags1 & TR1_CON))
- {
- o_ptr->art_flags1 |= TR1_CON;
- if (randint(2) == 1) return;
- }
-
- if (!(o_ptr->art_flags1 & TR1_DEX))
- {
- o_ptr->art_flags1 |= TR1_DEX;
- if (randint(2) == 1) return;
- }
- }
- else if (artifact_bias == BIAS_MAGE)
- {
- if (!(o_ptr->art_flags1 & TR1_INT))
- {
- o_ptr->art_flags1 |= TR1_INT;
- if (randint(2) == 1) return;
- }
- }
- else if (artifact_bias == BIAS_PRIESTLY)
- {
- if (!(o_ptr->art_flags1 & TR1_WIS))
- {
- o_ptr->art_flags1 |= TR1_WIS;
- if (randint(2) == 1) return;
- }
- }
- else if (artifact_bias == BIAS_RANGER)
- {
- if (!(o_ptr->art_flags1 & TR1_CON))
- {
- o_ptr->art_flags1 |= TR1_CON;
- if (randint(2) == 1) return ; /* 50% chance of being a "free" power */
- }
-
- if (!(o_ptr->art_flags1 & TR1_DEX))
- {
- o_ptr->art_flags1 |= TR1_DEX;
- if (randint(2) == 1) return;
- }
-
- if (!(o_ptr->art_flags1 & TR1_STR))
- {
- o_ptr->art_flags1 |= TR1_STR;
- if (randint(2) == 1) return;
- }
- }
- else if (artifact_bias == BIAS_ROGUE)
- {
- if (!(o_ptr->art_flags1 & TR1_STEALTH))
- {
- o_ptr->art_flags1 |= TR1_STEALTH;
- if (randint(2) == 1) return;
- }
- if (!(o_ptr->art_flags1 & TR1_SEARCH))
- {
- o_ptr->art_flags1 |= TR1_SEARCH;
- if (randint(2) == 1) return;
- }
- }
- else if (artifact_bias == BIAS_STR)
- {
- if (!(o_ptr->art_flags1 & TR1_STR))
- {
- o_ptr->art_flags1 |= TR1_STR;
- if (randint(2) == 1) return;
- }
- }
- else if (artifact_bias == BIAS_WIS)
- {
- if (!(o_ptr->art_flags1 & TR1_WIS))
- {
- o_ptr->art_flags1 |= TR1_WIS;
- if (randint(2) == 1) return;
- }
- }
- else if (artifact_bias == BIAS_INT)
- {
- if (!(o_ptr->art_flags1 & TR1_INT))
- {
- o_ptr->art_flags1 |= TR1_INT;
- if (randint(2) == 1) return;
- }
- }
- else if (artifact_bias == BIAS_DEX)
- {
- if (!(o_ptr->art_flags1 & TR1_DEX))
- {
- o_ptr->art_flags1 |= TR1_DEX;
- if (randint(2) == 1) return;
- }
- }
- else if (artifact_bias == BIAS_CON)
- {
- if (!(o_ptr->art_flags1 & TR1_CON))
- {
- o_ptr->art_flags1 |= TR1_CON;
- if (randint(2) == 1) return;
- }
- }
- else if (artifact_bias == BIAS_CHR)
- {
- if (!(o_ptr->art_flags1 & TR1_CHR))
- {
- o_ptr->art_flags1 |= TR1_CHR;
- if (randint(2) == 1) return;
- }
- }
-
-
- switch (randint(this_type))
- {
- case 1:
- case 2:
- o_ptr->art_flags1 |= TR1_STR;
- /* if (is_scroll) msg_print("It makes you feel strong!"); */
- if (!(artifact_bias) && randint(13) != 1)
- artifact_bias = BIAS_STR;
- else if (!(artifact_bias) && randint(7) == 1)
- artifact_bias = BIAS_WARRIOR;
- break;
- case 3:
- case 4:
- o_ptr->art_flags1 |= TR1_INT;
- /* if (is_scroll) msg_print("It makes you feel smart!"); */
- if (!(artifact_bias) && randint(13) != 1)
- artifact_bias = BIAS_INT;
- else if (!(artifact_bias) && randint(7) == 1)
- artifact_bias = BIAS_MAGE;
- break;
- case 5:
- case 6:
- o_ptr->art_flags1 |= TR1_WIS;
- /* if (is_scroll) msg_print("It makes you feel wise!"); */
- if (!(artifact_bias) && randint(13) != 1)
- artifact_bias = BIAS_WIS;
- else if (!(artifact_bias) && randint(7) == 1)
- artifact_bias = BIAS_PRIESTLY;
- break;
- case 7:
- case 8:
- o_ptr->art_flags1 |= TR1_DEX;
- /* if (is_scroll) msg_print("It makes you feel nimble!"); */
- if (!(artifact_bias) && randint(13) != 1)
- artifact_bias = BIAS_DEX;
- else if (!(artifact_bias) && randint(7) == 1)
- artifact_bias = BIAS_ROGUE;
- break;
- case 9:
- case 10:
- o_ptr->art_flags1 |= TR1_CON;
- /* if (is_scroll) msg_print("It makes you feel healthy!"); */
- if (!(artifact_bias) && randint(13) != 1)
- artifact_bias = BIAS_CON;
- else if (!(artifact_bias) && randint(9) == 1)
- artifact_bias = BIAS_RANGER;
- break;
- case 11:
- case 12:
- o_ptr->art_flags1 |= TR1_CHR;
- /* if (is_scroll) msg_print("It makes you look great!"); */
- if (!(artifact_bias) && randint(13) != 1)
- artifact_bias = BIAS_CHR;
- break;
- case 13:
- case 14:
- o_ptr->art_flags1 |= TR1_STEALTH;
- /* if (is_scroll) msg_print("It looks muffled."); */
- if (!(artifact_bias) && randint(3) == 1)
- artifact_bias = BIAS_ROGUE;
- break;
- case 15:
- case 16:
- o_ptr->art_flags1 |= TR1_SEARCH;
- /* if (is_scroll) msg_print("It makes you see better."); */
- if (!(artifact_bias) && randint(9) == 1)
- artifact_bias = BIAS_RANGER;
- break;
- case 17:
- case 18:
- o_ptr->art_flags1 |= TR1_INFRA;
- /* if (is_scroll) msg_print("It makes you see tiny red animals.");*/
- break;
- case 19:
- o_ptr->art_flags1 |= TR1_SPEED;
- /* if (is_scroll) msg_print("It makes you move faster!"); */
- if (!(artifact_bias) && randint(11) == 1)
- artifact_bias = BIAS_ROGUE;
- break;
- case 20:
- case 21:
- o_ptr->art_flags1 |= TR1_TUNNEL;
- /* if (is_scroll) msg_print("Gravel flies from it!"); */
- break;
- case 22:
- case 23:
- if (o_ptr->tval == TV_BOW) random_plus(o_ptr, is_scroll);
- else
- {
- o_ptr->art_flags1 |= TR1_BLOWS;
- /* if (is_scroll) msg_print("It seems faster!"); */
- if (!(artifact_bias) && randint(11) == 1)
- artifact_bias = BIAS_WARRIOR;
- }
- break;
- }
-}
-
-
-void random_resistance (object_type * o_ptr, bool_ is_scroll, int specific)
-{
- /* To avoid a number of possible bugs */
- if (!specific)
- {
- if (artifact_bias == BIAS_ACID)
- {
- if (!(o_ptr->art_flags2 & TR2_RES_ACID))
- {
- o_ptr->art_flags2 |= TR2_RES_ACID;
- if (rand_int(2) == 0) return;
- }
- if (rand_int(BIAS_LUCK) == 0 && !(o_ptr->art_flags2 & TR2_IM_ACID))
- {
- o_ptr->art_flags2 |= TR2_IM_ACID;
- if (rand_int(2) == 0) return;
- }
- }
- else if (artifact_bias == BIAS_ELEC)
- {
- if (!(o_ptr->art_flags2 & TR2_RES_ELEC))
- {
- o_ptr->art_flags2 |= TR2_RES_ELEC;
- if (rand_int(2) == 0) return;
- }
- if (o_ptr->tval >= TV_CLOAK && o_ptr->tval <= TV_HARD_ARMOR &&
- !(o_ptr->art_flags3 & TR3_SH_ELEC))
- {
- o_ptr->art_flags2 |= TR3_SH_ELEC;
- if (rand_int(2) == 0) return;
- }
- if (rand_int(BIAS_LUCK) == 0 && !(o_ptr->art_flags2 & TR2_IM_ELEC))
- {
- o_ptr->art_flags2 |= TR2_IM_ELEC;
- if (rand_int(2) == 1) return;
- }
- }
- else if (artifact_bias == BIAS_FIRE)
- {
- if (!(o_ptr->art_flags2 & TR2_RES_FIRE))
- {
- o_ptr->art_flags2 |= TR2_RES_FIRE;
- if (rand_int(2) == 0) return;
- }
- if (o_ptr->tval >= TV_CLOAK && o_ptr->tval <= TV_HARD_ARMOR &&
- !(o_ptr->art_flags3 & TR3_SH_FIRE))
- {
- o_ptr->art_flags2 |= TR3_SH_FIRE;
- if (rand_int(2) == 0) return;
- }
- if (rand_int(BIAS_LUCK) == 0 && !(o_ptr->art_flags2 & TR2_IM_FIRE))
- {
- o_ptr->art_flags2 |= TR2_IM_FIRE;
- if (rand_int(2) == 0) return;
- }
- }
- else if (artifact_bias == BIAS_COLD)
- {
- if (!(o_ptr->art_flags2 & TR2_RES_COLD))
- {
- o_ptr->art_flags2 |= TR2_RES_COLD;
- if (rand_int(2) == 0) return;
- }
- if (rand_int(BIAS_LUCK) == 0 && !(o_ptr->art_flags2 & TR2_IM_COLD))
- {
- o_ptr->art_flags2 |= TR2_IM_COLD;
- if (rand_int(2) == 0) return;
- }
- }
- else if (artifact_bias == BIAS_POIS)
- {
- if (!(o_ptr->art_flags2 & TR2_RES_POIS))
- {
- o_ptr->art_flags2 |= TR2_RES_POIS;
- if (rand_int(2) == 0) return;
- }
- }
- else if (artifact_bias == BIAS_WARRIOR)
- {
- if (rand_int(3) && (!(o_ptr->art_flags2 & TR2_RES_FEAR)))
- {
- o_ptr->art_flags2 |= TR2_RES_FEAR;
- if (rand_int(2) == 0) return;
- }
- if ((rand_int(3) == 0) && (!(o_ptr->art_flags3 & TR3_NO_MAGIC)))
- {
- o_ptr->art_flags3 |= TR3_NO_MAGIC;
- if (rand_int(2) == 0) return;
- }
- }
- else if (artifact_bias == BIAS_NECROMANTIC)
- {
- if (!(o_ptr->art_flags2 & TR2_RES_NETHER))
- {
- o_ptr->art_flags2 |= TR2_RES_NETHER;
- if (rand_int(2) == 0) return;
- }
- if (!(o_ptr->art_flags2 & TR2_RES_POIS))
- {
- o_ptr->art_flags2 |= TR2_RES_POIS;
- if (rand_int(2) == 0) return;
- }
- if (!(o_ptr->art_flags2 & TR2_RES_DARK))
- {
- o_ptr->art_flags2 |= TR2_RES_DARK;
- if (rand_int(2) == 0) return;
- }
- }
- else if (artifact_bias == BIAS_CHAOS)
- {
- if (!(o_ptr->art_flags2 & TR2_RES_CHAOS))
- {
- o_ptr->art_flags2 |= TR2_RES_CHAOS;
- if (rand_int(2) == 0) return;
- }
- if (!(o_ptr->art_flags2 & TR2_RES_CONF))
- {
- o_ptr->art_flags2 |= TR2_RES_CONF;
- if (rand_int(2) == 0) return;
- }
- if (!(o_ptr->art_flags2 & TR2_RES_DISEN))
- {
- o_ptr->art_flags2 |= TR2_RES_DISEN;
- if (rand_int(2) == 0) return;
- }
- }
- }
-
- switch (specific ? specific : randint(41))
- {
- case 1 :
- if (randint(WEIRD_LUCK) != 1)
- random_resistance(o_ptr, is_scroll, specific);
- else
- {
- o_ptr->art_flags2 |= TR2_IM_ACID;
- /* if (is_scroll) msg_print("It looks totally incorruptible."); */
- if (!(artifact_bias))
- artifact_bias = BIAS_ACID;
- }
- break;
- case 2:
- if (randint(WEIRD_LUCK) != 1)
- random_resistance(o_ptr, is_scroll, specific);
- else
- {
- o_ptr->art_flags2 |= TR2_IM_ELEC;
- /* if (is_scroll) msg_print("It looks completely grounded."); */
- if (!(artifact_bias))
- artifact_bias = BIAS_ELEC;
- }
- break;
- case 3:
- if (randint(WEIRD_LUCK) != 1)
- random_resistance(o_ptr, is_scroll, specific);
- else
- {
- o_ptr->art_flags2 |= TR2_IM_COLD;
- /* if (is_scroll) msg_print("It feels very warm."); */
- if (!(artifact_bias))
- artifact_bias = BIAS_COLD;
- }
- break;
- case 4:
- if (randint(WEIRD_LUCK) != 1)
- random_resistance(o_ptr, is_scroll, specific);
- else
- {
- o_ptr->art_flags2 |= TR2_IM_FIRE;
- /* if (is_scroll) msg_print("It feels very cool."); */
- if (!(artifact_bias))
- artifact_bias = BIAS_FIRE;
- }
- break;
- case 5:
- case 6:
- case 13:
- o_ptr->art_flags2 |= TR2_RES_ACID;
- /* if (is_scroll) msg_print("It makes your stomach rumble."); */
- if (!(artifact_bias))
- artifact_bias = BIAS_ACID;
- break;
- case 7:
- case 8:
- case 14:
- o_ptr->art_flags2 |= TR2_RES_ELEC;
- /* if (is_scroll) msg_print("It makes you feel grounded."); */
- if (!(artifact_bias))
- artifact_bias = BIAS_ELEC;
- break;
- case 9:
- case 10:
- case 15:
- o_ptr->art_flags2 |= TR2_RES_FIRE;
- /* if (is_scroll) msg_print("It makes you feel cool!");*/
- if (!(artifact_bias))
- artifact_bias = BIAS_FIRE;
- break;
- case 11:
- case 12:
- case 16:
- o_ptr->art_flags2 |= TR2_RES_COLD;
- /* if (is_scroll) msg_print("It makes you feel full of hot air!");*/
- if (!(artifact_bias))
- artifact_bias = BIAS_COLD;
- break;
- case 17:
- case 18:
- o_ptr->art_flags2 |= TR2_RES_POIS;
- /* if (is_scroll) msg_print("It makes breathing easier for you."); */
- if (!(artifact_bias) && randint(4) != 1)
- artifact_bias = BIAS_POIS;
- else if (!(artifact_bias) && randint(2) == 1)
- artifact_bias = BIAS_NECROMANTIC;
- else if (!(artifact_bias) && randint(2) == 1)
- artifact_bias = BIAS_ROGUE;
- break;
- case 19:
- case 20:
- o_ptr->art_flags2 |= TR2_RES_FEAR;
- /* if (is_scroll) msg_print("It makes you feel brave!"); */
- if (!(artifact_bias) && randint(3) == 1)
- artifact_bias = BIAS_WARRIOR;
- break;
- case 21:
- o_ptr->art_flags2 |= TR2_RES_LITE;
- /* if (is_scroll) msg_print("It makes everything look darker.");*/
- break;
- case 22:
- o_ptr->art_flags2 |= TR2_RES_DARK;
- /* if (is_scroll) msg_print("It makes everything look brigher.");*/
- break;
- case 23:
- case 24:
- o_ptr->art_flags2 |= TR2_RES_BLIND;
- /* if (is_scroll) msg_print("It makes you feel you are wearing glasses.");*/
- break;
- case 25:
- case 26:
- o_ptr->art_flags2 |= TR2_RES_CONF;
- /* if (is_scroll) msg_print("It makes you feel very determined.");*/
- if (!(artifact_bias) && randint(6) == 1)
- artifact_bias = BIAS_CHAOS;
- break;
- case 27:
- case 28:
- o_ptr->art_flags2 |= TR2_RES_SOUND;
- /* if (is_scroll) msg_print("It makes you feel deaf!");*/
- break;
- case 29:
- case 30:
- o_ptr->art_flags2 |= TR2_RES_SHARDS;
- /* if (is_scroll) msg_print("It makes your skin feel thicker.");*/
- break;
- case 31:
- case 32:
- o_ptr->art_flags2 |= TR2_RES_NETHER;
- /* if (is_scroll) msg_print("It makes you feel like visiting a graveyard!");*/
- if (!(artifact_bias) && randint(3) == 1)
- artifact_bias = BIAS_NECROMANTIC;
- break;
- case 33:
- case 34:
- o_ptr->art_flags2 |= TR2_RES_NEXUS;
- /* if (is_scroll) msg_print("It makes you feel normal.");*/
- break;
- case 35:
- case 36:
- o_ptr->art_flags2 |= TR2_RES_CHAOS;
- /* if (is_scroll) msg_print("It makes you feel very firm.");*/
- if (!(artifact_bias) && randint(2) == 1)
- artifact_bias = BIAS_CHAOS;
- break;
- case 37:
- case 38:
- o_ptr->art_flags2 |= TR2_RES_DISEN;
- /* if (is_scroll) msg_print("It is surrounded by a static feeling.");*/
- break;
- case 39:
- if (o_ptr->tval >= TV_CLOAK && o_ptr->tval <= TV_HARD_ARMOR)
- o_ptr->art_flags3 |= TR3_SH_ELEC;
- else
- random_resistance(o_ptr, is_scroll, specific);
- if (!(artifact_bias))
- artifact_bias = BIAS_ELEC;
- break;
- case 40:
- if (o_ptr->tval >= TV_CLOAK && o_ptr->tval <= TV_HARD_ARMOR)
- o_ptr->art_flags3 |= TR3_SH_FIRE;
- else
- random_resistance(o_ptr, is_scroll, specific);
- if (!(artifact_bias))
- artifact_bias = BIAS_FIRE;
- break;
- case 41:
- if (o_ptr->tval == TV_SHIELD || o_ptr->tval == TV_CLOAK ||
- o_ptr->tval == TV_HELM || o_ptr->tval == TV_HARD_ARMOR)
- o_ptr->art_flags2 |= TR2_REFLECT;
- else
- random_resistance(o_ptr, is_scroll, specific);
- break;
- }
-}
-
-void random_misc(object_type * o_ptr, bool_ is_scroll)
-{
-
- if (artifact_bias == BIAS_RANGER)
- {
- if (!(o_ptr->art_flags2 & TR2_SUST_CON))
- {
- o_ptr->art_flags2 |= TR2_SUST_CON;
- if (randint(2) == 1) return;
- }
- }
- else if (artifact_bias == BIAS_STR)
- {
- if (!(o_ptr->art_flags2 & TR2_SUST_STR))
- {
- o_ptr->art_flags2 |= TR2_SUST_STR;
- if (randint(2) == 1) return;
- }
- }
- else if (artifact_bias == BIAS_WIS)
- {
- if (!(o_ptr->art_flags2 & TR2_SUST_WIS))
- {
- o_ptr->art_flags2 |= TR2_SUST_WIS;
- if (randint(2) == 1) return;
- }
- }
- else if (artifact_bias == BIAS_INT)
- {
- if (!(o_ptr->art_flags2 & TR2_SUST_INT))
- {
- o_ptr->art_flags2 |= TR2_SUST_INT;
- if (randint(2) == 1) return;
- }
- }
- else if (artifact_bias == BIAS_DEX)
- {
- if (!(o_ptr->art_flags2 & TR2_SUST_DEX))
- {
- o_ptr->art_flags2 |= TR2_SUST_DEX;
- if (randint(2) == 1) return;
- }
- }
- else if (artifact_bias == BIAS_CON)
- {
- if (!(o_ptr->art_flags2 & TR2_SUST_CON))
- {
- o_ptr->art_flags2 |= TR2_SUST_CON;
- if (randint(2) == 1) return;
- }
- }
- else if (artifact_bias == BIAS_CHR)
- {
- if (!(o_ptr->art_flags2 & TR2_SUST_CHR))
- {
- o_ptr->art_flags2 |= TR2_SUST_CHR;
- if (randint(2) == 1) return;
- }
- }
- else if (artifact_bias == BIAS_CHAOS)
- {
- if (!(o_ptr->art_flags3 & TR3_TELEPORT))
- {
- o_ptr->art_flags3 |= TR3_TELEPORT;
- if (randint(2) == 1) return;
- }
- }
- else if (artifact_bias == BIAS_FIRE)
- {
- if (!(o_ptr->art_flags3 & TR3_LITE1))
- {
- o_ptr->art_flags3 |= TR3_LITE1; /* Freebie */
- }
- }
-
-
- switch (randint(31))
- {
- case 1:
- o_ptr->art_flags2 |= TR2_SUST_STR;
- /* if (is_scroll) msg_print("It makes you feel you cannot become weaker."); */
- if (!artifact_bias)
- artifact_bias = BIAS_STR;
- break;
-
- case 2:
- o_ptr->art_flags2 |= TR2_SUST_INT;
- /* if (is_scroll) msg_print("It makes you feel you cannot become more stupid.");*/
- if (!artifact_bias)
- artifact_bias = BIAS_INT;
- break;
-
- case 3:
- o_ptr->art_flags2 |= TR2_SUST_WIS;
- /* if (is_scroll) msg_print("It makes you feel you cannot become simpler.");*/
- if (!artifact_bias)
- artifact_bias = BIAS_WIS;
- break;
-
- case 4:
- o_ptr->art_flags2 |= TR2_SUST_DEX;
- /* if (is_scroll) msg_print("It makes you feel you cannot become clumsier.");*/
- if (!artifact_bias)
- artifact_bias = BIAS_DEX;
- break;
-
- case 5:
- o_ptr->art_flags2 |= TR2_SUST_CON;
- /* if (is_scroll) msg_print("It makes you feel you cannot become less healthy.");*/
- if (!artifact_bias)
- artifact_bias = BIAS_CON;
- break;
-
- case 6:
- o_ptr->art_flags2 |= TR2_SUST_CHR;
- /* if (is_scroll) msg_print("It makes you feel you cannot become uglier.");*/
- if (!artifact_bias)
- artifact_bias = BIAS_CHR;
- break;
-
- case 7:
- case 8:
- case 14:
- o_ptr->art_flags2 |= TR2_FREE_ACT;
- /* if (is_scroll) msg_print("It makes you feel like a young rebel!");*/
- break;
-
- case 9:
- o_ptr->art_flags2 |= TR2_HOLD_LIFE;
- /* if (is_scroll) msg_print("It makes you feel immortal.");*/
- if (!artifact_bias && (randint(5) == 1))
- artifact_bias = BIAS_PRIESTLY;
- else if (!artifact_bias && (randint(6) == 1))
- artifact_bias = BIAS_NECROMANTIC;
- break;
-
- case 10:
- case 11:
- o_ptr->art_flags3 |= TR3_LITE1;
- /* if (is_scroll) msg_print("It starts shining.");*/
- break;
-
- case 12:
- case 13:
- o_ptr->art_flags3 |= TR3_FEATHER;
- /* if (is_scroll) msg_print("It feels lighter.");*/
- break;
-
- case 15:
- case 16:
- case 17:
- o_ptr->art_flags3 |= TR3_SEE_INVIS;
- /* if (is_scroll) msg_print("It makes you see the air!");*/
- break;
-
- case 18:
- o_ptr->art_esp |= 1 << (rand_int(32));
- /* if (is_scroll) msg_print("It makes you hear voices inside your head!");*/
- if (!artifact_bias && (randint(9) == 1))
- artifact_bias = BIAS_MAGE;
- break;
-
- case 19:
- case 20:
- o_ptr->art_flags3 |= TR3_SLOW_DIGEST;
- /* if (is_scroll) msg_print("It makes you feel less hungry.");*/
- break;
-
- case 21:
- case 22:
- o_ptr->art_flags3 |= TR3_REGEN;
- /* if (is_scroll) msg_print("It looks as good as new.");*/
- break;
-
- case 23:
- o_ptr->art_flags3 |= TR3_TELEPORT;
- /* if (is_scroll) msg_print("Its position feels uncertain!");*/
- break;
-
- case 24:
- case 25:
- case 26:
- if (o_ptr->tval >= TV_BOOTS) random_misc(o_ptr, is_scroll);
- else
- {
- o_ptr->art_flags3 |= TR3_SHOW_MODS;
- o_ptr->to_a = 4 + (randint(11));
- }
- break;
-
- case 27:
- case 28:
- case 29:
- o_ptr->art_flags3 |= TR3_SHOW_MODS;
- o_ptr->to_h += 4 + (randint(11));
- o_ptr->to_d += 4 + (randint(11));
- break;
-
- case 30:
- o_ptr->art_flags3 |= TR3_NO_MAGIC;
- break;
-
- case 31:
- o_ptr->art_flags3 |= TR3_NO_TELE;
- break;
- }
-
-
-}
-
-
-void random_slay (object_type * o_ptr, bool_ is_scroll)
-{
- if (artifact_bias == BIAS_CHAOS && !(o_ptr->tval == TV_BOW))
- {
- if (!(o_ptr->art_flags1 & TR1_CHAOTIC))
- {
- o_ptr->art_flags1 |= TR1_CHAOTIC;
- if (randint(2) == 1) return;
- }
- }
-
- else if (artifact_bias == BIAS_PRIESTLY &&
- (o_ptr->tval == TV_SWORD || o_ptr->tval == TV_POLEARM || o_ptr->tval == TV_AXE) &&
- !(o_ptr->art_flags3 & TR3_BLESSED))
- {
- /* A free power for "priestly" random artifacts */
- o_ptr->art_flags3 |= TR3_BLESSED;
- }
-
- else if (artifact_bias == BIAS_NECROMANTIC && !(o_ptr->tval == TV_BOW))
- {
- if (!(o_ptr->art_flags1 & TR1_VAMPIRIC))
- {
- o_ptr->art_flags1 |= TR1_VAMPIRIC;
- if (randint(2) == 1) return;
- }
- if (!(o_ptr->art_flags1 & TR1_BRAND_POIS) && (randint(2) == 1))
- {
- o_ptr->art_flags1 |= TR1_BRAND_POIS;
- if (randint(2) == 1) return;
- }
- }
-
- else if (artifact_bias == BIAS_RANGER && !(o_ptr->tval == TV_BOW))
- {
- if (!(o_ptr->art_flags1 & TR1_SLAY_ANIMAL))
- {
- o_ptr->art_flags1 |= TR1_SLAY_ANIMAL;
- if (randint(2) == 1) return;
- }
- }
-
- else if (artifact_bias == BIAS_ROGUE && !(o_ptr->tval == TV_BOW))
- {
- if (!(o_ptr->art_flags1 & TR1_BRAND_POIS))
- {
- o_ptr->art_flags1 |= TR1_BRAND_POIS;
- if (randint(2) == 1) return;
- }
- }
-
- else if (artifact_bias == BIAS_POIS && !(o_ptr->tval == TV_BOW))
- {
- if (!(o_ptr->art_flags1 & TR1_BRAND_POIS))
- {
- o_ptr->art_flags1 |= TR1_BRAND_POIS;
- if (randint(2) == 1) return;
- }
- }
-
- else if (artifact_bias == BIAS_FIRE && !(o_ptr->tval == TV_BOW))
- {
- if (!(o_ptr->art_flags1 & TR1_BRAND_FIRE))
- {
- o_ptr->art_flags1 |= TR1_BRAND_FIRE;
- if (randint(2) == 1) return;
- }
- }
-
- else if (artifact_bias == BIAS_COLD && !(o_ptr->tval == TV_BOW))
- {
- if (!(o_ptr->art_flags1 & TR1_BRAND_COLD))
- {
- o_ptr->art_flags1 |= TR1_BRAND_COLD;
- if (randint(2) == 1) return;
- }
- }
-
- else if (artifact_bias == BIAS_ELEC && !(o_ptr->tval == TV_BOW))
- {
- if (!(o_ptr->art_flags1 & TR1_BRAND_ELEC))
- {
- o_ptr->art_flags1 |= TR1_BRAND_ELEC;
- if (randint(2) == 1) return;
- }
- }
-
- else if (artifact_bias == BIAS_ACID && !(o_ptr->tval == TV_BOW))
- {
- if (!(o_ptr->art_flags1 & TR1_BRAND_ACID))
- {
- o_ptr->art_flags1 |= TR1_BRAND_ACID;
- if (randint(2) == 1) return;
- }
- }
-
- else if (artifact_bias == BIAS_LAW && !(o_ptr->tval == TV_BOW))
- {
- if (!(o_ptr->art_flags1 & TR1_SLAY_EVIL))
- {
- o_ptr->art_flags1 |= TR1_SLAY_EVIL;
- if (randint(2) == 1) return;
- }
- if (!(o_ptr->art_flags1 & TR1_SLAY_UNDEAD))
- {
- o_ptr->art_flags1 |= TR1_SLAY_UNDEAD;
- if (randint(2) == 1) return;
- }
- if (!(o_ptr->art_flags1 & TR1_SLAY_DEMON))
- {
- o_ptr->art_flags1 |= TR1_SLAY_DEMON;
- if (randint(2) == 1) return;
- }
- }
-
- if (!(o_ptr->tval == TV_BOW))
- {
- switch (randint(34))
- {
- case 1:
- case 2:
- o_ptr->art_flags1 |= TR1_SLAY_ANIMAL;
- /* if (is_scroll) msg_print("You start hating animals.");*/
- break;
-
- case 3:
- case 4:
- o_ptr->art_flags1 |= TR1_SLAY_EVIL;
- /* if (is_scroll) msg_print("You hate evil creatures.");*/
- if (!artifact_bias && (randint(2) == 1))
- artifact_bias = BIAS_LAW;
- else if (!artifact_bias && (randint(9) == 1))
- artifact_bias = BIAS_PRIESTLY;
- break;
-
- case 5:
- case 6:
- o_ptr->art_flags1 |= TR1_SLAY_UNDEAD;
- /* if (is_scroll) msg_print("You hate undead creatures.");*/
- if (!artifact_bias && (randint(9) == 1))
- artifact_bias = BIAS_PRIESTLY;
- break;
-
- case 7:
- case 8:
- o_ptr->art_flags1 |= TR1_SLAY_DEMON;
- /* if (is_scroll) msg_print("You hate demons.");*/
- if (!artifact_bias && (randint(9) == 1))
- artifact_bias = BIAS_PRIESTLY;
- break;
-
- case 9:
- case 10:
- o_ptr->art_flags1 |= TR1_SLAY_ORC;
- /* if (is_scroll) msg_print("You hate orcs.");*/
- break;
-
- case 11:
- case 12:
- o_ptr->art_flags1 |= TR1_SLAY_TROLL;
- /* if (is_scroll) msg_print("You hate trolls.");*/
- break;
-
- case 13:
- case 14:
- o_ptr->art_flags1 |= TR1_SLAY_GIANT;
- /* if (is_scroll) msg_print("You hate giants.");*/
- break;
-
- case 15:
- case 16:
- o_ptr->art_flags1 |= TR1_SLAY_DRAGON;
- /* if (is_scroll) msg_print("You hate dragons.");*/
- break;
-
- case 17:
- o_ptr->art_flags1 |= TR1_KILL_DRAGON;
- /* if (is_scroll) msg_print("You feel an intense hatred of dragons.");*/
- break;
-
- case 18:
- case 19:
- if (o_ptr->tval == TV_SWORD)
- {
- o_ptr->art_flags1 |= TR1_VORPAL;
- /* if (is_scroll) msg_print("It looks extremely sharp!");*/
- if (!artifact_bias && (randint(9) == 1))
- artifact_bias = BIAS_WARRIOR;
- }
- else random_slay(o_ptr, is_scroll);
- break;
-
- case 20:
- o_ptr->art_flags1 |= TR1_IMPACT;
- /* if (is_scroll) msg_print("The ground trembles beneath you.");*/
- break;
-
- case 21:
- case 22:
- o_ptr->art_flags1 |= TR1_BRAND_FIRE;
- /* if (is_scroll) msg_print("It feels hot!");*/
- if (!artifact_bias)
- artifact_bias = BIAS_FIRE;
- break;
-
- case 23:
- case 24:
- o_ptr->art_flags1 |= TR1_BRAND_COLD;
- /* if (is_scroll) msg_print("It feels cold!");*/
- if (!artifact_bias)
- artifact_bias = BIAS_COLD;
- break;
-
- case 25:
- case 26:
- o_ptr->art_flags1 |= TR1_BRAND_ELEC;
- /* if (is_scroll) msg_print("Ouch! You get zapped!");*/
- if (!artifact_bias)
- artifact_bias = BIAS_ELEC;
- break;
-
- case 27:
- case 28:
- o_ptr->art_flags1 |= TR1_BRAND_ACID;
- /* if (is_scroll) msg_print("Its smell makes you feel dizzy.");*/
- if (!artifact_bias)
- artifact_bias = BIAS_ACID;
- break;
-
- case 29:
- case 30:
- o_ptr->art_flags1 |= TR1_BRAND_POIS;
- /* if (is_scroll) msg_print("It smells rotten.");*/
- if (!artifact_bias && (randint(3) != 1))
- artifact_bias = BIAS_POIS;
- else if (!artifact_bias && randint(6) == 1)
- artifact_bias = BIAS_NECROMANTIC;
- else if (!artifact_bias)
- artifact_bias = BIAS_ROGUE;
- break;
-
- case 31:
- case 32:
- o_ptr->art_flags1 |= TR1_VAMPIRIC;
- /* if (is_scroll) msg_print("You think it bit you!");*/
- if (!artifact_bias)
- artifact_bias = BIAS_NECROMANTIC;
- break;
-
- default:
- o_ptr->art_flags1 |= TR1_CHAOTIC;
- /* if (is_scroll) msg_print("It looks very confusing.");*/
- if (!artifact_bias)
- artifact_bias = BIAS_CHAOS;
- break;
- }
- }
- else
- {
- switch (randint(6))
- {
- case 1:
- case 2:
- case 3:
- o_ptr->art_flags3 |= TR3_XTRA_MIGHT;
- /* if (is_scroll) msg_print("It looks mightier than before."); */
- if (!artifact_bias && randint(9) == 1)
- artifact_bias = BIAS_RANGER;
- break;
-
- default:
- o_ptr->art_flags3 |= TR3_XTRA_SHOTS;
- /* if (is_scroll) msg_print("It seems faster!"); */
- if (!artifact_bias && randint(9) == 1)
- artifact_bias = BIAS_RANGER;
- break;
- }
- }
-}
-
-
-
-
-/*
- * Determines if an item is not identified
- */
-static bool_ item_tester_hook_unknown(object_type *o_ptr)
-{
- return (object_known_p(o_ptr) ? FALSE : TRUE);
-}
-
-
-/*
- * Identify an object in the inventory (or on the floor)
- * This routine does *not* automatically combine objects.
- * Returns TRUE if something was identified, else FALSE.
- */
-bool_ ident_spell(void)
-{
- int item;
-
- object_type *o_ptr;
-
- char o_name[80];
-
- cptr q, s;
-
- /* Get an item */
- item_tester_hook = item_tester_hook_unknown;
- q = "Identify which item? ";
- s = "You have nothing to identify.";
- if (!get_item(&item, q, s, (USE_EQUIP | USE_INVEN | USE_FLOOR))) return (FALSE);
-
- /* Get the item */
- o_ptr = get_object(item);
-
- /* Identify it fully */
- object_aware(o_ptr);
- object_known(o_ptr);
-
- /* Recalculate bonuses */
- p_ptr->update |= (PU_BONUS);
-
- /* Combine / Reorder the pack (later) */
- p_ptr->notice |= (PN_COMBINE | PN_REORDER);
-
- /* Window stuff */
- p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
-
- /* Description */
- object_desc(o_name, o_ptr, TRUE, 3);
-
- /* Describe */
- if (item >= INVEN_WIELD)
- {
- msg_format("%^s: %s (%c).",
- describe_use(item), o_name, index_to_label(item));
- }
- else if (item >= 0)
- {
- msg_format("In your pack: %s (%c).",
- o_name, index_to_label(item));
- }
- else
- {
- msg_format("On the ground: %s.",
- 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');
- }
- /* Process the appropriate hooks */
- process_hooks(HOOK_IDENTIFY, "(d,s)", item, "normal");
-
- /* Something happened */
- return (TRUE);
-}
-
-/*
- * Identify all objects in the level
- */
-bool_ ident_all(void)
-{
- int i;
-
- object_type *o_ptr;
-
- for (i = 1; i < o_max; i++)
- {
- /* Acquire object */
- o_ptr = &o_list[i];
-
- /* Identify it fully */
- 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);
-
- /* Build note and write */
- sprintf(note, "Found The %s", item_name);
- add_note(note, 'A');
- }
- /* Process the appropriate hooks */
- process_hooks(HOOK_IDENTIFY, "(d,s)", -i, "normal");
- }
-
- /* Something happened */
- return (TRUE);
-}
-
-
-
-/*
- * Determine if an object is not fully identified
- */
-static bool_ item_tester_hook_no_mental(object_type *o_ptr)
-{
- return ((o_ptr->ident & (IDENT_MENTAL)) ? FALSE : TRUE);
-}
-
-/*
- * Fully "identify" an object in the inventory -BEN-
- * This routine returns TRUE if an item was identified.
- */
-bool_ identify_fully(void)
-{
- int item;
- object_type *o_ptr;
- char o_name[80];
-
- cptr q, s;
-
- /* Get an item */
- item_tester_hook = item_tester_hook_no_mental;
- q = "Identify which item? ";
- s = "You have nothing to identify.";
- if (!get_item(&item, q, s, (USE_EQUIP | USE_INVEN | USE_FLOOR))) return (FALSE);
-
- /* Get the item */
- o_ptr = get_object(item);
-
- /* Do the identification */
- make_item_fully_identified(o_ptr);
-
- /* Recalculate bonuses */
- p_ptr->update |= (PU_BONUS);
-
- /* Combine / Reorder the pack (later) */
- p_ptr->notice |= (PN_COMBINE | PN_REORDER);
-
- /* Window stuff */
- p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
-
- /* Description */
- object_desc(o_name, o_ptr, TRUE, 3);
-
- /* Describe */
- if (item >= INVEN_WIELD)
- {
- msg_format("%^s: %s (%c).",
- describe_use(item), o_name, index_to_label(item));
- }
- else if (item >= 0)
- {
- msg_format("In your pack: %s (%c).",
- o_name, index_to_label(item));
- }
- else
- {
- msg_format("On the ground: %s.",
- 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');
- }
-
- /* Describe it fully */
- object_out_desc(o_ptr, NULL, FALSE, TRUE);
-
- /* Process the appropriate hooks */
- process_hooks(HOOK_IDENTIFY, "(d,s)", item, "full");
-
- /* Success */
- return (TRUE);
-}
-
-
-
-
-/*
- * Hook for "get_item()". Determine if something is rechargable.
- */
-bool_ item_tester_hook_recharge(object_type *o_ptr)
-{
- u32b f1, f2, f3, f4, f5, esp;
-
- /* Extract the flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
-
- /* Some objects cannot be recharged */
- if (f4 & TR4_NO_RECHARGE) return (FALSE);
-
- /* Recharge staffs */
- if (o_ptr->tval == TV_STAFF) return (TRUE);
-
- /* Recharge wands */
- if (o_ptr->tval == TV_WAND) return (TRUE);
-
- /* Hack -- Recharge rods */
- if (o_ptr->tval == TV_ROD_MAIN) return (TRUE);
-
- /* Nope */
- return (FALSE);
-}
-
-
-/*
- * Recharge a wand/staff/rod from the pack or on the floor.
- * This function has been rewritten in Oangband. -LM-
- *
- * Mage -- Recharge I --> recharge(90)
- * Mage -- Recharge II --> recharge(150)
- * Mage -- Recharge III --> recharge(220)
- *
- * Priest or Necromancer -- Recharge --> recharge(140)
- *
- * Scroll of recharging --> recharge(130)
- * Scroll of *recharging* --> recharge(200)
- *
- * 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.
- *
- * XXX XXX XXX Beware of "sliding index errors".
- */
-bool_ recharge(int power)
-{
- int recharge_strength, recharge_amount;
- int item, lev;
-
- bool_ fail = FALSE;
- byte fail_type = 1;
-
-
- cptr q, s;
-
- u32b f1, f2, f3, f4, f5, esp;
- char o_name[80];
-
- object_type *o_ptr;
-
- /* Only accept legal items */
- item_tester_hook = item_tester_hook_recharge;
-
- /* Get an item */
- q = "Recharge which item? ";
- s = "You have nothing to recharge.";
- if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return (FALSE);
-
- /* Get the item */
- o_ptr = get_object(item);
-
- /* Extract the flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
-
- /* Extract the object "level" */
- lev = k_info[o_ptr->k_idx].level;
-
- /* Recharge a rod */
- if (o_ptr->tval == TV_ROD_MAIN)
- {
- /* Extract a recharge strength by comparing object level to power. */
- recharge_strength = ((power > lev) ? (power - lev) : 0) / 5;
-
- /* Paranoia */
- if (recharge_strength < 0) recharge_strength = 0;
-
- /* Back-fire */
- if ((rand_int(recharge_strength) == 0) && (!(f4 & TR4_RECHARGE)))
- {
- /* Activate the failure code. */
- fail = TRUE;
- }
-
- /* Recharge */
- else
- {
- /* Recharge amount */
- recharge_amount = (power * damroll(3, 2));
-
- /* Recharge by that amount */
- if (o_ptr->timeout + recharge_amount < o_ptr->pval2)
- o_ptr->timeout += recharge_amount;
- else
- o_ptr->timeout = o_ptr->pval2;
- }
- }
-
-
- /* Recharge wand/staff */
- else
- {
- /* Extract a recharge strength by comparing object level to power.
- * Divide up a stack of wands' charges to calculate charge penalty.
- */
- if ((o_ptr->tval == TV_WAND) && (o_ptr->number > 1))
- recharge_strength = (100 + power - lev -
- (8 * o_ptr->pval / o_ptr->number)) / 15;
-
- /* All staffs, unstacked wands. */
- else recharge_strength = (100 + power - lev -
- (8 * o_ptr->pval)) / 15;
-
-
- /* Back-fire XXX XXX XXX */
- if (((rand_int(recharge_strength) == 0) && (!(f4 & TR4_RECHARGE))) ||
- (f4 & TR4_NO_RECHARGE))
- {
- /* Activate the failure code. */
- fail = TRUE;
- }
-
- /* If the spell didn't backfire, recharge the wand or staff. */
- else
- {
- /* Recharge based on the standard number of charges. */
- recharge_amount = randint((power / (lev + 2)) + 1);
-
- /* Multiple wands in a stack increase recharging somewhat. */
- if ((o_ptr->tval == TV_WAND) && (o_ptr->number > 1))
- {
- recharge_amount +=
- (randint(recharge_amount * (o_ptr->number - 1))) / 2;
- if (recharge_amount < 1) recharge_amount = 1;
- if (recharge_amount > 12) recharge_amount = 12;
- }
-
- /* But each staff in a stack gets fewer additional charges,
- * although always at least one.
- */
- if ((o_ptr->tval == TV_STAFF) && (o_ptr->number > 1))
- {
- recharge_amount /= o_ptr->number;
- if (recharge_amount < 1) recharge_amount = 1;
- }
-
- /* Recharge the wand or staff. */
- o_ptr->pval += recharge_amount;
-
- if (!(f4 & TR4_RECHARGE))
- {
- /* Hack -- we no longer "know" the item */
- o_ptr->ident &= ~(IDENT_KNOWN);
- }
-
- /* Hack -- we no longer think the item is empty */
- o_ptr->ident &= ~(IDENT_EMPTY);
- }
- }
-
- /* Mark as recharged -- For alchemists */
- o_ptr->art_flags4 |= TR4_RECHARGED;
-
- /* Inflict the penalties for failing a recharge. */
- if (fail)
- {
- /* Artifacts are never destroyed. */
- if (artifact_p(o_ptr))
- {
- object_desc(o_name, o_ptr, TRUE, 0);
- msg_format("The recharging backfires - %s is completely drained!", o_name);
-
- /* Artifact rods. */
- if (o_ptr->tval == TV_ROD_MAIN)
- o_ptr->timeout = 0;
-
- /* Artifact wands and staffs. */
- else if ((o_ptr->tval == TV_WAND) || (o_ptr->tval == TV_STAFF))
- o_ptr->pval = 0;
- }
- else
- {
- /* Get the object description */
- object_desc(o_name, o_ptr, FALSE, 0);
-
- /*** Determine Seriousness of Failure ***/
-
- /* Mages recharge objects more safely. */
- if (has_ability(AB_PERFECT_CASTING))
- {
- /* 10% chance to blow up one rod, otherwise draining. */
- if (o_ptr->tval == TV_ROD_MAIN)
- {
- if (randint(10) == 1) fail_type = 2;
- else fail_type = 1;
- }
- /* 75% chance to blow up one wand, otherwise draining. */
- else if (o_ptr->tval == TV_WAND)
- {
- if (randint(3) != 1) fail_type = 2;
- else fail_type = 1;
- }
- /* 50% chance to blow up one staff, otherwise no effect. */
- else if (o_ptr->tval == TV_STAFF)
- {
- if (randint(2) == 1) fail_type = 2;
- else fail_type = 0;
- }
- }
-
- /* All other classes get no special favors. */
- else
- {
- /* 33% chance to blow up one rod, otherwise draining. */
- if (o_ptr->tval == TV_ROD_MAIN)
- {
- if (randint(3) == 1) fail_type = 2;
- else fail_type = 1;
- }
- /* 20% chance of the entire stack, else destroy one wand. */
- else if (o_ptr->tval == TV_WAND)
- {
- if (randint(5) == 1) fail_type = 3;
- else fail_type = 2;
- }
- /* Blow up one staff. */
- else if (o_ptr->tval == TV_STAFF)
- {
- fail_type = 2;
- }
- }
-
- /*** Apply draining and destruction. ***/
-
- /* Drain object or stack of objects. */
- if (fail_type == 1)
- {
- if (o_ptr->tval == TV_ROD_MAIN)
- {
- msg_print("The recharge backfires, draining the rod further!");
- if (o_ptr->timeout < 10000)
- o_ptr->timeout = 0;
- }
- else if (o_ptr->tval == TV_WAND)
- {
- msg_format("You save your %s from destruction, but all charges are lost.", o_name);
- o_ptr->pval = 0;
- }
- /* Staffs aren't drained. */
- }
-
- /* Destroy an object or one in a stack of objects. */
- if (fail_type == 2)
- {
- if (o_ptr->number > 1)
- msg_format("Wild magic consumes one of your %s!", o_name);
- else
- msg_format("Wild magic consumes your %s!", o_name);
-
- /* Reduce rod stack maximum timeout, drain wands. */
- if (o_ptr->tval == TV_WAND) o_ptr->pval = 0;
-
- /* Reduce and describe */
- inc_stack_size(item, -1);
- }
-
- /* Destroy all memebers of a stack of objects. */
- if (fail_type == 3)
- {
- if (o_ptr->number > 1)
- msg_format("Wild magic consumes all your %s!", o_name);
- else
- msg_format("Wild magic consumes your %s!", o_name);
-
-
- /* Reduce and describe inventory */
- inc_stack_size(item, -999);
- }
- }
- }
-
-
- /* Combine / Reorder the pack (later) */
- p_ptr->notice |= (PN_COMBINE | PN_REORDER);
-
- /* Window stuff */
- p_ptr->window |= (PW_INVEN);
-
- /* Something was done */
- return (TRUE);
-}
-
-
-
-/*
- * Apply a "project()" directly to all viewable monsters
- *
- * Note that affected monsters are NOT auto-tracked by this usage.
- */
-bool_ project_hack(int typ, int dam)
-{
- int i, x, y;
- int flg = PROJECT_JUMP | PROJECT_KILL | PROJECT_HIDE;
- bool_ obvious = FALSE;
-
-
- /* Affect all (nearby) monsters */
- for (i = 1; i < m_max; i++)
- {
- monster_type *m_ptr = &m_list[i];
-
- /* Paranoia -- Skip dead monsters */
- if (!m_ptr->r_idx) continue;
-
- /* Location */
- y = m_ptr->fy;
- x = m_ptr->fx;
-
- /* Require line of sight */
- if (!player_has_los_bold(y, x)) continue;
-
- /* Jump directly to the target monster */
- if (project(0, 0, y, x, dam, typ, flg)) obvious = TRUE;
- }
-
- /* Result */
- return (obvious);
-}
-
-/*
- * Apply a "project()" a la meteor shower
- */
-void project_meteor(int radius, int typ, int dam, u32b flg)
-{
- cave_type *c_ptr;
- int x, y, dx, dy, d, count = 0, i;
- int b = radius + randint(radius);
- for (i = 0; i < b; i++)
- {
- for (count = 0; count < 1000; count++)
- {
- x = p_ptr->px - 5 + randint(10);
- y = p_ptr->py - 5 + randint(10);
- if ((x < 0) || (x >= cur_wid) ||
- (y < 0) || (y >= cur_hgt)) continue;
- dx = (p_ptr->px > x) ? (p_ptr->px - x) : (x - p_ptr->px);
- dy = (p_ptr->py > y) ? (p_ptr->py - y) : (y - p_ptr->py);
- /* Approximate distance */
- d = (dy > dx) ? (dy + (dx >> 1)) : (dx + (dy >> 1));
- c_ptr = &cave[y][x];
- /* Check distance */
- if ((d <= 5) &&
- /* Check line of sight */
- (player_has_los_bold(y, x)) &&
- /* But don't explode IN a wall, letting the player attack through walls */
- !(c_ptr->info & CAVE_WALL))
- break;
- }
- if (count >= 1000) break;
- project(0, 2, y, x, dam, typ, PROJECT_JUMP | flg);
- }
-}
-
-
-/*
- * Speed monsters
- */
-bool_ speed_monsters(void)
-{
- return (project_hack(GF_OLD_SPEED, p_ptr->lev));
-}
-
-/*
- * Slow monsters
- */
-bool_ slow_monsters(void)
-{
- return (project_hack(GF_OLD_SLOW, p_ptr->lev));
-}
-
-/*
- * Paralyzation monsters
- */
-bool_ conf_monsters(void)
-{
- return (project_hack(GF_OLD_CONF, p_ptr->lev));
-}
-
-/*
- * Sleep monsters
- */
-bool_ sleep_monsters(void)
-{
- return (project_hack(GF_OLD_SLEEP, p_ptr->lev));
-}
-
-/*
- * Scare monsters
- */
-bool_ scare_monsters(void)
-{
- return (project_hack(GF_FEAR, p_ptr->lev));
-}
-
-
-/*
- * Banish evil monsters
- */
-bool_ banish_evil(int dist)
-{
- return (project_hack(GF_AWAY_EVIL, dist));
-}
-
-
-/*
- * Turn undead
- */
-bool_ turn_undead(void)
-{
- return (project_hack(GF_TURN_UNDEAD, p_ptr->lev));
-}
-
-
-/*
- * Dispel undead monsters
- */
-bool_ dispel_undead(int dam)
-{
- return (project_hack(GF_DISP_UNDEAD, dam));
-}
-
-/*
- * Dispel evil monsters
- */
-bool_ dispel_evil(int dam)
-{
- return (project_hack(GF_DISP_EVIL, dam));
-}
-
-/*
- * Dispel good monsters
- */
-bool_ dispel_good(int dam)
-{
- return (project_hack(GF_DISP_GOOD, dam));
-}
-
-/*
- * Dispel all monsters
- */
-bool_ dispel_monsters(int dam)
-{
- return (project_hack(GF_DISP_ALL, dam));
-}
-
-/*
- * Dispel 'living' monsters
- */
-bool_ dispel_living(int dam)
-{
- return (project_hack(GF_DISP_LIVING, dam));
-}
-
-/*
- * Dispel demons
- */
-bool_ dispel_demons(int dam)
-{
- return (project_hack(GF_DISP_DEMON, dam));
-}
-
-
-/*
- * Wake up all monsters, and speed up "los" monsters.
- */
-void aggravate_monsters(int who)
-{
- int i;
- bool_ sleep = FALSE;
- bool_ speed = FALSE;
-
-
- /* Aggravate everyone nearby */
- for (i = 1; i < m_max; i++)
- {
- monster_type *m_ptr = &m_list[i];
- monster_race *r_ptr = race_inf(m_ptr);
-
- /* Paranoia -- Skip dead monsters */
- if (!m_ptr->r_idx) continue;
-
- /* Skip aggravating monster (or player) */
- if (i == who) continue;
-
- /* Wake up nearby sleeping monsters */
- if (m_ptr->cdis < MAX_SIGHT * 2)
- {
- /* Wake up */
- if (m_ptr->csleep)
- {
- /* Wake up */
- m_ptr->csleep = 0;
- sleep = TRUE;
- }
- }
-
- /* Speed up monsters in line of sight */
- if (player_has_los_bold(m_ptr->fy, m_ptr->fx))
- {
- /* Speed up (instantly) to racial base + 10 */
- if (m_ptr->mspeed < r_ptr->speed + 10)
- {
- /* Speed up */
- m_ptr->mspeed = r_ptr->speed + 10;
- speed = TRUE;
- }
-
- /* Pets may get angry (50% chance) */
- if (is_friend(m_ptr))
- {
- if (randint(2) == 1)
- {
- change_side(m_ptr);
- }
- }
- }
- }
-
- /* Messages */
- if (speed) msg_print("You feel a sudden stirring nearby!");
- else if (sleep) msg_print("You hear a sudden stirring in the distance!");
-}
-
-/*
- * Generic genocide race selection
- */
-bool_ get_genocide_race(cptr msg, char *typ)
-{
- int i, j;
- cave_type *c_ptr;
-
- msg_print(msg);
- if (!tgt_pt(&i, &j)) return FALSE;
-
- c_ptr = &cave[j][i];
-
- if (c_ptr->m_idx)
- {
- monster_type *m_ptr = &m_list[c_ptr->m_idx];
- monster_race *r_ptr = race_inf(m_ptr);
-
- *typ = r_ptr->d_char;
- return TRUE;
- }
-
- msg_print("You must select a monster.");
- return FALSE;
-}
-
-/*
- * Inflict dam damage of type typee to all monster of the given race
- */
-bool_ invoke(int dam, int typee)
-{
- int i;
- char typ;
- bool_ result = FALSE;
- int msec = delay_factor * delay_factor * delay_factor;
-
- if (dungeon_flags2 & DF2_NO_GENO) return (FALSE);
-
- /* Hack -- when you are fated to die, you cant cheat :) */
- if (dungeon_type == DUNGEON_DEATH)
- {
- msg_print("A mysterious force stops the genocide.");
- return FALSE;
- }
-
- /* Get a monster symbol */
- if (!get_genocide_race("Target a monster to select the race to invoke on.", &typ)) return FALSE;
-
- /* Delete the monsters of that "type" */
- for (i = 1; i < m_max; i++)
- {
- monster_type *m_ptr = &m_list[i];
- monster_race *r_ptr = race_inf(m_ptr);
-
- /* Paranoia -- Skip dead monsters */
- if (!m_ptr->r_idx) continue;
-
- /* Hack -- Skip Unique Monsters */
- if (r_ptr->flags1 & (RF1_UNIQUE)) continue;
-
- /* Hack -- Skip Quest Monsters */
- if (m_ptr->mflag & MFLAG_QUEST) continue;
-
- /* Skip "wrong" monsters */
- if (r_ptr->d_char != typ) continue;
-
- project_m(0, 0, m_ptr->fy, m_ptr->fx, dam, typee);
-
- /* Visual feedback */
- move_cursor_relative(p_ptr->py, p_ptr->px);
-
- /* Window stuff */
- p_ptr->window |= (PW_PLAYER);
-
- /* Handle */
- handle_stuff();
-
- /* Fresh */
- Term_fresh();
-
- /* Delay */
- Term_xtra(TERM_XTRA_DELAY, msec);
-
- /* Take note */
- result = TRUE;
- }
-
- return (result);
-}
-
-
-/*
- * Delete all non-unique/non-quest monsters of a given "type" from the level
- */
-bool_ genocide_aux(bool_ player_cast, char typ)
-{
- int i;
- bool_ result = FALSE;
- int msec = delay_factor * delay_factor * delay_factor;
- int dam = 0;
-
- /* Delete the monsters of that "type" */
- for (i = 1; i < m_max; i++)
- {
- monster_type *m_ptr = &m_list[i];
- monster_race *r_ptr = race_inf(m_ptr);
-
- /* Paranoia -- Skip dead monsters */
- if (!m_ptr->r_idx) continue;
-
- /* Hack -- Skip Unique Monsters */
- if (r_ptr->flags1 & (RF1_UNIQUE)) continue;
-
- /* Hack -- Skip Quest Monsters */
- if (m_ptr->mflag & MFLAG_QUEST) continue;
-
- /* Skip "wrong" monsters */
- if (r_ptr->d_char != typ) continue;
-
- /* Oups */
- if (r_ptr->flags2 & RF2_DEATH_ORB)
- {
- int wx, wy;
- int attempts = 500;
-
- monster_race_desc(r_name, m_ptr->r_idx, 0);
-
- do
- {
- scatter(&wy, &wx, m_ptr->fy, m_ptr->fx, 10);
- }
- while (!(in_bounds(wy, wx) && cave_floor_bold(wy, wx)) && --attempts);
-
- if (place_monster_aux(wy, wx, m_ptr->r_idx, FALSE, TRUE, MSTATUS_ENEMY))
- {
- cmsg_format(TERM_L_BLUE, "The spell seems to produce an ... interesting effect on the %s.", r_name);
- }
-
- return TRUE;
- }
-
- /* Delete the monster */
- delete_monster_idx(i);
-
- if (player_cast)
- {
- /* Keep track of damage */
- dam += randint(4);
- }
-
- /* Handle */
- handle_stuff();
-
- /* Fresh */
- Term_fresh();
-
- /* Delay */
- Term_xtra(TERM_XTRA_DELAY, msec);
-
- /* Take note */
- result = TRUE;
- }
-
- if (player_cast)
- {
- /* Take damage */
- take_hit(dam, "the strain of casting Genocide");
-
- /* Visual feedback */
- move_cursor_relative(p_ptr->py, p_ptr->px);
-
- /* Redraw */
- p_ptr->redraw |= (PR_HP);
-
- /* Window stuff */
- p_ptr->window |= (PW_PLAYER);
-
- /* Handle */
- handle_stuff();
-
- /* Fresh */
- Term_fresh();
- }
-
- return (result);
-}
-
-bool_ genocide(bool_ player_cast)
-{
- char typ;
-
- if (dungeon_flags2 & DF2_NO_GENO) return (FALSE);
-
- /* Hack -- when you are fated to die, you cant cheat :) */
- if (dungeon_type == DUNGEON_DEATH)
- {
- msg_print("A mysterious force stops the genocide.");
- return FALSE;
- }
-
- /* Mega-Hack -- Get a monster symbol */
- if (!get_genocide_race("Target a monster to select the race to genocide.", &typ)) return FALSE;
-
- return (genocide_aux(player_cast, typ));
-}
-
-
-/*
- * Delete all nearby (non-unique) monsters
- */
-bool_ mass_genocide(bool_ player_cast)
-{
- int i;
- bool_ result = FALSE;
- int msec = delay_factor * delay_factor * delay_factor;
- int dam = 0;
-
- if (dungeon_flags2 & DF2_NO_GENO) return (FALSE);
-
- /* Hack -- when you are fated to die, you cant cheat :) */
- if (dungeon_type == DUNGEON_DEATH)
- {
- msg_print("A mysterious force stops the genocide.");
- return FALSE;
- }
-
- /* Delete the (nearby) monsters */
- for (i = 1; i < m_max; i++)
- {
- monster_type *m_ptr = &m_list[i];
- monster_race *r_ptr = race_inf(m_ptr);
-
- /* Paranoia -- Skip dead monsters */
- if (!m_ptr->r_idx) continue;
-
- /* Hack -- Skip unique monsters */
- if (r_ptr->flags1 & (RF1_UNIQUE)) continue;
-
- /* Hack -- Skip Quest Monsters */
- if (m_ptr->mflag & MFLAG_QUEST) continue;
-
- /* Skip distant monsters */
- if (m_ptr->cdis > MAX_SIGHT) continue;
-
- /* Oups */
- if (r_ptr->flags2 & RF2_DEATH_ORB)
- {
- int wx, wy;
- int attempts = 500;
-
- monster_race_desc(r_name, m_ptr->r_idx, 0);
-
- do
- {
- scatter(&wy, &wx, m_ptr->fy, m_ptr->fx, 10);
- }
- while (!(in_bounds(wy, wx) && cave_floor_bold(wy, wx)) && --attempts);
-
- if (place_monster_aux(wy, wx, m_ptr->r_idx, FALSE, TRUE, MSTATUS_ENEMY))
- {
- cmsg_format(TERM_L_BLUE, "The spell seems to produce an ... interesting effect on the %s.", r_name);
- }
-
- return TRUE;
- }
-
- /* Delete the monster */
- delete_monster_idx(i);
-
- if (player_cast)
- {
- /* Keep track of damage. */
- dam += randint(3);
- }
-
- /* Handle */
- handle_stuff();
-
- /* Fresh */
- Term_fresh();
-
- /* Delay */
- Term_xtra(TERM_XTRA_DELAY, msec);
-
- /* Note effect */
- result = TRUE;
- }
-
- if (player_cast)
- {
- /* Take damage */
- take_hit(dam, "the strain of casting Mass Genocide");
-
- /* Visual feedback */
- move_cursor_relative(p_ptr->py, p_ptr->px);
-
- /* Redraw */
- p_ptr->redraw |= (PR_HP);
-
- /* Window stuff */
- p_ptr->window |= (PW_PLAYER);
-
- /* Handle */
- handle_stuff();
-
- /* Fresh */
- Term_fresh();
- }
-
- return (result);
-}
-
-/* Probe a monster */
-void do_probe(int m_idx)
-{
- char m_name[80];
- monster_type *m_ptr = &m_list[m_idx];
-
- /* Get "the monster" or "something" */
- monster_desc(m_name, m_ptr, 0x04);
-
- /* Describe the monster */
- if (!wizard && (m_ptr->status != MSTATUS_COMPANION)) msg_format("%^s has %d hit points.", m_name, m_ptr->hp);
- else
- {
- int i;
- char t_name[80];
- msg_format("%^s has %d(%d) hit points, %d ac, %d speed.", m_name, m_ptr->hp, m_ptr->maxhp, m_ptr->ac, m_ptr->mspeed - 110);
- msg_format("%^s attacks with:", m_name);
-
- for (i = 0; i < 4; i++)
- {
- msg_format(" Blow %d: %dd%d", i, m_ptr->blow[i].d_dice, m_ptr->blow[i].d_side);
- }
-
- if (m_ptr->target > 0)
- monster_desc(t_name, &m_list[m_ptr->target], 0x04);
- else if (!m_ptr->target)
- sprintf(t_name, "you");
- else
- sprintf(t_name, "nothing");
- msg_format("%^s target is %s.", m_name, t_name);
-
- msg_format("%^s has %ld exp and needs %ld.", m_name, m_ptr->exp, MONSTER_EXP(m_ptr->level + 1));
- }
-
- /* Learn all of the non-spell, non-treasure flags */
- lore_do_probe(m_idx);
-}
-
-/*
- * Probe nearby monsters
- */
-bool_ probing(void)
-{
- int i;
-
- bool_ probe = FALSE;
-
-
- /* Probe all (nearby) monsters */
- for (i = 1; i < m_max; i++)
- {
- monster_type *m_ptr = &m_list[i];
-
- /* Paranoia -- Skip dead monsters */
- if (!m_ptr->r_idx) continue;
-
- /* Require line of sight */
- if (!player_has_los_bold(m_ptr->fy, m_ptr->fx)) continue;
-
- /* Probe visible monsters */
- if (m_ptr->ml)
- {
- /* Start the message */
- if (!probe) msg_print("Probing...");
-
- /* Actualy probe */
- do_probe(i);
-
- /* Probe worked */
- probe = TRUE;
- }
- }
-
- /* Done */
- if (probe)
- {
- msg_print("That's all.");
- }
-
- /* Result */
- return (probe);
-}
-
-
-/*
- * Wipe -- Empties a part of the dungeon
- */
-void wipe(int y1, int x1, int r)
-{
- int y, x, k;
-
- cave_type *c_ptr;
-
- bool_ flag = FALSE;
-
- if (dungeon_flags2 & DF2_NO_GENO)
- {
- msg_print("Not on special levels!");
- return;
- }
- if (p_ptr->inside_quest)
- {
- return;
- }
-
- /* Big area of affect */
- for (y = (y1 - r); y <= (y1 + r); y++)
- {
- for (x = (x1 - r); x <= (x1 + r); x++)
- {
- /* Skip illegal grids */
- if (!in_bounds(y, x)) continue;
-
- /* Extract the distance */
- k = distance(y1, x1, y, x);
-
- /* Stay in the circle of death */
- if (k > r) continue;
-
- /* Access the grid */
- c_ptr = &cave[y][x];
-
- /* Lose room and vault */
- c_ptr->info &= ~(CAVE_ROOM | CAVE_ICKY);
-
- /* Lose light and knowledge */
- c_ptr->info &= ~(CAVE_MARK | CAVE_GLOW);
-
- if (m_list[c_ptr->m_idx].status != MSTATUS_COMPANION) delete_monster(y, x);
- delete_object(y, x);
- place_floor_convert_glass(y, x);
- }
- }
-
-
- /* Hack -- Affect player */
- if (flag)
- {
- /* Message */
- msg_print("There is a searing blast of light!");
-
- /* Blind the player */
- if (!p_ptr->resist_blind && !p_ptr->resist_lite)
- {
- /* Become blind */
- (void)set_blind(p_ptr->blind + 10 + randint(10));
- }
- }
-
-
- /* Mega-Hack -- Forget the view */
- p_ptr->update |= (PU_UN_VIEW);
-
- /* Update stuff */
- p_ptr->update |= (PU_VIEW | PU_FLOW | PU_MON_LITE);
-
- /* Update the monsters */
- p_ptr->update |= (PU_MONSTERS);
-
- /* Redraw map */
- p_ptr->redraw |= (PR_MAP);
-
- /* Window stuff */
- p_ptr->window |= (PW_OVERHEAD);
-}
-
-
-/*
- * The spell of destruction
- *
- * This spell "deletes" monsters (instead of "killing" them).
- *
- * Later we may use one function for both "destruction" and
- * "earthquake" by using the "full" to select "destruction".
- */
-void destroy_area(int y1, int x1, int r, bool_ full, bool_ bypass)
-{
- int y, x, k, t;
-
- cave_type *c_ptr;
-
- bool_ flag = FALSE;
-
-
- /* XXX XXX */
- full = full ? full : 0;
-
- if (dungeon_flags2 & DF2_NO_GENO)
- {
- msg_print("Not on special levels!");
- return;
- }
- if (p_ptr->inside_quest && (!bypass))
- {
- return;
- }
-
- /* Big area of affect */
- for (y = (y1 - r); y <= (y1 + r); y++)
- {
- for (x = (x1 - r); x <= (x1 + r); x++)
- {
- /* Skip illegal grids */
- if (!in_bounds(y, x)) continue;
-
- /* Extract the distance */
- k = distance(y1, x1, y, x);
-
- /* Stay in the circle of death */
- if (k > r) continue;
-
- /* Access the grid */
- c_ptr = &cave[y][x];
-
- /* Lose room and vault */
- c_ptr->info &= ~(CAVE_ROOM | CAVE_ICKY);
-
- /* Lose light and knowledge */
- c_ptr->info &= ~(CAVE_MARK | CAVE_GLOW);
-
- /* Hack -- Notice player affect */
- if ((x == p_ptr->px) && (y == p_ptr->py))
- {
- /* Hurt the player later */
- flag = TRUE;
-
- /* Do not hurt this grid */
- continue;
- }
-
- /* Hack -- Skip the epicenter */
- if ((y == y1) && (x == x1)) continue;
-
- /* Delete the monster (if any) */
- if ((m_list[c_ptr->m_idx].status != MSTATUS_COMPANION) ||
- (!(m_list[c_ptr->m_idx].mflag & MFLAG_QUEST)) ||
- (!(m_list[c_ptr->m_idx].mflag & MFLAG_QUEST2)))
- delete_monster(y, x);
-
- /* Destroy "valid" grids */
- if (cave_valid_bold(y, x))
- {
- /* Delete objects */
- delete_object(y, x);
-
- /* Wall (or floor) type */
- t = rand_int(200);
-
- /* Granite */
- if (t < 20)
- {
- /* Create granite wall */
- cave_set_feat(y, x, FEAT_WALL_EXTRA);
- }
-
- /* Quartz */
- else if (t < 70)
- {
- /* Create quartz vein */
- cave_set_feat(y, x, FEAT_QUARTZ);
- }
-
- /* Magma */
- else if (t < 100)
- {
- /* Create magma vein */
- cave_set_feat(y, x, FEAT_MAGMA);
- }
-
- /* Floor */
- else
- {
- /* Create floor */
- cave_set_feat(y, x, FEAT_FLOOR);
- }
- }
- }
- }
-
-
- /* Hack -- Affect player */
- if (flag)
- {
- /* Message */
- msg_print("There is a searing blast of light!");
-
- /* Blind the player */
- if (!p_ptr->resist_blind && !p_ptr->resist_lite)
- {
- /* Become blind */
- (void)set_blind(p_ptr->blind + 10 + randint(10));
- }
- }
-
-
- /* Mega-Hack -- Forget the view */
- p_ptr->update |= (PU_UN_VIEW);
-
- /* Update stuff */
- p_ptr->update |= (PU_VIEW | PU_FLOW | PU_MON_LITE);
-
- /* Update the monsters */
- p_ptr->update |= (PU_MONSTERS);
-
- /* Redraw map */
- p_ptr->redraw |= (PR_MAP);
-
- /* Window stuff */
- p_ptr->window |= (PW_OVERHEAD);
-}
-
-
-/*
- * Induce an "earthquake" of the given radius at the given location.
- *
- * This will turn some walls into floors and some floors into walls.
- *
- * The player will take damage and "jump" into a safe grid if possible,
- * otherwise, he will "tunnel" through the rubble instantaneously.
- *
- * 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.
- *
- * 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.
- */
-void earthquake(int cy, int cx, int r)
-{
- int i, t, y, x, yy, xx, dy, dx, oy, ox;
- int damage = 0;
- int sn = 0, sy = 0, sx = 0;
- bool_ hurt = FALSE;
- cave_type *c_ptr;
- bool_ map[32][32];
-
- if (p_ptr->inside_quest)
- {
- return;
- }
-
- /* Paranoia -- Enforce maximum range */
- if (r > 12) r = 12;
-
- /* Clear the "maximal blast" area */
- for (y = 0; y < 32; y++)
- {
- for (x = 0; x < 32; x++)
- {
- map[y][x] = FALSE;
- }
- }
-
- /* Check around the epicenter */
- for (dy = -r; dy <= r; dy++)
- {
- for (dx = -r; dx <= r; dx++)
- {
- /* Extract the location */
- yy = cy + dy;
- xx = cx + dx;
-
- /* Skip illegal grids */
- if (!in_bounds(yy, xx)) continue;
-
- /* Skip distant grids */
- if (distance(cy, cx, yy, xx) > r) continue;
-
- /* Access the grid */
- c_ptr = &cave[yy][xx];
-
- /* Lose room and vault */
- c_ptr->info &= ~(CAVE_ROOM | CAVE_ICKY);
-
- /* Lose light and knowledge */
- c_ptr->info &= ~(CAVE_GLOW | CAVE_MARK);
-
- /* Skip the epicenter */
- if (!dx && !dy) continue;
-
- /* Skip most grids */
- if (rand_int(100) < 85) continue;
-
- /* Damage this grid */
- map[16 + yy - cy][16 + xx - cx] = TRUE;
-
- /* Hack -- Take note of player damage */
- if ((yy == p_ptr->py) && (xx == p_ptr->px)) hurt = TRUE;
- }
- }
-
- /* First, affect the player (if necessary) */
- if (hurt && !p_ptr->wraith_form)
- {
- /* Check around the player */
- for (i = 0; i < 8; i++)
- {
- /* Access the location */
- y = p_ptr->py + ddy[i];
- x = p_ptr->px + ddx[i];
-
- /* Skip non-empty grids */
- if (!cave_empty_bold(y, x)) continue;
-
- /* Important -- Skip "quake" grids */
- if (map[16 + y - cy][16 + x - cx]) continue;
-
- /* Count "safe" grids */
- sn++;
-
- /* Randomize choice */
- if (rand_int(sn) > 0) continue;
-
- /* Save the safe location */
- sy = y;
- sx = x;
- }
-
- /* Random message */
- switch (randint(3))
- {
- case 1:
- {
- msg_print("The cave ceiling collapses!");
- break;
- }
- case 2:
- {
- msg_print("The cave floor twists in an unnatural way!");
- break;
- }
- default:
- {
- msg_print("The cave quakes! You are pummeled with debris!");
- break;
- }
- }
-
- /* Hurt the player a lot */
- if (!sn)
- {
- /* Message and damage */
- msg_print("You are severely crushed!");
- damage = 300;
- }
-
- /* Destroy the grid, and push the player to safety */
- else
- {
- /* Calculate results */
- switch (randint(3))
- {
- case 1:
- {
- msg_print("You nimbly dodge the blast!");
- damage = 0;
- break;
- }
- case 2:
- {
- msg_print("You are bashed by rubble!");
- damage = damroll(10, 4);
- (void)set_stun(p_ptr->stun + randint(50));
- break;
- }
- case 3:
- {
- msg_print("You are crushed between the floor and ceiling!");
- damage = damroll(10, 4);
- (void)set_stun(p_ptr->stun + randint(50));
- break;
- }
- }
-
- /* Save the old location */
- oy = p_ptr->py;
- ox = p_ptr->px;
-
- /* Move the player to the safe location */
- p_ptr->py = sy;
- p_ptr->px = sx;
-
- /* Redraw the old spot */
- lite_spot(oy, ox);
-
- /* Redraw the new spot */
- lite_spot(p_ptr->py, p_ptr->px);
-
- /* Check for new panel */
- verify_panel();
- }
-
- /* Important -- no wall on player */
- map[16 + p_ptr->py - cy][16 + p_ptr->px - cx] = FALSE;
-
- /* Semi-wraiths have to be hurt *some*, says DG */
- if (PRACE_FLAG(PR1_SEMI_WRAITH))
- damage /= 4;
-
- /* Take some damage */
- if (damage) take_hit(damage, "an earthquake");
- }
-
-
- /* Examine the quaked region */
- for (dy = -r; dy <= r; dy++)
- {
- for (dx = -r; dx <= r; dx++)
- {
- /* Extract the location */
- yy = cy + dy;
- xx = cx + dx;
-
- /* Skip unaffected grids */
- if (!map[16 + yy - cy][16 + xx - cx]) continue;
-
- /* Access the grid */
- c_ptr = &cave[yy][xx];
-
- /* Process monsters */
- if (c_ptr->m_idx)
- {
- monster_type *m_ptr = &m_list[c_ptr->m_idx];
- monster_race *r_ptr = race_inf(m_ptr);
-
- /* Most monsters cannot co-exist with rock */
- if (!(r_ptr->flags2 & (RF2_KILL_WALL)) &&
- !(r_ptr->flags2 & (RF2_PASS_WALL)))
- {
- char m_name[80];
-
- /* Assume not safe */
- sn = 0;
-
- /* Monster can move to escape the wall */
- if (!(r_ptr->flags1 & (RF1_NEVER_MOVE)))
- {
- /* Look for safety */
- for (i = 0; i < 8; i++)
- {
- /* Access the grid */
- y = yy + ddy[i];
- x = xx + ddx[i];
-
- /* Skip non-empty grids */
- if (!cave_empty_bold(y, x)) continue;
-
- /* Hack -- no safety on glyph of warding */
- if (cave[y][x].feat == FEAT_GLYPH) continue;
- if (cave[y][x].feat == FEAT_MINOR_GLYPH) continue;
-
- /* ... nor on the Pattern */
- if ((cave[y][x].feat <= FEAT_PATTERN_XTRA2) &&
- (cave[y][x].feat >= FEAT_PATTERN_START))
- continue;
-
- /* Important -- Skip "quake" grids */
- if (map[16 + y - cy][16 + x - cx]) continue;
-
- /* Count "safe" grids */
- sn++;
-
- /* Randomize choice */
- if (rand_int(sn) > 0) continue;
-
- /* Save the safe grid */
- sy = y;
- sx = x;
- }
- }
-
- /* Describe the monster */
- monster_desc(m_name, m_ptr, 0);
-
- /* Scream in pain */
- msg_format("%^s wails out in pain!", m_name);
-
- /* Take damage from the quake */
- damage = (sn ? damroll(4, 8) : 200);
-
- /* Monster is certainly awake */
- m_ptr->csleep = 0;
-
- /* Apply damage directly */
- m_ptr->hp -= damage;
-
- /* Delete (not kill) "dead" monsters */
- if (m_ptr->hp < 0)
- {
- /* Message */
- msg_format("%^s is embedded in the rock!", m_name);
-
- /* Delete the monster */
- delete_monster(yy, xx);
-
- /* No longer safe */
- sn = 0;
- }
-
- /* Hack -- Escape from the rock */
- if (sn)
- {
- int m_idx = cave[yy][xx].m_idx;
-
- /* Update the new location */
- cave[sy][sx].m_idx = m_idx;
-
- /* Update the old location */
- cave[yy][xx].m_idx = 0;
-
- /* Move the monster */
- m_ptr->fy = sy;
- m_ptr->fx = sx;
-
- /* Update the monster (new location) */
- update_mon(m_idx, TRUE);
-
- /* Redraw the old grid */
- lite_spot(yy, xx);
-
- /* Redraw the new grid */
- lite_spot(sy, sx);
- }
- }
- }
- }
- }
-
-
- /* Examine the quaked region */
- for (dy = -r; dy <= r; dy++)
- {
- for (dx = -r; dx <= r; dx++)
- {
- /* Extract the location */
- yy = cy + dy;
- xx = cx + dx;
-
- /* Skip unaffected grids */
- if (!map[16 + yy - cy][16 + xx - cx]) continue;
-
- /* Access the cave grid */
- c_ptr = &cave[yy][xx];
-
- /* Paranoia -- never affect player */
- if ((yy == p_ptr->py) && (xx == p_ptr->px)) continue;
-
- /* Destroy location (if valid) */
- if (cave_valid_bold(yy, xx))
- {
- bool_ floor = cave_floor_bold(yy, xx);
-
- /* Delete objects */
- delete_object(yy, xx);
-
- /* Wall (or floor) type */
- t = (floor ? rand_int(100) : 200);
-
- /* Granite */
- if (t < 20)
- {
- /* Create granite wall */
- cave_set_feat(yy, xx, FEAT_WALL_EXTRA);
- }
-
- /* Quartz */
- else if (t < 70)
- {
- /* Create quartz vein */
- cave_set_feat(yy, xx, FEAT_QUARTZ);
- }
-
- /* Magma */
- else if (t < 100)
- {
- /* Create magma vein */
- cave_set_feat(yy, xx, FEAT_MAGMA);
- }
-
- /* Floor */
- else
- {
- /* Create floor */
- cave_set_feat(yy, xx, FEAT_FLOOR);
- }
- }
- }
- }
-
-
- /* Mega-Hack -- Forget the view */
- p_ptr->update |= (PU_UN_VIEW);
-
- /* Update stuff */
- p_ptr->update |= (PU_VIEW | PU_FLOW | PU_MON_LITE);
-
- /* Update the monsters */
- p_ptr->update |= (PU_DISTANCE);
-
- /* Update the health bar */
- p_ptr->redraw |= (PR_HEALTH);
-
- /* Redraw map */
- p_ptr->redraw |= (PR_MAP);
-
- /* Window stuff */
- p_ptr->window |= (PW_OVERHEAD);
-}
-
-
-
-/*
- * This routine clears the entire "temp" set.
- *
- * This routine will Perma-Lite all "temp" grids.
- *
- * This routine is used (only) by "lite_room()"
- *
- * Dark grids are illuminated.
- *
- * Also, process all affected monsters.
- *
- * SMART monsters always wake up when illuminated
- * NORMAL monsters wake up 1/4 the time when illuminated
- * STUPID monsters wake up 1/10 the time when illuminated
- */
-static void cave_temp_room_lite(void)
-{
- int i;
-
- /* Apply flag changes */
- for (i = 0; i < temp_n; i++)
- {
- int y = temp_y[i];
- int x = temp_x[i];
-
- cave_type *c_ptr = &cave[y][x];
-
- /* No longer in the array */
- c_ptr->info &= ~(CAVE_TEMP);
-
- /* Update only non-CAVE_GLOW grids */
- /* if (c_ptr->info & (CAVE_GLOW)) continue; */
-
- /* Perma-Lite */
- c_ptr->info |= (CAVE_GLOW);
- }
-
- /* Fully update the visuals */
- p_ptr->update |= (PU_UN_VIEW | PU_VIEW | PU_MONSTERS | PU_MON_LITE);
-
- /* Update stuff */
- update_stuff();
-
- /* Process the grids */
- for (i = 0; i < temp_n; i++)
- {
- int y = temp_y[i];
- int x = temp_x[i];
-
- cave_type *c_ptr = &cave[y][x];
-
- /* Redraw the grid */
- lite_spot(y, x);
-
- /* Process affected monsters */
- if (c_ptr->m_idx)
- {
- int chance = 25;
-
- monster_type *m_ptr = &m_list[c_ptr->m_idx];
-
- monster_race *r_ptr = race_inf(m_ptr);
-
- /* Update the monster */
- update_mon(c_ptr->m_idx, FALSE);
-
- /* Stupid monsters rarely wake up */
- if (r_ptr->flags2 & (RF2_STUPID)) chance = 10;
-
- /* Smart monsters always wake up */
- if (r_ptr->flags2 & (RF2_SMART)) chance = 100;
-
- /* Sometimes monsters wake up */
- if (m_ptr->csleep && (rand_int(100) < chance))
- {
- /* Wake up! */
- m_ptr->csleep = 0;
-
- /* Notice the "waking up" */
- if (m_ptr->ml)
- {
- char m_name[80];
-
- /* Acquire the monster name */
- monster_desc(m_name, m_ptr, 0);
-
- /* Dump a message */
- msg_format("%^s wakes up.", m_name);
- }
- }
- }
- }
-
- /* None left */
- temp_n = 0;
-}
-
-
-
-/*
- * This routine clears the entire "temp" set.
- *
- * This routine will "darken" all "temp" grids.
- *
- * In addition, some of these grids will be "unmarked".
- *
- * This routine is used (only) by "unlite_room()"
- *
- * Also, process all affected monsters
- */
-static void cave_temp_room_unlite(void)
-{
- int i;
-
- /* Apply flag changes */
- for (i = 0; i < temp_n; i++)
- {
- int y = temp_y[i];
- int x = temp_x[i];
-
- cave_type *c_ptr = &cave[y][x];
-
- /* 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))
- {
- /* Forget the grid */
- c_ptr->info &= ~(CAVE_MARK);
-
- /* Notice */
- /* note_spot(y, x); */
- }
- }
-
- /* Fully update the visuals */
- p_ptr->update |= (PU_UN_VIEW | PU_VIEW | PU_MONSTERS | PU_MON_LITE);
-
- /* Update stuff */
- update_stuff();
-
- /* Process the grids */
- for (i = 0; i < temp_n; i++)
- {
- int y = temp_y[i];
- int x = temp_x[i];
-
- /* Redraw the grid */
- lite_spot(y, x);
- }
-
- /* None left */
- temp_n = 0;
-}
-
-
-
-
-/*
- * Aux function -- see below
- */
-static void cave_temp_room_aux(int y, int x)
-{
- cave_type *c_ptr = &cave[y][x];
-
- /* Avoid infinite recursion */
- if (c_ptr->info & (CAVE_TEMP)) return;
-
- /* Do not "leave" the current room */
- if (!(c_ptr->info & (CAVE_ROOM))) return;
-
- /* Paranoia -- verify space */
- if (temp_n == TEMP_MAX) return;
-
- /* Mark the grid as "seen" */
- c_ptr->info |= (CAVE_TEMP);
-
- /* Add it to the "seen" set */
- temp_y[temp_n] = y;
- temp_x[temp_n] = x;
- temp_n++;
-}
-
-
-
-
-/*
- * Illuminate any room containing the given location.
- */
-void lite_room(int y1, int x1)
-{
- int i, x, y;
-
- /* Add the initial grid */
- cave_temp_room_aux(y1, x1);
-
- /* While grids are in the queue, add their neighbors */
- for (i = 0; i < temp_n; i++)
- {
- x = temp_x[i], y = temp_y[i];
-
- /* Walls get lit, but stop light */
- if (!cave_floor_bold(y, x)) continue;
-
- /* Spread adjacent */
- cave_temp_room_aux(y + 1, x);
- cave_temp_room_aux(y - 1, x);
- cave_temp_room_aux(y, x + 1);
- cave_temp_room_aux(y, x - 1);
-
- /* Spread diagonal */
- cave_temp_room_aux(y + 1, x + 1);
- cave_temp_room_aux(y - 1, x - 1);
- cave_temp_room_aux(y - 1, x + 1);
- cave_temp_room_aux(y + 1, x - 1);
- }
-
- /* Now, lite them all up at once */
- cave_temp_room_lite();
-}
-
-
-/*
- * Darken all rooms containing the given location
- */
-void unlite_room(int y1, int x1)
-{
- int i, x, y;
-
- /* Add the initial grid */
- cave_temp_room_aux(y1, x1);
-
- /* Spread, breadth first */
- for (i = 0; i < temp_n; i++)
- {
- x = temp_x[i], y = temp_y[i];
-
- /* Walls get dark, but stop darkness */
- if (!cave_floor_bold(y, x)) continue;
-
- /* Spread adjacent */
- cave_temp_room_aux(y + 1, x);
- cave_temp_room_aux(y - 1, x);
- cave_temp_room_aux(y, x + 1);
- cave_temp_room_aux(y, x - 1);
-
- /* Spread diagonal */
- cave_temp_room_aux(y + 1, x + 1);
- cave_temp_room_aux(y - 1, x - 1);
- cave_temp_room_aux(y - 1, x + 1);
- cave_temp_room_aux(y + 1, x - 1);
- }
-
- /* Now, darken them all at once */
- cave_temp_room_unlite();
-}
-
-
-
-/*
- * Hack -- call light around the player
- * Affect all monsters in the projection radius
- */
-bool_ lite_area(int dam, int rad)
-{
- int flg = PROJECT_GRID | PROJECT_KILL;
-
- /* Hack -- Message */
- if (!p_ptr->blind)
- {
- msg_print("You are surrounded by a white light.");
- }
-
- /* Hook into the "project()" function */
- (void)project(0, rad, p_ptr->py, p_ptr->px, dam, GF_LITE_WEAK, flg);
-
- /* Lite up the room */
- lite_room(p_ptr->py, p_ptr->px);
-
- /* Assume seen */
- return (TRUE);
-}
-
-
-/*
- * Hack -- call darkness around the player
- * Affect all monsters in the projection radius
- */
-bool_ unlite_area(int dam, int rad)
-{
- int flg = PROJECT_GRID | PROJECT_KILL;
-
- /* Hack -- Message */
- if (!p_ptr->blind)
- {
- msg_print("Darkness surrounds you.");
- }
-
- /* Hook into the "project()" function */
- (void)project(0, rad, p_ptr->py, p_ptr->px, dam, GF_DARK_WEAK, flg);
-
- /* Lite up the room */
- unlite_room(p_ptr->py, p_ptr->px);
-
- /* Assume seen */
- return (TRUE);
-}
-
-
-/*
- * Cast a ball spell
- * Stop if we hit a monster, act as a "ball"
- * Allow "target" mode to pass over monsters
- * Affect grids, objects, and monsters
- */
-bool_ fire_ball(int typ, int dir, int dam, int rad)
-{
- int tx, ty;
-
- int flg = PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL;
-
- /* Use the given direction */
- tx = p_ptr->px + 99 * ddx[dir];
- ty = p_ptr->py + 99 * ddy[dir];
-
- /* Hack -- Use an actual "target" */
- if ((dir == 5) && target_okay())
- {
- flg &= ~(PROJECT_STOP);
- tx = target_col;
- ty = target_row;
- }
-
- /* Analyze the "dir" and the "target". Hurt items on floor. */
- return (project(0, (rad > 16) ? 16 : rad, ty, tx, dam, typ, flg));
-}
-
-/*
- * Cast a cloud spell
- * Stop if we hit a monster, act as a "ball"
- * Allow "target" mode to pass over monsters
- * Affect grids, objects, and monsters
- */
-bool_ fire_cloud(int typ, int dir, int dam, int rad, int time)
-{
- int tx, ty;
-
- int flg = PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_STAY;
-
- /* Use the given direction */
- tx = p_ptr->px + 99 * ddx[dir];
- ty = p_ptr->py + 99 * ddy[dir];
-
- /* Hack -- Use an actual "target" */
- if ((dir == 5) && target_okay())
- {
- flg &= ~(PROJECT_STOP);
- tx = target_col;
- ty = target_row;
- }
- project_time = time;
-
- /* Analyze the "dir" and the "target". Hurt items on floor. */
- return (project(0, (rad > 16) ? 16 : rad, ty, tx, dam, typ, flg));
-}
-
-/*
- * Cast a wave spell
- * Stop if we hit a monster, act as a "ball"
- * Allow "target" mode to pass over monsters
- * Affect grids, objects, and monsters
- */
-bool_ fire_wave(int typ, int dir, int dam, int rad, int time, s32b eff)
-{
- project_time_effect = eff;
- return (fire_cloud(typ, dir, dam, rad, time));
-}
-
-/*
- * Cast a persistant beam spell
- * Pass through monsters, as a "beam"
- * Affect monsters (not grids or objects)
- */
-bool_ fire_wall(int typ, int dir, int dam, int time)
-{
- int flg = PROJECT_BEAM | PROJECT_KILL | PROJECT_STAY | PROJECT_GRID;
- project_time = time;
- return (project_hook(typ, dir, dam, flg));
-}
-
-/*
- * Cast a druidistic ball spell
- * Stop if we hit a monster, act as a "ball"
- * Allow "target" mode to pass over monsters
- * Affect grids, objects, and monsters
- */
-bool_ fire_druid_ball(int typ, int dir, int dam, int rad)
-{
- int tx, ty;
-
- int flg = PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_MANA_PATH;
-
- /* Use the given direction */
- tx = p_ptr->px + 99 * ddx[dir];
- ty = p_ptr->py + 99 * ddy[dir];
-
- /* Hack -- Use an actual "target" */
- if ((dir == 5) && target_okay())
- {
- flg &= ~(PROJECT_STOP);
- tx = target_col;
- ty = target_row;
- }
-
- /* Analyze the "dir" and the "target". Hurt items on floor. */
- return (project(0, (rad > 16) ? 16 : rad, ty, tx, dam, typ, flg));
-}
-
-
-/*
- * Cast a ball-beamed spell
- * Stop if we hit a monster, act as a "ball"
- * Allow "target" mode to pass over monsters
- * Affect grids, objects, and monsters
- */
-bool_ fire_ball_beam(int typ, int dir, int dam, int rad)
-{
- int tx, ty;
-
- int flg = PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_BEAM;
-
- /* Use the given direction */
- tx = p_ptr->px + 99 * ddx[dir];
- ty = p_ptr->py + 99 * ddy[dir];
-
- /* Hack -- Use an actual "target" */
- if ((dir == 5) && target_okay())
- {
- flg &= ~(PROJECT_STOP);
- tx = target_col;
- ty = target_row;
- }
-
- /* Analyze the "dir" and the "target". Hurt items on floor. */
- return (project(0, (rad > 16) ? 16 : rad, ty, tx, dam, typ, flg));
-}
-
-
-void teleport_swap(int dir)
-{
- int tx, ty;
- cave_type * c_ptr;
- monster_type * m_ptr;
- monster_race * r_ptr;
-
- if (p_ptr->resist_continuum)
- {
- msg_print("The space-time continuum can't be disrupted.");
- return;
- }
-
- if ((dir == 5) && target_okay())
- {
- tx = target_col;
- ty = target_row;
- }
- else
- {
- tx = p_ptr->px + ddx[dir];
- ty = p_ptr->py + ddy[dir];
- }
- c_ptr = &cave[ty][tx];
-
- if (!c_ptr->m_idx)
- {
- msg_print("You can't trade places with that!");
- }
- else
- {
- m_ptr = &m_list[c_ptr->m_idx];
- r_ptr = race_inf(m_ptr);
-
- if (r_ptr->flags3 & RF3_RES_TELE)
- {
- msg_print("Your teleportation is blocked!");
- }
- else
- {
- sound(SOUND_TELEPORT);
-
- cave[p_ptr->py][p_ptr->px].m_idx = c_ptr->m_idx;
-
- /* Update the old location */
- c_ptr->m_idx = 0;
-
- /* Move the monster */
- m_ptr->fy = p_ptr->py;
- m_ptr->fx = p_ptr->px;
-
- /* Move the player */
- p_ptr->px = tx;
- p_ptr->py = ty;
-
- tx = m_ptr->fx;
- ty = m_ptr->fy;
-
- /* Update the monster (new location) */
- update_mon(cave[ty][tx].m_idx, TRUE);
-
- /* Redraw the old grid */
- lite_spot(ty, tx);
-
- /* Redraw the new grid */
- lite_spot(p_ptr->py, p_ptr->px);
-
- /* Execute the inscription */
- c_ptr = &cave[m_ptr->fy][m_ptr->fx];
- if (c_ptr->inscription)
- {
- if (inscription_info[c_ptr->inscription].when & INSCRIP_EXEC_MONST_WALK)
- {
- execute_inscription(c_ptr->inscription, m_ptr->fy, m_ptr->fx);
- }
- }
- c_ptr = &cave[p_ptr->py][p_ptr->px];
- if (c_ptr->inscription)
- {
- 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);
- }
- }
-
- /* Check for new panel (redraw map) */
- verify_panel();
-
- /* Update stuff */
- p_ptr->update |= (PU_VIEW | PU_FLOW | PU_MON_LITE);
-
- /* Update the monsters */
- p_ptr->update |= (PU_DISTANCE);
-
- /* Redraw trap detection status */
- p_ptr->redraw |= (PR_DTRAP);
-
- /* Window stuff */
- p_ptr->window |= (PW_OVERHEAD);
-
- /* Handle stuff XXX XXX XXX */
- handle_stuff();
- }
- }
-}
-
-void swap_position(int lty, int ltx)
-{
- int tx = ltx, ty = lty;
- cave_type * c_ptr;
- monster_type * m_ptr;
-
- if (p_ptr->resist_continuum)
- {
- msg_print("The space-time continuum can't be disrupted.");
- return;
- }
-
- c_ptr = &cave[ty][tx];
-
- if (!c_ptr->m_idx)
- {
- sound(SOUND_TELEPORT);
-
- /* Keep trace of the old location */
- tx = p_ptr->px;
- ty = p_ptr->py;
-
- /* Move the player */
- p_ptr->px = ltx;
- p_ptr->py = lty;
-
- /* Redraw the old grid */
- lite_spot(ty, tx);
-
- /* Redraw the new grid */
- lite_spot(p_ptr->py, p_ptr->px);
-
- /* Check for new panel (redraw map) */
- verify_panel();
-
- /* Update stuff */
- p_ptr->update |= (PU_VIEW | PU_FLOW | PU_MON_LITE);
-
- /* Update the monsters */
- p_ptr->update |= (PU_DISTANCE);
-
- /* Redraw trap detection status */
- p_ptr->redraw |= (PR_DTRAP);
-
- /* Window stuff */
- p_ptr->window |= (PW_OVERHEAD);
-
- /* Handle stuff XXX XXX XXX */
- handle_stuff();
- }
- else
- {
- m_ptr = &m_list[c_ptr->m_idx];
-
- sound(SOUND_TELEPORT);
-
- cave[p_ptr->py][p_ptr->px].m_idx = c_ptr->m_idx;
-
- /* Update the old location */
- c_ptr->m_idx = 0;
-
- /* Move the monster */
- m_ptr->fy = p_ptr->py;
- m_ptr->fx = p_ptr->px;
-
- /* Move the player */
- p_ptr->px = tx;
- p_ptr->py = ty;
-
- tx = m_ptr->fx;
- ty = m_ptr->fy;
-
- /* Update the monster (new location) */
- update_mon(cave[ty][tx].m_idx, TRUE);
-
- /* Redraw the old grid */
- lite_spot(ty, tx);
-
- /* Redraw the new grid */
- lite_spot(p_ptr->py, p_ptr->px);
-
- /* Check for new panel (redraw map) */
- verify_panel();
-
- /* Update stuff */
- p_ptr->update |= (PU_VIEW | PU_FLOW | PU_MON_LITE);
-
- /* Update the monsters */
- p_ptr->update |= (PU_DISTANCE);
-
- /* Redraw trap detection status */
- p_ptr->redraw |= (PR_DTRAP);
-
- /* Window stuff */
- p_ptr->window |= (PW_OVERHEAD);
-
- /* Handle stuff XXX XXX XXX */
- handle_stuff();
- }
-}
-
-
-/*
- * Hack -- apply a "projection()" in a direction (or at the target)
- */
-bool_ project_hook(int typ, int dir, int dam, int flg)
-{
- int tx, ty;
-
- /* Pass through the target if needed */
- flg |= (PROJECT_THRU);
-
- /* 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;
- }
-
- /* Analyze the "dir" and the "target", do NOT explode */
- return (project(0, 0, ty, tx, dam, typ, flg));
-}
-
-
-/*
- * Cast a bolt spell
- * Stop if we hit a monster, as a "bolt"
- * Affect monsters (not grids or objects)
- */
-bool_ fire_bolt(int typ, int dir, int dam)
-{
- int flg = PROJECT_STOP | PROJECT_KILL;
- return (project_hook(typ, dir, dam, flg));
-}
-
-/*
- * Cast a druidistic bolt spell
- * Stop if we hit a monster, as a "bolt"
- * Affect monsters (not grids or objects)
- */
-bool_ fire_druid_bolt(int typ, int dir, int dam)
-{
- int flg = PROJECT_STOP | PROJECT_KILL | PROJECT_MANA_PATH;
- return (project_hook(typ, dir, dam, flg));
-}
-
-
-/*
- * Cast a druidistic beam spell
- * Pass through monsters, as a "beam"
- * Affect monsters (not grids or objects)
- */
-bool_ fire_druid_beam(int typ, int dir, int dam)
-{
- int flg = PROJECT_BEAM | PROJECT_KILL | PROJECT_MANA_PATH;
- return (project_hook(typ, dir, dam, flg));
-}
-
-/*
- * Cast a beam spell
- * Pass through monsters, as a "beam"
- * Affect monsters (not grids or objects)
- */
-bool_ fire_beam(int typ, int dir, int dam)
-{
- int flg = PROJECT_BEAM | PROJECT_KILL;
- return (project_hook(typ, dir, dam, flg));
-}
-
-
-/*
- * Cast a bolt spell, or rarely, a beam spell
- */
-bool_ fire_bolt_or_beam(int prob, int typ, int dir, int dam)
-{
- if (rand_int(100) < prob)
- {
- return (fire_beam(typ, dir, dam));
- }
- else
- {
- return (fire_bolt(typ, dir, dam));
- }
-}
-
-bool_ fire_godly_wrath(int y, int x, int typ, int rad, int dam)
-{
- int flg = PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL;
-
- return (project(0, rad, y, x, dam, typ, flg));
-}
-
-bool_ fire_explosion(int y, int x, int typ, int rad, int dam)
-{
- int flg = PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL;
-
- return (project(0, rad, y, x, dam, typ, flg));
-}
-
-/*
- * Some of the old functions
- */
-bool_ lite_line(int dir)
-{
- int flg = PROJECT_BEAM | PROJECT_GRID | PROJECT_KILL;
- return (project_hook(GF_LITE_WEAK, dir, damroll(6, 8), flg));
-}
-
-
-bool_ drain_life(int dir, int dam)
-{
- int flg = PROJECT_STOP | PROJECT_KILL;
- return (project_hook(GF_OLD_DRAIN, dir, dam, flg));
-}
-
-
-bool_ wall_to_mud(int dir)
-{
- int flg = PROJECT_BEAM | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL;
- return (project_hook(GF_KILL_WALL, dir, 20 + randint(30), flg));
-}
-
-
-bool_ wizard_lock(int dir)
-{
- int flg = PROJECT_BEAM | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL;
- return (project_hook(GF_JAM_DOOR, dir, 20 + randint(30), flg));
-}
-
-
-bool_ destroy_door(int dir)
-{
- int flg = PROJECT_BEAM | PROJECT_GRID | PROJECT_ITEM;
- return (project_hook(GF_KILL_DOOR, dir, 0, flg));
-}
-
-
-bool_ disarm_trap(int dir)
-{
- int flg = PROJECT_BEAM | PROJECT_GRID | PROJECT_ITEM;
- return (project_hook(GF_KILL_TRAP, dir, 0, flg));
-}
-
-
-bool_ heal_monster(int dir)
-{
- int flg = PROJECT_STOP | PROJECT_KILL;
- return (project_hook(GF_OLD_HEAL, dir, damroll(4, 6), flg));
-}
-
-
-bool_ speed_monster(int dir)
-{
- int flg = PROJECT_STOP | PROJECT_KILL;
- return (project_hook(GF_OLD_SPEED, dir, p_ptr->lev, flg));
-}
-
-
-bool_ slow_monster(int dir)
-{
- int flg = PROJECT_STOP | PROJECT_KILL;
- return (project_hook(GF_OLD_SLOW, dir, p_ptr->lev, flg));
-}
-
-
-bool_ sleep_monster(int dir)
-{
- int flg = PROJECT_STOP | PROJECT_KILL;
- return (project_hook(GF_OLD_SLEEP, dir, p_ptr->lev, flg));
-}
-
-
-bool_ stasis_monster(int dir)
-{
- int flg = PROJECT_STOP | PROJECT_KILL;
- return (project_hook(GF_STASIS, dir, p_ptr->lev, flg));
-}
-
-
-bool_ confuse_monster(int dir, int plev)
-{
- int flg = PROJECT_STOP | PROJECT_KILL;
- return (project_hook(GF_OLD_CONF, dir, plev, flg));
-}
-
-
-bool_ stun_monster(int dir, int plev)
-{
- int flg = PROJECT_STOP | PROJECT_KILL;
- return (project_hook(GF_STUN, dir, plev, flg));
-}
-
-
-bool_ poly_monster(int dir)
-{
- int flg = PROJECT_STOP | PROJECT_KILL;
- return (project_hook(GF_OLD_POLY, dir, p_ptr->lev, flg));
-}
-
-
-bool_ clone_monster(int dir)
-{
- int flg = PROJECT_STOP | PROJECT_KILL;
- return (project_hook(GF_OLD_CLONE, dir, 0, flg));
-}
-
-
-bool_ fear_monster(int dir, int plev)
-{
- int flg = PROJECT_STOP | PROJECT_KILL;
- return (project_hook(GF_TURN_ALL, dir, plev, flg));
-}
-
-
-bool_ death_ray(int dir, int plev)
-{
- int flg = PROJECT_STOP | PROJECT_KILL;
- return (project_hook(GF_DEATH_RAY, dir, plev, flg));
-}
-
-
-bool_ teleport_monster(int dir)
-{
- int flg = PROJECT_BEAM | PROJECT_KILL;
-
- if (p_ptr->resist_continuum)
- {
- msg_print("The space-time continuum can't be disrupted.");
- return FALSE;
- }
-
- return (project_hook(GF_AWAY_ALL, dir, MAX_SIGHT * 5, flg));
-}
-
-
-/*
- * Hooks -- affect adjacent grids (radius 1 ball attack)
- */
-bool_ door_creation(void)
-{
- int flg = PROJECT_GRID | PROJECT_ITEM | PROJECT_HIDE;
- return (project(0, 1, p_ptr->py, p_ptr->px, 0, GF_MAKE_DOOR, flg));
-}
-
-
-bool_ trap_creation(void)
-{
- int flg = PROJECT_GRID | PROJECT_ITEM | PROJECT_HIDE;
- return (project(0, 1, p_ptr->py, p_ptr->px, 0, GF_MAKE_TRAP, flg));
-}
-
-
-bool_ glyph_creation(void)
-{
- int flg = PROJECT_GRID | PROJECT_ITEM;
- return (project(0, 1, p_ptr->py, p_ptr->px, 0, GF_MAKE_GLYPH, flg));
-}
-
-
-bool_ wall_stone(int y, int x)
-{
- cave_type *c_ptr = &cave[y][x];
- int flg = PROJECT_GRID | PROJECT_ITEM;
- int featflags = f_info[c_ptr->feat].flags1;
-
- bool_ dummy = (project(0, 1, y, x, 0, GF_STONE_WALL, flg));
-
- if (!(featflags & FF1_PERMANENT) && !(featflags & FF1_WALL))
- cave_set_feat(y, x, FEAT_FLOOR);
-
- /* Update stuff */
- p_ptr->update |= (PU_VIEW | PU_FLOW | PU_MON_LITE);
-
- /* Update the monsters */
- p_ptr->update |= (PU_MONSTERS);
-
- /* Redraw map */
- p_ptr->redraw |= (PR_MAP);
-
- /* Window stuff */
- p_ptr->window |= (PW_OVERHEAD);
-
- return dummy;
-}
-
-
-bool_ destroy_doors_touch(void)
-{
- int flg = PROJECT_GRID | PROJECT_ITEM | PROJECT_HIDE;
- return (project(0, 1, p_ptr->py, p_ptr->px, 0, GF_KILL_DOOR, flg));
-}
-
-bool_ destroy_traps_touch(void)
-{
- int flg = PROJECT_GRID | PROJECT_ITEM | PROJECT_HIDE;
- return (project(0, 1, p_ptr->py, p_ptr->px, 0, GF_KILL_TRAP, flg));
-}
-
-bool_ sleep_monsters_touch(void)
-{
- int flg = PROJECT_KILL | PROJECT_HIDE;
- return (project(0, 1, p_ptr->py, p_ptr->px, p_ptr->lev, GF_OLD_SLEEP, flg));
-}
-
-
-void call_chaos(void)
-{
- int Chaos_type, dummy, dir;
- int plev = p_ptr->lev;
- bool_ line_chaos = FALSE;
-
- int hurt_types[30] =
- {
- GF_ELEC, GF_POIS, GF_ACID, GF_COLD,
- GF_FIRE, GF_MISSILE, GF_ARROW, GF_PLASMA,
- GF_HOLY_FIRE, GF_WATER, GF_LITE, GF_DARK,
- GF_FORCE, GF_INERTIA, GF_MANA, GF_METEOR,
- GF_ICE, GF_CHAOS, GF_NETHER, GF_DISENCHANT,
- GF_SHARDS, GF_SOUND, GF_NEXUS, GF_CONFUSION,
- GF_TIME, GF_GRAVITY, GF_ROCKET, GF_NUKE,
- GF_HELL_FIRE, GF_DISINTEGRATE
- };
-
- Chaos_type = hurt_types[randint(30) - 1];
- if (randint(4) == 1) line_chaos = TRUE;
-
- if (randint(6) == 1)
- {
- for (dummy = 1; dummy < 10; dummy++)
- {
- if (dummy - 5)
- {
- if (line_chaos)
- fire_beam(Chaos_type, dummy, 75);
- else
- fire_ball(Chaos_type, dummy, 75, 2);
- }
- }
- }
- else if (randint(3) == 1)
- {
- fire_ball(Chaos_type, 0, 300, 8);
- }
- else
- {
- if (!get_aim_dir(&dir)) return;
- if (line_chaos)
- fire_beam(Chaos_type, dir, 150);
- else
- fire_ball(Chaos_type, dir, 150, 3 + (plev / 35));
- }
-}
-
-
-/*
- * Activate the evil Topi Ylinen curse
- * rr9: Stop the nasty things when a Cyberdemon is summoned
- * or the player gets paralyzed.
- */
-void activate_ty_curse(void)
-{
- int i = 0;
- bool_ stop_ty = FALSE;
-
- do
- {
- switch (randint(27))
- {
- case 1:
- case 2:
- case 3:
- case 16:
- case 17:
- aggravate_monsters(1);
- if (randint(6) != 1) break;
- case 4:
- case 5:
- case 6:
- activate_hi_summon();
- if (randint(6) != 1) break;
-case 7: case 8: case 9: case 18:
- (void) summon_specific(p_ptr->py, p_ptr->px, dun_level, 0);
- if (randint(6) != 1) break;
-case 10: case 11: case 12:
- msg_print("You feel your life draining away...");
- lose_exp(p_ptr->exp / 16);
- if (randint(6) != 1) break;
-case 13: case 14: case 15: case 19: case 20:
- if (p_ptr->free_act && (randint(100) < p_ptr->skill_sav))
- {
- /* Do nothing */ ;
- }
- else
- {
- msg_print("You feel like a statue!");
- if (p_ptr->free_act)
- set_paralyzed (p_ptr->paralyzed + randint(3));
- else
- set_paralyzed (p_ptr->paralyzed + randint(13));
- stop_ty = TRUE;
- }
- if (randint(6) != 1) break;
-case 21: case 22: case 23:
- (void)do_dec_stat((randint(6)) - 1, STAT_DEC_NORMAL);
- if (randint(6) != 1) break;
- case 24:
- msg_print("Huh? Who am I? What am I doing here?");
- lose_all_info();
- break;
- case 25:
- /*
- * Only summon Cyberdemons deep in the dungeon.
- */
- if ((dun_level > 65) && !stop_ty)
- {
- summon_cyber();
- stop_ty = TRUE;
- break;
- }
- default:
- while (i < 6)
- {
- do
- {
- (void)do_dec_stat(i, STAT_DEC_NORMAL);
- }
- while (randint(2) == 1);
-
- i++;
- }
- }
- }
- while ((randint(3) == 1) && !stop_ty);
-}
-
-/*
- * Activate the ultra evil Dark God curse
- */
-void activate_dg_curse(void)
-{
- int i = 0;
- bool_ stop_dg = FALSE;
-
- do
- {
- switch (randint(30))
- {
- case 1:
- case 2:
- case 3:
- case 16:
- case 17:
- aggravate_monsters(1);
- if (randint(8) != 1) break;
- case 4:
- case 5:
- case 6:
- msg_print("Oh! You feel that the curse is replicating itself!");
- curse_equipment_dg(100, 50 * randint(2));
- if (randint(8) != 1) break;
- case 7:
- case 8:
- case 9:
- case 18:
- curse_equipment(100, 50 * randint(2));
- if (randint(8) != 1) break;
- case 10:
- case 11:
- case 12:
- msg_print("You feel your life draining away...");
- lose_exp(p_ptr->exp / 12);
- if (rand_int(2))
- {
- msg_print("You feel the coldness of the Black Breath attacking you!");
- p_ptr->black_breath = TRUE;
- }
- if (randint(8) != 1) break;
- case 13:
- case 14:
- case 15:
- if (p_ptr->free_act && (randint(100) < p_ptr->skill_sav))
- {
- /* Do nothing */ ;
- }
- else
- {
- msg_print("You feel like a statue!");
- if (p_ptr->free_act)
- set_paralyzed (p_ptr->paralyzed + randint(3));
- else
- set_paralyzed (p_ptr->paralyzed + randint(13));
- stop_dg = TRUE;
- }
- if (randint(7) != 1) break;
- case 19:
- case 20:
- {
- msg_print("Woah! You see 10 little Morgoths dancing before you!");
- set_confused(p_ptr->confused + randint(13 * 2));
- if (rand_int(2)) stop_dg = TRUE;
- }
- if (randint(7) != 1) break;
- case 21:
- case 22:
- case 23:
- (void)do_dec_stat((randint(6)) - 1, STAT_DEC_PERMANENT);
- if (randint(7) != 1) break;
- case 24:
- msg_print("Huh? Who am I? What am I doing here?");
- lose_all_info();
- break;
-case 27: case 28: case 29:
- if (p_ptr->inventory[INVEN_WIELD].k_idx)
- {
- msg_print("Your weapon now seems useless...");
- p_ptr->inventory[INVEN_WIELD].art_flags4 = TR4_NEVER_BLOW;
- }
- break;
- case 25:
- /*
- * Only summon Thunderlords not too shallow in the dungeon.
- */
- if ((dun_level > 25) && !stop_dg)
- {
- msg_print("Oh! You attracted some evil Thunderlords!");
- summon_dragon_riders();
-
- /* This is evil -- DG */
- if (rand_int(2)) stop_dg = TRUE;
- break;
- }
- default:
- while (i < 6)
- {
- do
- {
- (void)do_dec_stat(i, STAT_DEC_NORMAL);
- }
- while (randint(2) == 1);
-
- i++;
- }
- }
- }
- while ((randint(4) == 1) && !stop_dg);
-}
-
-
-void activate_hi_summon(void)
-{
- int i;
-
- for (i = 0; i < (randint(9) + (dun_level / 40)); i++)
- {
- switch (randint(26) + (dun_level / 20) )
- {
- case 1:
- case 2:
- (void) summon_specific(p_ptr->py, p_ptr->px, dun_level, SUMMON_ANT);
- break;
- case 3:
- case 4:
- (void) summon_specific(p_ptr->py, p_ptr->px, dun_level, SUMMON_SPIDER);
- break;
- case 5:
- case 6:
- (void) summon_specific(p_ptr->py, p_ptr->px, dun_level, SUMMON_HOUND);
- break;
- case 7:
- case 8:
- (void) summon_specific(p_ptr->py, p_ptr->px, dun_level, SUMMON_HYDRA);
- break;
- case 9:
- case 10:
- (void) summon_specific(p_ptr->py, p_ptr->px, dun_level, SUMMON_ANGEL);
- break;
- case 11:
- case 12:
- (void) summon_specific(p_ptr->py, p_ptr->px, dun_level, SUMMON_UNDEAD);
- break;
- case 13:
- case 14:
- (void) summon_specific(p_ptr->py, p_ptr->px, dun_level, SUMMON_DRAGON);
- break;
- case 15:
- case 16:
- (void) summon_specific(p_ptr->py, p_ptr->px, dun_level, SUMMON_DEMON);
- break;
- case 17:
- (void) summon_specific(p_ptr->py, p_ptr->px, dun_level, SUMMON_WRAITH);
- break;
- case 18:
- case 19:
- (void) summon_specific(p_ptr->py, p_ptr->px, dun_level, SUMMON_UNIQUE);
- break;
- case 20:
- case 21:
- (void) summon_specific(p_ptr->py, p_ptr->px, dun_level, SUMMON_HI_UNDEAD);
- break;
- case 22:
- case 23:
- (void) summon_specific(p_ptr->py, p_ptr->px, dun_level, SUMMON_HI_DRAGON);
- break;
- case 24:
- case 25:
- (void) summon_specific(p_ptr->py, p_ptr->px, 100, SUMMON_HI_DEMON);
- break;
- default:
- (void) summon_specific(p_ptr->py, p_ptr->px, (((dun_level * 3) / 2) + 5), 0);
- }
- }
-}
-
-
-void summon_cyber(void)
-{
- int i;
- int max_cyber = (dun_level / 50) + randint(6);
-
- for (i = 0; i < max_cyber; i++)
- {
- (void)summon_specific(p_ptr->py, p_ptr->px, 100, SUMMON_HI_DEMON);
- }
-}
-
-void summon_dragon_riders()
-{
- int i;
- int max_dr = (dun_level / 50) + randint(6);
-
- for (i = 0; i < max_dr; i++)
- {
- (void)summon_specific(p_ptr->py, p_ptr->px, 100, SUMMON_THUNDERLORD);
- }
-}
-
-
-void wall_breaker(void)
-{
- int dummy = 5;
-
- if (randint(80 + p_ptr->lev) < 70)
- {
- do
- {
- dummy = randint(9);
- }
- while ((dummy == 5) || (dummy == 0));
-
- wall_to_mud (dummy);
- }
- else if (randint(100) > 30)
- {
- /* Prevent destruction of quest levels and town */
- if (!is_quest(dun_level) && dun_level)
- earthquake(p_ptr->py, p_ptr->px, 1);
- }
- else
- {
- for (dummy = 1; dummy < 10; dummy++)
- {
- if (dummy - 5) wall_to_mud(dummy);
- }
- }
-}
-
-
-void bless_weapon(void)
-{
- int item;
- object_type *o_ptr;
- u32b f1, f2, f3, f4, f5, esp;
- char o_name[80];
- cptr q, s;
-
- /* Assume enchant weapon */
- item_tester_hook = item_tester_hook_weapon;
-
- /* Get an item */
- q = "Bless which weapon? ";
- s = "You have weapon to bless.";
- 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, FALSE, 0);
-
- /* Extract the flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
-
- if (o_ptr->ident & (IDENT_CURSED))
- {
-
- if (((f3 & (TR3_HEAVY_CURSE)) && (randint (100) < 33)) ||
- (f3 & (TR3_PERMA_CURSE)))
- {
-
- msg_format("The black aura on %s %s disrupts the blessing!",
- ((item >= 0) ? "your" : "the"), o_name);
- return;
- }
-
- msg_format("A malignant aura leaves %s %s.",
- ((item >= 0) ? "your" : "the"), o_name);
-
- /* Uncurse it */
- o_ptr->ident &= ~(IDENT_CURSED);
-
- /* Hack -- Assume felt */
- o_ptr->ident |= (IDENT_SENSE);
-
- /* Take note */
- o_ptr->sense = SENSE_UNCURSED;
-
- /* Recalculate the bonuses */
- p_ptr->update |= (PU_BONUS);
-
- /* Window stuff */
- p_ptr->window |= (PW_EQUIP);
- }
-
- /*
- * Next, we try to bless it. Artifacts have a 1/3 chance of
- * being blessed, otherwise, the operation simply disenchants
- * them, godly power negating the magic. Ok, the explanation
- * is silly, but otherwise priests would always bless every
- * artifact weapon they find. Ego weapons and normal weapons
- * can be blessed automatically.
- */
- if (f3 & TR3_BLESSED)
- {
- msg_format("%s %s %s blessed already.",
- ((item >= 0) ? "Your" : "The"), o_name,
- ((o_ptr->number > 1) ? "were" : "was"));
- return;
- }
-
- if (!(o_ptr->art_name || o_ptr->name1) || (randint(3) == 1))
- {
- /* Describe */
- msg_format("%s %s shine%s!",
- ((item >= 0) ? "Your" : "The"), o_name,
- ((o_ptr->number > 1) ? "" : "s"));
- o_ptr->art_flags3 |= TR3_BLESSED;
- }
- else
- {
- bool_ dis_happened = FALSE;
-
- msg_print("The artifact resists your blessing!");
-
- /* Disenchant tohit */
- if (o_ptr->to_h > 0)
- {
- o_ptr->to_h--;
- dis_happened = TRUE;
- }
-
- if ((o_ptr->to_h > 5) && (rand_int(100) < 33)) o_ptr->to_h--;
-
- /* Disenchant todam */
- if (o_ptr->to_d > 0)
- {
- o_ptr->to_d--;
- dis_happened = TRUE;
- }
-
- if ((o_ptr->to_d > 5) && (rand_int(100) < 33)) o_ptr->to_d--;
-
- /* Disenchant toac */
- if (o_ptr->to_a > 0)
- {
- o_ptr->to_a--;
- dis_happened = TRUE;
- }
-
- if ((o_ptr->to_a > 5) && (rand_int(100) < 33)) o_ptr->to_a--;
-
- if (dis_happened)
- {
- msg_print("There is a static feeling in the air...");
- msg_format("%s %s %s disenchanted!",
- ((item >= 0) ? "Your" : "The"), o_name,
- ((o_ptr->number > 1) ? "were" : "was"));
- }
- }
-
- /* Recalculate bonuses */
- p_ptr->update |= (PU_BONUS);
-
- /* Window stuff */
- p_ptr->window |= (PW_EQUIP | PW_PLAYER);
-}
-
-
-/*
- * Detect all "nonliving", "undead" or "demonic" monsters on current panel
- */
-bool_ detect_monsters_nonliving(int rad)
-{
- int i, y, x;
- bool_ flag = FALSE;
-
- /* Scan monsters */
- for (i = 1; i < m_max; i++)
- {
- monster_type *m_ptr = &m_list[i];
- monster_race *r_ptr = race_inf(m_ptr);
-
- /* Skip dead monsters */
- if (!m_ptr->r_idx) continue;
-
- /* Location */
- y = m_ptr->fy;
- x = m_ptr->fx;
-
- /* Only detect nearby monsters */
- if (m_ptr->cdis > rad) continue;
-
- /* Detect evil monsters */
- if ((r_ptr->flags3 & (RF3_NONLIVING)) ||
- (r_ptr->flags3 & (RF3_UNDEAD)) ||
- (r_ptr->flags3 & (RF3_DEMON)))
- {
- /* Update monster recall window */
- if (monster_race_idx == m_ptr->r_idx)
- {
- /* Window stuff */
- p_ptr->window |= (PW_MONSTER);
- }
-
- /* Repair visibility later */
- repair_monsters = TRUE;
-
- /* Hack -- Detect monster */
- m_ptr->mflag |= (MFLAG_MARK | MFLAG_SHOW);
-
- /* Hack -- See monster */
- m_ptr->ml = TRUE;
-
- /* Redraw */
- if (panel_contains(y, x)) lite_spot(y, x);
-
- /* Detect */
- flag = TRUE;
- }
- }
-
- /* Describe */
- if (flag)
- {
- /* Describe result */
- msg_print("You sense the presence of unnatural beings!");
- }
-
- /* Result */
- return (flag);
-}
-
-
-/*
- * Confuse monsters
- */
-bool_ confuse_monsters(int dam)
-{
- return (project_hack(GF_OLD_CONF, dam));
-}
-
-
-/*
- * Charm monsters
- */
-bool_ charm_monsters(int dam)
-{
- return (project_hack(GF_CHARM, dam));
-}
-
-
-/*
- * Charm animals
- */
-bool_ charm_animals(int dam)
-{
- return (project_hack(GF_CONTROL_ANIMAL, dam));
-}
-
-/*
- * Charm demons
- */
-bool_ charm_demons(int dam)
-{
- return (project_hack(GF_CONTROL_DEMON, dam));
-}
-
-
-/*
- * Stun monsters
- */
-bool_ stun_monsters(int dam)
-{
- return (project_hack(GF_STUN, dam));
-}
-
-
-/*
- * Stasis monsters
- */
-bool_ stasis_monsters(int dam)
-{
- return (project_hack(GF_STASIS, dam));
-}
-
-
-/*
- * Mindblast monsters
- */
-bool_ mindblast_monsters(int dam)
-{
- return (project_hack(GF_PSI, dam));
-}
-
-
-/*
- * Banish all monsters
- */
-bool_ banish_monsters(int dist)
-{
- return (project_hack(GF_AWAY_ALL, dist));
-}
-
-
-/*
- * Turn evil
- */
-bool_ turn_evil(int dam)
-{
- return (project_hack(GF_TURN_EVIL, dam));
-}
-
-
-/*
- * Turn everyone
- */
-bool_ turn_monsters(int dam)
-{
- return (project_hack(GF_TURN_ALL, dam));
-}
-
-
-/*
- * Death-ray all monsters (note: OBSCENELY powerful)
- */
-bool_ deathray_monsters(void)
-{
- return (project_hack(GF_DEATH_RAY, p_ptr->lev));
-}
-
-
-bool_ charm_monster(int dir, int plev)
-{
- int flg = PROJECT_STOP | PROJECT_KILL;
- return (project_hook(GF_CHARM, dir, plev, flg));
-}
-
-bool_ star_charm_monster(int dir, int plev)
-{
- int flg = PROJECT_STOP | PROJECT_KILL;
- return (project_hook(GF_STAR_CHARM, dir, plev, flg));
-}
-
-
-bool_ control_one_undead(int dir, int plev)
-{
- int flg = PROJECT_STOP | PROJECT_KILL;
- return (project_hook(GF_CONTROL_UNDEAD, dir, plev, flg));
-}
-
-
-bool_ charm_animal(int dir, int plev)
-{
- int flg = PROJECT_STOP | PROJECT_KILL;
- return (project_hook(GF_CONTROL_ANIMAL, dir, plev, flg));
-}
-
-void change_wild_mode(void)
-{
- if (p_ptr->immovable && !p_ptr->wild_mode)
- {
- msg_print("Hmm, blinking there will take time.");
- }
-
- if (p_ptr->word_recall && !p_ptr->wild_mode)
- {
- msg_print("You will soon be recalled.");
- return;
- }
-
- p_ptr->wild_mode = !p_ptr->wild_mode;
-
- autosave_checkpoint();
-
- /* Leaving */
- p_ptr->leaving = TRUE;
-}
-
-
-void alter_reality(void)
-{
- msg_print("The world changes!");
-
- autosave_checkpoint();
-
- /* Leaving */
- p_ptr->leaving = TRUE;
-}
-
-/* Heal insanity. */
-bool_ heal_insanity(int val)
-{
- if (p_ptr->csane < p_ptr->msane)
- {
- p_ptr->csane += val;
-
- if (p_ptr->csane >= p_ptr->msane)
- {
- p_ptr->csane = p_ptr->msane;
- p_ptr->csane_frac = 0;
- }
-
- p_ptr->redraw |= PR_SANITY;
- p_ptr->window |= (PW_PLAYER);
-
- if (val < 5)
- {
- msg_print("You feel a little better.");
- }
- else if (val < 15)
- {
- msg_print("You feel better.");
- }
- else if (val < 35)
- {
- msg_print("You feel much better.");
- }
- else
- {
- msg_print("You feel very good.");
- }
-
- return TRUE;
- }
-
- return FALSE;
-}
-
-/*
- * Send the player shooting through walls in the given direction until
- * they reach a non-wall space, or a monster, or a permanent wall.
- */
-bool_ passwall(int dir, bool_ safe)
-{
- int x = p_ptr->px, y = p_ptr->py, ox = p_ptr->px, oy = p_ptr->py, lx = p_ptr->px, ly = p_ptr->py;
- cave_type *c_ptr;
- bool_ ok = FALSE;
-
- if (p_ptr->wild_mode) return FALSE;
- if (p_ptr->inside_quest) return FALSE;
- if (dungeon_flags2 & DF2_NO_TELEPORT) return FALSE;
-
- /* Must go somewhere */
- if (dir == 5) return FALSE;
-
- while (TRUE)
- {
- x += ddx[dir];
- y += ddy[dir];
- c_ptr = &cave[y][x];
-
- /* Perm walls stops the transfer */
- if ((!in_bounds(y, x)) && (f_info[c_ptr->feat].flags1 & FF1_PERMANENT))
- {
- /* get the last working position */
- x -= ddx[dir];
- y -= ddy[dir];
- ok = FALSE;
- break;
- }
-
- /* Never on a monster */
- if (c_ptr->m_idx) continue;
-
- /* Never stop in vaults */
- if (c_ptr->info & CAVE_ICKY) continue;
-
- /* From now on, the location COULD be used in special case */
- lx = x;
- ly = y;
-
- /* Pass over walls */
- if (f_info[c_ptr->feat].flags1 & FF1_WALL) continue;
-
- /* So it must be ok */
- ok = TRUE;
- break;
- }
-
- if (!ok)
- {
- x = lx;
- y = ly;
-
- if (!safe)
- {
- msg_print("You emerge in the wall!");
- take_hit(damroll(10, 8), "becoming one with a wall");
- }
- place_floor_convert_glass(y, x);
- }
-
- /* Move */
- p_ptr->px = x;
- p_ptr->py = y;
-
- /* Redraw the old spot */
- lite_spot(oy, ox);
-
- /* Redraw the new spot */
- lite_spot(p_ptr->py, p_ptr->px);
-
- /* Check for new panel (redraw map) */
- verify_panel();
-
- /* Update stuff */
- p_ptr->update |= (PU_VIEW | PU_FLOW | PU_MON_LITE);
-
- /* Update the monsters */
- p_ptr->update |= (PU_DISTANCE);
-
- /* Redraw trap detection status */
- p_ptr->redraw |= (PR_DTRAP);
-
- /* Window stuff */
- p_ptr->window |= (PW_OVERHEAD);
-
- /* Handle stuff XXX XXX XXX */
- handle_stuff();
-
- return (TRUE);
-}
-
-/*
- * Print a batch of dungeons.
- */
-static void print_dungeon_batch(int *p, int start, int max, bool_ mode)
-{
- char buf[80];
- int i, j;
- byte attr;
-
-
- if (mode) prt(format(" %-31s", "Name"), 1, 20);
-
- for (i = 0, j = start; i < 20 && j < max; i++, j++)
- {
- dungeon_info_type *d_ptr = &d_info[p[j]];
-
- strnfmt(buf, 80, " %c) %-30s", I2A(i), d_name + d_ptr->name);
- if (mode)
- {
- if (d_ptr->min_plev > p_ptr->lev)
- {
- attr = TERM_L_DARK;
- }
- else
- {
- attr = TERM_WHITE;
- }
- c_prt(attr, buf, 2 + i, 20);
- }
- }
- if (mode) prt("", 2 + i, 20);
-
- prt(format("Select a dungeon (a-%c), * to list, @ to select by name, +/- to scroll:", I2A(i - 1)), 0, 0);
-}
-
-int reset_recall_aux()
-{
- char which;
- int *p;
- int max = 0, i, start = 0;
- int ret;
- bool_ mode = FALSE;
-
-
- C_MAKE(p, max_d_idx, int);
-
- /* Count the max */
- for (i = 1; i < max_d_idx; i++)
- {
- /* skip "blocked" dungeons */
- if (d_info[i].flags1 & DF1_NO_RECALL) continue;
-
- if (max_dlv[i])
- {
- p[max++] = i;
- }
- }
-
- character_icky = TRUE;
- Term_save();
-
- while (1)
- {
- print_dungeon_batch(p, start, max, mode);
- which = inkey();
-
- if (which == ESCAPE)
- {
- ret = -1;
- break;
- }
-
- else if (which == '*' || which == '?' || which == ' ')
- {
- mode = (mode) ? FALSE : TRUE;
- Term_load();
- character_icky = FALSE;
- }
-
- else if (which == '+')
- {
- start += 20;
- if (start >= max) start -= 20;
- Term_load();
- character_icky = FALSE;
- }
-
- else if (which == '-')
- {
- start -= 20;
- if (start < 0) start += 20;
- Term_load();
- character_icky = FALSE;
- }
-
- else if (which == '@')
- {
- char buf[80], buf2[80];
-
- strcpy(buf, (d_info[p_ptr->recall_dungeon].name + d_name));
- if (!get_string("Which dungeon? ", buf, 79)) continue;
-
- /* Find the index corresponding to the name */
- for (i = 1; i < max_d_idx; i++)
- {
- sprintf(buf2, "%s", d_info[i].name + d_name);
-
- /* Lowercase the name */
- strlower(buf);
- strlower(buf2);
- if (strstr(buf2, buf))
- {
- /* valid dungeon found */
- break;
- }
- }
-
- if (i >= max_d_idx)
- {
- msg_print("Never heard of that place!");
- msg_print(NULL);
- continue;
- }
- else if (d_info[i].flags1 & DF1_NO_RECALL)
- {
- msg_print("This place blocks my magic!");
- msg_print(NULL);
- continue;
- }
- else if (d_info[i].min_plev > p_ptr->lev)
- {
- msg_print("You cannot go there yet!");
- msg_print(NULL);
- continue;
- }
- ret = i;
- break;
- }
-
- else
- {
- which = tolower(which);
- if (start + A2I(which) >= max)
- {
- bell();
- continue;
- }
- if (start + A2I(which) < 0)
- {
- bell();
- continue;
- }
- ret = p[start + A2I(which)];
- break;
- }
- }
-
- Term_load();
- character_icky = FALSE;
-
- C_FREE(p, max_d_idx, int);
-
- return ret;
-}
-
-bool_ reset_recall(bool_ no_trepas_max_depth)
-{
- int dun, depth, max;
-
- /* Choose dungeon */
- dun = reset_recall_aux();
-
- if (dun < 1) return FALSE;
-
- /* Choose depth */
- if (!no_trepas_max_depth)
- max = d_info[dun].maxdepth;
- else
- max = max_dlv[dun];
- depth = get_quantity(format("Which level in %s(%d-%d)? ",
- d_info[dun].name + d_name,
- d_info[dun].mindepth, max),
- max);
-
- if (depth < 1) return FALSE;
-
- /* Enforce minimum level */
- if (depth < d_info[dun].mindepth) depth = d_info[dun].mindepth;
-
- /* Mega hack -- Forbid levels 99 and 100 */
- if ((depth == 99) || (depth == 100)) depth = 98;
-
- p_ptr->recall_dungeon = dun;
- max_dlv[p_ptr->recall_dungeon] = depth;
-
- return TRUE;
-}
-
-/* The only way to get rid of the dreaded DG_CURSE*/
-void remove_dg_curse()
-{
- int k;
-
- /* Parse all the items */
- for (k = INVEN_WIELD; k < INVEN_TOTAL; k++)
- {
- object_type *o_ptr = &p_ptr->inventory[k];
-
- if (o_ptr->k_idx && (o_ptr->art_flags4 & TR4_DG_CURSE))
- {
- o_ptr->art_flags3 &= ~TR3_HEAVY_CURSE;
- o_ptr->art_flags3 &= ~TR3_CURSED;
- o_ptr->art_flags4 &= ~TR4_DG_CURSE;
- msg_print("The Morgothian Curse withers away.");
- }
- }
-}
-
-/*
- * Creates a between gate
- */
-void create_between_gate(int dist, int y, int x)
-{
- int ii, ij, plev = get_skill(SKILL_CONVEYANCE);
-
- if (dungeon_flags2 & DF2_NO_TELEPORT)
- {
- msg_print("Not on special levels!");
- return;
- }
-
- if ((!x) || (!y))
- {
- 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) > dist) ||
- (rand_int(plev * plev / 2) == 0))
- {
- msg_print("You fail to exit the void correctly!");
- p_ptr->energy -= 100;
- get_pos_player(10, &ij, &ii);
- }
- }
- else
- {
- ij = y;
- ii = x;
- }
- if (!(f_info[cave[p_ptr->py][p_ptr->px].feat].flags1 & FF1_PERMANENT))
- {
- cave_set_feat(p_ptr->py, p_ptr->px, FEAT_BETWEEN);
- cave[p_ptr->py][p_ptr->px].special = ii + (ij << 8);
- }
- if (!(f_info[cave[ij][ii].feat].flags1 & FF1_PERMANENT))
- {
- cave_set_feat(ij, ii, FEAT_BETWEEN);
- cave[ij][ii].special = p_ptr->px + (p_ptr->py << 8);
- }
-}
diff --git a/src/spells2.cc b/src/spells2.cc
new file mode 100644
index 00000000..c0d435ea
--- /dev/null
+++ b/src/spells2.cc
@@ -0,0 +1,5579 @@
+/*
+ * 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 "spells2.hpp"
+
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "cmd1.hpp"
+#include "cmd7.hpp"
+#include "dungeon_flag.hpp"
+#include "dungeon_info_type.hpp"
+#include "feature_flag.hpp"
+#include "feature_type.hpp"
+#include "files.hpp"
+#include "game.hpp"
+#include "hook_identify_in.hpp"
+#include "hooks.hpp"
+#include "melee2.hpp"
+#include "monster2.hpp"
+#include "monster3.hpp"
+#include "monster_race.hpp"
+#include "monster_race_flag.hpp"
+#include "monster_spell_flag.hpp"
+#include "monster_type.hpp"
+#include "notes.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_flag.hpp"
+#include "object_kind.hpp"
+#include "object_type.hpp"
+#include "options.hpp"
+#include "player_race_flag.hpp"
+#include "player_type.hpp"
+#include "skills.hpp"
+#include "spells1.hpp"
+#include "spells3.hpp"
+#include "stats.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "util.h"
+#include "variable.h"
+#include "variable.hpp"
+#include "xtra1.hpp"
+#include "xtra2.hpp"
+#include "z-rand.hpp"
+
+#include <boost/algorithm/string/predicate.hpp>
+#include <cassert>
+#include <chrono>
+#include <sstream>
+#include <thread>
+#include <vector>
+
+using boost::algorithm::iequals;
+using std::this_thread::sleep_for;
+using std::chrono::milliseconds;
+
+#define WEIRD_LUCK 12
+#define BIAS_LUCK 20
+/*
+ * Bias luck needs to be higher than weird luck,
+ * since it is usually tested several times...
+ */
+
+static void summon_dragon_riders();
+
+
+/*
+ * Grow things
+ */
+void grow_things(s16b type, int rad)
+{
+ int a, i, j;
+
+ for (a = 0; a < rad * rad + 11; a++)
+ {
+ i = (rand_int((rad * 2) + 1)-rad + rand_int((rad * 2) + 1)-rad) / 2;
+ j = (rand_int((rad * 2) + 1)-rad + rand_int((rad * 2) + 1)-rad) / 2;
+
+ if (!in_bounds(p_ptr->py + j, p_ptr->px + i)) continue;
+ if (distance(p_ptr->py, p_ptr->px, p_ptr->py + j, p_ptr->px + i) > rad) continue;
+
+ if (cave_clean_bold(p_ptr->py + j, p_ptr->px + i))
+ {
+ cave_set_feat(p_ptr->py + j, p_ptr->px + i, type);
+ }
+ }
+}
+
+/*
+ * Grow trees
+ */
+void grow_trees(int rad)
+{
+ auto const &f_info = game->edit_data.f_info;
+
+ int a, i, j;
+
+ for (a = 0; a < rad * rad + 11; a++)
+ {
+ i = (rand_int((rad * 2) + 1)-rad + rand_int((rad * 2) + 1)-rad) / 2;
+ j = (rand_int((rad * 2) + 1)-rad + rand_int((rad * 2) + 1)-rad) / 2;
+
+ if (!in_bounds(p_ptr->py + j, p_ptr->px + i)) continue;
+ if (distance(p_ptr->py, p_ptr->px, p_ptr->py + j, p_ptr->px + i) > rad) continue;
+
+ if (cave_clean_bold(p_ptr->py + j, p_ptr->px + i) && (f_info[cave[p_ptr->py][p_ptr->px].feat].flags & FF_SUPPORT_GROWTH))
+ {
+ cave_set_feat(p_ptr->py + j, p_ptr->px + i, FEAT_TREES);
+ }
+ }
+}
+
+/*
+ * Grow grass
+ */
+void grow_grass(int rad)
+{
+ auto const &f_info = game->edit_data.f_info;
+
+ int a, i, j;
+
+ for (a = 0; a < rad * rad + 11; a++)
+ {
+ i = (rand_int((rad * 2) + 1)-rad + rand_int((rad * 2) + 1)-rad) / 2;
+ j = (rand_int((rad * 2) + 1)-rad + rand_int((rad * 2) + 1)-rad) / 2;
+
+ if (!in_bounds(p_ptr->py + j, p_ptr->px + i)) continue;
+ if (distance(p_ptr->py, p_ptr->px, p_ptr->py + j, p_ptr->px + i) > rad) continue;
+
+ if (cave_clean_bold(p_ptr->py + j, p_ptr->px + i) && (f_info[cave[p_ptr->py][p_ptr->px].feat].flags & FF_SUPPORT_GROWTH))
+ {
+ cave_set_feat(p_ptr->py + j, p_ptr->px + i, FEAT_GRASS);
+ }
+ }
+}
+
+/*
+ * Increase players hit points, notice effects
+ */
+bool_ hp_player(int num)
+{
+ bool_ dead = p_ptr->chp < 0;
+
+ /* Healing needed */
+ if (p_ptr->chp < p_ptr->mhp)
+ {
+ /* Gain hitpoints */
+ p_ptr->chp += num;
+
+ /* Enforce maximum */
+ if ((p_ptr->chp >= p_ptr->mhp) ||
+ /* prevent wrapping */
+ (!dead && (p_ptr->chp < 0)))
+ {
+ p_ptr->chp = p_ptr->mhp;
+ p_ptr->chp_frac = 0;
+ }
+
+ /* Redraw */
+ p_ptr->redraw |= (PR_FRAME);
+
+ /* Window stuff */
+ p_ptr->window |= (PW_PLAYER);
+
+ /* Heal 0-4 */
+ if (num < 5)
+ {
+ msg_print("You feel a little better.");
+ }
+
+ /* Heal 5-14 */
+ else if (num < 15)
+ {
+ msg_print("You feel better.");
+ }
+
+ /* Heal 15-34 */
+ else if (num < 35)
+ {
+ msg_print("You feel much better.");
+ }
+
+ /* Heal 35+ */
+ else
+ {
+ msg_print("You feel very good.");
+ }
+
+ /* Notice */
+ return (TRUE);
+ }
+
+ /* Ignore */
+ return (FALSE);
+}
+
+
+
+/*
+ * Leave a "glyph of warding" which prevents monster movement
+ */
+void warding_glyph()
+{
+ /* XXX XXX XXX */
+ if (!cave_clean_bold(p_ptr->py, p_ptr->px))
+ {
+ msg_print("The object resists the spell.");
+ return;
+ }
+
+ /* Create a glyph */
+ cave_set_feat(p_ptr->py, p_ptr->px, FEAT_GLYPH);
+}
+
+void explosive_rune()
+{
+ /* XXX XXX XXX */
+ if (!cave_clean_bold(p_ptr->py, p_ptr->px))
+ {
+ msg_print("The object resists the spell.");
+ return;
+ }
+
+ /* Create a glyph */
+ cave_set_feat(p_ptr->py, p_ptr->px, FEAT_MINOR_GLYPH);
+}
+
+
+
+/*
+ * Array of stat "descriptions"
+ */
+static cptr desc_stat_pos[] =
+{
+ "strong",
+ "smart",
+ "wise",
+ "dextrous",
+ "healthy",
+ "cute"
+};
+
+/*
+ * Array of long descriptions of stat
+ */
+
+static cptr long_desc_stat[] =
+{
+ "strength",
+ "intelligence",
+ "wisdom",
+ "dexterity",
+ "constitution",
+ "charisma"
+};
+
+/*
+ * Array of stat "descriptions"
+ */
+static cptr desc_stat_neg[] =
+{
+ "weak",
+ "stupid",
+ "naive",
+ "clumsy",
+ "sickly",
+ "ugly"
+};
+
+
+/*
+ * Lose a "point"
+ */
+bool_ do_dec_stat(int stat, int mode)
+{
+ bool_ sust = FALSE;
+
+ /* Access the "sustain" */
+ switch (stat)
+ {
+ case A_STR:
+ if (p_ptr->sustain_str) sust = TRUE;
+ break;
+ case A_INT:
+ if (p_ptr->sustain_int) sust = TRUE;
+ break;
+ case A_WIS:
+ if (p_ptr->sustain_wis) sust = TRUE;
+ break;
+ case A_DEX:
+ if (p_ptr->sustain_dex) sust = TRUE;
+ break;
+ case A_CON:
+ if (p_ptr->sustain_con) sust = TRUE;
+ break;
+ case A_CHR:
+ if (p_ptr->sustain_chr) sust = TRUE;
+ break;
+ }
+
+ /* Sustain */
+ if (sust)
+ {
+ /* Message */
+ msg_format("You feel %s for a moment, but the feeling passes.",
+ desc_stat_neg[stat]);
+
+ /* Notice effect */
+ return (TRUE);
+ }
+
+ /* Attempt to reduce the stat */
+ if (dec_stat(stat, 10, mode))
+ {
+ /* Message */
+ msg_format("You feel very %s.", desc_stat_neg[stat]);
+
+ /* Notice effect */
+ return (TRUE);
+ }
+
+ /* Nothing obvious */
+ return (FALSE);
+}
+
+
+/*
+ * Restore lost "points" in a stat
+ */
+bool_ do_res_stat(int stat, bool_ full)
+{
+ /* Keep a copy of the current stat, so we can evaluate it if necessary */
+ int cur_stat = p_ptr->stat_cur[stat];
+
+ /* Attempt to increase */
+ if (res_stat(stat, full))
+ {
+ /* Message, depending on whether we got stronger or weaker */
+ if (cur_stat > p_ptr->stat_max[stat])
+ {
+ msg_format("You feel your %s boost drain away.", long_desc_stat[stat]);
+ }
+ else
+ {
+ msg_format("You feel less %s.", desc_stat_neg[stat]);
+ }
+
+ /* Notice */
+ return (TRUE);
+ }
+
+ /* Nothing obvious */
+ return (FALSE);
+}
+
+
+/*
+ * Increases a stat by one randomized level -RAK-
+ *
+ * Note that this function (used by stat potions) now restores
+ * the stat BEFORE increasing it.
+ */
+static bool_ inc_stat(int stat)
+{
+ int value, gain;
+
+ /* Then augment the current/max stat */
+ value = p_ptr->stat_cur[stat];
+
+ /* Cannot go above 18/100 */
+ if (value < 18 + 100)
+ {
+ /* Gain one (sometimes two) points */
+ if (value < 18)
+ {
+ gain = ((rand_int(100) < 75) ? 1 : 2);
+ value += gain;
+ }
+
+ /* Gain 1/6 to 1/3 of distance to 18/100 */
+ else if (value < 18 + 98)
+ {
+ /* Approximate gain value */
+ gain = (((18 + 100) - value) / 2 + 3) / 2;
+
+ /* Paranoia */
+ if (gain < 1) gain = 1;
+
+ /* Apply the bonus */
+ value += randint(gain) + gain / 2;
+
+ /* Maximal value */
+ if (value > 18 + 99) value = 18 + 99;
+ }
+
+ /* Gain one point at a time */
+ else
+ {
+ value++;
+ }
+
+ /* Save the new value */
+ p_ptr->stat_cur[stat] = value;
+
+ /* Bring up the maximum too */
+ if (value > p_ptr->stat_max[stat])
+ {
+ p_ptr->stat_max[stat] = value;
+ }
+
+ /* Recalculate bonuses */
+ p_ptr->update |= (PU_BONUS);
+
+ /* Success */
+ return (TRUE);
+ }
+
+ /* Nothing to gain */
+ return (FALSE);
+}
+
+
+/*
+ * Gain a "point" in a stat
+ */
+bool_ do_inc_stat(int stat)
+{
+ bool_ res;
+
+ /* Restore strength */
+ res = res_stat(stat, TRUE);
+
+ /* Attempt to increase */
+ if (inc_stat(stat))
+ {
+ /* Message */
+ msg_format("Wow! You feel very %s!", desc_stat_pos[stat]);
+
+ /* Notice */
+ return (TRUE);
+ }
+
+ /* Restoration worked */
+ if (res)
+ {
+ /* Message */
+ msg_format("You feel less %s.", desc_stat_neg[stat]);
+
+ /* Notice */
+ return (TRUE);
+ }
+
+ /* Nothing obvious */
+ return (FALSE);
+}
+
+
+/*
+ * Process all identify hooks
+ */
+void identify_hooks(int i, object_type *o_ptr, identify_mode mode)
+{
+ /* Process the appropriate hooks */
+ hook_identify_in in = { o_ptr, mode };
+ process_hooks_new(HOOK_IDENTIFY, &in, NULL);
+}
+
+
+/*
+ * Identify everything being carried.
+ * Done by a potion of "self knowledge".
+ */
+bool_ identify_pack()
+{
+ int i;
+
+ /* Simply identify and know every item */
+ for (i = 0; i < INVEN_TOTAL; i++)
+ {
+ object_type *o_ptr = &p_ptr->inventory[i];
+
+ /* Skip non-objects */
+ if (!o_ptr->k_idx) continue;
+
+ /* Aware and Known */
+ object_aware(o_ptr);
+ object_known(o_ptr);
+
+ /* Process the appropriate hooks */
+ identify_hooks(i, o_ptr, IDENT_NORMAL);
+ }
+
+ p_ptr->notice |= (PN_COMBINE | PN_REORDER);
+ p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
+ return TRUE;
+}
+
+/*
+ * common portions of identify_fully and identify_pack_fully
+ */
+static void make_item_fully_identified(object_type *o_ptr)
+{
+ /* Identify it fully */
+ object_aware(o_ptr);
+ object_known(o_ptr);
+
+ /* Mark the item as fully known */
+ o_ptr->ident |= (IDENT_MENTAL);
+}
+
+/*
+ * Identify everything being carried.
+ * Done by a potion of "self knowledge".
+ */
+void identify_pack_fully()
+{
+ int i;
+
+ /* Simply identify and know every item */
+ for (i = 0; i < INVEN_TOTAL; i++)
+ {
+ object_type *o_ptr = &p_ptr->inventory[i];
+
+ /* Skip non-objects */
+ if (!o_ptr->k_idx) continue;
+
+ make_item_fully_identified(o_ptr);
+
+ /* Process the appropriate hooks */
+ identify_hooks(i, o_ptr, IDENT_FULL);
+ }
+
+ p_ptr->update |= (PU_BONUS);
+ p_ptr->notice |= (PN_COMBINE | PN_REORDER);
+ p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
+}
+
+/*
+ * Used by the "enchant" function (chance of failure)
+ * (modified for Zangband, we need better stuff there...) -- TY
+ */
+static int enchant_table[16] =
+{
+ 0, 10, 50, 100, 200,
+ 300, 400, 500, 650, 800,
+ 950, 987, 993, 995, 998,
+ 1000
+};
+
+static bool_ remove_curse_object(object_type *o_ptr, bool_ all)
+{
+ /* Skip non-objects */
+ if (!o_ptr->k_idx) return FALSE;
+
+ /* Uncursed already */
+ if (!cursed_p(o_ptr)) return FALSE;
+
+ /* Extract the flags */
+ auto const flags = object_flags(o_ptr);
+
+ /* Heavily Cursed Items need a special spell */
+ if (!all && (flags & TR_HEAVY_CURSE)) return FALSE;
+
+ /* Perma-Cursed Items can NEVER be uncursed */
+ if (flags & TR_PERMA_CURSE) return FALSE;
+
+ /* Uncurse it */
+ o_ptr->ident &= ~(IDENT_CURSED);
+
+ /* Hack -- Assume felt */
+ o_ptr->ident |= (IDENT_SENSE);
+
+ /* Strip curse flags */
+ o_ptr->art_flags &= ~TR_CURSED;
+ o_ptr->art_flags &= ~TR_HEAVY_CURSE;
+
+ /* Take note */
+ o_ptr->sense = SENSE_UNCURSED;
+
+ /* Reverse the curse effect */
+ /* jk - scrolls of *remove curse* have a 1 in (55-level chance to */
+ /* reverse the curse effects - a ring of damage(-15) {cursed} then */
+ /* becomes a ring of damage (+15) */
+ /* this does not go for artifacts - a Sword of Mormegil +40,+60 would */
+ /* be somewhat unbalancing */
+ /* due to the nature of this procedure, it only works on cursed items */
+ /* ie you get only one chance! */
+ if ((randint(55-p_ptr->lev) == 1) && !artifact_p(o_ptr))
+ {
+ if (o_ptr->to_a < 0) o_ptr->to_a = -o_ptr->to_a;
+ if (o_ptr->to_h < 0) o_ptr->to_h = -o_ptr->to_h;
+ if (o_ptr->to_d < 0) o_ptr->to_d = -o_ptr->to_d;
+ if (o_ptr->pval < 0) o_ptr->pval = -o_ptr->pval;
+ }
+
+ /* Recalculate the bonuses */
+ p_ptr->update |= (PU_BONUS);
+
+ /* Window stuff */
+ p_ptr->window |= (PW_EQUIP);
+
+ return TRUE;
+}
+
+/*
+ * Removes curses from items in inventory
+ *
+ * Note that Items which are "Perma-Cursed" (The One Ring,
+ * The Crown of Morgoth) can NEVER be uncursed.
+ *
+ * Note that if "all" is FALSE, then Items which are
+ * "Heavy-Cursed" (Mormegil, Calris, and Weapons of Morgul)
+ * will not be uncursed.
+ */
+static int remove_curse_aux(int all)
+{
+ int i, cnt = 0;
+
+ /* Attempt to uncurse items being worn */
+ for (i = 0; i < INVEN_TOTAL; i++)
+ {
+ object_type *o_ptr = &p_ptr->inventory[i];
+
+ if (!remove_curse_object(o_ptr, all)) continue;
+
+ /* Count the uncursings */
+ cnt++;
+ }
+
+ /* Return "something uncursed" */
+ return (cnt);
+}
+
+
+/*
+ * Remove most curses
+ */
+bool_ remove_curse()
+{
+ return (remove_curse_aux(FALSE) ? TRUE : FALSE);
+}
+
+/*
+ * Remove all curses
+ */
+bool_ remove_all_curse()
+{
+ return (remove_curse_aux(TRUE) ? TRUE : FALSE);
+}
+
+
+
+/*
+ * Restores any drained experience
+ */
+bool_ restore_level()
+{
+ /* Restore experience */
+ if (p_ptr->exp < p_ptr->max_exp)
+ {
+ /* Message */
+ msg_print("You feel your life energies returning.");
+
+ /* Restore the experience */
+ p_ptr->exp = p_ptr->max_exp;
+
+ /* Check the experience */
+ check_experience();
+
+ /* Did something */
+ return (TRUE);
+ }
+
+ /* No effect */
+ return (FALSE);
+}
+
+
+bool_ alchemy() /* Turns an object into gold, gain some of its value in a shop */
+{
+ int item, amt = 1;
+ int old_number;
+ long price;
+ bool_ force = FALSE;
+ char o_name[80];
+ char out_val[160];
+
+ /* Hack -- force destruction */
+ if (command_arg > 0) force = TRUE;
+
+ /* Get an item */
+ if (!get_item(&item,
+ "Turn which item to gold? ",
+ "You have nothing to turn to gold.",
+ (USE_INVEN | USE_FLOOR),
+ object_filter::True()))
+ {
+ return (FALSE);
+ }
+
+ /* Get the item */
+ object_type *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 FALSE;
+ }
+
+
+ /* 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)
+ {
+ /* Make a verification */
+ sprintf(out_val, "Really turn %s to gold? ", o_name);
+ if (!get_check(out_val)) return FALSE;
+ }
+
+ /* Artifacts cannot be destroyed */
+ if (artifact_p(o_ptr))
+ {
+ byte feel = SENSE_SPECIAL;
+
+ /* Message */
+ msg_format("You fail to turn %s to gold!", 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 FALSE;
+ }
+
+ price = object_value_real(o_ptr);
+
+ if (price <= 0)
+ /* Message */
+ msg_format("You turn %s to fool's gold.", o_name);
+ else
+ {
+ price /= 3;
+
+ if (amt > 1) price *= amt;
+
+ msg_format("You turn %s to %ld coins worth of gold.", o_name, price);
+ p_ptr->au += price;
+
+ /* Redraw gold */
+ p_ptr->redraw |= (PR_FRAME);
+
+ /* Window stuff */
+ p_ptr->window |= (PW_PLAYER);
+
+ }
+
+ /* Eliminate the item */
+ inc_stack_size(item, -amt);
+
+ return TRUE;
+}
+
+
+
+static int report_magics_aux(int dur)
+{
+ if (dur <= 5)
+ {
+ return 0;
+ }
+ else if (dur <= 10)
+ {
+ return 1;
+ }
+ else if (dur <= 20)
+ {
+ return 2;
+ }
+ else if (dur <= 50)
+ {
+ return 3;
+ }
+ else if (dur <= 100)
+ {
+ return 4;
+ }
+ else if (dur <= 200)
+ {
+ return 5;
+ }
+ else
+ {
+ return 6;
+ }
+}
+
+static cptr report_magic_durations[] =
+{
+ "for a short time",
+ "for a little while",
+ "for a while",
+ "for a long while",
+ "for a long time",
+ "for a very long time",
+ "for an incredibly long time",
+ "until you hit a monster"
+};
+
+
+void report_magics()
+{
+ int i = 0, j, k;
+
+ char Dummy[80];
+
+ cptr info[128];
+ int info2[128];
+
+ if (p_ptr->blind)
+ {
+ info2[i] = report_magics_aux(p_ptr->blind);
+ info[i++] = "You cannot see";
+ }
+ if (p_ptr->confused)
+ {
+ info2[i] = report_magics_aux(p_ptr->confused);
+ info[i++] = "You are confused";
+ }
+ if (p_ptr->afraid)
+ {
+ info2[i] = report_magics_aux(p_ptr->afraid);
+ info[i++] = "You are terrified";
+ }
+ if (p_ptr->poisoned)
+ {
+ info2[i] = report_magics_aux(p_ptr->poisoned);
+ info[i++] = "You are poisoned";
+ }
+ if (p_ptr->image)
+ {
+ info2[i] = report_magics_aux(p_ptr->image);
+ info[i++] = "You are hallucinating";
+ }
+
+ if (p_ptr->blessed)
+ {
+ info2[i] = report_magics_aux(p_ptr->blessed);
+ info[i++] = "You feel righteous";
+ }
+ if (p_ptr->hero)
+ {
+ info2[i] = report_magics_aux(p_ptr->hero);
+ info[i++] = "You feel heroic";
+ }
+ if (p_ptr->shero)
+ {
+ info2[i] = report_magics_aux(p_ptr->shero);
+ info[i++] = "You are in a battle rage";
+ }
+ if (p_ptr->protevil)
+ {
+ info2[i] = report_magics_aux(p_ptr->protevil);
+ info[i++] = "You are protected from evil";
+ }
+ if (p_ptr->shield)
+ {
+ info2[i] = report_magics_aux(p_ptr->shield);
+ info[i++] = "You are protected by a mystic shield";
+ }
+ if (p_ptr->invuln)
+ {
+ info2[i] = report_magics_aux(p_ptr->invuln);
+ info[i++] = "You are invulnerable";
+ }
+ if (p_ptr->tim_wraith)
+ {
+ info2[i] = report_magics_aux(p_ptr->tim_wraith);
+ info[i++] = "You are incorporeal";
+ }
+ if (p_ptr->confusing)
+ {
+ info2[i] = 7;
+ info[i++] = "Your hands are glowing dull red.";
+ }
+ if (p_ptr->word_recall)
+ {
+ info2[i] = report_magics_aux(p_ptr->word_recall);
+ info[i++] = "You waiting to be recalled";
+ }
+ if (p_ptr->oppose_acid)
+ {
+ info2[i] = report_magics_aux(p_ptr->oppose_acid);
+ info[i++] = "You are resistant to acid";
+ }
+ if (p_ptr->oppose_elec)
+ {
+ info2[i] = report_magics_aux(p_ptr->oppose_elec);
+ info[i++] = "You are resistant to lightning";
+ }
+ if (p_ptr->oppose_fire)
+ {
+ info2[i] = report_magics_aux(p_ptr->oppose_fire);
+ info[i++] = "You are resistant to fire";
+ }
+ if (p_ptr->oppose_cold)
+ {
+ info2[i] = report_magics_aux(p_ptr->oppose_cold);
+ info[i++] = "You are resistant to cold";
+ }
+ if (p_ptr->oppose_pois)
+ {
+ info2[i] = report_magics_aux(p_ptr->oppose_pois);
+ info[i++] = "You are resistant to poison";
+ }
+
+ /* Save the screen */
+ character_icky = TRUE;
+ Term_save();
+
+ /* Erase the screen */
+ for (k = 1; k < 24; k++) prt("", k, 13);
+
+ /* Label the information */
+ prt(" Your Current Magic:", 1, 15);
+
+ /* We will print on top of the map (column 13) */
+ for (k = 2, j = 0; j < i; j++)
+ {
+ /* Show the info */
+ sprintf( Dummy, "%s %s.", info[j],
+ report_magic_durations[info2[j]] );
+ prt(Dummy, k++, 15);
+
+ /* Every 20 entries (lines 2 to 21), start over */
+ if ((k == 22) && (j + 1 < i))
+ {
+ prt("-- more --", k, 15);
+ inkey();
+ for (; k > 2; k--) prt("", k, 15);
+ }
+ }
+
+ /* Pause */
+ prt("[Press any key to continue]", k, 13);
+ inkey();
+
+ /* Restore the screen */
+ Term_load();
+ character_icky = FALSE;
+}
+
+
+
+/*
+ * Forget everything
+ */
+bool_ lose_all_info()
+{
+ int i;
+
+ /* Forget info about objects */
+ for (i = 0; i < INVEN_TOTAL; i++)
+ {
+ object_type *o_ptr = &p_ptr->inventory[i];
+
+ /* Skip non-objects */
+ if (!o_ptr->k_idx) continue;
+
+ /* Allow "protection" by the MENTAL flag */
+ if (o_ptr->ident & (IDENT_MENTAL)) continue;
+
+ /* Remove sensing */
+ o_ptr->sense = SENSE_NONE;
+
+ /* Hack -- Clear the "empty" flag */
+ o_ptr->ident &= ~(IDENT_EMPTY);
+
+ /* Hack -- Clear the "known" flag */
+ o_ptr->ident &= ~(IDENT_KNOWN);
+
+ /* Hack -- Clear the "felt" flag */
+ o_ptr->ident &= ~(IDENT_SENSE);
+ }
+
+ /* Recalculate bonuses */
+ p_ptr->update |= (PU_BONUS);
+
+ /* Combine / Reorder the pack (later) */
+ p_ptr->notice |= (PN_COMBINE | PN_REORDER);
+
+ /* Window stuff */
+ p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
+
+ /* Mega-Hack -- Forget the map */
+ wiz_dark();
+
+ /* It worked */
+ return (TRUE);
+}
+
+
+/*
+ * Detect all doors on current panel
+ */
+bool_ detect_doors(int rad)
+{
+ int y, x;
+
+ bool_ detect = FALSE;
+
+ cave_type *c_ptr;
+
+
+ /* Scan the panel */
+ for (y = p_ptr->py - rad; y <= p_ptr->py + rad; y++)
+ {
+ for (x = p_ptr->px - rad; x <= p_ptr->px + rad; x++)
+ {
+ if (!in_bounds(y, x)) continue;
+
+ if (distance(p_ptr->py, p_ptr->px, y, x) > rad) continue;
+
+ c_ptr = &cave[y][x];
+
+ /* Detect secret doors */
+ if (c_ptr->feat == FEAT_SECRET)
+ {
+ /* Remove feature mimics */
+ cave[y][x].mimic = 0;
+
+ /* Pick a door XXX XXX XXX */
+ cave_set_feat(y, x, FEAT_DOOR_HEAD + 0x00);
+ }
+
+ /* Detect doors */
+ if (((c_ptr->feat >= FEAT_DOOR_HEAD) &&
+ (c_ptr->feat <= FEAT_DOOR_TAIL)) ||
+ ((c_ptr->feat == FEAT_OPEN) ||
+ (c_ptr->feat == FEAT_BROKEN)))
+ {
+ /* Hack -- Memorize */
+ c_ptr->info |= (CAVE_MARK);
+
+ /* Reveal it */
+ /* c_ptr->mimic = 0; */
+
+ /* Redraw */
+ lite_spot(y, x);
+
+ /* Obvious */
+ detect = TRUE;
+ }
+ }
+ }
+
+ /* Describe */
+ if (detect)
+ {
+ msg_print("You sense the presence of doors!");
+ }
+
+ /* Result */
+ return (detect);
+}
+
+
+/*
+ * Detect all stairs on current panel
+ */
+bool_ detect_stairs(int rad)
+{
+ int y, x;
+
+ bool_ detect = FALSE;
+
+ cave_type *c_ptr;
+
+
+ /* Scan the panel */
+ for (y = p_ptr->py - rad; y <= p_ptr->py + rad; y++)
+ {
+ for (x = p_ptr->px - rad; x <= p_ptr->px + rad; x++)
+ {
+ if (!in_bounds(y, x)) continue;
+
+ if (distance(p_ptr->py, p_ptr->px, y, x) > rad) continue;
+
+ c_ptr = &cave[y][x];
+
+ /* Detect stairs */
+ if ((c_ptr->feat == FEAT_LESS) ||
+ (c_ptr->feat == FEAT_MORE) ||
+ (c_ptr->feat == FEAT_SHAFT_DOWN) ||
+ (c_ptr->feat == FEAT_SHAFT_UP) ||
+ (c_ptr->feat == FEAT_WAY_LESS) ||
+ (c_ptr->feat == FEAT_WAY_MORE))
+ {
+ /* Hack -- Memorize */
+ c_ptr->info |= (CAVE_MARK);
+
+ /* Redraw */
+ lite_spot(y, x);
+
+ /* Obvious */
+ detect = TRUE;
+ }
+ }
+ }
+
+ /* Describe */
+ if (detect)
+ {
+ msg_print("You sense the presence of ways out of this area!");
+ }
+
+ /* Result */
+ return (detect);
+}
+
+
+/*
+ * Detect any treasure on the current panel
+ */
+bool_ detect_treasure(int rad)
+{
+ int y, x;
+
+ bool_ detect = FALSE;
+
+ cave_type *c_ptr;
+
+
+ /* Scan the current panel */
+ for (y = p_ptr->py - rad; y <= p_ptr->py + rad; y++)
+ {
+ for (x = p_ptr->px - rad; x <= p_ptr->px + rad; x++)
+ {
+ if (!in_bounds(y, x)) continue;
+
+ if (distance(p_ptr->py, p_ptr->px, y, x) > rad) continue;
+
+ c_ptr = &cave[y][x];
+
+ /* Notice embedded gold */
+ if ((c_ptr->feat == FEAT_MAGMA_H) ||
+ (c_ptr->feat == FEAT_QUARTZ_H))
+ {
+ /* Expose the gold */
+ cave_set_feat(y, x, c_ptr->feat + 0x02);
+ }
+ else if (c_ptr->feat == FEAT_SANDWALL_H)
+ {
+ /* Expose the gold */
+ cave_set_feat(y, x, FEAT_SANDWALL_K);
+ }
+
+ /* Magma/Quartz + Known Gold */
+ if ((c_ptr->feat == FEAT_MAGMA_K) ||
+ (c_ptr->feat == FEAT_QUARTZ_K) ||
+ (c_ptr->feat == FEAT_SANDWALL_K))
+ {
+ /* Hack -- Memorize */
+ c_ptr->info |= (CAVE_MARK);
+
+ /* Redraw */
+ lite_spot(y, x);
+
+ /* Detect */
+ detect = TRUE;
+ }
+ }
+ }
+
+ /* Describe */
+ if (detect)
+ {
+ msg_print("You sense the presence of buried treasure!");
+ }
+
+
+
+ /* Result */
+ return (detect);
+}
+
+
+/*
+ * Detect monsters on current panel using a
+ * predicate function P and an update function U.
+ * The "update function" is called exactly once if
+ * the predicate succeeds. The
+ */
+template<typename P> static bool detect_monsters_fn(int radius, P p) {
+ bool flag = false;
+ /* Scan monsters */
+ for (int i = 1; i < m_max; i++)
+ {
+ monster_type *m_ptr = &m_list[i];
+
+ /* Skip dead monsters */
+ if (!m_ptr->r_idx)
+ {
+ continue;
+ }
+
+ /* Location */
+ int const y = m_ptr->fy;
+ int const x = m_ptr->fx;
+
+ /* Only detect nearby monsters */
+ if (m_ptr->cdis > radius)
+ {
+ continue;
+ }
+ /* Detect monsters which fulfill the predicate */
+ auto r_ptr = m_ptr->race();
+ if (p(r_ptr.get()))
+ {
+ /* Repair visibility later */
+ repair_monsters = TRUE;
+
+ /* Hack -- Detect monster */
+ m_ptr->mflag |= (MFLAG_MARK | MFLAG_SHOW);
+
+ /* Hack -- See monster */
+ m_ptr->ml = TRUE;
+
+ /* Redraw */
+ if (panel_contains(y, x)) lite_spot(y, x);
+
+ /* Detect */
+ flag = TRUE;
+ }
+ }
+ /* Result */
+ return flag;
+}
+
+/*
+ * Detect all (string) monsters on current panel
+ */
+static bool_ detect_monsters_string(cptr chars, int rad)
+{
+ auto predicate = [chars](monster_race *r_ptr) -> bool {
+ return strchr(chars, r_ptr->d_char);
+ };
+
+ /* Describe */
+ if (detect_monsters_fn(rad, predicate))
+ {
+ /* Describe result */
+ msg_print("You sense the presence of monsters!");
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+
+/**
+ * Detect objects on the current panel.
+ */
+template <typename P> bool detect_objects_fn(int radius, const char *object_message, const char *monsters, P p)
+{
+ bool detect = false;
+
+ /* Scan objects */
+ for (int i = 1; i < o_max; i++)
+ {
+ object_type *o_ptr = &o_list[i];
+
+ /* Skip dead objects */
+ if (!o_ptr->k_idx) continue;
+
+ /* Location */
+ int y, x;
+
+ /* Skip held objects */
+ if (o_ptr->held_m_idx)
+ {
+ /* Access the monster */
+ monster_type *m_ptr = &m_list[o_ptr->held_m_idx];
+ auto const r_ptr = m_ptr->race();
+
+ if (!(r_ptr->flags & RF_MIMIC))
+ {
+ continue; /* Skip mimics completely */
+ }
+ else
+ {
+ /* Location */
+ y = m_ptr->fy;
+ x = m_ptr->fx;
+ }
+ }
+ else
+ {
+ /* Location */
+ y = o_ptr->iy;
+ x = o_ptr->ix;
+ }
+
+ /* Only detect nearby objects */
+ if (distance(p_ptr->py, p_ptr->px, y, x) > radius)
+ {
+ continue;
+ }
+
+ /* Detect objects that satisfy predicate */
+ if (p(o_ptr))
+ {
+ /* Hack -- memorize it */
+ o_ptr->marked = TRUE;
+
+ /* Redraw */
+ if (panel_contains(y, x)) lite_spot(y, x);
+
+ /* Detect */
+ detect = TRUE;
+ }
+ }
+
+ /* Describe */
+ if (detect)
+ {
+ msg_print(object_message);
+ }
+
+ if (detect_monsters_string(monsters, radius))
+ {
+ detect = true;
+ }
+
+ /* Result */
+ return detect;
+}
+
+
+/*
+ * Detect all "gold" objects on the current panel
+ */
+bool detect_objects_gold(int rad)
+{
+ auto predicate = [](object_type const *o_ptr) -> bool {
+ return o_ptr->tval == TV_GOLD;
+ };
+
+ return detect_objects_fn(
+ rad,
+ "You sense the presence of treasure!",
+ "$",
+ predicate);
+}
+
+
+/*
+ * Detect all "normal" objects on the current panel
+ */
+bool detect_objects_normal(int rad)
+{
+ auto predicate = [](object_type const *o_ptr) -> bool {
+ return o_ptr->tval != TV_GOLD;
+ };
+ const char *object_message = "You sense the presence of objects!";
+ const char *monsters = "!=?|";
+
+ return detect_objects_fn(
+ rad,
+ object_message,
+ monsters,
+ predicate);
+}
+
+
+/*
+ * Detect all "normal" monsters on the current panel
+ */
+bool_ detect_monsters_normal(int rad)
+{
+ auto predicate = [](monster_race *r_ptr) -> bool {
+ return (!(r_ptr->flags & RF_INVISIBLE)) ||
+ p_ptr->see_inv || p_ptr->tim_invis;
+ };
+
+ if (detect_monsters_fn(rad, predicate))
+ {
+ /* Describe result */
+ msg_print("You sense the presence of monsters!");
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+
+/*
+ * Detect all "invisible" monsters on current panel
+ */
+bool_ detect_monsters_invis(int rad)
+{
+ auto predicate = [](monster_race *r_ptr) -> bool {
+ return bool(r_ptr->flags & RF_INVISIBLE);
+ };
+
+ if (detect_monsters_fn(rad, predicate))
+ {
+ /* Describe result */
+ msg_print("You sense the presence of invisible creatures!");
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+
+
+/*
+ * Detect orcs
+ */
+void detect_monsters_orcs(int rad)
+{
+ auto predicate = [](monster_race *r_ptr) -> bool {
+ return bool(r_ptr->flags & RF_ORC);
+ };
+
+ if (detect_monsters_fn(rad, predicate))
+ {
+ msg_print("You sense the presence of orcs!");
+ }
+}
+
+
+
+/*
+ * Detect everything
+ */
+bool_ detect_all(int rad)
+{
+ bool_ detect = FALSE;
+
+ /* Detect everything */
+ if (detect_doors(rad)) detect = TRUE;
+ if (detect_stairs(rad)) detect = TRUE;
+ if (detect_treasure(rad)) detect = TRUE;
+ if (detect_objects_gold(rad)) detect = TRUE;
+ if (detect_objects_normal(rad)) detect = TRUE;
+ if (detect_monsters_invis(rad)) detect = TRUE;
+ if (detect_monsters_normal(rad)) detect = TRUE;
+
+ /* Result */
+ return (detect);
+}
+
+
+
+/*
+ * Create stairs at the player location
+ */
+void stair_creation()
+{
+ /* XXX XXX XXX */
+ if (!cave_valid_bold(p_ptr->py, p_ptr->px))
+ {
+ msg_print("The object resists the spell.");
+ return;
+ }
+
+ if (dungeon_flags & DF_FLAT)
+ {
+ msg_print("No stair creation in non dungeons...");
+ return;
+ }
+
+ if (dungeon_flags & DF_SPECIAL)
+ {
+ msg_print("No stair creation on special levels...");
+ return;
+ }
+
+ /* XXX XXX XXX */
+ delete_object(p_ptr->py, p_ptr->px);
+
+ /* Create a staircase */
+ if (p_ptr->inside_quest)
+ {
+ /* quest */
+ msg_print("There is no effect!");
+ }
+ else if (!dun_level)
+ {
+ /* Town/wilderness */
+ cave_set_feat(p_ptr->py, p_ptr->px, FEAT_MORE);
+ }
+ else if (is_quest(dun_level) || (dun_level >= MAX_DEPTH - 1))
+ {
+ /* Quest level */
+ cave_set_feat(p_ptr->py, p_ptr->px, FEAT_LESS);
+ }
+ else if (rand_int(100) < 50)
+ {
+ cave_set_feat(p_ptr->py, p_ptr->px, FEAT_MORE);
+ }
+ else
+ {
+ cave_set_feat(p_ptr->py, p_ptr->px, FEAT_LESS);
+ }
+}
+
+
+
+
+/*
+ * Hook to specify "weapon"
+ */
+static object_filter_t const &item_tester_hook_weapon()
+{
+ using namespace object_filter;
+ static auto instance =
+ Or(
+ TVal(TV_MSTAFF),
+ TVal(TV_BOOMERANG),
+ TVal(TV_SWORD),
+ TVal(TV_AXE),
+ TVal(TV_HAFTED),
+ TVal(TV_POLEARM),
+ TVal(TV_BOW),
+ TVal(TV_BOLT),
+ TVal(TV_ARROW),
+ TVal(TV_SHOT),
+ And(
+ TVal(TV_DAEMON_BOOK),
+ SVal(SV_DEMONBLADE)));
+ return instance;
+}
+
+
+/*
+ * Hook to specify "armour"
+ */
+static object_filter_t const &item_tester_hook_armour()
+{
+ using namespace object_filter;
+ static auto instance =
+ Or(
+ TVal(TV_DRAG_ARMOR),
+ TVal(TV_HARD_ARMOR),
+ TVal(TV_SOFT_ARMOR),
+ TVal(TV_SHIELD),
+ TVal(TV_CLOAK),
+ TVal(TV_CROWN),
+ TVal(TV_HELM),
+ TVal(TV_BOOTS),
+ TVal(TV_GLOVES),
+ And(
+ TVal(TV_DAEMON_BOOK),
+ Or(
+ SVal(SV_DEMONHORN),
+ SVal(SV_DEMONSHIELD))));
+ return instance;
+}
+
+
+/*
+ * Check if an object is artifactable
+ */
+object_filter_t const &item_tester_hook_artifactable()
+{
+ using namespace object_filter;
+ static auto instance = And(
+ // Check base item family
+ Or(
+ item_tester_hook_weapon(),
+ item_tester_hook_armour(),
+ TVal(TV_DIGGING),
+ TVal(TV_RING),
+ TVal(TV_AMULET)),
+ // Only unenchanted items
+ Not(IsArtifactP()),
+ Not(IsEgo()));
+ return instance;
+}
+
+
+/*
+ * Enchants a plus onto an item. -RAK-
+ *
+ * Revamped! Now takes item pointer, number of times to try enchanting,
+ * and a flag of what to try enchanting. Artifacts resist enchantment
+ * some of the time, and successful enchantment to at least +0 might
+ * break a curse on the item. -CFT-
+ *
+ * Note that an item can technically be enchanted all the way to +15 if
+ * you wait a very, very, long time. Going from +9 to +10 only works
+ * about 5% of the time, and from +10 to +11 only about 1% of the time.
+ *
+ * Note that this function can now be used on "piles" of items, and
+ * the larger the pile, the lower the chance of success.
+ */
+bool_ enchant(object_type *o_ptr, int n, int eflag)
+{
+ int i, chance, prob;
+ bool_ res = FALSE;
+ auto const a = artifact_p(o_ptr);
+
+ /* Extract the flags */
+ auto const flags = object_flags(o_ptr);
+
+ /* Break curse if item is cursed the curse isn't permanent */
+ auto maybe_break_curse = [o_ptr, &flags]()
+ {
+ if (cursed_p(o_ptr) && (!(flags & TR_PERMA_CURSE)))
+ {
+ msg_print("The curse is broken!");
+ o_ptr->ident &= ~(IDENT_CURSED);
+ o_ptr->ident |= (IDENT_SENSE);
+
+ if (o_ptr->art_flags & TR_CURSED)
+ o_ptr->art_flags &= ~TR_CURSED;
+ if (o_ptr->art_flags & TR_HEAVY_CURSE)
+ o_ptr->art_flags &= ~TR_HEAVY_CURSE;
+
+ o_ptr->sense = SENSE_UNCURSED;
+ }
+ };
+
+ /* Large piles resist enchantment */
+ prob = o_ptr->number * 100;
+
+ /* Missiles are easy to enchant */
+ if ((o_ptr->tval == TV_BOLT) ||
+ (o_ptr->tval == TV_ARROW) ||
+ (o_ptr->tval == TV_SHOT))
+ {
+ prob = prob / 20;
+ }
+
+ /* Try "n" times */
+ for (i = 0; i < n; i++)
+ {
+ /* Hack -- Roll for pile resistance */
+ if (rand_int(prob) >= 100) continue;
+
+ /* Enchant to hit */
+ if (eflag & (ENCH_TOHIT))
+ {
+ if (o_ptr->to_h < 0) chance = 0;
+ else if (o_ptr->to_h > 15) chance = 1000;
+ else chance = enchant_table[o_ptr->to_h];
+
+ if ((randint(1000) > chance) && (!a || (rand_int(100) < 50)))
+ {
+ o_ptr->to_h++;
+ res = TRUE;
+
+ /* break curse? */
+ if ((o_ptr->to_h >= 0) && (rand_int(100) < 25))
+ {
+ maybe_break_curse();
+ }
+ }
+ }
+
+ /* Enchant to damage */
+ if (eflag & (ENCH_TODAM))
+ {
+ if (o_ptr->to_d < 0) chance = 0;
+ else if (o_ptr->to_d > 15) chance = 1000;
+ else chance = enchant_table[o_ptr->to_d];
+
+ if ((randint(1000) > chance) && (!a || (rand_int(100) < 50)))
+ {
+ o_ptr->to_d++;
+ res = TRUE;
+
+ /* break curse? */
+ if ((o_ptr->to_d >= 0) && (rand_int(100) < 25))
+ {
+ maybe_break_curse();
+ }
+ }
+ }
+
+
+ /* Enchant to damage */
+ if (eflag & (ENCH_PVAL))
+ {
+ if (o_ptr->pval < 0) chance = 0;
+ else if (o_ptr->pval > 6) chance = 1000;
+ else chance = enchant_table[o_ptr->pval * 2];
+
+ if ((randint(1000) > chance) && (!a || (rand_int(100) < 50)))
+ {
+ o_ptr->pval++;
+ res = TRUE;
+
+ /* break curse? */
+ if ((o_ptr->pval >= 0) && (rand_int(100) < 25))
+ {
+ maybe_break_curse();
+ }
+ }
+ }
+
+ /* Enchant to armor class */
+ if (eflag & (ENCH_TOAC))
+ {
+ if (o_ptr->to_a < 0) chance = 0;
+ else if (o_ptr->to_a > 15) chance = 1000;
+ else chance = enchant_table[o_ptr->to_a];
+
+ if ((randint(1000) > chance) && (!a || (rand_int(100) < 50)))
+ {
+ o_ptr->to_a++;
+ res = TRUE;
+
+ /* break curse? */
+ if ((o_ptr->to_a >= 0) && (rand_int(100) < 25))
+ {
+ maybe_break_curse();
+ }
+ }
+ }
+ }
+
+ /* Failure */
+ if (!res) return (FALSE);
+
+ /* Recalculate bonuses */
+ p_ptr->update |= (PU_BONUS);
+
+ /* Combine / Reorder the pack (later) */
+ p_ptr->notice |= (PN_COMBINE | PN_REORDER);
+
+ /* Window stuff */
+ p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
+
+ /* Success */
+ return (TRUE);
+}
+
+
+
+/*
+ * Enchant an item (in the inventory or on the floor)
+ * Note that "num_ac" requires armour, else weapon
+ * Returns TRUE if attempted, FALSE if cancelled
+ */
+bool_ enchant_spell(int num_hit, int num_dam, int num_ac, int num_pval)
+{
+ int item;
+ bool_ okay = FALSE;
+ char o_name[80];
+ cptr q, s;
+
+
+ /* Assume enchant weapon */
+ object_filter_t object_filter = item_tester_hook_weapon();
+
+ /* Enchant armor if requested */
+ if (num_ac)
+ {
+ object_filter = item_tester_hook_armour();
+ }
+
+ /* Get an item */
+ q = "Enchant which item? ";
+ s = "You have nothing to enchant.";
+ if (!get_item(&item, q, s, (USE_EQUIP | USE_INVEN | USE_FLOOR), object_filter)) return (FALSE);
+
+ /* Get the item */
+ object_type *o_ptr = get_object(item);
+
+ /* Description */
+ object_desc(o_name, o_ptr, FALSE, 0);
+
+ /* Describe */
+ msg_format("%s %s glow%s brightly!",
+ ((item >= 0) ? "Your" : "The"), o_name,
+ ((o_ptr->number > 1) ? "" : "s"));
+
+ /* Enchant */
+ if (enchant(o_ptr, num_hit, ENCH_TOHIT)) okay = TRUE;
+ if (enchant(o_ptr, num_dam, ENCH_TODAM)) okay = TRUE;
+ if (enchant(o_ptr, num_ac, ENCH_TOAC)) okay = TRUE;
+ if (enchant(o_ptr, num_pval, ENCH_PVAL)) okay = TRUE;
+
+ /* Failure */
+ if (!okay)
+ {
+ /* Flush */
+ flush_on_failure();
+
+ /* Message */
+ msg_print("The enchantment failed.");
+ }
+
+ /* Something happened */
+ return (TRUE);
+}
+
+void curse_artifact(object_type * o_ptr)
+{
+ if (o_ptr->pval) o_ptr->pval = 0 - ((o_ptr->pval) + randint(4));
+ if (o_ptr->to_a) o_ptr->to_a = 0 - ((o_ptr->to_a) + randint(4));
+ if (o_ptr->to_h) o_ptr->to_h = 0 - ((o_ptr->to_h) + randint(4));
+ if (o_ptr->to_d) o_ptr->to_d = 0 - ((o_ptr->to_d) + randint(4));
+ o_ptr->art_flags |= TR_HEAVY_CURSE | TR_CURSED;
+ if (randint(3) == 1) o_ptr-> art_flags |= TR_TY_CURSE;
+ if (randint(2) == 1) o_ptr-> art_flags |= TR_AGGRAVATE;
+ if (randint(3) == 1) o_ptr-> art_flags |= TR_DRAIN_EXP;
+ if (randint(3) == 1) o_ptr-> art_flags |= TR_BLACK_BREATH;
+ if (randint(2) == 1) o_ptr-> art_flags |= TR_TELEPORT;
+ else if (randint(3) == 1) o_ptr->art_flags |= TR_NO_TELE;
+ o_ptr->ident |= IDENT_CURSED;
+}
+
+
+
+void random_resistance(object_type *o_ptr, int specific)
+{
+ /* To avoid a number of possible bugs */
+ if (!specific)
+ {
+ if (artifact_bias == BIAS_ACID)
+ {
+ if (!(o_ptr->art_flags & TR_RES_ACID))
+ {
+ o_ptr->art_flags |= TR_RES_ACID;
+ if (rand_int(2) == 0) return;
+ }
+ if (rand_int(BIAS_LUCK) == 0 && !(o_ptr->art_flags & TR_IM_ACID))
+ {
+ o_ptr->art_flags |= TR_IM_ACID;
+ if (rand_int(2) == 0) return;
+ }
+ }
+ else if (artifact_bias == BIAS_ELEC)
+ {
+ if (!(o_ptr->art_flags & TR_RES_ELEC))
+ {
+ o_ptr->art_flags |= TR_RES_ELEC;
+ if (rand_int(2) == 0) return;
+ }
+ if (o_ptr->tval >= TV_CLOAK && o_ptr->tval <= TV_HARD_ARMOR &&
+ !(o_ptr->art_flags & TR_SH_ELEC))
+ {
+ o_ptr->art_flags |= TR_SH_ELEC;
+ if (rand_int(2) == 0) return;
+ }
+ if (rand_int(BIAS_LUCK) == 0 && !(o_ptr->art_flags & TR_IM_ELEC))
+ {
+ o_ptr->art_flags |= TR_IM_ELEC;
+ if (rand_int(2) == 1) return;
+ }
+ }
+ else if (artifact_bias == BIAS_FIRE)
+ {
+ if (!(o_ptr->art_flags & TR_RES_FIRE))
+ {
+ o_ptr->art_flags |= TR_RES_FIRE;
+ if (rand_int(2) == 0) return;
+ }
+ if (o_ptr->tval >= TV_CLOAK && o_ptr->tval <= TV_HARD_ARMOR &&
+ !(o_ptr->art_flags & TR_SH_FIRE))
+ {
+ o_ptr->art_flags |= TR_SH_FIRE;
+ if (rand_int(2) == 0) return;
+ }
+ if (rand_int(BIAS_LUCK) == 0 && !(o_ptr->art_flags & TR_IM_FIRE))
+ {
+ o_ptr->art_flags |= TR_IM_FIRE;
+ if (rand_int(2) == 0) return;
+ }
+ }
+ else if (artifact_bias == BIAS_COLD)
+ {
+ if (!(o_ptr->art_flags & TR_RES_COLD))
+ {
+ o_ptr->art_flags |= TR_RES_COLD;
+ if (rand_int(2) == 0) return;
+ }
+ if (rand_int(BIAS_LUCK) == 0 && !(o_ptr->art_flags & TR_IM_COLD))
+ {
+ o_ptr->art_flags |= TR_IM_COLD;
+ if (rand_int(2) == 0) return;
+ }
+ }
+ else if (artifact_bias == BIAS_POIS)
+ {
+ if (!(o_ptr->art_flags & TR_RES_POIS))
+ {
+ o_ptr->art_flags |= TR_RES_POIS;
+ if (rand_int(2) == 0) return;
+ }
+ }
+ else if (artifact_bias == BIAS_WARRIOR)
+ {
+ if (rand_int(3) && (!(o_ptr->art_flags & TR_RES_FEAR)))
+ {
+ o_ptr->art_flags |= TR_RES_FEAR;
+ if (rand_int(2) == 0) return;
+ }
+ if ((rand_int(3) == 0) && (!(o_ptr->art_flags & TR_NO_MAGIC)))
+ {
+ o_ptr->art_flags |= TR_NO_MAGIC;
+ if (rand_int(2) == 0) return;
+ }
+ }
+ else if (artifact_bias == BIAS_NECROMANTIC)
+ {
+ if (!(o_ptr->art_flags & TR_RES_NETHER))
+ {
+ o_ptr->art_flags |= TR_RES_NETHER;
+ if (rand_int(2) == 0) return;
+ }
+ if (!(o_ptr->art_flags & TR_RES_POIS))
+ {
+ o_ptr->art_flags |= TR_RES_POIS;
+ if (rand_int(2) == 0) return;
+ }
+ if (!(o_ptr->art_flags & TR_RES_DARK))
+ {
+ o_ptr->art_flags |= TR_RES_DARK;
+ if (rand_int(2) == 0) return;
+ }
+ }
+ else if (artifact_bias == BIAS_CHAOS)
+ {
+ if (!(o_ptr->art_flags & TR_RES_CHAOS))
+ {
+ o_ptr->art_flags |= TR_RES_CHAOS;
+ if (rand_int(2) == 0) return;
+ }
+ if (!(o_ptr->art_flags & TR_RES_CONF))
+ {
+ o_ptr->art_flags |= TR_RES_CONF;
+ if (rand_int(2) == 0) return;
+ }
+ if (!(o_ptr->art_flags & TR_RES_DISEN))
+ {
+ o_ptr->art_flags |= TR_RES_DISEN;
+ if (rand_int(2) == 0) return;
+ }
+ }
+ }
+
+ switch (specific ? specific : randint(41))
+ {
+ case 1 :
+ if (randint(WEIRD_LUCK) != 1)
+ random_resistance(o_ptr, specific);
+ else
+ {
+ o_ptr->art_flags |= TR_IM_ACID;
+ /* if (is_scroll) msg_print("It looks totally incorruptible."); */
+ if (!(artifact_bias))
+ artifact_bias = BIAS_ACID;
+ }
+ break;
+ case 2:
+ if (randint(WEIRD_LUCK) != 1)
+ random_resistance(o_ptr, specific);
+ else
+ {
+ o_ptr->art_flags |= TR_IM_ELEC;
+ /* if (is_scroll) msg_print("It looks completely grounded."); */
+ if (!(artifact_bias))
+ artifact_bias = BIAS_ELEC;
+ }
+ break;
+ case 3:
+ if (randint(WEIRD_LUCK) != 1)
+ random_resistance(o_ptr, specific);
+ else
+ {
+ o_ptr->art_flags |= TR_IM_COLD;
+ /* if (is_scroll) msg_print("It feels very warm."); */
+ if (!(artifact_bias))
+ artifact_bias = BIAS_COLD;
+ }
+ break;
+ case 4:
+ if (randint(WEIRD_LUCK) != 1)
+ random_resistance(o_ptr, specific);
+ else
+ {
+ o_ptr->art_flags |= TR_IM_FIRE;
+ /* if (is_scroll) msg_print("It feels very cool."); */
+ if (!(artifact_bias))
+ artifact_bias = BIAS_FIRE;
+ }
+ break;
+ case 5:
+ case 6:
+ case 13:
+ o_ptr->art_flags |= TR_RES_ACID;
+ /* if (is_scroll) msg_print("It makes your stomach rumble."); */
+ if (!(artifact_bias))
+ artifact_bias = BIAS_ACID;
+ break;
+ case 7:
+ case 8:
+ case 14:
+ o_ptr->art_flags |= TR_RES_ELEC;
+ /* if (is_scroll) msg_print("It makes you feel grounded."); */
+ if (!(artifact_bias))
+ artifact_bias = BIAS_ELEC;
+ break;
+ case 9:
+ case 10:
+ case 15:
+ o_ptr->art_flags |= TR_RES_FIRE;
+ /* if (is_scroll) msg_print("It makes you feel cool!");*/
+ if (!(artifact_bias))
+ artifact_bias = BIAS_FIRE;
+ break;
+ case 11:
+ case 12:
+ case 16:
+ o_ptr->art_flags |= TR_RES_COLD;
+ /* if (is_scroll) msg_print("It makes you feel full of hot air!");*/
+ if (!(artifact_bias))
+ artifact_bias = BIAS_COLD;
+ break;
+ case 17:
+ case 18:
+ o_ptr->art_flags |= TR_RES_POIS;
+ /* if (is_scroll) msg_print("It makes breathing easier for you."); */
+ if (!(artifact_bias) && randint(4) != 1)
+ artifact_bias = BIAS_POIS;
+ else if (!(artifact_bias) && randint(2) == 1)
+ artifact_bias = BIAS_NECROMANTIC;
+ else if (!(artifact_bias) && randint(2) == 1)
+ artifact_bias = BIAS_ROGUE;
+ break;
+ case 19:
+ case 20:
+ o_ptr->art_flags |= TR_RES_FEAR;
+ /* if (is_scroll) msg_print("It makes you feel brave!"); */
+ if (!(artifact_bias) && randint(3) == 1)
+ artifact_bias = BIAS_WARRIOR;
+ break;
+ case 21:
+ o_ptr->art_flags |= TR_RES_LITE;
+ /* if (is_scroll) msg_print("It makes everything look darker.");*/
+ break;
+ case 22:
+ o_ptr->art_flags |= TR_RES_DARK;
+ /* if (is_scroll) msg_print("It makes everything look brigher.");*/
+ break;
+ case 23:
+ case 24:
+ o_ptr->art_flags |= TR_RES_BLIND;
+ /* if (is_scroll) msg_print("It makes you feel you are wearing glasses.");*/
+ break;
+ case 25:
+ case 26:
+ o_ptr->art_flags |= TR_RES_CONF;
+ /* if (is_scroll) msg_print("It makes you feel very determined.");*/
+ if (!(artifact_bias) && randint(6) == 1)
+ artifact_bias = BIAS_CHAOS;
+ break;
+ case 27:
+ case 28:
+ o_ptr->art_flags |= TR_RES_SOUND;
+ /* if (is_scroll) msg_print("It makes you feel deaf!");*/
+ break;
+ case 29:
+ case 30:
+ o_ptr->art_flags |= TR_RES_SHARDS;
+ /* if (is_scroll) msg_print("It makes your skin feel thicker.");*/
+ break;
+ case 31:
+ case 32:
+ o_ptr->art_flags |= TR_RES_NETHER;
+ /* if (is_scroll) msg_print("It makes you feel like visiting a graveyard!");*/
+ if (!(artifact_bias) && randint(3) == 1)
+ artifact_bias = BIAS_NECROMANTIC;
+ break;
+ case 33:
+ case 34:
+ o_ptr->art_flags |= TR_RES_NEXUS;
+ /* if (is_scroll) msg_print("It makes you feel normal.");*/
+ break;
+ case 35:
+ case 36:
+ o_ptr->art_flags |= TR_RES_CHAOS;
+ /* if (is_scroll) msg_print("It makes you feel very firm.");*/
+ if (!(artifact_bias) && randint(2) == 1)
+ artifact_bias = BIAS_CHAOS;
+ break;
+ case 37:
+ case 38:
+ o_ptr->art_flags |= TR_RES_DISEN;
+ /* if (is_scroll) msg_print("It is surrounded by a static feeling.");*/
+ break;
+ case 39:
+ if (o_ptr->tval >= TV_CLOAK && o_ptr->tval <= TV_HARD_ARMOR)
+ o_ptr->art_flags |= TR_SH_ELEC;
+ else
+ random_resistance(o_ptr, specific);
+ if (!(artifact_bias))
+ artifact_bias = BIAS_ELEC;
+ break;
+ case 40:
+ if (o_ptr->tval >= TV_CLOAK && o_ptr->tval <= TV_HARD_ARMOR)
+ o_ptr->art_flags |= TR_SH_FIRE;
+ else
+ random_resistance(o_ptr, specific);
+ if (!(artifact_bias))
+ artifact_bias = BIAS_FIRE;
+ break;
+ case 41:
+ if (o_ptr->tval == TV_SHIELD || o_ptr->tval == TV_CLOAK ||
+ o_ptr->tval == TV_HELM || o_ptr->tval == TV_HARD_ARMOR)
+ o_ptr->art_flags |= TR_REFLECT;
+ else
+ random_resistance(o_ptr, specific);
+ break;
+ }
+}
+
+
+
+/*
+ * 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))
+ {
+ 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.
+ * Returns TRUE if something was identified, else FALSE.
+ */
+bool_ ident_spell()
+{
+ /* Get an item */
+ int item;
+ if (!get_item(&item,
+ "Identify which item? ",
+ "You have nothing to identify.",
+ (USE_EQUIP | USE_INVEN | USE_FLOOR),
+ object_filter::Not(object_known_p))) return (FALSE);
+
+ /* Get the item */
+ object_type *o_ptr = get_object(item);
+
+ /* Identify it fully */
+ object_aware(o_ptr);
+ object_known(o_ptr);
+
+ /* Recalculate bonuses */
+ p_ptr->update |= (PU_BONUS);
+
+ /* Combine / Reorder the pack (later) */
+ p_ptr->notice |= (PN_COMBINE | PN_REORDER);
+
+ /* Window stuff */
+ p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
+
+ /* Description */
+ char o_name[80];
+ object_desc(o_name, o_ptr, TRUE, 3);
+
+ /* Describe */
+ if (item >= INVEN_WIELD)
+ {
+ msg_format("%^s: %s (%c).",
+ describe_use(item), o_name, index_to_label(item));
+ }
+ else if (item >= 0)
+ {
+ msg_format("In your pack: %s (%c).",
+ o_name, index_to_label(item));
+ }
+ else
+ {
+ msg_format("On the ground: %s.",
+ o_name);
+ }
+
+ /* Make note of found artifacts */
+ note_found_object(o_ptr);
+
+ /* Process the appropriate hooks */
+ identify_hooks(item, o_ptr, IDENT_NORMAL);
+
+ /* Something happened */
+ return (TRUE);
+}
+
+/*
+ * Identify all objects in the level
+ */
+bool_ ident_all()
+{
+ int i;
+
+ object_type *o_ptr;
+
+ for (i = 1; i < o_max; i++)
+ {
+ /* Acquire object */
+ o_ptr = &o_list[i];
+
+ /* Identify it fully */
+ object_aware(o_ptr);
+ object_known(o_ptr);
+
+ /* Make note of found artifacts */
+ note_found_object(o_ptr);
+
+ /* Process the appropriate hooks */
+ identify_hooks(-i, o_ptr, IDENT_NORMAL);
+ }
+
+ /* Something happened */
+ return (TRUE);
+}
+
+
+
+/*
+ * Determine if an object is not fully identified
+ */
+static bool item_tester_hook_no_mental(object_type const *o_ptr)
+{
+ return ((o_ptr->ident & (IDENT_MENTAL)) ? false : true);
+}
+
+/*
+ * Fully "identify" an object in the inventory -BEN-
+ * This routine returns TRUE if an item was identified.
+ */
+bool_ identify_fully()
+{
+ /* Get an item */
+ int item;
+ if (!get_item(&item,
+ "Identify which item? ",
+ "You have nothing to identify.",
+ (USE_EQUIP | USE_INVEN | USE_FLOOR),
+ item_tester_hook_no_mental))
+ {
+ return (FALSE);
+ }
+
+ /* Get the item */
+ object_type *o_ptr = get_object(item);
+
+ /* Do the identification */
+ make_item_fully_identified(o_ptr);
+
+ /* Recalculate bonuses */
+ p_ptr->update |= (PU_BONUS);
+
+ /* Combine / Reorder the pack (later) */
+ p_ptr->notice |= (PN_COMBINE | PN_REORDER);
+
+ /* Window stuff */
+ p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
+
+ /* Description */
+ char o_name[80];
+ object_desc(o_name, o_ptr, TRUE, 3);
+
+ /* Describe */
+ if (item >= INVEN_WIELD)
+ {
+ msg_format("%^s: %s (%c).",
+ describe_use(item), o_name, index_to_label(item));
+ }
+ else if (item >= 0)
+ {
+ msg_format("In your pack: %s (%c).",
+ o_name, index_to_label(item));
+ }
+ else
+ {
+ msg_format("On the ground: %s.",
+ o_name);
+ }
+
+ /* Make note of found artifacts */
+ note_found_object(o_ptr);
+
+ /* Describe it fully */
+ object_out_desc(o_ptr, NULL, FALSE, TRUE);
+
+ /* Process the appropriate hooks */
+ identify_hooks(item, o_ptr, IDENT_FULL);
+
+ /* Success */
+ return (TRUE);
+}
+
+
+
+
+/*
+ * Hook for "get_item()". Determine if something is rechargable.
+ */
+object_filter_t const &item_tester_hook_recharge()
+{
+ using namespace object_filter;
+ static auto instance =
+ And(
+ // Must NOT have NO_RECHARGE flag.
+ Not(HasFlags(TR_NO_RECHARGE)),
+ // ... and must be a device.
+ Or(
+ TVal(TV_STAFF),
+ TVal(TV_WAND),
+ TVal(TV_ROD_MAIN)));
+ return instance;
+}
+
+
+/*
+ * Recharge a wand/staff/rod from the pack or on the floor.
+ * This function has been rewritten in Oangband. -LM-
+ *
+ * Mage -- Recharge I --> recharge(90)
+ * Mage -- Recharge II --> recharge(150)
+ * Mage -- Recharge III --> recharge(220)
+ *
+ * Priest or Necromancer -- Recharge --> recharge(140)
+ *
+ * Scroll of recharging --> recharge(130)
+ * Scroll of *recharging* --> recharge(200)
+ *
+ * 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.
+ *
+ * XXX XXX XXX Beware of "sliding index errors".
+ */
+bool_ recharge(int power)
+{
+ auto const &k_info = game->edit_data.k_info;
+
+ int recharge_strength, recharge_amount;
+ int lev;
+ bool_ fail = FALSE;
+ byte fail_type = 1;
+
+ char o_name[80];
+
+ /* Get an item */
+ int item;
+ if (!get_item(&item,
+ "Recharge which item? ",
+ "You have nothing to recharge.",
+ (USE_INVEN | USE_FLOOR),
+ item_tester_hook_recharge()))
+ {
+ return (FALSE);
+ }
+
+ /* Get the item */
+ object_type *o_ptr = get_object(item);
+
+ /* Extract the flags */
+ auto const flags = object_flags(o_ptr);
+
+ /* Extract the object "level" */
+ lev = k_info[o_ptr->k_idx].level;
+
+ /* Recharge a rod */
+ if (o_ptr->tval == TV_ROD_MAIN)
+ {
+ /* Extract a recharge strength by comparing object level to power. */
+ recharge_strength = ((power > lev) ? (power - lev) : 0) / 5;
+
+ /* Paranoia */
+ if (recharge_strength < 0) recharge_strength = 0;
+
+ /* Back-fire */
+ if ((rand_int(recharge_strength) == 0) && (!(flags & TR_RECHARGE)))
+ {
+ /* Activate the failure code. */
+ fail = TRUE;
+ }
+
+ /* Recharge */
+ else
+ {
+ /* Recharge amount */
+ recharge_amount = (power * damroll(3, 2));
+
+ /* Recharge by that amount */
+ if (o_ptr->timeout + recharge_amount < o_ptr->pval2)
+ o_ptr->timeout += recharge_amount;
+ else
+ o_ptr->timeout = o_ptr->pval2;
+ }
+ }
+
+
+ /* Recharge wand/staff */
+ else
+ {
+ /* Extract a recharge strength by comparing object level to power.
+ * Divide up a stack of wands' charges to calculate charge penalty.
+ */
+ if ((o_ptr->tval == TV_WAND) && (o_ptr->number > 1))
+ recharge_strength = (100 + power - lev -
+ (8 * o_ptr->pval / o_ptr->number)) / 15;
+
+ /* All staffs, unstacked wands. */
+ else recharge_strength = (100 + power - lev -
+ (8 * o_ptr->pval)) / 15;
+
+
+ /* Back-fire XXX XXX XXX */
+ if (((rand_int(recharge_strength) == 0) && (!(flags & TR_RECHARGE))) ||
+ (flags & TR_NO_RECHARGE))
+ {
+ /* Activate the failure code. */
+ fail = TRUE;
+ }
+
+ /* If the spell didn't backfire, recharge the wand or staff. */
+ else
+ {
+ /* Recharge based on the standard number of charges. */
+ recharge_amount = randint((power / (lev + 2)) + 1);
+
+ /* Multiple wands in a stack increase recharging somewhat. */
+ if ((o_ptr->tval == TV_WAND) && (o_ptr->number > 1))
+ {
+ recharge_amount +=
+ (randint(recharge_amount * (o_ptr->number - 1))) / 2;
+ if (recharge_amount < 1) recharge_amount = 1;
+ if (recharge_amount > 12) recharge_amount = 12;
+ }
+
+ /* But each staff in a stack gets fewer additional charges,
+ * although always at least one.
+ */
+ if ((o_ptr->tval == TV_STAFF) && (o_ptr->number > 1))
+ {
+ recharge_amount /= o_ptr->number;
+ if (recharge_amount < 1) recharge_amount = 1;
+ }
+
+ /* Recharge the wand or staff. */
+ o_ptr->pval += recharge_amount;
+
+ if (!(flags & TR_RECHARGE))
+ {
+ /* Hack -- we no longer "know" the item */
+ o_ptr->ident &= ~(IDENT_KNOWN);
+ }
+
+ /* Hack -- we no longer think the item is empty */
+ o_ptr->ident &= ~(IDENT_EMPTY);
+ }
+ }
+
+ /* Mark as recharged */
+ o_ptr->art_flags |= TR_RECHARGED;
+
+ /* Inflict the penalties for failing a recharge. */
+ if (fail)
+ {
+ /* Artifacts are never destroyed. */
+ if (artifact_p(o_ptr))
+ {
+ object_desc(o_name, o_ptr, TRUE, 0);
+ msg_format("The recharging backfires - %s is completely drained!", o_name);
+
+ /* Artifact rods. */
+ if (o_ptr->tval == TV_ROD_MAIN)
+ o_ptr->timeout = 0;
+
+ /* Artifact wands and staffs. */
+ else if ((o_ptr->tval == TV_WAND) || (o_ptr->tval == TV_STAFF))
+ o_ptr->pval = 0;
+ }
+ else
+ {
+ /* Get the object description */
+ object_desc(o_name, o_ptr, FALSE, 0);
+
+ /*** Determine Seriousness of Failure ***/
+
+ /* Mages recharge objects more safely. */
+ if (p_ptr->has_ability(AB_PERFECT_CASTING))
+ {
+ /* 10% chance to blow up one rod, otherwise draining. */
+ if (o_ptr->tval == TV_ROD_MAIN)
+ {
+ if (randint(10) == 1) fail_type = 2;
+ else fail_type = 1;
+ }
+ /* 75% chance to blow up one wand, otherwise draining. */
+ else if (o_ptr->tval == TV_WAND)
+ {
+ if (randint(3) != 1) fail_type = 2;
+ else fail_type = 1;
+ }
+ /* 50% chance to blow up one staff, otherwise no effect. */
+ else if (o_ptr->tval == TV_STAFF)
+ {
+ if (randint(2) == 1) fail_type = 2;
+ else fail_type = 0;
+ }
+ }
+
+ /* All other classes get no special favors. */
+ else
+ {
+ /* 33% chance to blow up one rod, otherwise draining. */
+ if (o_ptr->tval == TV_ROD_MAIN)
+ {
+ if (randint(3) == 1) fail_type = 2;
+ else fail_type = 1;
+ }
+ /* 20% chance of the entire stack, else destroy one wand. */
+ else if (o_ptr->tval == TV_WAND)
+ {
+ if (randint(5) == 1) fail_type = 3;
+ else fail_type = 2;
+ }
+ /* Blow up one staff. */
+ else if (o_ptr->tval == TV_STAFF)
+ {
+ fail_type = 2;
+ }
+ }
+
+ /*** Apply draining and destruction. ***/
+
+ /* Drain object or stack of objects. */
+ if (fail_type == 1)
+ {
+ if (o_ptr->tval == TV_ROD_MAIN)
+ {
+ msg_print("The recharge backfires, draining the rod further!");
+ if (o_ptr->timeout < 10000)
+ o_ptr->timeout = 0;
+ }
+ else if (o_ptr->tval == TV_WAND)
+ {
+ msg_format("You save your %s from destruction, but all charges are lost.", o_name);
+ o_ptr->pval = 0;
+ }
+ /* Staffs aren't drained. */
+ }
+
+ /* Destroy an object or one in a stack of objects. */
+ if (fail_type == 2)
+ {
+ if (o_ptr->number > 1)
+ msg_format("Wild magic consumes one of your %s!", o_name);
+ else
+ msg_format("Wild magic consumes your %s!", o_name);
+
+ /* Reduce rod stack maximum timeout, drain wands. */
+ if (o_ptr->tval == TV_WAND) o_ptr->pval = 0;
+
+ /* Reduce and describe */
+ inc_stack_size(item, -1);
+ }
+
+ /* Destroy all memebers of a stack of objects. */
+ if (fail_type == 3)
+ {
+ if (o_ptr->number > 1)
+ msg_format("Wild magic consumes all your %s!", o_name);
+ else
+ msg_format("Wild magic consumes your %s!", o_name);
+
+
+ /* Reduce and describe inventory */
+ inc_stack_size(item, -999);
+ }
+ }
+ }
+
+
+ /* Combine / Reorder the pack (later) */
+ p_ptr->notice |= (PN_COMBINE | PN_REORDER);
+
+ /* Window stuff */
+ p_ptr->window |= (PW_INVEN);
+
+ /* Something was done */
+ return (TRUE);
+}
+
+
+
+/*
+ * Apply a "project()" directly to all viewable monsters
+ *
+ * Note that affected monsters are NOT auto-tracked by this usage.
+ */
+bool_ project_hack(int typ, int dam)
+{
+ int i, x, y;
+ int flg = PROJECT_JUMP | PROJECT_KILL | PROJECT_HIDE;
+ bool_ obvious = FALSE;
+
+
+ /* Affect all (nearby) monsters */
+ for (i = 1; i < m_max; i++)
+ {
+ monster_type *m_ptr = &m_list[i];
+
+ /* Paranoia -- Skip dead monsters */
+ if (!m_ptr->r_idx) continue;
+
+ /* Location */
+ y = m_ptr->fy;
+ x = m_ptr->fx;
+
+ /* Require line of sight */
+ if (!player_has_los_bold(y, x)) continue;
+
+ /* Jump directly to the target monster */
+ if (project(0, 0, y, x, dam, typ, flg)) obvious = TRUE;
+ }
+
+ /* Result */
+ return (obvious);
+}
+
+/*
+ * Apply a "project()" a la meteor shower
+ */
+void project_meteor(int radius, int typ, int dam, u32b flg)
+{
+ cave_type *c_ptr;
+ int x, y, dx, dy, d, count = 0, i;
+ int b = radius + randint(radius);
+ for (i = 0; i < b; i++)
+ {
+ for (count = 0; count < 1000; count++)
+ {
+ x = p_ptr->px - 5 + randint(10);
+ y = p_ptr->py - 5 + randint(10);
+ if ((x < 0) || (x >= cur_wid) ||
+ (y < 0) || (y >= cur_hgt)) continue;
+ dx = (p_ptr->px > x) ? (p_ptr->px - x) : (x - p_ptr->px);
+ dy = (p_ptr->py > y) ? (p_ptr->py - y) : (y - p_ptr->py);
+ /* Approximate distance */
+ d = (dy > dx) ? (dy + (dx >> 1)) : (dx + (dy >> 1));
+ c_ptr = &cave[y][x];
+ /* Check distance */
+ if ((d <= 5) &&
+ /* Check line of sight */
+ (player_has_los_bold(y, x)) &&
+ /* But don't explode IN a wall, letting the player attack through walls */
+ !(c_ptr->info & CAVE_WALL))
+ break;
+ }
+ if (count >= 1000) break;
+ project(0, 2, y, x, dam, typ, PROJECT_JUMP | flg);
+ }
+}
+
+
+/*
+ * Banish evil monsters
+ */
+bool_ banish_evil(int dist)
+{
+ return (project_hack(GF_AWAY_EVIL, dist));
+}
+
+
+
+/*
+ * Dispel undead monsters
+ */
+bool_ dispel_undead(int dam)
+{
+ return (project_hack(GF_DISP_UNDEAD, dam));
+}
+
+/*
+ * Dispel evil monsters
+ */
+bool_ dispel_evil(int dam)
+{
+ return (project_hack(GF_DISP_EVIL, dam));
+}
+
+/*
+ * Dispel good monsters
+ */
+bool_ dispel_good(int dam)
+{
+ return (project_hack(GF_DISP_GOOD, dam));
+}
+
+/*
+ * Dispel all monsters
+ */
+bool_ dispel_monsters(int dam)
+{
+ return (project_hack(GF_DISP_ALL, dam));
+}
+
+
+/*
+ * Wake up all monsters, and speed up "los" monsters.
+ */
+void aggravate_monsters(int who)
+{
+ int i;
+ bool_ sleep = FALSE;
+ bool_ speed = FALSE;
+
+
+ /* Aggravate everyone nearby */
+ for (i = 1; i < m_max; i++)
+ {
+ monster_type *m_ptr = &m_list[i];
+
+ /* Paranoia -- Skip dead monsters */
+ if (!m_ptr->r_idx) continue;
+
+ /* Skip aggravating monster (or player) */
+ if (i == who) continue;
+
+ /* Wake up nearby sleeping monsters */
+ if (m_ptr->cdis < MAX_SIGHT * 2)
+ {
+ /* Wake up */
+ if (m_ptr->csleep)
+ {
+ /* Wake up */
+ m_ptr->csleep = 0;
+ sleep = TRUE;
+ }
+ }
+
+ /* Speed up monsters in line of sight */
+ if (player_has_los_bold(m_ptr->fy, m_ptr->fx))
+ {
+ auto const r_ptr = m_ptr->race();
+
+ /* Speed up (instantly) to racial base + 10 */
+ if (m_ptr->mspeed < r_ptr->speed + 10)
+ {
+ /* Speed up */
+ m_ptr->mspeed = r_ptr->speed + 10;
+ speed = TRUE;
+ }
+
+ /* Pets may get angry (50% chance) */
+ if (is_friend(m_ptr))
+ {
+ if (randint(2) == 1)
+ {
+ change_side(m_ptr);
+ }
+ }
+ }
+ }
+
+ /* Messages */
+ if (speed) msg_print("You feel a sudden stirring nearby!");
+ else if (sleep) msg_print("You hear a sudden stirring in the distance!");
+}
+
+/*
+ * Generic genocide race selection
+ */
+static bool get_genocide_race(cptr msg, char *typ)
+{
+ int i, j;
+ cave_type *c_ptr;
+
+ msg_print(msg);
+ if (!tgt_pt(&i, &j)) return FALSE;
+
+ c_ptr = &cave[j][i];
+
+ if (c_ptr->m_idx)
+ {
+ monster_type *m_ptr = &m_list[c_ptr->m_idx];
+ auto const r_ptr = m_ptr->race();
+
+ *typ = r_ptr->d_char;
+ return true;
+ }
+
+ msg_print("You must select a monster.");
+ return false;
+}
+
+
+/*
+ * Delete all non-unique/non-quest monsters of a given "type" from the level
+ */
+bool_ genocide_aux(bool_ player_cast, char typ)
+{
+ int i;
+ bool_ result = FALSE;
+ auto const msec = options->delay_factor_ms();
+ int dam = 0;
+
+ /* Delete the monsters of that "type" */
+ for (i = 1; i < m_max; i++)
+ {
+ monster_type *m_ptr = &m_list[i];
+ auto const r_ptr = m_ptr->race();
+
+ /* Paranoia -- Skip dead monsters */
+ if (!m_ptr->r_idx) continue;
+
+ /* Hack -- Skip Unique Monsters */
+ if (r_ptr->flags & RF_UNIQUE) continue;
+
+ /* Hack -- Skip Quest Monsters */
+ if (m_ptr->mflag & MFLAG_QUEST) continue;
+
+ /* Skip "wrong" monsters */
+ if (r_ptr->d_char != typ) continue;
+
+ /* Oups */
+ if (r_ptr->flags & RF_DEATH_ORB)
+ {
+ int wx, wy;
+ int attempts = 500;
+ char buf[256];
+
+ monster_race_desc(buf, m_ptr->r_idx, 0);
+
+ do
+ {
+ scatter(&wy, &wx, m_ptr->fy, m_ptr->fx, 10);
+ }
+ while (!(in_bounds(wy, wx) && cave_floor_bold(wy, wx)) && --attempts);
+
+ if (place_monster_aux(wy, wx, m_ptr->r_idx, FALSE, TRUE, MSTATUS_ENEMY))
+ {
+ cmsg_format(TERM_L_BLUE, "The spell seems to produce an ... interesting effect on the %s.", buf);
+ }
+
+ return TRUE;
+ }
+
+ /* Delete the monster */
+ delete_monster_idx(i);
+
+ if (player_cast)
+ {
+ /* Keep track of damage */
+ dam += randint(4);
+ }
+
+ /* Handle */
+ handle_stuff();
+
+ /* Fresh */
+ Term_fresh();
+
+ /* Delay */
+ sleep_for(milliseconds(msec));
+
+ /* Take note */
+ result = TRUE;
+ }
+
+ if (player_cast)
+ {
+ /* Take damage */
+ take_hit(dam, "the strain of casting Genocide");
+
+ /* Visual feedback */
+ move_cursor_relative(p_ptr->py, p_ptr->px);
+
+ /* Redraw */
+ p_ptr->redraw |= (PR_FRAME);
+
+ /* Window stuff */
+ p_ptr->window |= (PW_PLAYER);
+
+ /* Handle */
+ handle_stuff();
+
+ /* Fresh */
+ Term_fresh();
+ }
+
+ return (result);
+}
+
+bool_ genocide(bool_ player_cast)
+{
+ char typ;
+
+ if (dungeon_flags & DF_NO_GENO) return (FALSE);
+
+ /* Hack -- when you are fated to die, you cant cheat :) */
+ if (dungeon_type == DUNGEON_DEATH)
+ {
+ msg_print("A mysterious force stops the genocide.");
+ return FALSE;
+ }
+
+ /* Mega-Hack -- Get a monster symbol */
+ if (!get_genocide_race("Target a monster to select the race to genocide.", &typ)) return FALSE;
+
+ return (genocide_aux(player_cast, typ));
+}
+
+
+/*
+ * Delete all nearby (non-unique) monsters
+ */
+bool_ mass_genocide(bool_ player_cast)
+{
+ int i;
+ bool_ result = FALSE;
+ auto const msec = options->delay_factor_ms();
+ int dam = 0;
+
+ /* Prevented? */
+ if ((dungeon_flags & DF_NO_GENO) || (dungeon_type == DUNGEON_DEATH))
+ {
+ msg_print("A mysterious force stops the genocide.");
+ return FALSE;
+ }
+
+ /* Delete the (nearby) monsters */
+ for (i = 1; i < m_max; i++)
+ {
+ monster_type *m_ptr = &m_list[i];
+ auto const r_ptr = m_ptr->race();
+
+ /* Paranoia -- Skip dead monsters */
+ if (!m_ptr->r_idx) continue;
+
+ /* Hack -- Skip unique monsters */
+ if (r_ptr->flags & RF_UNIQUE) continue;
+
+ /* Hack -- Skip Quest Monsters */
+ if (m_ptr->mflag & MFLAG_QUEST) continue;
+
+ /* Skip distant monsters */
+ if (m_ptr->cdis > MAX_SIGHT) continue;
+
+ /* Oups */
+ if (r_ptr->flags & RF_DEATH_ORB)
+ {
+ int wx, wy;
+ int attempts = 500;
+ char buf[256];
+
+ monster_race_desc(buf, m_ptr->r_idx, 0);
+
+ do
+ {
+ scatter(&wy, &wx, m_ptr->fy, m_ptr->fx, 10);
+ }
+ while (!(in_bounds(wy, wx) && cave_floor_bold(wy, wx)) && --attempts);
+
+ if (place_monster_aux(wy, wx, m_ptr->r_idx, FALSE, TRUE, MSTATUS_ENEMY))
+ {
+ cmsg_format(TERM_L_BLUE, "The spell seems to produce an ... interesting effect on the %s.", buf);
+ }
+
+ return TRUE;
+ }
+
+ /* Delete the monster */
+ delete_monster_idx(i);
+
+ if (player_cast)
+ {
+ /* Keep track of damage. */
+ dam += randint(3);
+ }
+
+ /* Handle */
+ handle_stuff();
+
+ /* Fresh */
+ Term_fresh();
+
+ /* Delay */
+ sleep_for(milliseconds(msec));
+
+ /* Note effect */
+ result = TRUE;
+ }
+
+ if (player_cast)
+ {
+ /* Take damage */
+ take_hit(dam, "the strain of casting Mass Genocide");
+
+ /* Visual feedback */
+ move_cursor_relative(p_ptr->py, p_ptr->px);
+
+ /* Redraw */
+ p_ptr->redraw |= (PR_FRAME);
+
+ /* Window stuff */
+ p_ptr->window |= (PW_PLAYER);
+
+ /* Handle */
+ handle_stuff();
+
+ /* Fresh */
+ Term_fresh();
+ }
+
+ return (result);
+}
+
+
+/*
+ * The spell of destruction
+ *
+ * This spell "deletes" monsters (instead of "killing" them).
+ *
+ * Later we may use one function for both "destruction" and
+ * "earthquake" by using the "full" to select "destruction".
+ */
+void destroy_area(int y1, int x1, int r)
+{
+ int y, x, k, t;
+
+ cave_type *c_ptr;
+
+ bool_ flag = FALSE;
+
+
+ if (dungeon_flags & DF_NO_GENO)
+ {
+ msg_print("Not on special levels!");
+ return;
+ }
+ if (p_ptr->inside_quest)
+ {
+ return;
+ }
+
+ /* Big area of affect */
+ for (y = (y1 - r); y <= (y1 + r); y++)
+ {
+ for (x = (x1 - r); x <= (x1 + r); x++)
+ {
+ /* Skip illegal grids */
+ if (!in_bounds(y, x)) continue;
+
+ /* Extract the distance */
+ k = distance(y1, x1, y, x);
+
+ /* Stay in the circle of death */
+ if (k > r) continue;
+
+ /* Access the grid */
+ c_ptr = &cave[y][x];
+
+ /* Lose room and vault */
+ c_ptr->info &= ~(CAVE_ROOM | CAVE_ICKY);
+
+ /* Lose light and knowledge */
+ c_ptr->info &= ~(CAVE_MARK | CAVE_GLOW);
+
+ /* Hack -- Notice player affect */
+ if ((x == p_ptr->px) && (y == p_ptr->py))
+ {
+ /* Hurt the player later */
+ flag = TRUE;
+
+ /* Do not hurt this grid */
+ continue;
+ }
+
+ /* Hack -- Skip the epicenter */
+ if ((y == y1) && (x == x1)) continue;
+
+ /* Delete the monster (if any) */
+ if ((m_list[c_ptr->m_idx].status != MSTATUS_COMPANION) ||
+ (!(m_list[c_ptr->m_idx].mflag & MFLAG_QUEST)) ||
+ (!(m_list[c_ptr->m_idx].mflag & MFLAG_QUEST2)))
+ delete_monster(y, x);
+
+ /* Destroy "valid" grids */
+ if (cave_valid_bold(y, x))
+ {
+ /* Delete objects */
+ delete_object(y, x);
+
+ /* Wall (or floor) type */
+ t = rand_int(200);
+
+ /* Granite */
+ if (t < 20)
+ {
+ /* Create granite wall */
+ cave_set_feat(y, x, FEAT_WALL_EXTRA);
+ }
+
+ /* Quartz */
+ else if (t < 70)
+ {
+ /* Create quartz vein */
+ cave_set_feat(y, x, FEAT_QUARTZ);
+ }
+
+ /* Magma */
+ else if (t < 100)
+ {
+ /* Create magma vein */
+ cave_set_feat(y, x, FEAT_MAGMA);
+ }
+
+ /* Floor */
+ else
+ {
+ /* Create floor */
+ cave_set_feat(y, x, FEAT_FLOOR);
+ }
+ }
+ }
+ }
+
+
+ /* Hack -- Affect player */
+ if (flag)
+ {
+ /* Message */
+ msg_print("There is a searing blast of light!");
+
+ /* Blind the player */
+ if (!p_ptr->resist_blind && !p_ptr->resist_lite)
+ {
+ /* Become blind */
+ set_blind(p_ptr->blind + 10 + randint(10));
+ }
+ }
+
+
+ /* Mega-Hack -- Forget the view */
+ p_ptr->update |= (PU_UN_VIEW);
+
+ /* Update stuff */
+ p_ptr->update |= (PU_VIEW | PU_FLOW | PU_MON_LITE);
+
+ /* Update the monsters */
+ p_ptr->update |= (PU_MONSTERS);
+
+ /* Redraw map */
+ p_ptr->redraw |= (PR_MAP);
+
+ /* Window stuff */
+ p_ptr->window |= (PW_OVERHEAD);
+}
+
+
+/*
+ * Induce an "earthquake" of the given radius at the given location.
+ *
+ * This will turn some walls into floors and some floors into walls.
+ *
+ * The player will take damage and "jump" into a safe grid if possible,
+ * otherwise, he will "tunnel" through the rubble instantaneously.
+ *
+ * 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.
+ *
+ * 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.
+ */
+void earthquake(int cy, int cx, int r)
+{
+ int i, t, y, x, yy, xx, dy, dx, oy, ox;
+ int damage = 0;
+ int sn = 0, sy = 0, sx = 0;
+ bool_ hurt = FALSE;
+ cave_type *c_ptr;
+ bool_ map[32][32];
+
+ if (p_ptr->inside_quest)
+ {
+ return;
+ }
+
+ /* Paranoia -- Enforce maximum range */
+ if (r > 12) r = 12;
+
+ /* Clear the "maximal blast" area */
+ for (y = 0; y < 32; y++)
+ {
+ for (x = 0; x < 32; x++)
+ {
+ map[y][x] = FALSE;
+ }
+ }
+
+ /* Check around the epicenter */
+ for (dy = -r; dy <= r; dy++)
+ {
+ for (dx = -r; dx <= r; dx++)
+ {
+ /* Extract the location */
+ yy = cy + dy;
+ xx = cx + dx;
+
+ /* Skip illegal grids */
+ if (!in_bounds(yy, xx)) continue;
+
+ /* Skip distant grids */
+ if (distance(cy, cx, yy, xx) > r) continue;
+
+ /* Access the grid */
+ c_ptr = &cave[yy][xx];
+
+ /* Lose room and vault */
+ c_ptr->info &= ~(CAVE_ROOM | CAVE_ICKY);
+
+ /* Lose light and knowledge */
+ c_ptr->info &= ~(CAVE_GLOW | CAVE_MARK);
+
+ /* Skip the epicenter */
+ if (!dx && !dy) continue;
+
+ /* Skip most grids */
+ if (rand_int(100) < 85) continue;
+
+ /* Damage this grid */
+ map[16 + yy - cy][16 + xx - cx] = TRUE;
+
+ /* Hack -- Take note of player damage */
+ if ((yy == p_ptr->py) && (xx == p_ptr->px)) hurt = TRUE;
+ }
+ }
+
+ /* First, affect the player (if necessary) */
+ if (hurt && !p_ptr->wraith_form)
+ {
+ /* Check around the player */
+ for (i = 0; i < 8; i++)
+ {
+ /* Access the location */
+ y = p_ptr->py + ddy[i];
+ x = p_ptr->px + ddx[i];
+
+ /* Skip non-empty grids */
+ if (!cave_empty_bold(y, x)) continue;
+
+ /* Important -- Skip "quake" grids */
+ if (map[16 + y - cy][16 + x - cx]) continue;
+
+ /* Count "safe" grids */
+ sn++;
+
+ /* Randomize choice */
+ if (rand_int(sn) > 0) continue;
+
+ /* Save the safe location */
+ sy = y;
+ sx = x;
+ }
+
+ /* Random message */
+ switch (randint(3))
+ {
+ case 1:
+ {
+ msg_print("The cave ceiling collapses!");
+ break;
+ }
+ case 2:
+ {
+ msg_print("The cave floor twists in an unnatural way!");
+ break;
+ }
+ default:
+ {
+ msg_print("The cave quakes! You are pummeled with debris!");
+ break;
+ }
+ }
+
+ /* Hurt the player a lot */
+ if (!sn)
+ {
+ /* Message and damage */
+ msg_print("You are severely crushed!");
+ damage = 300;
+ }
+
+ /* Destroy the grid, and push the player to safety */
+ else
+ {
+ /* Calculate results */
+ switch (randint(3))
+ {
+ case 1:
+ {
+ msg_print("You nimbly dodge the blast!");
+ damage = 0;
+ break;
+ }
+ case 2:
+ {
+ msg_print("You are bashed by rubble!");
+ damage = damroll(10, 4);
+ set_stun(p_ptr->stun + randint(50));
+ break;
+ }
+ case 3:
+ {
+ msg_print("You are crushed between the floor and ceiling!");
+ damage = damroll(10, 4);
+ set_stun(p_ptr->stun + randint(50));
+ break;
+ }
+ }
+
+ /* Save the old location */
+ oy = p_ptr->py;
+ ox = p_ptr->px;
+
+ /* Move the player to the safe location */
+ p_ptr->py = sy;
+ p_ptr->px = sx;
+
+ /* Redraw the old spot */
+ lite_spot(oy, ox);
+
+ /* Redraw the new spot */
+ lite_spot(p_ptr->py, p_ptr->px);
+
+ /* Check for new panel */
+ verify_panel();
+ }
+
+ /* Important -- no wall on player */
+ map[16 + p_ptr->py - cy][16 + p_ptr->px - cx] = FALSE;
+
+ /* Semi-wraiths have to be hurt *some*, says DG */
+ if (race_flags_p(PR_SEMI_WRAITH))
+ damage /= 4;
+
+ /* Take some damage */
+ if (damage) take_hit(damage, "an earthquake");
+ }
+
+
+ /* Examine the quaked region */
+ for (dy = -r; dy <= r; dy++)
+ {
+ for (dx = -r; dx <= r; dx++)
+ {
+ /* Extract the location */
+ yy = cy + dy;
+ xx = cx + dx;
+
+ /* Skip unaffected grids */
+ if (!map[16 + yy - cy][16 + xx - cx]) continue;
+
+ /* Access the grid */
+ c_ptr = &cave[yy][xx];
+
+ /* Process monsters */
+ if (c_ptr->m_idx)
+ {
+ monster_type *m_ptr = &m_list[c_ptr->m_idx];
+ auto const r_ptr = m_ptr->race();
+
+ /* Most monsters cannot co-exist with rock */
+ if (!(r_ptr->flags & RF_KILL_WALL) &&
+ !(r_ptr->flags & RF_PASS_WALL))
+ {
+ char m_name[80];
+
+ /* Assume not safe */
+ sn = 0;
+
+ /* Monster can move to escape the wall */
+ if (!(r_ptr->flags & RF_NEVER_MOVE))
+ {
+ /* Look for safety */
+ for (i = 0; i < 8; i++)
+ {
+ /* Access the grid */
+ y = yy + ddy[i];
+ x = xx + ddx[i];
+
+ /* Skip non-empty grids */
+ if (!cave_empty_bold(y, x)) continue;
+
+ /* Hack -- no safety on glyph of warding */
+ if (cave[y][x].feat == FEAT_GLYPH) continue;
+ if (cave[y][x].feat == FEAT_MINOR_GLYPH) continue;
+
+ /* ... nor on the Pattern */
+ if ((cave[y][x].feat <= FEAT_PATTERN_XTRA2) &&
+ (cave[y][x].feat >= FEAT_PATTERN_START))
+ continue;
+
+ /* Important -- Skip "quake" grids */
+ if (map[16 + y - cy][16 + x - cx]) continue;
+
+ /* Count "safe" grids */
+ sn++;
+
+ /* Randomize choice */
+ if (rand_int(sn) > 0) continue;
+
+ /* Save the safe grid */
+ sy = y;
+ sx = x;
+ }
+ }
+
+ /* Describe the monster */
+ monster_desc(m_name, m_ptr, 0);
+
+ /* Scream in pain */
+ msg_format("%^s wails out in pain!", m_name);
+
+ /* Take damage from the quake */
+ damage = (sn ? damroll(4, 8) : 200);
+
+ /* Monster is certainly awake */
+ m_ptr->csleep = 0;
+
+ /* Apply damage directly */
+ m_ptr->hp -= damage;
+
+ /* Delete (not kill) "dead" monsters */
+ if (m_ptr->hp < 0)
+ {
+ /* Message */
+ msg_format("%^s is embedded in the rock!", m_name);
+
+ /* Delete the monster */
+ delete_monster(yy, xx);
+
+ /* No longer safe */
+ sn = 0;
+ }
+
+ /* Hack -- Escape from the rock */
+ if (sn)
+ {
+ int m_idx = cave[yy][xx].m_idx;
+
+ /* Update the new location */
+ cave[sy][sx].m_idx = m_idx;
+
+ /* Update the old location */
+ cave[yy][xx].m_idx = 0;
+
+ /* Move the monster */
+ m_ptr->fy = sy;
+ m_ptr->fx = sx;
+
+ /* Update the monster (new location) */
+ update_mon(m_idx, TRUE);
+
+ /* Redraw the old grid */
+ lite_spot(yy, xx);
+
+ /* Redraw the new grid */
+ lite_spot(sy, sx);
+ }
+ }
+ }
+ }
+ }
+
+
+ /* Examine the quaked region */
+ for (dy = -r; dy <= r; dy++)
+ {
+ for (dx = -r; dx <= r; dx++)
+ {
+ /* Extract the location */
+ yy = cy + dy;
+ xx = cx + dx;
+
+ /* Skip unaffected grids */
+ if (!map[16 + yy - cy][16 + xx - cx]) continue;
+
+ /* Access the cave grid */
+ c_ptr = &cave[yy][xx];
+
+ /* Paranoia -- never affect player */
+ if ((yy == p_ptr->py) && (xx == p_ptr->px)) continue;
+
+ /* Destroy location (if valid) */
+ if (cave_valid_bold(yy, xx))
+ {
+ bool_ floor = cave_floor_bold(yy, xx);
+
+ /* Delete objects */
+ delete_object(yy, xx);
+
+ /* Wall (or floor) type */
+ t = (floor ? rand_int(100) : 200);
+
+ /* Granite */
+ if (t < 20)
+ {
+ /* Create granite wall */
+ cave_set_feat(yy, xx, FEAT_WALL_EXTRA);
+ }
+
+ /* Quartz */
+ else if (t < 70)
+ {
+ /* Create quartz vein */
+ cave_set_feat(yy, xx, FEAT_QUARTZ);
+ }
+
+ /* Magma */
+ else if (t < 100)
+ {
+ /* Create magma vein */
+ cave_set_feat(yy, xx, FEAT_MAGMA);
+ }
+
+ /* Floor */
+ else
+ {
+ /* Create floor */
+ cave_set_feat(yy, xx, FEAT_FLOOR);
+ }
+ }
+ }
+ }
+
+
+ /* Mega-Hack -- Forget the view */
+ p_ptr->update |= (PU_UN_VIEW);
+
+ /* Update stuff */
+ p_ptr->update |= (PU_VIEW | PU_FLOW | PU_MON_LITE);
+
+ /* Update the monsters */
+ p_ptr->update |= (PU_DISTANCE);
+
+ /* Update the health bar */
+ p_ptr->redraw |= (PR_FRAME);
+
+ /* Redraw map */
+ p_ptr->redraw |= (PR_MAP);
+
+ /* Window stuff */
+ p_ptr->window |= (PW_OVERHEAD);
+}
+
+
+
+/*
+ * This routine clears the entire "temp" set.
+ *
+ * This routine will Perma-Lite all "temp" grids.
+ *
+ * This routine is used (only) by "lite_room()"
+ *
+ * Dark grids are illuminated.
+ *
+ * Also, process all affected monsters.
+ *
+ * SMART monsters always wake up when illuminated
+ * NORMAL monsters wake up 1/4 the time when illuminated
+ * STUPID monsters wake up 1/10 the time when illuminated
+ */
+static void cave_temp_room_lite()
+{
+ int i;
+
+ /* Apply flag changes */
+ for (i = 0; i < temp_n; i++)
+ {
+ int y = temp_y[i];
+ int x = temp_x[i];
+
+ cave_type *c_ptr = &cave[y][x];
+
+ /* No longer in the array */
+ c_ptr->info &= ~(CAVE_TEMP);
+
+ /* Update only non-CAVE_GLOW grids */
+ /* if (c_ptr->info & (CAVE_GLOW)) continue; */
+
+ /* Perma-Lite */
+ c_ptr->info |= (CAVE_GLOW);
+ }
+
+ /* Fully update the visuals */
+ p_ptr->update |= (PU_UN_VIEW | PU_VIEW | PU_MONSTERS | PU_MON_LITE);
+
+ /* Update stuff */
+ update_stuff();
+
+ /* Process the grids */
+ for (i = 0; i < temp_n; i++)
+ {
+ int y = temp_y[i];
+ int x = temp_x[i];
+
+ cave_type *c_ptr = &cave[y][x];
+
+ /* Redraw the grid */
+ lite_spot(y, x);
+
+ /* Process affected monsters */
+ if (c_ptr->m_idx)
+ {
+ int chance = 25;
+
+ monster_type *m_ptr = &m_list[c_ptr->m_idx];
+ auto const r_ptr = m_ptr->race();
+
+ /* Update the monster */
+ update_mon(c_ptr->m_idx, FALSE);
+
+ /* Stupid monsters rarely wake up */
+ if (r_ptr->flags & RF_STUPID) chance = 10;
+
+ /* Smart monsters always wake up */
+ if (r_ptr->flags & RF_SMART) chance = 100;
+
+ /* Sometimes monsters wake up */
+ if (m_ptr->csleep && (rand_int(100) < chance))
+ {
+ /* Wake up! */
+ m_ptr->csleep = 0;
+
+ /* Notice the "waking up" */
+ if (m_ptr->ml)
+ {
+ char m_name[80];
+
+ /* Acquire the monster name */
+ monster_desc(m_name, m_ptr, 0);
+
+ /* Dump a message */
+ msg_format("%^s wakes up.", m_name);
+ }
+ }
+ }
+ }
+
+ /* None left */
+ temp_n = 0;
+}
+
+
+
+/*
+ * This routine clears the entire "temp" set.
+ *
+ * This routine will "darken" all "temp" grids.
+ *
+ * In addition, some of these grids will be "unmarked".
+ *
+ * This routine is used (only) by "unlite_room()"
+ *
+ * Also, process all affected monsters
+ */
+static void cave_temp_room_unlite()
+{
+ int i;
+
+ /* Apply flag changes */
+ for (i = 0; i < temp_n; i++)
+ {
+ int y = temp_y[i];
+ int x = temp_x[i];
+
+ cave_type *c_ptr = &cave[y][x];
+
+ /* 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))
+ {
+ /* Forget the grid */
+ c_ptr->info &= ~(CAVE_MARK);
+
+ /* Notice */
+ /* note_spot(y, x); */
+ }
+ }
+
+ /* Fully update the visuals */
+ p_ptr->update |= (PU_UN_VIEW | PU_VIEW | PU_MONSTERS | PU_MON_LITE);
+
+ /* Update stuff */
+ update_stuff();
+
+ /* Process the grids */
+ for (i = 0; i < temp_n; i++)
+ {
+ int y = temp_y[i];
+ int x = temp_x[i];
+
+ /* Redraw the grid */
+ lite_spot(y, x);
+ }
+
+ /* None left */
+ temp_n = 0;
+}
+
+
+
+
+/*
+ * Aux function -- see below
+ */
+static void cave_temp_room_aux(int y, int x)
+{
+ cave_type *c_ptr = &cave[y][x];
+
+ /* Avoid infinite recursion */
+ if (c_ptr->info & (CAVE_TEMP)) return;
+
+ /* Do not "leave" the current room */
+ if (!(c_ptr->info & (CAVE_ROOM))) return;
+
+ /* Paranoia -- verify space */
+ if (temp_n == TEMP_MAX) return;
+
+ /* Mark the grid as "seen" */
+ c_ptr->info |= (CAVE_TEMP);
+
+ /* Add it to the "seen" set */
+ temp_y[temp_n] = y;
+ temp_x[temp_n] = x;
+ temp_n++;
+}
+
+
+
+
+/*
+ * Illuminate any room containing the given location.
+ */
+void lite_room(int y1, int x1)
+{
+ int i, x, y;
+
+ /* Add the initial grid */
+ cave_temp_room_aux(y1, x1);
+
+ /* While grids are in the queue, add their neighbors */
+ for (i = 0; i < temp_n; i++)
+ {
+ x = temp_x[i], y = temp_y[i];
+
+ /* Walls get lit, but stop light */
+ if (!cave_floor_bold(y, x)) continue;
+
+ /* Spread adjacent */
+ cave_temp_room_aux(y + 1, x);
+ cave_temp_room_aux(y - 1, x);
+ cave_temp_room_aux(y, x + 1);
+ cave_temp_room_aux(y, x - 1);
+
+ /* Spread diagonal */
+ cave_temp_room_aux(y + 1, x + 1);
+ cave_temp_room_aux(y - 1, x - 1);
+ cave_temp_room_aux(y - 1, x + 1);
+ cave_temp_room_aux(y + 1, x - 1);
+ }
+
+ /* Now, lite them all up at once */
+ cave_temp_room_lite();
+}
+
+
+/*
+ * Darken all rooms containing the given location
+ */
+void unlite_room(int y1, int x1)
+{
+ int i, x, y;
+
+ /* Add the initial grid */
+ cave_temp_room_aux(y1, x1);
+
+ /* Spread, breadth first */
+ for (i = 0; i < temp_n; i++)
+ {
+ x = temp_x[i], y = temp_y[i];
+
+ /* Walls get dark, but stop darkness */
+ if (!cave_floor_bold(y, x)) continue;
+
+ /* Spread adjacent */
+ cave_temp_room_aux(y + 1, x);
+ cave_temp_room_aux(y - 1, x);
+ cave_temp_room_aux(y, x + 1);
+ cave_temp_room_aux(y, x - 1);
+
+ /* Spread diagonal */
+ cave_temp_room_aux(y + 1, x + 1);
+ cave_temp_room_aux(y - 1, x - 1);
+ cave_temp_room_aux(y - 1, x + 1);
+ cave_temp_room_aux(y + 1, x - 1);
+ }
+
+ /* Now, darken them all at once */
+ cave_temp_room_unlite();
+}
+
+
+
+/*
+ * Hack -- call light around the player
+ * Affect all monsters in the projection radius
+ */
+bool_ lite_area(int dam, int rad)
+{
+ int flg = PROJECT_GRID | PROJECT_KILL;
+
+ /* Hack -- Message */
+ if (!p_ptr->blind)
+ {
+ msg_print("You are surrounded by a white light.");
+ }
+
+ /* Hook into the "project()" function */
+ project(0, rad, p_ptr->py, p_ptr->px, dam, GF_LITE_WEAK, flg);
+
+ /* Lite up the room */
+ lite_room(p_ptr->py, p_ptr->px);
+
+ /* Assume seen */
+ return (TRUE);
+}
+
+
+/*
+ * Hack -- call darkness around the player
+ * Affect all monsters in the projection radius
+ */
+bool_ unlite_area(int dam, int rad)
+{
+ int flg = PROJECT_GRID | PROJECT_KILL;
+
+ /* Hack -- Message */
+ if (!p_ptr->blind)
+ {
+ msg_print("Darkness surrounds you.");
+ }
+
+ /* Hook into the "project()" function */
+ project(0, rad, p_ptr->py, p_ptr->px, dam, GF_DARK_WEAK, flg);
+
+ /* Lite up the room */
+ unlite_room(p_ptr->py, p_ptr->px);
+
+ /* Assume seen */
+ return (TRUE);
+}
+
+
+/*
+ * Cast a ball spell
+ * Stop if we hit a monster, act as a "ball"
+ * Allow "target" mode to pass over monsters
+ * Affect grids, objects, and monsters
+ */
+bool_ fire_ball(int typ, int dir, int dam, int rad)
+{
+ int tx, ty;
+
+ int flg = PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL;
+
+ /* Use the given direction */
+ tx = p_ptr->px + 99 * ddx[dir];
+ ty = p_ptr->py + 99 * ddy[dir];
+
+ /* Hack -- Use an actual "target" */
+ if ((dir == 5) && target_okay())
+ {
+ flg &= ~(PROJECT_STOP);
+ tx = target_col;
+ ty = target_row;
+ }
+
+ /* Analyze the "dir" and the "target". Hurt items on floor. */
+ return (project(0, (rad > 16) ? 16 : rad, ty, tx, dam, typ, flg));
+}
+
+/*
+ * Cast a cloud spell
+ * Stop if we hit a monster, act as a "ball"
+ * Allow "target" mode to pass over monsters
+ * Affect grids, objects, and monsters
+ */
+bool_ fire_cloud(int typ, int dir, int dam, int rad, int time)
+{
+ int tx, ty;
+
+ int flg = PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_STAY;
+
+ /* Use the given direction */
+ tx = p_ptr->px + 99 * ddx[dir];
+ ty = p_ptr->py + 99 * ddy[dir];
+
+ /* Hack -- Use an actual "target" */
+ if ((dir == 5) && target_okay())
+ {
+ flg &= ~(PROJECT_STOP);
+ tx = target_col;
+ ty = target_row;
+ }
+ project_time = time;
+
+ /* Analyze the "dir" and the "target". Hurt items on floor. */
+ return (project(0, (rad > 16) ? 16 : rad, ty, tx, dam, typ, flg));
+}
+
+/*
+ * Cast a wave spell
+ * Stop if we hit a monster, act as a "ball"
+ * Allow "target" mode to pass over monsters
+ * Affect grids, objects, and monsters
+ */
+bool_ fire_wave(int typ, int dir, int dam, int rad, int time, s32b eff)
+{
+ project_time_effect = eff;
+ return (fire_cloud(typ, dir, dam, rad, time));
+}
+
+/*
+ * Cast a persistant beam spell
+ * Pass through monsters, as a "beam"
+ * Affect monsters (not grids or objects)
+ */
+bool_ fire_wall(int typ, int dir, int dam, int time)
+{
+ int flg = PROJECT_BEAM | PROJECT_KILL | PROJECT_STAY | PROJECT_GRID;
+ project_time = time;
+ return (project_hook(typ, dir, dam, flg));
+}
+
+
+
+void teleport_swap(int dir)
+{
+ if (p_ptr->resist_continuum)
+ {
+ msg_print("The space-time continuum can't be disrupted.");
+ return;
+ }
+
+ int tx, ty;
+ if ((dir == 5) && target_okay())
+ {
+ tx = target_col;
+ ty = target_row;
+ }
+ else
+ {
+ tx = p_ptr->px + ddx[dir];
+ ty = p_ptr->py + ddy[dir];
+ }
+
+ cave_type *c_ptr = &cave[ty][tx];
+
+ if (!c_ptr->m_idx)
+ {
+ msg_print("You can't trade places with that!");
+ }
+ else
+ {
+ monster_type *m_ptr = &m_list[c_ptr->m_idx];
+ auto const r_ptr = m_ptr->race();
+
+ if (r_ptr->flags & RF_RES_TELE)
+ {
+ msg_print("Your teleportation is blocked!");
+ }
+ else
+ {
+ cave[p_ptr->py][p_ptr->px].m_idx = c_ptr->m_idx;
+
+ /* Update the old location */
+ c_ptr->m_idx = 0;
+
+ /* Move the monster */
+ m_ptr->fy = p_ptr->py;
+ m_ptr->fx = p_ptr->px;
+
+ /* Move the player */
+ p_ptr->px = tx;
+ p_ptr->py = ty;
+
+ tx = m_ptr->fx;
+ ty = m_ptr->fy;
+
+ /* Update the monster (new location) */
+ update_mon(cave[ty][tx].m_idx, TRUE);
+
+ /* Redraw the old grid */
+ lite_spot(ty, tx);
+
+ /* Redraw the new grid */
+ lite_spot(p_ptr->py, p_ptr->px);
+
+ /* Execute the inscription */
+ c_ptr = &cave[m_ptr->fy][m_ptr->fx];
+ if (c_ptr->inscription)
+ {
+ if (inscription_info[c_ptr->inscription].when & INSCRIP_EXEC_MONST_WALK)
+ {
+ execute_inscription(c_ptr->inscription, m_ptr->fy, m_ptr->fx);
+ }
+ }
+ c_ptr = &cave[p_ptr->py][p_ptr->px];
+ if (c_ptr->inscription)
+ {
+ 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);
+ }
+ }
+
+ /* Check for new panel (redraw map) */
+ verify_panel();
+
+ /* Update stuff */
+ p_ptr->update |= (PU_VIEW | PU_FLOW | PU_MON_LITE);
+
+ /* Update the monsters */
+ p_ptr->update |= (PU_DISTANCE);
+
+ /* Window stuff */
+ p_ptr->window |= (PW_OVERHEAD);
+
+ /* Handle stuff XXX XXX XXX */
+ handle_stuff();
+ }
+ }
+}
+
+void swap_position(int lty, int ltx)
+{
+ int tx = ltx, ty = lty;
+ cave_type * c_ptr;
+ monster_type * m_ptr;
+
+ if (p_ptr->resist_continuum)
+ {
+ msg_print("The space-time continuum can't be disrupted.");
+ return;
+ }
+
+ c_ptr = &cave[ty][tx];
+
+ if (!c_ptr->m_idx)
+ {
+ /* Keep trace of the old location */
+ tx = p_ptr->px;
+ ty = p_ptr->py;
+
+ /* Move the player */
+ p_ptr->px = ltx;
+ p_ptr->py = lty;
+
+ /* Redraw the old grid */
+ lite_spot(ty, tx);
+
+ /* Redraw the new grid */
+ lite_spot(p_ptr->py, p_ptr->px);
+
+ /* Check for new panel (redraw map) */
+ verify_panel();
+
+ /* Update stuff */
+ p_ptr->update |= (PU_VIEW | PU_FLOW | PU_MON_LITE);
+
+ /* Update the monsters */
+ p_ptr->update |= (PU_DISTANCE);
+
+ /* Window stuff */
+ p_ptr->window |= (PW_OVERHEAD);
+
+ /* Handle stuff XXX XXX XXX */
+ handle_stuff();
+ }
+ else
+ {
+ m_ptr = &m_list[c_ptr->m_idx];
+
+ cave[p_ptr->py][p_ptr->px].m_idx = c_ptr->m_idx;
+
+ /* Update the old location */
+ c_ptr->m_idx = 0;
+
+ /* Move the monster */
+ m_ptr->fy = p_ptr->py;
+ m_ptr->fx = p_ptr->px;
+
+ /* Move the player */
+ p_ptr->px = tx;
+ p_ptr->py = ty;
+
+ tx = m_ptr->fx;
+ ty = m_ptr->fy;
+
+ /* Update the monster (new location) */
+ update_mon(cave[ty][tx].m_idx, TRUE);
+
+ /* Redraw the old grid */
+ lite_spot(ty, tx);
+
+ /* Redraw the new grid */
+ lite_spot(p_ptr->py, p_ptr->px);
+
+ /* Check for new panel (redraw map) */
+ verify_panel();
+
+ /* Update stuff */
+ p_ptr->update |= (PU_VIEW | PU_FLOW | PU_MON_LITE);
+
+ /* Update the monsters */
+ p_ptr->update |= (PU_DISTANCE);
+
+ /* Window stuff */
+ p_ptr->window |= (PW_OVERHEAD);
+
+ /* Handle stuff XXX XXX XXX */
+ handle_stuff();
+ }
+}
+
+
+/*
+ * Hack -- apply a "projection()" in a direction (or at the target)
+ */
+bool_ project_hook(int typ, int dir, int dam, int flg)
+{
+ int tx, ty;
+
+ /* Pass through the target if needed */
+ flg |= (PROJECT_THRU);
+
+ /* 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;
+ }
+
+ /* Analyze the "dir" and the "target", do NOT explode */
+ return (project(0, 0, ty, tx, dam, typ, flg));
+}
+
+
+/*
+ * Cast a bolt spell
+ * Stop if we hit a monster, as a "bolt"
+ * Affect monsters (not grids or objects)
+ */
+bool_ fire_bolt(int typ, int dir, int dam)
+{
+ int flg = PROJECT_STOP | PROJECT_KILL;
+ return (project_hook(typ, dir, dam, flg));
+}
+
+
+/*
+ * Cast a beam spell
+ * Pass through monsters, as a "beam"
+ * Affect monsters (not grids or objects)
+ */
+bool_ fire_beam(int typ, int dir, int dam)
+{
+ int flg = PROJECT_BEAM | PROJECT_KILL;
+ return (project_hook(typ, dir, dam, flg));
+}
+
+
+/*
+ * Cast a bolt spell, or rarely, a beam spell
+ */
+bool_ fire_bolt_or_beam(int prob, int typ, int dir, int dam)
+{
+ if (rand_int(100) < prob)
+ {
+ return (fire_beam(typ, dir, dam));
+ }
+ else
+ {
+ return (fire_bolt(typ, dir, dam));
+ }
+}
+
+
+/*
+ * Some of the old functions
+ */
+bool_ lite_line(int dir)
+{
+ int flg = PROJECT_BEAM | PROJECT_GRID | PROJECT_KILL;
+ return (project_hook(GF_LITE_WEAK, dir, damroll(6, 8), flg));
+}
+
+
+bool_ drain_life(int dir, int dam)
+{
+ int flg = PROJECT_STOP | PROJECT_KILL;
+ return (project_hook(GF_OLD_DRAIN, dir, dam, flg));
+}
+
+
+bool_ wall_to_mud(int dir)
+{
+ int flg = PROJECT_BEAM | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL;
+ return (project_hook(GF_KILL_WALL, dir, 20 + randint(30), flg));
+}
+
+
+bool_ wizard_lock(int dir)
+{
+ int flg = PROJECT_BEAM | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL;
+ return (project_hook(GF_JAM_DOOR, dir, 20 + randint(30), flg));
+}
+
+bool_ slow_monster(int dir)
+{
+ int flg = PROJECT_STOP | PROJECT_KILL;
+ return (project_hook(GF_OLD_SLOW, dir, p_ptr->lev, flg));
+}
+
+
+bool_ sleep_monster(int dir)
+{
+ int flg = PROJECT_STOP | PROJECT_KILL;
+ return (project_hook(GF_OLD_SLEEP, dir, p_ptr->lev, flg));
+}
+
+
+bool_ confuse_monster(int dir, int plev)
+{
+ int flg = PROJECT_STOP | PROJECT_KILL;
+ return (project_hook(GF_OLD_CONF, dir, plev, flg));
+}
+
+
+bool_ poly_monster(int dir)
+{
+ int flg = PROJECT_STOP | PROJECT_KILL;
+ return (project_hook(GF_OLD_POLY, dir, p_ptr->lev, flg));
+}
+
+
+bool_ fear_monster(int dir, int plev)
+{
+ int flg = PROJECT_STOP | PROJECT_KILL;
+ return (project_hook(GF_TURN_ALL, dir, plev, flg));
+}
+
+
+bool_ teleport_monster(int dir)
+{
+ int flg = PROJECT_BEAM | PROJECT_KILL;
+
+ if (p_ptr->resist_continuum)
+ {
+ msg_print("The space-time continuum can't be disrupted.");
+ return FALSE;
+ }
+
+ return (project_hook(GF_AWAY_ALL, dir, MAX_SIGHT * 5, flg));
+}
+
+bool_ wall_stone(int y, int x)
+{
+ auto const &f_info = game->edit_data.f_info;
+
+ cave_type *c_ptr = &cave[y][x];
+ int flg = PROJECT_GRID | PROJECT_ITEM;
+ auto const featflags = f_info[c_ptr->feat].flags;
+
+ bool_ dummy = (project(0, 1, y, x, 0, GF_STONE_WALL, flg));
+
+ if (!(featflags & FF_PERMANENT) && !(featflags & FF_WALL))
+ cave_set_feat(y, x, FEAT_FLOOR);
+
+ /* Update stuff */
+ p_ptr->update |= (PU_VIEW | PU_FLOW | PU_MON_LITE);
+
+ /* Update the monsters */
+ p_ptr->update |= (PU_MONSTERS);
+
+ /* Redraw map */
+ p_ptr->redraw |= (PR_MAP);
+
+ /* Window stuff */
+ p_ptr->window |= (PW_OVERHEAD);
+
+ return dummy;
+}
+
+
+bool_ destroy_doors_touch()
+{
+ int flg = PROJECT_GRID | PROJECT_ITEM | PROJECT_HIDE;
+ return (project(0, 1, p_ptr->py, p_ptr->px, 0, GF_KILL_DOOR, flg));
+}
+
+bool_ sleep_monsters_touch()
+{
+ int flg = PROJECT_KILL | PROJECT_HIDE;
+ return (project(0, 1, p_ptr->py, p_ptr->px, p_ptr->lev, GF_OLD_SLEEP, flg));
+}
+
+
+void call_chaos()
+{
+ int Chaos_type, dummy, dir;
+ int plev = p_ptr->lev;
+ bool_ line_chaos = FALSE;
+
+ int hurt_types[30] =
+ {
+ GF_ELEC, GF_POIS, GF_ACID, GF_COLD,
+ GF_FIRE, GF_MISSILE, GF_ARROW, GF_PLASMA,
+ GF_HOLY_FIRE, GF_WATER, GF_LITE, GF_DARK,
+ GF_FORCE, GF_INERTIA, GF_MANA, GF_METEOR,
+ GF_ICE, GF_CHAOS, GF_NETHER, GF_DISENCHANT,
+ GF_SHARDS, GF_SOUND, GF_NEXUS, GF_CONFUSION,
+ GF_TIME, GF_GRAVITY, GF_ROCKET, GF_NUKE,
+ GF_HELL_FIRE, GF_DISINTEGRATE
+ };
+
+ Chaos_type = hurt_types[randint(30) - 1];
+ if (randint(4) == 1) line_chaos = TRUE;
+
+ if (randint(6) == 1)
+ {
+ for (dummy = 1; dummy < 10; dummy++)
+ {
+ if (dummy - 5)
+ {
+ if (line_chaos)
+ fire_beam(Chaos_type, dummy, 75);
+ else
+ fire_ball(Chaos_type, dummy, 75, 2);
+ }
+ }
+ }
+ else if (randint(3) == 1)
+ {
+ fire_ball(Chaos_type, 0, 300, 8);
+ }
+ else
+ {
+ if (!get_aim_dir(&dir)) return;
+ if (line_chaos)
+ fire_beam(Chaos_type, dir, 150);
+ else
+ fire_ball(Chaos_type, dir, 150, 3 + (plev / 35));
+ }
+}
+
+
+static void activate_hi_summon()
+{
+ int i;
+
+ for (i = 0; i < (randint(9) + (dun_level / 40)); i++)
+ {
+ switch (randint(26) + (dun_level / 20) )
+ {
+ case 1:
+ case 2:
+ summon_specific(p_ptr->py, p_ptr->px, dun_level, SUMMON_ANT);
+ break;
+ case 3:
+ case 4:
+ summon_specific(p_ptr->py, p_ptr->px, dun_level, SUMMON_SPIDER);
+ break;
+ case 5:
+ case 6:
+ summon_specific(p_ptr->py, p_ptr->px, dun_level, SUMMON_HOUND);
+ break;
+ case 7:
+ case 8:
+ summon_specific(p_ptr->py, p_ptr->px, dun_level, SUMMON_HYDRA);
+ break;
+ case 9:
+ case 10:
+ summon_specific(p_ptr->py, p_ptr->px, dun_level, SUMMON_ANGEL);
+ break;
+ case 11:
+ case 12:
+ summon_specific(p_ptr->py, p_ptr->px, dun_level, SUMMON_UNDEAD);
+ break;
+ case 13:
+ case 14:
+ summon_specific(p_ptr->py, p_ptr->px, dun_level, SUMMON_DRAGON);
+ break;
+ case 15:
+ case 16:
+ summon_specific(p_ptr->py, p_ptr->px, dun_level, SUMMON_DEMON);
+ break;
+ case 17:
+ summon_specific(p_ptr->py, p_ptr->px, dun_level, SUMMON_WRAITH);
+ break;
+ case 18:
+ case 19:
+ summon_specific(p_ptr->py, p_ptr->px, dun_level, SUMMON_UNIQUE);
+ break;
+ case 20:
+ case 21:
+ summon_specific(p_ptr->py, p_ptr->px, dun_level, SUMMON_HI_UNDEAD);
+ break;
+ case 22:
+ case 23:
+ summon_specific(p_ptr->py, p_ptr->px, dun_level, SUMMON_HI_DRAGON);
+ break;
+ case 24:
+ case 25:
+ summon_specific(p_ptr->py, p_ptr->px, 100, SUMMON_HI_DEMON);
+ break;
+ default:
+ summon_specific(p_ptr->py, p_ptr->px, (((dun_level * 3) / 2) + 5), 0);
+ }
+ }
+}
+
+
+/*
+ * Activate the evil Topi Ylinen curse
+ * rr9: Stop the nasty things when a Cyberdemon is summoned
+ * or the player gets paralyzed.
+ */
+void activate_ty_curse()
+{
+ int i = 0;
+ bool_ stop_ty = FALSE;
+
+ do
+ {
+ switch (randint(27))
+ {
+ case 1:
+ case 2:
+ case 3:
+ case 16:
+ case 17:
+ aggravate_monsters(1);
+ if (randint(6) != 1) break;
+ case 4:
+ case 5:
+ case 6:
+ activate_hi_summon();
+ if (randint(6) != 1) break;
+case 7: case 8: case 9: case 18:
+ summon_specific(p_ptr->py, p_ptr->px, dun_level, 0);
+ if (randint(6) != 1) break;
+case 10: case 11: case 12:
+ msg_print("You feel your life draining away...");
+ lose_exp(p_ptr->exp / 16);
+ if (randint(6) != 1) break;
+case 13: case 14: case 15: case 19: case 20:
+ if (p_ptr->free_act && (randint(100) < p_ptr->skill_sav))
+ {
+ /* Do nothing */ ;
+ }
+ else
+ {
+ msg_print("You feel like a statue!");
+ if (p_ptr->free_act)
+ set_paralyzed(randint(3));
+ else
+ set_paralyzed(randint(13));
+ stop_ty = TRUE;
+ }
+ if (randint(6) != 1) break;
+case 21: case 22: case 23:
+ do_dec_stat((randint(6)) - 1, STAT_DEC_NORMAL);
+ if (randint(6) != 1) break;
+ case 24:
+ msg_print("Huh? Who am I? What am I doing here?");
+ lose_all_info();
+ break;
+ case 25:
+ /*
+ * Only summon Cyberdemons deep in the dungeon.
+ */
+ if ((dun_level > 65) && !stop_ty)
+ {
+ summon_cyber();
+ stop_ty = TRUE;
+ break;
+ }
+ default:
+ while (i < 6)
+ {
+ do
+ {
+ do_dec_stat(i, STAT_DEC_NORMAL);
+ }
+ while (randint(2) == 1);
+
+ i++;
+ }
+ }
+ }
+ while ((randint(3) == 1) && !stop_ty);
+}
+
+/*
+ * Activate the ultra evil Dark God curse
+ */
+void activate_dg_curse()
+{
+ int i = 0;
+ bool_ stop_dg = FALSE;
+
+ do
+ {
+ switch (randint(30))
+ {
+ case 1:
+ case 2:
+ case 3:
+ case 16:
+ case 17:
+ aggravate_monsters(1);
+ if (randint(8) != 1) break;
+ case 4:
+ case 5:
+ case 6:
+ msg_print("Oh! You feel that the curse is replicating itself!");
+ curse_equipment_dg(100, 50 * randint(2));
+ if (randint(8) != 1) break;
+ case 7:
+ case 8:
+ case 9:
+ case 18:
+ curse_equipment(100, 50 * randint(2));
+ if (randint(8) != 1) break;
+ case 10:
+ case 11:
+ case 12:
+ msg_print("You feel your life draining away...");
+ lose_exp(p_ptr->exp / 12);
+ if (rand_int(2))
+ {
+ msg_print("You feel the coldness of the Black Breath attacking you!");
+ p_ptr->black_breath = TRUE;
+ }
+ if (randint(8) != 1) break;
+ case 13:
+ case 14:
+ case 15:
+ if (p_ptr->free_act && (randint(100) < p_ptr->skill_sav))
+ {
+ /* Do nothing */ ;
+ }
+ else
+ {
+ msg_print("You feel like a statue!");
+ if (p_ptr->free_act)
+ set_paralyzed(randint(3));
+ else
+ set_paralyzed(randint(13));
+ stop_dg = TRUE;
+ }
+ if (randint(7) != 1) break;
+ case 19:
+ case 20:
+ {
+ msg_print("Woah! You see 10 little Morgoths dancing before you!");
+ set_confused(p_ptr->confused + randint(13 * 2));
+ if (rand_int(2)) stop_dg = TRUE;
+ }
+ if (randint(7) != 1) break;
+ case 21:
+ case 22:
+ case 23:
+ do_dec_stat((randint(6)) - 1, STAT_DEC_PERMANENT);
+ if (randint(7) != 1) break;
+ case 24:
+ msg_print("Huh? Who am I? What am I doing here?");
+ lose_all_info();
+ break;
+case 27: case 28: case 29:
+ if (p_ptr->inventory[INVEN_WIELD].k_idx)
+ {
+ msg_print("Your weapon now seems useless...");
+ p_ptr->inventory[INVEN_WIELD].art_flags = TR_NEVER_BLOW;
+ }
+ break;
+ case 25:
+ /*
+ * Only summon Thunderlords not too shallow in the dungeon.
+ */
+ if ((dun_level > 25) && !stop_dg)
+ {
+ msg_print("Oh! You attracted some evil Thunderlords!");
+ summon_dragon_riders();
+
+ /* This is evil -- DG */
+ if (rand_int(2)) stop_dg = TRUE;
+ break;
+ }
+ default:
+ while (i < 6)
+ {
+ do
+ {
+ do_dec_stat(i, STAT_DEC_NORMAL);
+ }
+ while (randint(2) == 1);
+
+ i++;
+ }
+ }
+ }
+ while ((randint(4) == 1) && !stop_dg);
+}
+
+
+void summon_cyber()
+{
+ int i;
+ int max_cyber = (dun_level / 50) + randint(6);
+
+ for (i = 0; i < max_cyber; i++)
+ {
+ summon_specific(p_ptr->py, p_ptr->px, 100, SUMMON_HI_DEMON);
+ }
+}
+
+static void summon_dragon_riders()
+{
+ int i;
+ int max_dr = (dun_level / 50) + randint(6);
+
+ for (i = 0; i < max_dr; i++)
+ {
+ summon_specific(p_ptr->py, p_ptr->px, 100, SUMMON_THUNDERLORD);
+ }
+}
+
+
+
+/*
+ * Confuse monsters
+ */
+bool_ confuse_monsters(int dam)
+{
+ return (project_hack(GF_OLD_CONF, dam));
+}
+
+
+/*
+ * Charm monsters
+ */
+bool_ charm_monsters(int dam)
+{
+ return (project_hack(GF_CHARM, dam));
+}
+
+
+/*
+ * Charm animals
+ */
+bool_ charm_animals(int dam)
+{
+ return (project_hack(GF_CONTROL_ANIMAL, dam));
+}
+
+
+/*
+ * Stun monsters
+ */
+bool_ stun_monsters(int dam)
+{
+ return (project_hack(GF_STUN, dam));
+}
+
+
+/*
+ * Mindblast monsters
+ */
+bool_ mindblast_monsters(int dam)
+{
+ return (project_hack(GF_PSI, dam));
+}
+
+
+/*
+ * Banish all monsters
+ */
+bool_ banish_monsters(int dist)
+{
+ return (project_hack(GF_AWAY_ALL, dist));
+}
+
+
+/*
+ * Turn everyone
+ */
+bool_ turn_monsters(int dam)
+{
+ return (project_hack(GF_TURN_ALL, dam));
+}
+
+
+bool_ charm_monster(int dir, int plev)
+{
+ int flg = PROJECT_STOP | PROJECT_KILL;
+ return (project_hook(GF_CHARM, dir, plev, flg));
+}
+
+bool_ control_one_undead(int dir, int plev)
+{
+ int flg = PROJECT_STOP | PROJECT_KILL;
+ return (project_hook(GF_CONTROL_UNDEAD, dir, plev, flg));
+}
+
+
+bool_ charm_animal(int dir, int plev)
+{
+ int flg = PROJECT_STOP | PROJECT_KILL;
+ return (project_hook(GF_CONTROL_ANIMAL, dir, plev, flg));
+}
+
+void change_wild_mode()
+{
+ if (p_ptr->immovable && !p_ptr->wild_mode)
+ {
+ msg_print("Hmm, blinking there will take time.");
+ }
+
+ if (p_ptr->word_recall && !p_ptr->wild_mode)
+ {
+ msg_print("You will soon be recalled.");
+ return;
+ }
+
+ p_ptr->wild_mode = !p_ptr->wild_mode;
+
+ autosave_checkpoint();
+
+ /* Leaving */
+ p_ptr->leaving = TRUE;
+}
+
+
+void alter_reality()
+{
+ msg_print("The world changes!");
+
+ autosave_checkpoint();
+
+ /* Leaving */
+ p_ptr->leaving = TRUE;
+}
+
+/* Heal insanity. */
+bool_ heal_insanity(int val)
+{
+ if (p_ptr->csane < p_ptr->msane)
+ {
+ p_ptr->csane += val;
+
+ if (p_ptr->csane >= p_ptr->msane)
+ {
+ p_ptr->csane = p_ptr->msane;
+ p_ptr->csane_frac = 0;
+ }
+
+ p_ptr->redraw |= (PR_FRAME);
+ p_ptr->window |= (PW_PLAYER);
+
+ if (val < 5)
+ {
+ msg_print("You feel a little better.");
+ }
+ else if (val < 15)
+ {
+ msg_print("You feel better.");
+ }
+ else if (val < 35)
+ {
+ msg_print("You feel much better.");
+ }
+ else
+ {
+ msg_print("You feel very good.");
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/*
+ * Send the player shooting through walls in the given direction until
+ * they reach a non-wall space, or a monster, or a permanent wall.
+ */
+bool_ passwall(int dir, bool_ safe)
+{
+ auto const &f_info = game->edit_data.f_info;
+
+ int x = p_ptr->px;
+ int y = p_ptr->py;
+ int ox = p_ptr->px;
+ int oy = p_ptr->py;
+ int lx = p_ptr->px;
+ int ly = p_ptr->py;
+ cave_type *c_ptr;
+ bool_ ok = FALSE;
+
+ if (p_ptr->wild_mode) return FALSE;
+ if (p_ptr->inside_quest) return FALSE;
+ if (dungeon_flags & DF_NO_TELEPORT) return FALSE;
+
+ /* Must go somewhere */
+ if (dir == 5) return FALSE;
+
+ while (TRUE)
+ {
+ x += ddx[dir];
+ y += ddy[dir];
+ c_ptr = &cave[y][x];
+
+ /* Perm walls stops the transfer */
+ if ((!in_bounds(y, x)) && (f_info[c_ptr->feat].flags & FF_PERMANENT))
+ {
+ /* get the last working position */
+ x -= ddx[dir];
+ y -= ddy[dir];
+ ok = FALSE;
+ break;
+ }
+
+ /* Never on a monster */
+ if (c_ptr->m_idx) continue;
+
+ /* Never stop in vaults */
+ if (c_ptr->info & CAVE_ICKY) continue;
+
+ /* From now on, the location COULD be used in special case */
+ lx = x;
+ ly = y;
+
+ /* Pass over walls */
+ if (f_info[c_ptr->feat].flags & FF_WALL) continue;
+
+ /* So it must be ok */
+ ok = TRUE;
+ break;
+ }
+
+ if (!ok)
+ {
+ x = lx;
+ y = ly;
+
+ if (!safe)
+ {
+ msg_print("You emerge in the wall!");
+ take_hit(damroll(10, 8), "becoming one with a wall");
+ }
+ place_floor_convert_glass(y, x);
+ }
+
+ /* Move */
+ p_ptr->px = x;
+ p_ptr->py = y;
+
+ /* Redraw the old spot */
+ lite_spot(oy, ox);
+
+ /* Redraw the new spot */
+ lite_spot(p_ptr->py, p_ptr->px);
+
+ /* Check for new panel (redraw map) */
+ verify_panel();
+
+ /* Update stuff */
+ p_ptr->update |= (PU_VIEW | PU_FLOW | PU_MON_LITE);
+
+ /* Update the monsters */
+ p_ptr->update |= (PU_DISTANCE);
+
+ /* Window stuff */
+ p_ptr->window |= (PW_OVERHEAD);
+
+ /* Handle stuff XXX XXX XXX */
+ handle_stuff();
+
+ return (TRUE);
+}
+
+/*
+ * Print a batch of dungeons.
+ */
+static void print_dungeon_batch(std::vector<int> const &dungeon_idxs,
+ int start,
+ bool_ mode)
+{
+ auto const &d_info = game->edit_data.d_info;
+
+ int i, j;
+ byte attr;
+
+ if (mode) prt(format(" %-31s", "Name"), 1, 20);
+
+ for (i = 0, j = start; i < 20 && j < static_cast<int>(dungeon_idxs.size()); i++, j++)
+ {
+ auto d_ptr = &d_info[dungeon_idxs[j]];
+
+ char buf[80];
+ strnfmt(buf, 80, " %c) %-30s", I2A(i), d_ptr->name.c_str());
+
+ if (mode)
+ {
+ if (d_ptr->min_plev > p_ptr->lev)
+ {
+ attr = TERM_L_DARK;
+ }
+ else
+ {
+ attr = TERM_WHITE;
+ }
+ c_prt(attr, buf, 2 + i, 20);
+ }
+ }
+ if (mode) prt("", 2 + i, 20);
+
+ prt(format("Select a dungeon (a-%c), * to list, @ to select by name, +/- to scroll:", I2A(i - 1)), 0, 0);
+}
+
+static int find_dungeon_by_name(char const *name)
+{
+ auto const &d_info = game->edit_data.d_info;
+
+ /* Find the index corresponding to the name */
+ for (std::size_t i = 1; i < d_info.size(); i++)
+ {
+ if (iequals(name, d_info[i].name))
+ {
+ return i;
+ }
+ }
+ /* Not found */
+ return -1;
+}
+
+static int reset_recall_aux()
+{
+ auto const &d_info = game->edit_data.d_info;
+
+ char which;
+ int start = 0;
+ int ret;
+ bool_ mode = FALSE;
+
+ // Dungeons available for recall
+ std::vector<int> dungeons;
+ for (size_t i = 1; i < d_info.size(); i++)
+ {
+ /* skip "blocked" dungeons */
+ if (d_info[i].flags & DF_NO_RECALL) continue;
+
+ if (max_dlv[i])
+ {
+ dungeons.push_back(i);
+ }
+ }
+
+ character_icky = TRUE;
+ Term_save();
+
+ while (1)
+ {
+ print_dungeon_batch(dungeons, start, mode);
+ which = inkey();
+
+ if (which == ESCAPE)
+ {
+ ret = -1;
+ break;
+ }
+
+ else if (which == '*' || which == '?' || which == ' ')
+ {
+ mode = (mode) ? FALSE : TRUE;
+ Term_load();
+ character_icky = FALSE;
+ }
+
+ else if (which == '+')
+ {
+ start += 20;
+ assert(start > 0);
+ if (static_cast<size_t>(start) >= dungeons.size())
+ {
+ start -= 20;
+ }
+ Term_load();
+ character_icky = FALSE;
+ }
+
+ else if (which == '-')
+ {
+ start -= 20;
+ if (start < 0)
+ {
+ start += 20;
+ }
+ Term_load();
+ character_icky = FALSE;
+ }
+
+ else if (which == '@')
+ {
+ char buf[80];
+ strcpy(buf, d_info[p_ptr->recall_dungeon].name.c_str());
+
+ if (!get_string("Which dungeon? ", buf, 79)) continue;
+
+ /* Find the index corresponding to the name */
+ int i = find_dungeon_by_name(buf);
+
+ if (i < 0)
+ {
+ msg_print("Never heard of that place!");
+ msg_print(NULL);
+ continue;
+ }
+ else if (d_info[i].flags & DF_NO_RECALL)
+ {
+ msg_print("This place blocks my magic!");
+ msg_print(NULL);
+ continue;
+ }
+ else if (d_info[i].min_plev > p_ptr->lev)
+ {
+ msg_print("You cannot go there yet!");
+ msg_print(NULL);
+ continue;
+ }
+ ret = i;
+ break;
+ }
+
+ else
+ {
+ which = tolower(which);
+ int i = start + A2I(which);
+
+ if (i < 0)
+ {
+ bell();
+ continue;
+ }
+ else if (static_cast<size_t>(i) >= dungeons.size()) // Cast to avoid compilation warning
+ {
+ bell();
+ continue;
+ }
+ else
+ {
+ ret = dungeons[i];
+ break;
+ }
+ }
+ }
+
+ Term_load();
+ character_icky = FALSE;
+
+ return ret;
+}
+
+bool_ reset_recall(bool_ no_trepas_max_depth)
+{
+ auto const &d_info = game->edit_data.d_info;
+
+ int dun, depth, max;
+
+ /* Choose dungeon */
+ dun = reset_recall_aux();
+
+ if (dun < 1) return FALSE;
+
+ /* Choose depth */
+ if (!no_trepas_max_depth)
+ max = d_info[dun].maxdepth;
+ else
+ max = max_dlv[dun];
+
+ depth = get_quantity(format("Which level in %s(%d-%d)? ",
+ d_info[dun].name.c_str(),
+ d_info[dun].mindepth, max),
+ max);
+
+ if (depth < 1) return FALSE;
+
+ /* Enforce minimum level */
+ if (depth < d_info[dun].mindepth) depth = d_info[dun].mindepth;
+
+ /* Mega hack -- Forbid levels 99 and 100 */
+ if ((depth == 99) || (depth == 100)) depth = 98;
+
+ p_ptr->recall_dungeon = dun;
+ max_dlv[p_ptr->recall_dungeon] = depth;
+
+ return TRUE;
+}
+
+/*
+ * Creates a between gate
+ */
+void create_between_gate(int dist, int y, int x)
+{
+ auto const &f_info = game->edit_data.f_info;
+
+ int ii, ij, plev = get_skill(SKILL_CONVEYANCE);
+
+ if (dungeon_flags & DF_NO_TELEPORT)
+ {
+ msg_print("Not on special levels!");
+ return;
+ }
+
+ if ((!x) || (!y))
+ {
+ 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) > dist) ||
+ (rand_int(plev * plev / 2) == 0))
+ {
+ msg_print("You fail to exit the void correctly!");
+ p_ptr->energy -= 100;
+ get_pos_player(10, &ij, &ii);
+ }
+ }
+ else
+ {
+ ij = y;
+ ii = x;
+ }
+ if (!(f_info[cave[p_ptr->py][p_ptr->px].feat].flags & FF_PERMANENT))
+ {
+ cave_set_feat(p_ptr->py, p_ptr->px, FEAT_BETWEEN);
+ cave[p_ptr->py][p_ptr->px].special = ii + (ij << 8);
+ }
+ if (!(f_info[cave[ij][ii].feat].flags & FF_PERMANENT))
+ {
+ cave_set_feat(ij, ii, FEAT_BETWEEN);
+ 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)
+{
+ auto const &f_info = game->edit_data.f_info;
+
+#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].flags & FF_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)
+{
+ auto const &f_info = game->edit_data.f_info;
+
+#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].flags & FF_PERMANENT) {
+ return;
+ }
+ if (!(kill_wall || (f_info[c_ptr->feat].flags & FF_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; i<length; i++)
+ {
+ /* stop at the end of tunnelable things */
+ if (!geomancy_can_tunnel(y, x)) {
+ break;
+ }
+
+ if (geomancy_can_tunnel(y - 1, x - 1)) { geomancy_random_wall(y - 1, x - 1); }
+ if (geomancy_can_tunnel(y - 1, x )) { geomancy_random_wall(y - 1, x ); }
+ if (geomancy_can_tunnel(y - 1, x + 1)) { geomancy_random_wall(y - 1, x + 1); }
+
+ if (geomancy_can_tunnel(y , x - 1)) { geomancy_random_wall(y , x - 1); }
+ if (geomancy_can_tunnel(y , x + 1)) { geomancy_random_wall(y , x + 1); }
+
+ if (geomancy_can_tunnel(y + 1, x - 1)) { geomancy_random_wall(y + 1, x - 1); }
+ if (geomancy_can_tunnel(y + 1, x )) { geomancy_random_wall(y + 1, x ); }
+ if (geomancy_can_tunnel(y + 1, x + 1)) { geomancy_random_wall(y + 1, x + 1); }
+
+ y = y + dy;
+ x = x + dx;
+ }
+
+ /* Step back towards origin */
+ y = y - dy;
+ x = x - dx;
+ while ((y != oy) || (x != ox))
+ {
+ geomancy_random_floor(y, x, TRUE);
+
+ /* Should we branch ? */
+ if (magik(20))
+ {
+ int rot = magik(50) ? -1 : 1;
+ geomancy_dig(y, x, rotate_dir(dir, rot), length / 3);
+ }
+
+ y = y - dy;
+ x = x - dx;
+ }
+}
+
+void channel_the_elements(int y, int x, int level)
+{
+ // Type of water to use (if any)
+ auto water_type = []() -> int {
+ return (get_skill(SKILL_WATER) >= 18) ? GF_WAVE : GF_WATER;
+ };
+ // Do we use hellfire?
+ auto use_hellfire = []() -> bool {
+ return get_skill(SKILL_FIRE) >= 15;
+ };
+ // Type of fire to use (if any)
+ auto fire_type = [&use_hellfire]() -> int {
+ return use_hellfire() ? GF_HELL_FIRE : GF_FIRE;
+ };
+
+ switch (cave[y][x].feat)
+ {
+ case FEAT_GRASS:
+ hp_player(p_ptr->mhp * (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;
+ if (!get_aim_dir(&dir)) break;
+
+ if (get_skill(SKILL_WATER) >= 8)
+ {
+ fire_beam(water_type(), dir, damroll(3, get_skill(SKILL_WATER)));
+ }
+ else
+ {
+ fire_bolt(water_type(), dir, damroll(3, get_skill(SKILL_WATER)));
+ }
+
+ break;
+ }
+
+ case FEAT_DEEP_WATER:
+ {
+ int dir;
+ if (!get_aim_dir(&dir)) break;
+
+ if (get_skill(SKILL_WATER) >= 8)
+ {
+ fire_beam(water_type(), dir, damroll(5, get_skill(SKILL_WATER)));
+ }
+ else
+ {
+ fire_bolt(water_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;
+
+ type = use_hellfire() ? 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;
+
+ fire_bolt(fire_type(), dir, damroll(get_skill_scale(SKILL_FIRE, 30), 15));
+ break;
+ }
+
+ case FEAT_DEEP_LAVA:
+ {
+ int dir;
+ if (!get_aim_dir(&dir)) break;
+
+ fire_ball(fire_type(), 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.");
+ }
+}
diff --git a/src/spells2.hpp b/src/spells2.hpp
new file mode 100644
index 00000000..0eeb3f5b
--- /dev/null
+++ b/src/spells2.hpp
@@ -0,0 +1,112 @@
+#pragma once
+
+#include "h-basic.h"
+#include "identify_mode.hpp"
+#include "monster_race_flag_set.hpp"
+#include "object_filter.hpp"
+#include "object_type_fwd.hpp"
+
+void curse_artifact(object_type * o_ptr);
+void grow_things(s16b type, int rad);
+void grow_grass(int rad);
+void grow_trees(int rad);
+bool_ hp_player(int num);
+bool_ heal_insanity(int val);
+void warding_glyph();
+void explosive_rune();
+bool_ do_dec_stat(int stat, int mode);
+bool_ do_res_stat(int stat, bool_ full);
+bool_ do_inc_stat(int stat);
+void identify_hooks(int i, object_type *o_ptr, identify_mode type);
+bool_ identify_pack();
+void identify_pack_fully();
+bool_ remove_curse();
+bool_ remove_all_curse();
+bool_ restore_level();
+bool_ lose_all_info();
+bool_ detect_traps(int rad);
+bool_ detect_doors(int rad);
+bool_ detect_stairs(int rad);
+bool_ detect_treasure(int rad);
+bool detect_objects_gold(int rad);
+bool detect_objects_normal(int rad);
+bool_ detect_monsters_normal(int rad);
+bool_ detect_monsters_invis(int rad);
+void detect_monsters_orcs(int rad);
+bool_ detect_all(int rad);
+void stair_creation();
+bool_ wall_stone(int y, int x);
+bool_ enchant(object_type *o_ptr, int n, int eflag);
+bool_ enchant_spell(int num_hit, int num_dam, int num_ac, int num_pval);
+bool_ ident_spell();
+bool_ ident_all();
+bool_ identify_fully();
+bool_ recharge(int num);
+void aggravate_monsters(int who);
+bool_ genocide_aux(bool_ player_cast, char typ);
+bool_ genocide(bool_ player_cast);
+bool_ mass_genocide(bool_ player_cast);
+void change_wild_mode();
+bool_ banish_evil(int dist);
+bool_ dispel_evil(int dam);
+bool_ dispel_good(int dam);
+bool_ dispel_undead(int dam);
+bool_ dispel_monsters(int dam);
+void destroy_area(int y1, int x1, int r);
+void earthquake(int cy, int cx, int r);
+void lite_room(int y1, int x1);
+void unlite_room(int y1, int x1);
+bool_ lite_area(int dam, int rad);
+bool_ unlite_area(int dam, int rad);
+bool_ fire_cloud(int typ, int dir, int dam, int rad, int time);
+bool_ fire_wave(int typ, int dir, int dam, int rad, int time, s32b eff);
+bool_ fire_wall(int typ, int dir, int dam, int time);
+bool_ fire_ball(int typ, int dir, int dam, int rad);
+bool_ fire_bolt(int typ, int dir, int dam);
+bool_ fire_beam(int typ, int dir, int dam);
+void call_chaos();
+bool_ fire_bolt_or_beam(int prob, int typ, int dir, int dam);
+bool_ lite_line(int dir);
+bool_ drain_life(int dir, int dam);
+bool_ wall_to_mud(int dir);
+bool_ wizard_lock(int dir);
+bool_ slow_monster(int dir);
+bool_ sleep_monster(int dir);
+bool_ confuse_monster(int dir, int plev);
+bool_ fear_monster(int dir, int plev);
+bool_ poly_monster(int dir);
+bool_ teleport_monster(int dir);
+bool_ trap_creation();
+bool_ destroy_doors_touch();
+bool_ destroy_traps_touch();
+bool_ sleep_monsters_touch();
+bool_ alchemy();
+void activate_ty_curse();
+void activate_dg_curse();
+void summon_cyber();
+bool_ confuse_monsters(int dam);
+bool_ charm_monsters(int dam);
+bool_ charm_animals(int dam);
+bool_ stun_monsters(int dam);
+bool_ banish_monsters(int dist);
+bool_ turn_monsters(int dam);
+bool_ charm_monster(int dir, int plev);
+bool_ control_one_undead(int dir, int plev);
+bool_ charm_animal(int dir, int plev);
+bool_ mindblast_monsters(int dam);
+void alter_reality();
+void report_magics();
+void teleport_swap(int dir);
+void swap_position(int lty, int ltx);
+object_filter_t const &item_tester_hook_recharge();
+bool_ project_hack(int typ, int dam);
+void project_meteor(int radius, int typ, int dam, u32b flg);
+object_filter_t const &item_tester_hook_artifactable();
+bool_ passwall(int dir, bool_ safe);
+bool_ project_hook(int typ, int dir, int dam, int flg);
+bool_ reset_recall(bool_ no_trepas_max_depth);
+void geomancy_random_wall(int y, int x);
+void geomancy_random_floor(int y, int x, bool_ kill_wall);
+void geomancy_dig(int oy, int ox, int dir, int length);
+void channel_the_elements(int y, int x, int level);
+void random_resistance(object_type *o_ptr, int specific);
diff --git a/src/spells3.cc b/src/spells3.cc
new file mode 100644
index 00000000..58d42cab
--- /dev/null
+++ b/src/spells3.cc
@@ -0,0 +1,4570 @@
+#include "spells3.hpp"
+
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "cmd5.hpp"
+#include "feature_flag.hpp"
+#include "feature_type.hpp"
+#include "game.hpp"
+#include "lua_bind.hpp"
+#include "mimic.hpp"
+#include "monster2.hpp"
+#include "monster3.hpp"
+#include "monster_race.hpp"
+#include "monster_race_flag.hpp"
+#include "monster_type.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_kind.hpp"
+#include "player_type.hpp"
+#include "school_book.hpp"
+#include "skills.hpp"
+#include "spell_type.hpp"
+#include "spells1.hpp"
+#include "spells2.hpp"
+#include "spells4.hpp"
+#include "spells5.hpp"
+#include "stats.hpp"
+#include "tables.hpp"
+#include "timer_type.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+#include "xtra2.hpp"
+#include "z-rand.hpp"
+
+#include <algorithm>
+#include <cassert>
+#include <vector>
+
+s32b NOXIOUSCLOUD = -1; /* Identifier */
+s32b AIRWINGS = -1; /* Identifier */
+s32b INVISIBILITY;
+s32b POISONBLOOD;
+s32b THUNDERSTORM;
+s32b STERILIZE;
+
+s32b BLINK;
+s32b TELEPORT;
+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;
+
+s32b STARIDENTIFY;
+s32b IDENTIFY;
+s32b VISION;
+s32b SENSEHIDDEN;
+s32b REVEALWAYS;
+s32b SENSEMONSTERS;
+
+s32b STONESKIN;
+s32b DIG;
+s32b STONEPRISON;
+s32b STRIKE;
+s32b SHAKE;
+
+s32b ERU_SEE;
+s32b ERU_LISTEN;
+s32b ERU_UNDERSTAND;
+s32b ERU_PROT;
+
+s32b GLOBELIGHT;
+s32b FIREFLASH;
+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;
+
+s32b MANATHRUST;
+s32b DELCURSES;
+s32b RESISTS;
+s32b MANASHIELD;
+
+s32b MANWE_SHIELD;
+s32b MANWE_AVATAR;
+s32b MANWE_BLESS;
+s32b MANWE_CALL;
+
+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;
+
+s32b CHARM;
+s32b CONFUSE;
+s32b ARMOROFFEAR;
+s32b STUN;
+
+s32b MAGELOCK;
+s32b SLOWMONSTER;
+s32b ESSENCESPEED;
+s32b BANISHMENT;
+
+s32b TULKAS_AIM;
+s32b TULKAS_WAVE;
+s32b TULKAS_SPIN;
+
+s32b DRAIN;
+s32b GENOCIDE;
+s32b WRAITHFORM;
+s32b FLAMEOFUDUN;
+
+s32b TIDALWAVE;
+s32b ICESTORM;
+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;
+
+s32b GROWTREE;
+s32b HEALING;
+s32b RECOVERY;
+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_HOLY_FIRE;
+s32b DEVICE_THUNDERLORDS;
+
+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;
+
+s32b AULE_FIREBRAND;
+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;
+
+s32b ULMO_BELEGAER;
+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;
+
+static void find_position(int y, int x, int *yy, int *xx)
+{
+ int attempts = 500;
+
+ do
+ {
+ scatter(yy, xx, y, x, 6);
+ }
+ while (!(in_bounds(*yy, *xx) && cave_floor_bold(*yy, *xx)) && --attempts);
+}
+
+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;
+ }
+ }
+}
+
+GENERATE_MONSTER_LOOKUP_FN(get_fire_golem, "Fire golem")
+
+// -------------------------------------------------------------
+
+casting_result 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_OBVIOUS;
+}
+
+const char *air_noxious_cloud_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "dam " FMTs32b " rad 3 dur " FMTs32b,
+ (7 + get_level_s(NOXIOUSCLOUD, 150)),
+ (5 + get_level_s(NOXIOUSCLOUD, 40)));
+ return buf;
+}
+
+casting_result air_wings_of_winds()
+{
+ if (get_level_s(AIRWINGS, 50) >= 16)
+ {
+ if (p_ptr->tim_fly == 0)
+ {
+ return cast(set_tim_fly(randint(10) + 5 + get_level_s(AIRWINGS, 25)));
+ }
+ }
+ else
+ {
+ if (p_ptr->tim_ffall == 0)
+ {
+ return cast(set_tim_ffall(randint(10) + 5 + get_level_s(AIRWINGS, 25)));
+ }
+ }
+
+ return CAST_HIDDEN;
+}
+
+const char *air_wings_of_winds_info()
+{
+ static char buf[128];
+ sprintf(buf, "dur " FMTs32b "+d10", (5 + get_level_s(AIRWINGS, 25)));
+ return buf;
+}
+
+casting_result air_invisibility()
+{
+ if (p_ptr->tim_invisible == 0)
+ {
+ return cast(set_invis(randint(20) + 15 + get_level_s(INVISIBILITY, 50), 20 + get_level_s(INVISIBILITY, 50)));
+ }
+
+ return CAST_HIDDEN;
+}
+
+const char *air_invisibility_info()
+{
+ static char buf[128];
+ sprintf(buf, "dur " FMTs32b "+d20 power " FMTs32b,
+ (15 + get_level_s(INVISIBILITY, 50)),
+ (20 + get_level_s(INVISIBILITY, 50)));
+ return buf;
+}
+
+casting_result air_poison_blood()
+{
+ casting_result result = NO_CAST;
+
+ if (p_ptr->oppose_pois == 0)
+ {
+ 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))
+ {
+ result = cplus(result, set_poison(randint(30) + 25 + get_level_s(POISONBLOOD, 25)));
+ }
+
+ return result;
+}
+
+const char *air_poison_blood_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "dur " FMTs32b "+d30",
+ (25 + get_level_s(POISONBLOOD, 25)));
+ return buf;
+}
+
+casting_result air_thunderstorm()
+{
+ if (p_ptr->tim_thunder == 0)
+ {
+ 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 CAST_HIDDEN;
+}
+
+const char *air_thunderstorm_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "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)));
+ return buf;
+}
+
+casting_result air_sterilize()
+{
+ set_no_breeders((30) + 20 + get_level_s(STERILIZE, 70));
+ return CAST_OBVIOUS;
+}
+
+const char *air_sterilize_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "dur " FMTs32b "+d30",
+ (20 + get_level_s(STERILIZE, 70)));
+ return buf;
+}
+
+casting_result 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_OBVIOUS;
+ }
+ else
+ {
+ teleport_player(10 + get_level_s(BLINK, 8));
+ return CAST_OBVIOUS;
+ }
+}
+
+const char *convey_blink_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "distance " FMTs32b,
+ (10 + get_level_s(BLINK, 8)));
+ return buf;
+}
+
+casting_result convey_teleport()
+{
+ p_ptr->energy -= (25 - get_level_s(TELEPORT, 50));
+ teleport_player(100 + get_level_s(TELEPORT, 100));
+ return CAST_OBVIOUS;
+}
+
+const char *convey_teleport_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "distance " FMTs32b,
+ (100 + get_level_s(TELEPORT, 100)));
+ return buf;
+}
+
+casting_result convey_teleport_away()
+{
+ if (get_level_s(TELEAWAY, 50) >= 20)
+ {
+ return cast(project_hack(GF_AWAY_ALL, 100));
+ }
+ else if (get_level_s(TELEAWAY, 50) >= 10)
+ {
+ int dir;
+ if (!get_aim_dir(&dir))
+ {
+ return NO_CAST;
+ }
+
+ return cast(fire_ball(GF_AWAY_ALL, dir, 100, 3 + get_level_s(TELEAWAY, 4)));
+ }
+ else
+ {
+ int dir;
+ if (!get_aim_dir(&dir))
+ {
+ return NO_CAST;
+ }
+ return cast(teleport_monster(dir));
+ }
+}
+
+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;
+}
+
+casting_result 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_OBVIOUS;
+ }
+ else if (c_ptr->m_idx > 0)
+ {
+ swap_position(y, x);
+ return CAST_OBVIOUS;
+ }
+ else if (!c_ptr->o_idxs.empty())
+ {
+ // Set the target
+ target_who = -1;
+ target_col = x;
+ target_row = y;
+ // Fetch item
+ 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_OBVIOUS;
+ }
+ else
+ {
+ return NO_CAST;
+ }
+}
+
+const 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 " FMTs32b "lb",
+ f, d, (1 + get_level_s(RECALL, 15)));
+ return buf;
+}
+
+casting_result convey_probability_travel()
+{
+ return cast(set_prob_travel(randint(20) + get_level_s(PROBABILITY_TRAVEL, 60)));
+}
+
+const char *convey_probability_travel_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "dur " FMTs32b "+d20",
+ get_level_s(PROBABILITY_TRAVEL, 60));
+ return buf;
+}
+
+casting_result 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;
+ }
+
+ 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));
+}
+
+const char *demonology_demon_blade_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "dur " FMTs32b "+d20 dam " FMTs32b "/blow",
+ (get_level_s(DEMON_BLADE, 80)),
+ (4 + get_level_s(DEMON_BLADE, 40)));
+ return buf;
+}
+
+casting_result demonology_demon_madness()
+{
+ casting_result result = NO_CAST;
+ 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;
+ }
+
+ // Calculate the coordinates of arrival
+ {
+ // Use the given direction
+ int tx = p_ptr->px + (ddx[dir] * 100);
+ int ty = p_ptr->py + (ddy[dir] * 100);
+
+ // Hack -- Use an actual "target"
+ if ((dir == 5) && target_okay())
+ {
+ tx = target_col;
+ ty = target_row;
+ }
+
+ y1 = ty;
+ x1 = tx;
+ }
+
+ // Calculate the appropriate place
+ y2 = p_ptr->py - (y1 - p_ptr->py);
+ x2 = p_ptr->px - (x1 - p_ptr->px);
+
+ result = cplus(result,
+ project(0, 1 + get_level(DEMON_MADNESS, 4),
+ 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),
+ y2, x2,
+ 20 + get_level_s(DEMON_MADNESS, 200),
+ type,
+ PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL));
+
+ return result;
+}
+
+const char *demonology_demon_madness_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "dam " FMTs32b " rad " FMTs32b,
+ (20 + get_level_s(DEMON_MADNESS, 200)),
+ (1 + get_level(DEMON_MADNESS, 4)));
+ return buf;
+}
+
+casting_result demonology_demon_field()
+{
+ int dir;
+
+ if (!get_aim_dir(&dir))
+ {
+ return NO_CAST;
+ }
+
+ return cast(fire_cloud(GF_NEXUS,
+ dir,
+ 20 + get_level_s(DEMON_FIELD, 70),
+ 7,
+ 30 + get_level_s(DEMON_FIELD, 100)));
+}
+
+const char *demonology_demon_field_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "dam " FMTs32b " dur " FMTs32b,
+ (20 + get_level_s(DEMON_FIELD, 70)),
+ (30 + get_level_s(DEMON_FIELD, 100)));
+ return buf;
+}
+
+casting_result demonology_doom_shield()
+{
+ 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)));
+}
+
+const char *demonology_doom_shield_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "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)));
+ return buf;
+}
+
+casting_result 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)))
+ {
+ 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)) * heal) / 100;
+
+ hp_player(heal);
+
+ delete_monster_idx(c_ptr->m_idx);
+ }
+
+ return CAST_OBVIOUS;
+ }
+ else
+ {
+ return NO_CAST;
+ }
+}
+
+const char *demonology_unholy_word_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "heal mhp%% of " FMTs32b "%%",
+ (30 + get_level(UNHOLY_WORD, 50)));
+ return buf;
+}
+
+casting_result demonology_demon_cloak()
+{
+ return cast(set_tim_reflect(randint(5) + 5 + get_level(DEMON_CLOAK, 15)));
+}
+
+const char *demonology_demon_cloak_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "dur " FMTs32b "+d5",
+ (5 + get_level(DEMON_CLOAK, 15)));
+ return buf;
+}
+
+casting_result 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))
+ {
+ return CAST_OBVIOUS;
+ }
+ else
+ {
+ msg_print("Something blocks your summoning!");
+ return CAST_HIDDEN;
+ }
+}
+
+const char *demonology_summon_demon_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "level " FMTs32b,
+ (5 + get_level_s(DEMON_SUMMON, 100)));
+ return buf;
+}
+
+casting_result 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))) / 100;
+ if (dam > 100 + get_level(DISCHARGE_MINION, 500))
+ {
+ dam = 100 + get_level(DISCHARGE_MINION, 500);
+ }
+
+ /* We use project instead of fire_ball because we must tell it exactly where to land */
+ return cast(project(0, 2, y, x, dam,
+ GF_GRAVITY,
+ PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL));
+ }
+ else
+ {
+ return NO_CAST;
+ }
+}
+
+const char *demonology_discharge_minion_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "dam " FMTs32b "%% max " FMTs32b,
+ (20 + get_level(DISCHARGE_MINION, 60)),
+ (100 + get_level(DISCHARGE_MINION, 500)));
+ return buf;
+}
+
+casting_result demonology_control_demon()
+{
+ int dir;
+ if (!get_aim_dir(&dir))
+ {
+ return NO_CAST;
+ }
+
+ return cast(fire_ball(GF_CONTROL_DEMON, dir, 50 + get_level_s(CONTROL_DEMON, 250), 0));
+}
+
+const char *demonology_control_demon_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "power " FMTs32b,
+ (50 + get_level_s(CONTROL_DEMON, 250)));
+ return buf;
+}
+
+casting_result divination_greater_identify()
+{
+ identify_fully();
+ return CAST_OBVIOUS;
+}
+
+casting_result divination_identify()
+{
+ if (get_level_s(IDENTIFY, 50) >= 17)
+ {
+ casting_result result = NO_CAST;
+ result = cplus(result, identify_pack());
+ return result;
+ }
+ else if (ident_spell())
+ {
+ return CAST_OBVIOUS;
+ }
+ else
+ {
+ return NO_CAST;
+ }
+}
+
+const char *divination_identify_info()
+{
+ static char buf[128];
+
+ if (get_level_s(IDENTIFY, 50) >= 27)
+ {
+ sprintf(buf, "rad " FMTs32b, get_level_s(IDENTIFY, 3));
+ return buf;
+ }
+ else
+ {
+ return "";
+ }
+}
+
+casting_result divination_vision()
+{
+ if (get_level_s(VISION, 50) >= 25)
+ {
+ wiz_lite_extra();
+ }
+ else
+ {
+ map_area();
+ }
+ return CAST_OBVIOUS;
+
+}
+
+casting_result divination_sense_hidden()
+{
+ casting_result result = NO_CAST;
+ result = cplus(result, set_tim_invis(10 + randint(20) + get_level_s(SENSEHIDDEN, 40)));
+
+ return result;
+}
+
+const char *divination_sense_hidden_info()
+{
+ static char buf[128];
+
+ if (get_level_s(SENSEHIDDEN, 50) >= 15)
+ {
+ sprintf(buf,
+ "rad " FMTs32b " dur " FMTs32b "+d20",
+ (15 + get_level_s(SENSEHIDDEN, 40)),
+ (10 + get_level_s(SENSEHIDDEN, 40)));
+ }
+ else
+ {
+ sprintf(buf,
+ "rad " FMTs32b,
+ (15 + get_level_s(SENSEHIDDEN, 40)));
+ }
+
+ return buf;
+}
+
+casting_result divination_reveal_ways()
+{
+ casting_result result = NO_CAST;
+ result = cplus(result, detect_doors(10 + get_level(REVEALWAYS, 40)));
+ result = cplus(result, detect_stairs(10 + get_level(REVEALWAYS, 40)));
+ return result;
+}
+
+const char *divination_reveal_ways_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "rad " FMTs32b,
+ (10 + get_level_s(REVEALWAYS, 40)));
+ return buf;
+}
+
+casting_result divination_sense_monsters()
+{
+ casting_result result = NO_CAST;
+
+ result = cplus(result, detect_monsters_normal(10 + get_level(SENSEMONSTERS, 40)));
+ if (get_level_s(SENSEMONSTERS, 50) >= 30)
+ {
+ result = cplus(result, set_tim_esp(10 + randint(10) + get_level_s(SENSEMONSTERS, 20)));
+ }
+ return result;
+}
+
+const char *divination_sense_monsters_info()
+{
+ static char buf[128];
+
+ if (get_level_s(SENSEMONSTERS, 50) >= 30)
+ {
+ sprintf(buf,
+ "rad " FMTs32b " dur " FMTs32b "+d10",
+ (10 + get_level_s(SENSEMONSTERS, 40)),
+ (10 + get_level_s(SENSEMONSTERS, 20)));
+ }
+ else
+ {
+ sprintf(buf,
+ "rad " FMTs32b,
+ (10 + get_level_s(SENSEMONSTERS, 40)));
+ }
+
+ return buf;
+}
+
+casting_result earth_stone_skin()
+{
+ int type;
+
+ type = 0;
+ if (get_level_s(STONESKIN, 50) >= 25)
+ {
+ type = SHIELD_COUNTER;
+ }
+
+ 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)));
+}
+
+const char *earth_stone_skin_info()
+{
+ static char buf[128];
+
+ if (get_level_s(STONESKIN, 50) >= 25)
+ {
+ sprintf(buf,
+ "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)),
+ (10 + get_level_s(STONESKIN, 50)));
+ }
+ else
+ {
+ sprintf(buf,
+ "dur " FMTs32b "+d10 AC " FMTs32b,
+ (10 + get_level_s(STONESKIN, 100)),
+ (10 + get_level_s(STONESKIN, 50)));
+ }
+
+ return buf;
+}
+
+casting_result earth_dig()
+{
+ int dir;
+ if (!get_aim_dir(&dir))
+ {
+ return NO_CAST;
+ }
+
+ return cast(wall_to_mud(dir));
+}
+
+casting_result 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_OBVIOUS;
+}
+
+casting_result 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)
+ {
+ return cast(fire_ball(GF_FORCE, dir, dmg, 1));
+ }
+ else
+ {
+ return cast(fire_ball(GF_FORCE, dir, dmg, 0));
+ }
+}
+
+const 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;
+}
+
+casting_result 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_OBVIOUS;
+}
+
+const char *earth_shake_info()
+{
+ static char buf[128];
+ sprintf(buf, "rad " FMTs32b, (4 + get_level_s(SHAKE, 10)));
+ return buf;
+}
+
+casting_result eru_see_the_music()
+{
+ 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)
+ {
+ result = cplus(result, set_blind(0));
+ }
+
+ return result;
+}
+
+const char *eru_see_the_music_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "dur " FMTs32b "+d20",
+ (10 + get_level_s(ERU_SEE, 100)));
+ return buf;
+}
+
+casting_result eru_listen_to_the_music()
+{
+ casting_result result = NO_CAST;
+
+ if (get_level_s(ERU_LISTEN, 50) >= 30)
+ {
+ result = cplus(result, ident_all());
+ result = cplus(result, identify_pack());
+ }
+ else if (get_level_s(ERU_LISTEN, 50) >= 14)
+ {
+ result = cplus(result, identify_pack());
+ }
+ else
+ {
+ result = cplus(result, ident_spell());
+ }
+
+ return result;
+}
+
+casting_result eru_know_the_music()
+{
+ if (get_level_s(ERU_UNDERSTAND, 50) >= 10)
+ {
+ identify_pack_fully();
+ return CAST_OBVIOUS;
+ }
+ else
+ {
+ return cast(identify_fully());
+ }
+}
+
+casting_result eru_lay_of_protection()
+{
+ return cast(fire_ball(GF_MAKE_GLYPH, 0, 1, 1 + get_level(ERU_PROT, 2)));
+}
+
+const char *eru_lay_of_protection_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "rad " FMTs32b,
+ (1 + get_level(ERU_PROT, 2)));
+ return buf;
+}
+
+casting_result fire_globe_of_light()
+{
+ casting_result result = NO_CAST;
+
+ if (get_level_s(GLOBELIGHT, 50) >= 3)
+ {
+ 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)
+ {
+ 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 result;
+}
+
+const char *fire_globe_of_light_info()
+{
+ static char buf[128];
+
+ if (get_level_s(GLOBELIGHT, 50) >= 15)
+ {
+ sprintf(buf, "dam " FMTs32b " rad " FMTs32b,
+ (10 + get_level_s(GLOBELIGHT, 100)),
+ (5 + get_level_s(GLOBELIGHT, 6)));
+ }
+ else
+ {
+ buf[0] = '\0';
+ }
+
+ return buf;
+}
+
+casting_result 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;
+ }
+
+ return cast(fire_ball(type, dir,
+ 20 + get_level_s(FIREFLASH, 500),
+ 2 + get_level_s(FIREFLASH, 5)));
+}
+
+const char *fire_fireflash_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "dam " FMTs32b " rad " FMTs32b,
+ (20 + get_level_s(FIREFLASH, 500)),
+ (2 + get_level_s(FIREFLASH, 5)));
+ return buf;
+}
+
+casting_result fire_fiery_shield()
+{
+ int type = SHIELD_FIRE;
+ if (get_level_s(FIERYAURA, 50) >= 8)
+ {
+ type = SHIELD_GREAT_FIRE;
+ }
+
+ 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)));
+}
+
+const char *fire_fiery_shield_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "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)));
+ return buf;
+}
+
+casting_result 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_OBVIOUS;
+}
+
+const char *fire_firewall_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "dam " FMTs32b " dur " FMTs32b,
+ (40 + get_level_s(FIREWALL, 150)),
+ (10 + get_level_s(FIREWALL, 14)));
+ return buf;
+}
+
+object_filter_t const &item_tester_hook_fire_golem()
+{
+ using namespace object_filter;
+ static auto instance = And(
+ TVal(TV_LITE),
+ Or(
+ SVal(SV_LITE_TORCH),
+ SVal(SV_LITE_LANTERN)));
+ return instance;
+}
+
+casting_result fire_golem()
+{
+ /* Can we reconnect ? */
+ if (do_control_reconnect())
+ {
+ msg_print("Control re-established.");
+ return NO_CAST;
+ }
+
+ int item;
+ 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,
+ item_tester_hook_fire_golem()))
+ {
+ return NO_CAST;
+ }
+
+ /* Destroy the source object */
+ inc_stack_size(item, -1);
+
+ /* Find a place for it */
+ int x, y;
+ find_position(p_ptr->py, p_ptr->px, &y, &x);
+
+ /* Summon it */
+ int r_idx = get_fire_golem();
+ m_allow_special[r_idx] = TRUE;
+ int m_idx = place_monster_one(y, x, r_idx, 0, FALSE, MSTATUS_FRIEND);
+ m_allow_special[r_idx] = 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_OBVIOUS;
+}
+
+const char *fire_golem_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "golem level " FMTs32b,
+ (7 + get_level_s(FIREGOLEM, 70)));
+ return buf;
+}
+
+casting_result geomancy_call_the_elements()
+{
+ int dir = 0;
+
+ if (get_level_s(CALL_THE_ELEMENTS, 50) >= 17)
+ {
+ if (!get_aim_dir(&dir))
+ {
+ return NO_CAST;
+ }
+ }
+
+ fire_ball(GF_ELEMENTAL_GROWTH,
+ dir,
+ 1,
+ 1 + get_level(CALL_THE_ELEMENTS, 5));
+
+ return CAST_OBVIOUS;
+}
+
+const char *geomancy_call_the_elements_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "rad " FMTs32b,
+ (1 + get_level(CALL_THE_ELEMENTS, 5)));
+ return buf;
+}
+
+casting_result geomancy_channel_elements()
+{
+ channel_the_elements(p_ptr->py, p_ptr->px, get_level_s(CHANNEL_ELEMENTS, 50));
+ return CAST_OBVIOUS;
+}
+
+typedef struct eff_type eff_type;
+struct eff_type {
+ s16b feat;
+ s16b low_effect;
+ s16b high_effect;
+ int 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;
+}
+
+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 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 NO_CAST;
+ }
+
+ 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;
+ u32b dir_flag = dir_to_eff_flags(dir);
+
+ 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 + dir_flag);
+
+ return CAST_OBVIOUS;
+ }
+}
+
+casting_result 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_OBVIOUS;
+ }
+}
+
+const char *geomancy_vaporize_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "rad " FMTs32b " dur " FMTs32b,
+ (1 + get_level_s(VAPORIZE, 4)),
+ (10 + get_level_s(VAPORIZE, 20)));
+ return buf;
+}
+
+bool_ geomancy_vaporize_depends()
+{
+ return get_skill(SKILL_AIR) >= 4;
+}
+
+casting_result 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_OBVIOUS;
+}
+
+const char *geomancy_geolysis_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "length " FMTs32b,
+ (5 + get_level_s(GEOLYSIS, 12)));
+ return buf;
+}
+
+bool_ geomancy_geolysis_depends()
+{
+ return get_skill(SKILL_EARTH) >= 7;
+}
+
+casting_result 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_OBVIOUS;
+}
+
+const char *geomancy_dripping_tread_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "dur " FMTs32b "+d15 movs",
+ (10 + get_level_s(DRIPPING_TREAD, 50)));
+ return buf;
+}
+
+bool_ geomancy_dripping_tread_depends()
+{
+ return get_skill(SKILL_WATER) >= 10;
+}
+
+casting_result geomancy_grow_barrier()
+{
+ int dir = 0;
+
+ if (get_level_s(GROW_BARRIER, 50) >= 20)
+ {
+ if (!get_aim_dir(&dir))
+ {
+ return NO_CAST;
+ }
+ }
+
+ fire_ball(GF_ELEMENTAL_WALL, dir, 1, 1);
+ return CAST_OBVIOUS;
+}
+
+bool_ geomancy_grow_barrier_depends()
+{
+ return get_skill(SKILL_EARTH) >= 12;
+}
+
+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;
+}
+
+casting_result 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_OBVIOUS;
+ }
+}
+
+const char *geomancy_elemental_minion_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "min level " FMTs32b,
+ (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);
+}
+
+casting_result mana_manathrust()
+{
+ int dir;
+ s16b num = 0;
+ s16b sides = 0;
+
+ if (!get_aim_dir(&dir))
+ {
+ return NO_CAST;
+ }
+
+ get_manathrust_dam(&num, &sides);
+ return cast(fire_bolt(GF_MANA, dir, damroll(num, sides)));
+}
+
+const char *mana_manathrust_info()
+{
+ s16b num = 0;
+ s16b sides = 0;
+ static char buf[128];
+
+ get_manathrust_dam(&num, &sides);
+ sprintf(buf,
+ "dam " FMTs16b "d" FMTs16b,
+ num,
+ sides);
+ return buf;
+}
+
+casting_result mana_remove_curses()
+{
+ casting_result result = NO_CAST;
+
+ if (get_level_s(DELCURSES, 50) >= 20)
+ {
+ result = cplus(result, remove_all_curse());
+ }
+ else
+ {
+ result = cplus(result, remove_curse());
+ }
+
+ if (result == CAST_OBVIOUS)
+ {
+ msg_print("The curse is broken!");
+ }
+
+ return result;
+}
+
+casting_result mana_elemental_shield()
+{
+ casting_result res = NO_CAST;
+
+ if (p_ptr->oppose_fire == 0)
+ {
+ res = cplus(res, set_oppose_fire(randint(10) + 15 + get_level_s(RESISTS, 50)));
+ }
+
+ if (p_ptr->oppose_cold == 0)
+ {
+ res = cplus(res, set_oppose_cold(randint(10) + 15 + get_level_s(RESISTS, 50)));
+ }
+
+ if (p_ptr->oppose_elec == 0)
+ {
+ res = cplus(res, set_oppose_elec(randint(10) + 15 + get_level_s(RESISTS, 50)));
+ }
+
+ if (p_ptr->oppose_acid == 0)
+ {
+ res = cplus(res, set_oppose_acid(randint(10) + 15 + get_level_s(RESISTS, 50)));
+ }
+
+ return res;
+}
+
+const char *mana_elemental_shield_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "dur " FMTs32b "+d10",
+ (15 + get_level_s(RESISTS, 50)));
+ return buf;
+}
+
+casting_result mana_disruption_shield()
+{
+ if (get_level_s(MANASHIELD, 50) >= 5)
+ {
+ if (p_ptr->invuln == 0)
+ {
+ return cast(set_invuln(randint(5) + 3 + get_level_s(MANASHIELD, 10)));
+ }
+ }
+ else if (p_ptr->disrupt_shield == 0)
+ {
+ return cast(set_disrupt_shield(randint(5) + 3 + get_level_s(MANASHIELD, 10)));
+ }
+
+ return NO_CAST;
+}
+
+const char *mana_disruption_shield_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "dur " FMTs32b "+d5",
+ (3 + get_level_s(MANASHIELD, 10)));
+ return buf;
+}
+
+casting_result manwe_wind_shield()
+{
+ casting_result res = NO_CAST;
+ s32b dur = get_level_s(MANWE_SHIELD, 50) + 10 + randint(20);
+
+ res = cplus(res, 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;
+ }
+
+ 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 res;
+}
+
+const char *manwe_wind_shield_info()
+{
+ static char buf[128];
+
+ sprintf(buf,
+ "dur " FMTs32b "+d20",
+ (get_level_s(MANWE_SHIELD, 50) + 10));
+
+ if (get_level_s(MANWE_SHIELD, 50) >= 10)
+ {
+ char tmp[128];
+ 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 " FMTs32b "d" FMTs32b,
+ (1 + get_level_s(MANWE_SHIELD, 2)),
+ (1 + get_level_s(MANWE_SHIELD, 6)));
+ strcat(buf, tmp);
+ }
+
+ return buf;
+}
+
+casting_result manwe_avatar()
+{
+ s16b mimic_idx = resolve_mimic_name("Maia");
+ assert(mimic_idx >= 0);
+
+ return cast(set_mimic(get_level_s(MANWE_AVATAR, 20) + randint(10),
+ mimic_idx,
+ p_ptr->lev));
+}
+
+const char *manwe_avatar_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "dur " FMTs32b "+d10",
+ get_level_s(MANWE_AVATAR, 20));
+ return buf;
+}
+
+casting_result manwe_blessing()
+{
+ casting_result res = NO_CAST;
+ s32b dur = get_level_s(MANWE_BLESS, 70) + 30 + randint(40);
+
+ 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)
+ {
+ res = cplus(res, set_hero(dur));
+ }
+ if (get_level_s(MANWE_BLESS, 50) >= 20)
+ {
+ res = cplus(res, set_shero(dur));
+ }
+ if (get_level_s(MANWE_BLESS, 50) >= 30)
+ {
+ res = cplus(res, set_holy(dur));
+ }
+
+ return res;
+}
+
+const char *manwe_blessing_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "dur " FMTs32b "+d40",
+ get_level_s(MANWE_BLESS, 70) + 30);
+ return buf;
+}
+
+casting_result 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));
+ return CAST_OBVIOUS;
+ }
+
+ return NO_CAST;
+}
+
+const char *manwe_call_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "level " FMTs32b,
+ get_level_s(MANWE_CALL, 70) + 20);
+ return buf;
+}
+
+void do_melkor_curse(int m_idx)
+{
+ assert(m_idx >= 0);
+
+ monster_type *m_ptr = &m_list[m_idx];
+
+ if (get_level_s(MELKOR_CURSE, 50) >= 35)
+ {
+ auto const r_ptr = m_ptr->race();
+
+ 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_FRAME;
+ }
+
+ 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;
+}
+
+casting_result 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_OBVIOUS;
+ }
+}
+
+casting_result melkor_corpse_explosion()
+{
+ return cast(fire_ball(GF_CORPSE_EXPL,
+ 0,
+ 20 + get_level_s(MELKOR_CORPSE_EXPLOSION, 70),
+ 2 + get_level_s(MELKOR_CORPSE_EXPLOSION, 5)));
+}
+
+const char *melkor_corpse_explosion_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "dam " FMTs32b "%%",
+ 20 + get_level_s(MELKOR_CORPSE_EXPLOSION, 70));
+ return buf;
+}
+
+casting_result melkor_mind_steal()
+{
+ 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
+ {
+ monster_type *m_ptr = &m_list[target_who];
+ int chance = get_level_s(MELKOR_MIND_STEAL, 50);
+
+ char buf[128];
+ monster_desc(buf, m_ptr, 0);
+ buf[0] = toupper(buf[0]);
+
+ auto const r_ptr = m_ptr->race();
+ if ((randint(m_ptr->level) < chance) &&
+ ((r_ptr->flags & RF_UNIQUE).empty()))
+ {
+ 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_OBVIOUS;
+ }
+}
+
+const char *melkor_mind_steal_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "chance 1d(mlvl)<" FMTs32b,
+ get_level_s(MELKOR_MIND_STEAL, 50));
+ return buf;
+}
+
+casting_result meta_recharge()
+{
+ return cast(recharge(60 + get_level_s(RECHARGE, 140)));
+}
+
+const char *meta_recharge_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "power " FMTs32b,
+ 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;
+}
+
+casting_result meta_spellbinder()
+{
+ auto spellbinder = &p_ptr->spellbinder;
+
+ if (spellbinder->spell_idxs.size() > 0)
+ {
+ struct trigger {
+ int idx;
+ cptr desc;
+ };
+ struct trigger triggers[] = {
+ { SPELLBINDER_HP75, "75% HP", },
+ { SPELLBINDER_HP50, "50% HP", },
+ { SPELLBINDER_HP25, "25% HP", },
+ { -1, NULL, },
+ };
+ int trigger_idx = -1;
+
+ assert(spellbinder->trigger >= 0);
+
+ for (trigger_idx = 0; triggers[trigger_idx].idx >= 0; trigger_idx++)
+ {
+ if (triggers[trigger_idx].idx == 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 (auto spell_idx : spellbinder->spell_idxs)
+ {
+ msg_print(spell_type_name(spell_at(spell_idx)));
+ }
+
+ /* Doesn't cost anything */
+ return NO_CAST;
+ }
+ else
+ {
+ char c;
+
+ if (!get_com("Trigger at [a]75% hp [b]50% hp [c]25% hp?", &c))
+ {
+ return NO_CAST;
+ }
+
+ switch (c)
+ {
+ case 'a':
+ spellbinder->trigger = SPELLBINDER_HP75;
+ break;
+ case 'b':
+ spellbinder->trigger = SPELLBINDER_HP50;
+ break;
+ case 'c':
+ spellbinder->trigger = SPELLBINDER_HP25;
+ break;
+ default:
+ return NO_CAST;
+
+ }
+
+ std::size_t n = get_spellbinder_max();
+ while (n > 0)
+ {
+ s32b s = get_school_spell("bind", 0);
+
+ if (s == -1)
+ {
+ spellbinder->trigger = 0;
+ spellbinder->spell_idxs.clear();
+ return CAST_OBVIOUS;
+ }
+ else
+ {
+ 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;
+ }
+ }
+
+ spellbinder->spell_idxs.push_back(s);
+ n--;
+ }
+
+ p_ptr->energy = p_ptr->energy - 3100;
+ msg_print("Spellbinder ready.");
+ return CAST_OBVIOUS;
+ }
+}
+
+const char *meta_spellbinder_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "number %d max level " FMTs32b,
+ get_spellbinder_max(),
+ (7 + get_level_s(SPELLBINDER, 35)));
+ return buf;
+}
+
+casting_result meta_disperse_magic()
+{
+ casting_result res = NO_CAST;
+
+ res = cplus(res, set_blind(0));
+ res = cplus(res, set_lite(0));
+ if (get_level_s(DISPERSEMAGIC, 50) >= 5)
+ {
+ res = cplus(res, set_confused(0));
+ res = cplus(res, set_image(0));
+ }
+ if (get_level_s(DISPERSEMAGIC, 50) >= 10)
+ {
+ 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)
+ {
+ res = cplus(res, set_stun(0));
+ res = cplus(res, set_cut(0));
+ }
+ if (get_level_s(DISPERSEMAGIC, 50) >= 20)
+ {
+ 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 res;
+}
+
+casting_result 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_OBVIOUS;
+}
+
+static void stop_inertia_controlled_spell()
+{
+ assert(TIMER_INERTIA_CONTROL != NULL);
+
+ p_ptr->inertia_controlled_spell = -1;
+ TIMER_INERTIA_CONTROL->disable();
+ p_ptr->update = p_ptr->update | PU_MANA;
+}
+
+void meta_inertia_control_hook_birth_objects()
+{
+ stop_inertia_controlled_spell();
+}
+
+casting_result meta_inertia_control()
+{
+ s32b s, difficulty, delay;
+ spell_type *spell;
+
+ 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", 0);
+ if (s == -1)
+ {
+ stop_inertia_controlled_spell();
+ return NO_CAST;
+ }
+
+ spell = spell_at(s);
+
+ 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 (difficulty > get_level_s(INERTIA_CONTROL, 10))
+ {
+ 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->set_delay_and_reset(delay);
+ TIMER_INERTIA_CONTROL->enable();
+ p_ptr->update |= PU_MANA;
+ msg_format("Inertia flow controlling spell %s.", spell_type_name(spell_at(s)));
+ return CAST_OBVIOUS;
+}
+
+const char *meta_inertia_control_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "level " FMTs32b,
+ 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))
+ {
+ lua_cast_school_spell(p_ptr->inertia_controlled_spell, TRUE);
+ }
+}
+
+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;
+ }
+ }
+}
+
+static int mind_charm_power()
+{
+ return 10 + get_level_s(CHARM, 150);
+}
+
+casting_result mind_charm()
+{
+ int pwr = mind_charm_power();
+ int level = get_level_s(CHARM, 50);
+
+ if (level >= 35)
+ {
+ return cast(project_hack(GF_CHARM, pwr));
+ }
+ else
+ {
+ int dir;
+ if (!get_aim_dir(&dir))
+ {
+ return NO_CAST;
+ }
+
+ if (level >= 15)
+ {
+ return cast(fire_ball(GF_CHARM, dir, pwr, 3));
+ }
+ else
+ {
+ return cast(fire_bolt(GF_CHARM, dir, pwr));
+ }
+ }
+}
+
+const 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);
+}
+
+casting_result mind_confuse()
+{
+ int pwr = mind_confuse_power();
+ int level = get_level_s(CONFUSE, 50);
+
+ if (level >= 35)
+ {
+ return cast(project_hack(GF_OLD_CONF, pwr));
+ }
+ else
+ {
+ int dir;
+ if (!get_aim_dir(&dir))
+ {
+ return NO_CAST;
+ }
+
+ if (level >= 15)
+ {
+ return cast(fire_ball(GF_OLD_CONF, dir, pwr, 3));
+ }
+ else
+ {
+ return cast(fire_bolt(GF_OLD_CONF, dir, pwr));
+ }
+ }
+}
+
+const 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);
+}
+
+casting_result mind_armor_of_fear()
+{
+ 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()));
+}
+
+const 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);
+}
+
+casting_result mind_stun()
+{
+ int dir;
+
+ if (!get_aim_dir(&dir))
+ {
+ return NO_CAST;
+ }
+
+ if (get_level_s(STUN, 50) >= 20)
+ {
+ return cast(fire_ball(GF_STUN, dir, mind_stun_power(), 3));
+ }
+ else
+ {
+ return cast(fire_bolt(GF_STUN, dir, mind_stun_power()));
+ }
+}
+
+const char *mind_stun_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "power %d",
+ mind_stun_power());
+ return buf;
+}
+
+casting_result tempo_magelock()
+{
+ auto const &f_info = game->edit_data.f_info;
+
+ 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].flags | FF_FLOOR)) ||
+ (f_info[c_ptr->feat].flags | FF_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_OBVIOUS;
+ } else {
+ int dir;
+ if (!get_aim_dir(&dir))
+ {
+ return NO_CAST;
+ }
+ return cast(wizard_lock(dir));
+ }
+}
+
+static s32b tempo_slow_monster_power()
+{
+ return 40 + get_level_s(SLOWMONSTER, 160);
+}
+
+casting_result 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)
+ {
+ return cast(fire_ball(GF_OLD_SLOW, dir, pwr, 1));
+ }
+ else
+ {
+ return cast(fire_bolt(GF_OLD_SLOW, dir, pwr));
+ }
+}
+
+const 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);
+}
+
+casting_result tempo_essence_of_speed()
+{
+ if (p_ptr->fast == 0)
+ {
+ return cast(set_fast(randint(10) + tempo_essence_of_speed_base_duration(),
+ tempo_essence_of_speed_bonus()));
+ }
+ return NO_CAST;
+}
+
+const 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);
+}
+
+casting_result tempo_banishment()
+{
+ casting_result result = NO_CAST;
+ s32b pwr = tempo_banishment_power();
+
+ result = cplus(result, project_hack(GF_AWAY_ALL, pwr));
+
+ if (get_level_s(BANISHMENT, 50) >= 15)
+ {
+ result = cplus(result,
+ project_hack(GF_STASIS, 20 + get_level_s(BANISHMENT, 120)));
+ }
+
+ return result;
+}
+
+const char *tempo_banishment_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "power " FMTs32b,
+ tempo_banishment_power());
+ return buf;
+}
+
+casting_result tulkas_divine_aim()
+{
+ casting_result result = NO_CAST;
+ s32b dur = get_level_s(TULKAS_AIM, 50) + randint(10);
+
+ result = cplus(result, set_strike(dur));
+ if (get_level_s(TULKAS_AIM, 50) >= 20)
+ {
+ result = cplus(result, set_tim_deadly(dur));
+ }
+
+ return result;
+}
+
+const char *tulkas_divine_aim_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "dur " FMTs32b "+d10",
+ get_level_s(TULKAS_AIM, 50));
+ return buf;
+}
+
+casting_result tulkas_wave_of_power()
+{
+ int dir;
+
+ if (!get_aim_dir(&dir))
+ {
+ return NO_CAST;
+ }
+
+ return cast(fire_bolt(GF_ATTACK, dir, get_level_s(TULKAS_WAVE, p_ptr->num_blow)));
+}
+
+const 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;
+}
+
+casting_result tulkas_whirlwind()
+{
+ return cast(fire_ball(GF_ATTACK, 0, 1, 1));
+}
+
+/* Return the number of Udun/Melkor spells in a given book */
+int udun_in_book(s32b sval, s32b pval)
+{
+ int count = 0;
+
+ random_book_setup(sval, pval);
+
+ /* Get the school book */
+ school_book *school_book = school_books_at(sval);
+
+ /* Go through spells */
+ for (auto spell_idx : school_book->spell_idxs) {
+ spell_type *spell = spell_at(spell_idx);
+ for (auto school_idx : spell_type_get_schools(spell))
+ {
+ if ((school_idx == SCHOOL_UDUN) ||
+ (school_idx == SCHOOL_MELKOR))
+ {
+ count++;
+ }
+ }
+ }
+
+ return count;
+}
+
+int levels_in_book(s32b sval, s32b pval)
+{
+ int levels = 0;
+
+ random_book_setup(sval, pval);
+
+ /* Get the school book */
+ school_book *school_book = school_books_at(sval);
+
+ /* Parse all spells */
+ for (auto spell_idx : school_book->spell_idxs)
+ {
+ spell_type *spell = spell_at(spell_idx);
+ levels += spell_type_skill_level(spell);
+ }
+
+ return levels;
+}
+
+static object_filter_t const &udun_object_is_drainable()
+{
+ using namespace object_filter;
+ static auto instance = Or(
+ TVal(TV_WAND),
+ TVal(TV_ROD_MAIN),
+ TVal(TV_STAFF));
+ return instance;
+}
+
+casting_result udun_drain()
+{
+ auto const &k_info = game->edit_data.k_info;
+
+ /* Ask for an item */
+ int item;
+ if (!get_item(&item,
+ "What item to drain?",
+ "You have nothing you can drain",
+ USE_INVEN,
+ udun_object_is_drainable()))
+ {
+ return NO_CAST;
+ }
+
+ /* Drain */
+ object_type *o_ptr = get_object(item);
+
+ switch (o_ptr->tval)
+ {
+ case TV_STAFF:
+ case TV_WAND:
+ {
+ auto 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_OBVIOUS;
+}
+
+casting_result 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_OBVIOUS;
+}
+
+static int udun_wraithform_base_duration()
+{
+ return 20 + get_level_s(WRAITHFORM, 40);
+}
+
+casting_result udun_wraithform()
+{
+ return cast(set_shadow(randint(30) + udun_wraithform_base_duration()));
+}
+
+const 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);
+}
+
+casting_result udun_flame_of_udun()
+{
+ return cast(set_mimic(randint(15) + udun_flame_of_udun_base_duration(),
+ resolve_mimic_name("Balrog"),
+ get_level_s(FLAMEOFUDUN, 50)));
+}
+
+const char *udun_flame_of_udun_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "dur %d+d15",
+ udun_flame_of_udun_base_duration());
+ 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);
+}
+
+casting_result water_tidal_wave()
+{
+ fire_wave(GF_WAVE,
+ 0,
+ tidal_wave_damage(),
+ 0,
+ tidal_wave_duration(),
+ EFF_WAVE);
+ return CAST_OBVIOUS;
+}
+
+const 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);
+}
+
+static int water_ice_storm_duration()
+{
+ return 20 + get_level_s(ICESTORM, 70);
+}
+
+casting_result 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_OBVIOUS;
+}
+
+const 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);;
+}
+
+casting_result 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_OBVIOUS;
+}
+
+const 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);
+}
+
+static int water_vapor_duration()
+{
+ return 5;
+}
+
+casting_result water_vapor()
+{
+ fire_cloud(GF_WATER,
+ 0,
+ water_vapor_damage(),
+ water_vapor_radius(),
+ water_vapor_duration());
+ return CAST_OBVIOUS;
+}
+
+const 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);
+}
+
+casting_result water_geyser()
+{
+ int dir, dice, sides;
+
+ if (!get_aim_dir(&dir))
+ {
+ return NO_CAST;
+ }
+
+ get_geyser_damage(&dice, &sides);
+ return cast(fire_bolt_or_beam(2 * get_level_s(GEYSER, 85),
+ GF_WATER,
+ dir,
+ damroll(dice, sides)));
+}
+
+const 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;
+}
+
+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);
+}
+
+casting_result yavanna_charm_animal()
+{
+ int dir;
+
+ if (!get_aim_dir(&dir))
+ {
+ return NO_CAST;
+ }
+
+ return cast(fire_ball(GF_CONTROL_ANIMAL,
+ dir,
+ charm_animal_power(),
+ charm_animal_radius()));
+}
+
+const 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);
+}
+
+casting_result yavanna_grow_grass()
+{
+ grow_grass(yavanna_grow_grass_radius());
+ return CAST_OBVIOUS;
+}
+
+const 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);
+}
+
+casting_result yavanna_tree_roots()
+{
+ return cast(set_roots(tree_roots_duration(),
+ tree_roots_ac(),
+ tree_roots_damage()));
+}
+
+const 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);
+}
+
+casting_result yavanna_water_bite()
+{
+ int rad = 0;
+
+ if (get_level_s(YAVANNA_WATER_BITE, 50) >= 25)
+ {
+ rad = 1;
+ }
+
+ return cast(set_project(randint(30) + water_bite_base_duration(),
+ GF_WATER,
+ water_bite_damage(),
+ rad,
+ PROJECT_STOP | PROJECT_KILL));
+}
+
+const 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);
+}
+
+casting_result 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_OBVIOUS;
+ }
+ else
+ {
+ msg_print("There is no tree there.");
+ return NO_CAST;
+ }
+}
+
+const char *yavanna_uproot_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "lev %d",
+ uproot_mlevel());
+ return buf;
+}
+
+static int nature_grow_trees_radius()
+{
+ return 2 + get_level_s(GROWTREE, 7);
+}
+
+casting_result nature_grow_trees()
+{
+ grow_trees(nature_grow_trees_radius());
+ return CAST_OBVIOUS;
+}
+
+const 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;
+}
+
+casting_result nature_healing()
+{
+ return cast(hp_player(nature_healing_hp()));
+}
+
+const char *nature_healing_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "heal %d%% = %dhp",
+ nature_healing_percentage(),
+ nature_healing_hp());
+ return buf;
+}
+
+casting_result nature_recovery()
+{
+ casting_result result = NO_CAST;
+
+ result = cplus(result, set_poisoned(p_ptr->poisoned / 2));
+ if (get_level_s(RECOVERY, 50) >= 5)
+ {
+ result = cplus(result, set_poisoned(0));
+ result = cplus(result, set_cut(0));
+ }
+ if (get_level_s(RECOVERY, 50) >= 10)
+ {
+ 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)
+ {
+ result = cplus(result, restore_level());
+ }
+
+ return result;
+}
+
+static int regeneration_base_duration()
+{
+ return 5 + get_level_s(REGENERATION, 50);
+}
+
+static int regeneration_power()
+{
+ return 300 + get_level_s(REGENERATION, 700);
+}
+
+casting_result nature_regeneration()
+{
+ if (p_ptr->tim_regen == 0)
+ {
+ return cast(set_tim_regen(randint(10) + regeneration_base_duration(),
+ regeneration_power()));
+ }
+ return NO_CAST;
+}
+
+const 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);
+}
+
+casting_result nature_summon_animal()
+{
+ summon_specific_level = summon_animal_level();
+ return cast(summon_specific_friendly(p_ptr->py,
+ p_ptr->px,
+ dun_level,
+ SUMMON_ANIMAL,
+ TRUE));
+}
+
+const char *nature_summon_animal_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "level %d",
+ summon_animal_level());
+ return buf;
+}
+
+casting_result 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_OBVIOUS;
+ }
+
+ return CAST_HIDDEN;
+}
+
+static int device_heal_monster_hp()
+{
+ return 20 + get_level_s(DEVICE_HEAL_MONSTER, 380);
+}
+
+casting_result device_heal_monster()
+{
+ int dir;
+
+ if (!get_aim_dir(&dir))
+ {
+ return NO_CAST;
+ }
+
+ return cast(fire_ball(GF_OLD_HEAL, dir, device_heal_monster_hp(), 0));
+}
+
+const char *device_heal_monster_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "heal %d",
+ device_heal_monster_hp());
+ return buf;
+}
+
+casting_result device_haste_monster()
+{
+ int dir;
+
+ if (!get_aim_dir(&dir))
+ {
+ return NO_CAST;
+ }
+
+ return cast(fire_ball(GF_OLD_SPEED, dir, 1, 0));
+}
+
+const char *device_haste_monster_info()
+{
+ return "speed +10";
+}
+
+casting_result device_wish()
+{
+ make_wish();
+ return CAST_OBVIOUS;
+}
+
+casting_result device_summon_monster()
+{
+ casting_result result = NO_CAST;
+ int i;
+
+ for (i = 0; i < 4 + get_level_s(DEVICE_SUMMON, 30); i++)
+ {
+ result = cplus(result, summon_specific(p_ptr->py, p_ptr->px, dun_level, 0));
+ }
+
+ return result;
+}
+
+static int device_mana_pct()
+{
+ return 20 + get_level_s(DEVICE_MANA, 50);
+}
+
+casting_result device_mana()
+{
+ increase_mana((p_ptr->msp * device_mana_pct()) / 100);
+ return CAST_OBVIOUS;
+}
+
+const char *device_mana_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "restore %d%%",
+ device_mana_pct());
+ return buf;
+}
+
+casting_result device_nothing()
+{
+ return CAST_HIDDEN;
+}
+
+static int holy_fire_damage()
+{
+ return 50 + get_level_s(DEVICE_HOLY_FIRE, 300);
+}
+
+casting_result device_holy_fire()
+{
+ return cast(project_hack(GF_HOLY_FIRE, holy_fire_damage()));
+}
+
+const char *device_holy_fire_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "dam %d",
+ holy_fire_damage());
+ return buf;
+}
+
+casting_result 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_OBVIOUS;
+ }
+
+ 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_OBVIOUS;
+ }
+
+ default:
+ assert(FALSE);
+ return NO_CAST;
+ }
+}
+
+void static start_lasting_spell(int spl)
+{
+ p_ptr->music_extra = -spl;
+}
+
+casting_result music_stop_singing_spell()
+{
+ start_lasting_spell(0);
+ return CAST_OBVIOUS;
+}
+
+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);
+}
+
+casting_result music_holding_pattern_spell()
+{
+ start_lasting_spell(MUSIC_HOLD);
+ return CAST_OBVIOUS;
+}
+
+const 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);
+}
+
+casting_result music_illusion_pattern_spell()
+{
+ start_lasting_spell(MUSIC_CONF);
+ return CAST_OBVIOUS;
+}
+
+const 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);
+}
+
+casting_result music_stun_pattern_spell()
+{
+ start_lasting_spell(MUSIC_STUN);
+ return CAST_OBVIOUS;
+}
+
+const 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;
+}
+
+casting_result music_song_of_the_sun_spell()
+{
+ start_lasting_spell(MUSIC_LITE);
+ return CAST_OBVIOUS;
+}
+
+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);
+}
+
+casting_result music_flow_of_life_spell()
+{
+ start_lasting_spell(MUSIC_HEAL);
+ return CAST_OBVIOUS;
+}
+
+const 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);
+}
+
+casting_result music_heroic_ballad_spell()
+{
+ start_lasting_spell(MUSIC_HERO);
+ return CAST_OBVIOUS;
+}
+
+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);
+}
+
+casting_result music_hobbit_melodies_spell()
+{
+ start_lasting_spell(MUSIC_TIME);
+ return CAST_OBVIOUS;
+}
+
+const 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);
+ return get_mana(MUSIC_MIND);
+}
+
+casting_result music_clairaudience_spell()
+{
+ start_lasting_spell(MUSIC_MIND);
+ return CAST_OBVIOUS;
+}
+
+const 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));
+ return buf;
+ }
+ else
+ {
+ return "";
+ }
+}
+
+casting_result music_blow_spell()
+{
+ fire_ball(GF_SOUND,
+ 0,
+ damroll(2 + get_level(MUSIC_BLOW, 10), 4 + get_level(MUSIC_BLOW, 40)),
+ 1 + get_level(MUSIC_BLOW, 12));
+ return CAST_OBVIOUS;
+}
+
+const char *music_blow_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "dam " FMTs32b "d" FMTs32b " rad " FMTs32b,
+ 2 + get_level(MUSIC_BLOW, 10),
+ 4 + get_level(MUSIC_BLOW, 40),
+ 1 + get_level(MUSIC_BLOW, 12));
+ return buf;
+}
+
+casting_result music_gush_of_wind_spell()
+{
+ fire_ball(GF_AWAY_ALL,
+ 0,
+ 10 + get_level(MUSIC_BLOW, 40),
+ 1 + get_level(MUSIC_BLOW, 12));
+ return CAST_OBVIOUS;
+}
+
+const char *music_gush_of_wind_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "dist " FMTs32b " rad " FMTs32b,
+ 10 + get_level(MUSIC_BLOW, 40),
+ 1 + get_level(MUSIC_BLOW, 12));
+ return buf;
+}
+
+casting_result music_horns_of_ylmir_spell()
+{
+ earthquake(p_ptr->py, p_ptr->px, 2 + get_level_s(MUSIC_YLMIR, 10));
+ return CAST_OBVIOUS;
+}
+
+const char *music_horns_of_ylmir_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "rad " FMTs32b,
+ 2 + get_level_s(MUSIC_YLMIR, 10));
+ return buf;
+}
+
+casting_result music_ambarkanta_spell()
+{
+ alter_reality();
+ return CAST_OBVIOUS;
+}
+
+casting_result 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;
+ }
+
+ return cast(set_project(level + randint(20),
+ type,
+ 4 + level,
+ rad,
+ PROJECT_STOP | PROJECT_KILL));
+}
+
+const 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 object_filter_t const &aule_enchant_weapon_item_tester()
+{
+ using namespace object_filter;
+ static auto instance = And(
+ // Cannot enchant artifacts, spell is probably already too overpowered.
+ Not(IsArtifact()),
+ // Only weapons which Aule likes
+ Or(
+ TVal(TV_MSTAFF),
+ TVal(TV_BOW),
+ TVal(TV_HAFTED),
+ TVal(TV_POLEARM),
+ TVal(TV_SWORD),
+ TVal(TV_AXE)));
+ return instance;
+}
+
+casting_result aule_enchant_weapon_spell()
+{
+ s32b level = get_level_s(AULE_ENCHANT_WEAPON, 50);
+ s16b num_h, num_d, num_p;
+
+ 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;
+ }
+
+ int item;
+ if (!get_item(&item,
+ "Which object do you want to enchant?",
+ "You have no objects to enchant.",
+ USE_INVEN,
+ aule_enchant_weapon_item_tester()))
+ {
+ return NO_CAST;
+ }
+
+ object_type *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_OBVIOUS;
+}
+
+const char *aule_enchant_weapon_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "tries " FMTs32b,
+ 1 + get_level_s(AULE_ENCHANT_WEAPON, 50)/12);
+ return buf;
+}
+
+static object_filter_t const &aule_enchant_armor_item_tester()
+{
+ using namespace object_filter;
+ static auto instance = And(
+ // No enchanting artifacts; the spell is already horribly
+ // overpowered.
+ Not(IsArtifact()),
+ // Only armor-like things can be enchanted
+ Or(
+ TVal(TV_BOOTS),
+ TVal(TV_GLOVES),
+ TVal(TV_HELM),
+ TVal(TV_CROWN),
+ TVal(TV_SHIELD),
+ TVal(TV_CLOAK),
+ TVal(TV_SOFT_ARMOR),
+ TVal(TV_HARD_ARMOR),
+ TVal(TV_DRAG_ARMOR)));
+ return instance;
+}
+
+casting_result aule_enchant_armour_spell()
+{
+ s32b level = get_level_s(AULE_ENCHANT_ARMOUR, 50);
+ s16b num_h, num_d, num_a, num_p;
+ int item;
+
+ 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;
+ }
+
+ if (!get_item(&item,
+ "Which object do you want to enchant?",
+ "You have no objects to enchant.",
+ USE_INVEN,
+ aule_enchant_armor_item_tester()))
+ {
+ return NO_CAST;
+ }
+
+ object_type *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_OBVIOUS;
+}
+
+const char *aule_enchant_armour_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "tries " FMTs32b,
+ 1 + get_level_s(AULE_ENCHANT_ARMOUR, 50)/10);
+ return buf;
+}
+
+casting_result 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));
+ return CAST_OBVIOUS;
+ }
+ else
+ {
+ return NO_CAST;
+ }
+}
+
+const char *aule_child_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "level " FMTs32b,
+ 20 + get_level_s(AULE_CHILD, 70));
+ return buf;
+}
+
+static int tears_of_luthien_hp()
+{
+ return 10 * get_level_s(MANDOS_TEARS_LUTHIEN, 30);
+}
+
+casting_result mandos_tears_of_luthien_spell()
+{
+ 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;
+}
+
+const char *mandos_tears_of_luthien_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "heals %d",
+ tears_of_luthien_hp());
+ return buf;
+}
+
+casting_result mandos_spirit_of_the_feanturi_spell()
+{
+ casting_result result = NO_CAST;
+ s32b level = get_level_s(MANDOS_SPIRIT_FEANTURI, 50);
+
+ result = cplus(result, set_afraid(0));
+ result = cplus(result, set_confused(0));
+
+ if (level >= 20)
+ {
+ result = cplus(result, do_res_stat(A_WIS, TRUE));
+ result = cplus(result, do_res_stat(A_INT, TRUE));
+ }
+
+ if (level >= 30)
+ {
+ result = cplus(result, set_image(0));
+ result = cplus(result, heal_insanity(p_ptr->msane * level / 100));
+ }
+
+ return result;
+}
+
+const 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);
+}
+
+casting_result mandos_tale_of_doom_spell()
+{
+ return cast(set_tim_precognition(tale_of_doom_duration()));
+}
+
+const 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);
+}
+
+casting_result mandos_call_to_the_halls_spell()
+{
+ int y, x;
+ s16b m_idx;
+ std::vector<int> summons {
+ test_monster_name("Experienced spirit"),
+ test_monster_name("Wise spirit")
+ };
+
+ int r_idx = summons[rand_int(summons.size())];
+ 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_OBVIOUS;
+ }
+ return NO_CAST;
+}
+
+const char *mandos_call_to_the_halls_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "level %d",
+ 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);
+}
+
+casting_result ulmo_song_of_belegaer_spell()
+{
+ int dir, dice, sides;
+
+ if (!get_aim_dir(&dir))
+ {
+ return NO_CAST;
+ }
+
+ get_belegaer_damage(&dice, &sides);
+ return cast(fire_bolt_or_beam(2 * get_level_s(ULMO_BELEGAER, 85),
+ GF_WATER,
+ dir,
+ damroll(dice, sides)));
+}
+
+const 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);
+}
+
+casting_result ulmo_draught_of_ulmonan_spell()
+{
+ casting_result result = NO_CAST;
+ s32b level = get_level_s(ULMO_DRAUGHT_ULMONAN, 50);
+
+ result = cplus(result, hp_player(draught_of_ulmonan_hp()));
+
+ 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)
+ {
+ 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)
+ {
+ result = cplus(result, set_parasite(0, 0));
+ result = cplus(result, set_mimic(0, 0, 0));
+ }
+
+ return result;
+}
+
+const 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);
+}
+
+casting_result ulmo_call_of_the_ulumuri_spell()
+{
+ int x,y;
+ s16b m_idx;
+ std::vector<int> summons {
+ test_monster_name("Water spirit"),
+ test_monster_name("Water elemental")
+ };
+
+ int r_idx = summons[rand_int(summons.size())];
+ 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_OBVIOUS;
+ }
+
+ return NO_CAST;
+}
+
+const 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);
+}
+
+casting_result 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_OBVIOUS;
+}
+
+const 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;
+}
+
+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);
+}
+
+casting_result varda_light_of_valinor_spell()
+{
+ casting_result result = NO_CAST;
+
+ if (get_level_s(VARDA_LIGHT_VALINOR, 50) >= 3)
+ {
+ 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)
+ {
+ result = cplus(result,
+ fire_ball(GF_LITE,
+ 0,
+ light_of_valinor_damage(),
+ light_of_valinor_radius()));
+ }
+
+ return result;
+}
+
+const char *varda_light_of_valinor_info()
+{
+ static char buf[128];
+ if (get_level_s(VARDA_LIGHT_VALINOR, 50) >= 15)
+ {
+ sprintf(buf,
+ "dam %d rad %d",
+ light_of_valinor_damage(),
+ light_of_valinor_radius());
+ return buf;
+ }
+ else
+ {
+ return "";
+ }
+}
+
+casting_result 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_OBVIOUS;
+}
+
+casting_result varda_evenstar_spell()
+{
+ wiz_lite_extra();
+ if (get_level_s(VARDA_EVENSTAR, 50) >= 40)
+ {
+ identify_pack();
+ }
+
+ return CAST_OBVIOUS;
+}
+
+static int star_kindler_bursts()
+{
+ return p_ptr->lev / 5;
+}
+
+static int star_kindler_damage()
+{
+ return 20 + get_level_s(VARDA_STARKINDLER, 100);
+}
+
+casting_result 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_OBVIOUS;
+}
+
+const 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;
+}
+
diff --git a/src/spells3.hpp b/src/spells3.hpp
new file mode 100644
index 00000000..12e6a78f
--- /dev/null
+++ b/src/spells3.hpp
@@ -0,0 +1,444 @@
+#pragma once
+
+#include "spell_type_fwd.hpp"
+#include "h-basic.h"
+#include "timer_type_fwd.hpp"
+
+extern s32b NOXIOUSCLOUD;
+extern s32b AIRWINGS;
+extern s32b INVISIBILITY;
+extern s32b POISONBLOOD;
+extern s32b THUNDERSTORM;
+extern s32b STERILIZE;
+
+casting_result air_noxious_cloud();
+const char *air_noxious_cloud_info();
+casting_result air_wings_of_winds();
+const char *air_wings_of_winds_info();
+casting_result air_invisibility();
+const char *air_invisibility_info();
+casting_result air_poison_blood();
+const char *air_poison_blood_info();
+casting_result air_thunderstorm();
+const char *air_thunderstorm_info();
+casting_result air_sterilize();
+const char *air_sterilize_info();
+
+extern s32b BLINK;
+extern s32b DISARM;
+extern s32b TELEPORT;
+extern s32b TELEAWAY;
+extern s32b RECALL;
+extern s32b PROBABILITY_TRAVEL;
+
+casting_result convey_blink();
+const char *convey_blink_info();
+casting_result convey_teleport();
+const char *convey_teleport_info();
+casting_result convey_teleport_away();
+casting_result convey_recall();
+const char *convey_recall_info();
+casting_result convey_probability_travel();
+const 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;
+
+casting_result demonology_demon_blade();
+const char *demonology_demon_blade_info();
+casting_result demonology_demon_madness();
+const char *demonology_demon_madness_info();
+casting_result demonology_demon_field();
+const char *demonology_demon_field_info();
+casting_result demonology_doom_shield();
+const char *demonology_doom_shield_info();
+casting_result demonology_unholy_word();
+const char *demonology_unholy_word_info();
+casting_result demonology_demon_cloak();
+const char *demonology_demon_cloak_info();
+casting_result demonology_summon_demon();
+const char *demonology_summon_demon_info();
+casting_result demonology_discharge_minion();
+const char *demonology_discharge_minion_info();
+casting_result demonology_control_demon();
+const char *demonology_control_demon_info();
+
+extern s32b STARIDENTIFY;
+extern s32b IDENTIFY;
+extern s32b VISION;
+extern s32b SENSEHIDDEN;
+extern s32b REVEALWAYS;
+extern s32b SENSEMONSTERS;
+
+casting_result divination_greater_identify();
+casting_result divination_identify();
+const char *divination_identify_info();
+casting_result divination_vision();
+casting_result divination_sense_hidden();
+const char *divination_sense_hidden_info();
+casting_result divination_reveal_ways();
+const char *divination_reveal_ways_info();
+casting_result divination_sense_monsters();
+const char *divination_sense_monsters_info();
+
+extern s32b STONESKIN;
+extern s32b DIG;
+extern s32b STONEPRISON;
+extern s32b STRIKE;
+extern s32b SHAKE;
+
+casting_result earth_stone_skin();
+const char *earth_stone_skin_info();
+casting_result earth_dig();
+casting_result earth_stone_prison();
+casting_result earth_strike();
+const char *earth_strike_info();
+casting_result earth_shake();
+const char *earth_shake_info();
+
+extern s32b ERU_SEE;
+extern s32b ERU_LISTEN;
+extern s32b ERU_UNDERSTAND;
+extern s32b ERU_PROT;
+
+casting_result eru_see_the_music();
+const char *eru_see_the_music_info();
+casting_result eru_listen_to_the_music();
+casting_result eru_know_the_music();
+casting_result eru_lay_of_protection();
+const char *eru_lay_of_protection_info();
+
+extern s32b GLOBELIGHT;
+extern s32b FIREFLASH;
+extern s32b FIERYAURA;
+extern s32b FIREWALL;
+extern s32b FIREGOLEM;
+
+casting_result fire_globe_of_light();
+const char *fire_globe_of_light_info();
+casting_result fire_fireflash();
+const char *fire_fireflash_info();
+casting_result fire_fiery_shield();
+const char *fire_fiery_shield_info();
+casting_result fire_firewall();
+const char *fire_firewall_info();
+casting_result fire_golem();
+const 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;
+
+casting_result geomancy_call_the_elements();
+const char *geomancy_call_the_elements_info();
+casting_result geomancy_channel_elements();
+casting_result geomancy_elemental_wave();
+casting_result geomancy_vaporize();
+const char *geomancy_vaporize_info();
+bool_ geomancy_vaporize_depends();
+casting_result geomancy_geolysis();
+const char *geomancy_geolysis_info();
+bool_ geomancy_geolysis_depends();
+casting_result geomancy_dripping_tread();
+const char *geomancy_dripping_tread_info();
+bool_ geomancy_dripping_tread_depends();
+casting_result geomancy_grow_barrier();
+bool_ geomancy_grow_barrier_depends();
+casting_result geomancy_elemental_minion();
+const char *geomancy_elemental_minion_info();
+
+extern s32b MANATHRUST;
+extern s32b DELCURSES;
+extern s32b RESISTS;
+extern s32b MANASHIELD;
+
+casting_result mana_manathrust();
+const char *mana_manathrust_info();
+casting_result mana_remove_curses();
+casting_result mana_elemental_shield();
+const char *mana_elemental_shield_info();
+casting_result mana_disruption_shield();
+const char *mana_disruption_shield_info();
+
+extern s32b MANWE_SHIELD;
+extern s32b MANWE_AVATAR;
+extern s32b MANWE_BLESS;
+extern s32b MANWE_CALL;
+
+casting_result manwe_wind_shield();
+const char *manwe_wind_shield_info();
+casting_result manwe_avatar();
+const char *manwe_avatar_info();
+casting_result manwe_blessing();
+const char *manwe_blessing_info();
+casting_result manwe_call();
+const 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);
+
+casting_result melkor_curse();
+casting_result melkor_corpse_explosion();
+const char *melkor_corpse_explosion_info();
+casting_result melkor_mind_steal();
+const 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;
+
+casting_result meta_recharge();
+const char *meta_recharge_info();
+casting_result meta_spellbinder();
+const char *meta_spellbinder_info();
+casting_result meta_disperse_magic();
+casting_result meta_tracker();
+casting_result meta_inertia_control();
+const 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();
+
+extern s32b CHARM;
+extern s32b CONFUSE;
+extern s32b ARMOROFFEAR;
+extern s32b STUN;
+
+casting_result mind_charm();
+const char *mind_charm_info();
+casting_result mind_confuse();
+const char *mind_confuse_info();
+casting_result mind_armor_of_fear();
+const char *mind_armor_of_fear_info();
+casting_result mind_stun();
+const char *mind_stun_info();
+
+extern s32b MAGELOCK;
+extern s32b SLOWMONSTER;
+extern s32b ESSENCESPEED;
+extern s32b BANISHMENT;
+
+casting_result tempo_magelock();
+casting_result tempo_slow_monster();
+const char *tempo_slow_monster_info();
+casting_result tempo_essence_of_speed();
+const char *tempo_essence_of_speed_info();
+casting_result tempo_banishment();
+const char *tempo_banishment_info();
+
+extern s32b TULKAS_AIM;
+extern s32b TULKAS_WAVE;
+extern s32b TULKAS_SPIN;
+
+casting_result tulkas_divine_aim();
+const char *tulkas_divine_aim_info();
+casting_result tulkas_wave_of_power();
+const char *tulkas_wave_of_power_info();
+casting_result tulkas_whirlwind();
+
+extern s32b DRAIN;
+extern s32b GENOCIDE;
+extern s32b WRAITHFORM;
+extern s32b FLAMEOFUDUN;
+
+int udun_in_book(s32b sval, s32b pval);
+int levels_in_book(s32b sval, s32b pval);
+
+casting_result udun_drain();
+casting_result udun_genocide();
+casting_result udun_wraithform();
+const char *udun_wraithform_info();
+casting_result udun_flame_of_udun();
+const char *udun_flame_of_udun_info();
+
+extern s32b TIDALWAVE;
+extern s32b ICESTORM;
+extern s32b ENTPOTION;
+extern s32b VAPOR;
+extern s32b GEYSER;
+
+casting_result water_tidal_wave();
+const char *water_tidal_wave_info();
+casting_result water_ice_storm();
+const char *water_ice_storm_info();
+casting_result water_ent_potion();
+const char *water_ent_potion_info();
+casting_result water_vapor();
+const char *water_vapor_info();
+casting_result water_geyser();
+const 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;
+
+casting_result yavanna_charm_animal();
+const char *yavanna_charm_animal_info();
+casting_result yavanna_grow_grass();
+const char *yavanna_grow_grass_info();
+casting_result yavanna_tree_roots();
+const char *yavanna_tree_roots_info();
+casting_result yavanna_water_bite();
+const char *yavanna_water_bite_info();
+casting_result yavanna_uproot();
+const char *yavanna_uproot_info();
+
+extern s32b GROWTREE;
+extern s32b HEALING;
+extern s32b RECOVERY;
+extern s32b REGENERATION;
+extern s32b SUMMONANNIMAL;
+extern s32b GROW_ATHELAS;
+
+casting_result nature_grow_trees();
+const char *nature_grow_trees_info();
+casting_result nature_healing();
+const char *nature_healing_info();
+casting_result nature_recovery();
+casting_result nature_regeneration();
+const char *nature_regeneration_info();
+casting_result nature_summon_animal();
+const char *nature_summon_animal_info();
+casting_result nature_grow_athelas();
+
+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_HOLY_FIRE;
+extern s32b DEVICE_THUNDERLORDS;
+
+casting_result device_heal_monster();
+const char *device_heal_monster_info();
+casting_result device_haste_monster();
+const char *device_haste_monster_info();
+casting_result device_wish();
+casting_result device_summon_monster();
+casting_result device_mana();
+const char *device_mana_info();
+casting_result device_nothing();
+casting_result device_holy_fire();
+const char *device_holy_fire_info();
+casting_result device_thunderlords();
+
+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;
+
+casting_result music_stop_singing_spell();
+int music_holding_pattern_lasting();
+casting_result music_holding_pattern_spell();
+const char *music_holding_pattern_info();
+int music_illusion_pattern_lasting();
+casting_result music_illusion_pattern_spell();
+const char *music_illusion_pattern_info();
+int music_stun_pattern_lasting();
+casting_result music_stun_pattern_spell();
+const char *music_stun_pattern_info();
+int music_song_of_the_sun_lasting();
+casting_result music_song_of_the_sun_spell();
+int music_flow_of_life_lasting();
+casting_result music_flow_of_life_spell();
+const char *music_flow_of_life_info();
+int music_heroic_ballad_lasting();
+casting_result music_heroic_ballad_spell();
+int music_hobbit_melodies_lasting();
+casting_result music_hobbit_melodies_spell();
+const char *music_hobbit_melodies_info();
+int music_clairaudience_lasting();
+casting_result music_clairaudience_spell();
+const char *music_clairaudience_info();
+casting_result music_blow_spell();
+const char *music_blow_info();
+casting_result music_gush_of_wind_spell();
+const char *music_gush_of_wind_info();
+casting_result music_horns_of_ylmir_spell();
+const char *music_horns_of_ylmir_info();
+casting_result music_ambarkanta_spell();
+
+extern s32b AULE_FIREBRAND;
+extern s32b AULE_ENCHANT_WEAPON;
+extern s32b AULE_ENCHANT_ARMOUR;
+extern s32b AULE_CHILD;
+
+casting_result aule_firebrand_spell();
+const char *aule_firebrand_info();
+casting_result aule_enchant_weapon_spell();
+const char *aule_enchant_weapon_info();
+casting_result aule_enchant_armour_spell();
+const char *aule_enchant_armour_info();
+casting_result aule_child_spell();
+const char *aule_child_info();
+
+extern s32b MANDOS_TEARS_LUTHIEN;
+extern s32b MANDOS_SPIRIT_FEANTURI;
+extern s32b MANDOS_TALE_DOOM;
+extern s32b MANDOS_CALL_HALLS;
+
+casting_result mandos_tears_of_luthien_spell();
+const char *mandos_tears_of_luthien_info();
+casting_result mandos_spirit_of_the_feanturi_spell();
+const char *mandos_spirit_of_the_feanturi_info();
+casting_result mandos_tale_of_doom_spell();
+const char *mandos_tale_of_doom_info();
+casting_result mandos_call_to_the_halls_spell();
+const 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;
+
+casting_result ulmo_song_of_belegaer_spell();
+const char *ulmo_song_of_belegaer_info();
+casting_result ulmo_draught_of_ulmonan_spell();
+const char *ulmo_draught_of_ulmonan_info();
+casting_result ulmo_call_of_the_ulumuri_spell();
+const char *ulmo_call_of_the_ulumuri_info();
+casting_result ulmo_wrath_of_ulmo_spell();
+const char *ulmo_wrath_of_ulmo_info();
+
+extern s32b VARDA_LIGHT_VALINOR;
+extern s32b VARDA_CALL_ALMAREN;
+extern s32b VARDA_EVENSTAR;
+extern s32b VARDA_STARKINDLER;
+
+casting_result varda_light_of_valinor_spell();
+const char *varda_light_of_valinor_info();
+casting_result varda_call_of_almaren_spell();
+casting_result varda_evenstar_spell();
+casting_result varda_star_kindler_spell();
+const char *varda_star_kindler_info();
diff --git a/src/spells4.cc b/src/spells4.cc
new file mode 100644
index 00000000..97c3d523
--- /dev/null
+++ b/src/spells4.cc
@@ -0,0 +1,537 @@
+#include "spells4.hpp"
+
+#include "cave.hpp"
+#include "cmd5.hpp"
+#include "gods.hpp"
+#include "lua_bind.hpp"
+#include "options.hpp"
+#include "player_type.hpp"
+#include "school_book.hpp"
+#include "spell_type.hpp"
+#include "spells3.hpp"
+#include "spells5.hpp"
+#include "spells6.hpp"
+#include "util.hpp"
+#include "util.h"
+#include "variable.hpp"
+#include "z-rand.hpp"
+
+#include <algorithm>
+#include <array>
+#include <cassert>
+#include <sstream>
+
+static std::array<school_book, SCHOOL_BOOKS_SIZE> &school_books() {
+ static std::array<school_book, SCHOOL_BOOKS_SIZE> *instance = new std::array<school_book, SCHOOL_BOOKS_SIZE>;
+ return *instance;
+}
+
+
+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 bool_ uses_piety_to_cast(int s)
+{
+ return spell_type_uses_piety_to_cast(spell_at(s));
+}
+
+/** 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)
+{
+ spell_type *spell = spell_at(s);
+
+ spell_type_description_foreach(spell,
+ [&y] (std::string const &text) -> void {
+ c_prt(TERM_L_BLUE, text.c_str(), y, 0);
+ y += 1;
+ });
+
+ if (spell_type_uses_piety_to_cast(spell))
+ {
+ c_prt(TERM_L_WHITE, "It uses piety to cast.", y, 0);
+ y++;
+ }
+
+ if (spell_type_castable_while_blind(spell))
+ {
+ c_prt(TERM_ORANGE, "It is castable even while blinded.", y, 0);
+ y++;
+ }
+
+ if (spell_type_castable_while_confused(spell))
+ {
+ c_prt(TERM_ORANGE, "It is castable even while confused.", y, 0);
+ y++;
+ }
+}
+
+school_book *school_books_at(int i)
+{
+ assert(i >= 0);
+ assert(i < SCHOOL_BOOKS_SIZE);
+ return &school_books()[i];
+}
+
+void school_book_add_spell(school_book *school_book, s32b spell_idx)
+{
+ assert(school_book != nullptr);
+ school_book->spell_idxs.insert(std::begin(school_book->spell_idxs), spell_idx);
+}
+
+int school_book_length(int sval)
+{
+ school_book *school_book = school_books_at(sval);
+ return school_book->spell_idxs.size();
+}
+
+int spell_x(int sval, int spell_idx, int i)
+{
+ assert(i >= 0);
+
+ if (sval == BOOK_RANDOM)
+ {
+ return spell_idx;
+ }
+ else
+ {
+ school_book *school_book = school_books_at(sval);
+ return school_book->spell_idxs.at(i);
+ }
+}
+
+bool_ school_book_contains_spell(int sval, s32b spell_idx)
+{
+ random_book_setup(sval, spell_idx);
+ school_book *school_book = school_books_at(sval);
+ return (school_book->spell_idxs.end() !=
+ std::find(school_book->spell_idxs.begin(),
+ school_book->spell_idxs.end(),
+ spell_idx));
+}
+
+static void push_spell(int book_idx, s32b spell_idx)
+{
+ school_book *school_book = school_books_at(book_idx);
+ assert(school_book != NULL);
+ school_book_add_spell(school_book, spell_idx);
+}
+
+void init_school_books()
+{
+ /* Note: We're adding the spells in the reverse order that
+ they appear in each book. This is because the list
+ operations insert at the front. */
+
+ /* Create the crystal of mana */
+ push_spell(TOME_MANA, MANASHIELD);
+ push_spell(TOME_MANA, RESISTS);
+ push_spell(TOME_MANA, DELCURSES);
+ push_spell(TOME_MANA, MANATHRUST);
+
+ /* The book of the eternal flame */
+ push_spell(TOME_FIRE, FIERYAURA);
+ push_spell(TOME_FIRE, FIREWALL);
+ push_spell(TOME_FIRE, FIREFLASH);
+ push_spell(TOME_FIRE, FIREGOLEM);
+ push_spell(TOME_FIRE, GLOBELIGHT);
+
+ /* The book of the blowing winds */
+ push_spell(TOME_WINDS, THUNDERSTORM);
+ push_spell(TOME_WINDS, AIRWINGS);
+ push_spell(TOME_WINDS, STERILIZE);
+ push_spell(TOME_WINDS, INVISIBILITY);
+ push_spell(TOME_WINDS, POISONBLOOD);
+ push_spell(TOME_WINDS, NOXIOUSCLOUD);
+
+ /* The book of the impenetrable earth */
+ push_spell(TOME_EARTH, STRIKE);
+ push_spell(TOME_EARTH, SHAKE);
+ push_spell(TOME_EARTH, STONEPRISON);
+ push_spell(TOME_EARTH, DIG);
+ push_spell(TOME_EARTH, STONESKIN);
+
+ /* The book of the unstopable wave */
+ push_spell(TOME_WATER, ICESTORM);
+ push_spell(TOME_WATER, TIDALWAVE);
+ push_spell(TOME_WATER, ENTPOTION);
+ push_spell(TOME_WATER, VAPOR);
+ push_spell(TOME_WATER, GEYSER);
+
+ /* Create the book of translocation */
+ push_spell(TOME_TRANSLOCATION, PROBABILITY_TRAVEL);
+ push_spell(TOME_TRANSLOCATION, RECALL);
+ push_spell(TOME_TRANSLOCATION, TELEAWAY);
+ push_spell(TOME_TRANSLOCATION, TELEPORT);
+ push_spell(TOME_TRANSLOCATION, BLINK);
+
+ /* Create the book of the tree */
+ if (game_module_idx == MODULE_THEME)
+ {
+ push_spell(TOME_NATURE, GROW_ATHELAS);
+ }
+ push_spell(TOME_NATURE, SUMMONANNIMAL);
+ push_spell(TOME_NATURE, REGENERATION);
+ push_spell(TOME_NATURE, RECOVERY);
+ push_spell(TOME_NATURE, HEALING);
+ push_spell(TOME_NATURE, GROWTREE);
+
+ /* Create the book of Knowledge */
+ push_spell(TOME_KNOWLEDGE, STARIDENTIFY);
+ push_spell(TOME_KNOWLEDGE, VISION);
+ push_spell(TOME_KNOWLEDGE, IDENTIFY);
+ push_spell(TOME_KNOWLEDGE, REVEALWAYS);
+ push_spell(TOME_KNOWLEDGE, SENSEHIDDEN);
+ push_spell(TOME_KNOWLEDGE, SENSEMONSTERS);
+
+ /* Create the book of the Time */
+ push_spell(TOME_TIME, BANISHMENT);
+ push_spell(TOME_TIME, ESSENCESPEED);
+ push_spell(TOME_TIME, SLOWMONSTER);
+ push_spell(TOME_TIME, MAGELOCK);
+
+ /* Create the book of meta spells */
+ push_spell(TOME_META, INERTIA_CONTROL);
+ push_spell(TOME_META, TRACKER);
+ push_spell(TOME_META, SPELLBINDER);
+ push_spell(TOME_META, DISPERSEMAGIC);
+ push_spell(TOME_META, RECHARGE);
+
+ /* Create the book of the mind */
+ push_spell(TOME_MIND, STUN);
+ push_spell(TOME_MIND, ARMOROFFEAR);
+ push_spell(TOME_MIND, CONFUSE);
+ push_spell(TOME_MIND, CHARM);
+
+ /* Create the book of hellflame */
+ push_spell(TOME_HELLFLAME, FLAMEOFUDUN);
+ push_spell(TOME_HELLFLAME, WRAITHFORM);
+ push_spell(TOME_HELLFLAME, GENOCIDE);
+ push_spell(TOME_HELLFLAME, DRAIN);
+
+ /* Create the book of eru */
+ push_spell(TOME_ERU, ERU_PROT);
+ push_spell(TOME_ERU, ERU_UNDERSTAND);
+ push_spell(TOME_ERU, ERU_LISTEN);
+ push_spell(TOME_ERU, ERU_SEE);
+
+ /* Create the book of manwe */
+ push_spell(TOME_MANWE, MANWE_AVATAR);
+ push_spell(TOME_MANWE, MANWE_CALL);
+ push_spell(TOME_MANWE, MANWE_SHIELD);
+ push_spell(TOME_MANWE, MANWE_BLESS);
+
+ /* Create the book of tulkas */
+ push_spell(TOME_TULKAS, TULKAS_WAVE);
+ push_spell(TOME_TULKAS, TULKAS_SPIN);
+ push_spell(TOME_TULKAS, TULKAS_AIM);
+
+ /* Create the book of melkor */
+ push_spell(TOME_MELKOR, MELKOR_MIND_STEAL);
+ push_spell(TOME_MELKOR, MELKOR_CORPSE_EXPLOSION);
+ push_spell(TOME_MELKOR, MELKOR_CURSE);
+
+ /* Create the book of yavanna */
+ push_spell(TOME_YAVANNA, YAVANNA_UPROOT);
+ push_spell(TOME_YAVANNA, YAVANNA_WATER_BITE);
+ push_spell(TOME_YAVANNA, YAVANNA_TREE_ROOTS);
+ push_spell(TOME_YAVANNA, YAVANNA_GROW_GRASS);
+ push_spell(TOME_YAVANNA, YAVANNA_CHARM_ANIMAL);
+
+ /* Create the book of beginner's cantrip */
+ push_spell(BOOK_CANTRIPS, SENSEHIDDEN);
+ push_spell(BOOK_CANTRIPS, SENSEMONSTERS);
+ push_spell(BOOK_CANTRIPS, BLINK);
+ push_spell(BOOK_CANTRIPS, ENTPOTION);
+ push_spell(BOOK_CANTRIPS, GLOBELIGHT);
+ push_spell(BOOK_CANTRIPS, MANATHRUST);
+
+ /* Create the book of teleporatation */
+ push_spell(BOOK_TELEPORTATION, TELEAWAY);
+ push_spell(BOOK_TELEPORTATION, TELEPORT);
+ push_spell(BOOK_TELEPORTATION, BLINK);
+
+ /* Create the book of summoning */
+ push_spell(BOOK_SUMMONING, SUMMONANNIMAL);
+ push_spell(BOOK_SUMMONING, FIREGOLEM);
+
+ /* Create the Armageddon Demonblade */
+ push_spell(BOOK_DEMON_SWORD, DEMON_FIELD);
+ push_spell(BOOK_DEMON_SWORD, DEMON_MADNESS);
+ push_spell(BOOK_DEMON_SWORD, DEMON_BLADE);
+
+ /* Create the Shield Demonblade */
+ push_spell(BOOK_DEMON_SHIELD, UNHOLY_WORD);
+ push_spell(BOOK_DEMON_SHIELD, DEMON_CLOAK);
+ push_spell(BOOK_DEMON_SHIELD, DOOM_SHIELD);
+
+ /* Create the Control Demonblade */
+ push_spell(BOOK_DEMON_HELM, CONTROL_DEMON);
+ push_spell(BOOK_DEMON_HELM, DISCHARGE_MINION);
+ push_spell(BOOK_DEMON_HELM, DEMON_SUMMON);
+
+ /* Create the Drums */
+ push_spell(BOOK_DRUMS, MUSIC_STUN);
+ push_spell(BOOK_DRUMS, MUSIC_CONF);
+ push_spell(BOOK_DRUMS, MUSIC_HOLD);
+ push_spell(BOOK_DRUMS, MUSIC_STOP);
+
+ /* Create the Harps */
+ push_spell(BOOK_HARPS, MUSIC_MIND);
+ push_spell(BOOK_HARPS, MUSIC_TIME);
+ push_spell(BOOK_HARPS, MUSIC_HEAL);
+ push_spell(BOOK_HARPS, MUSIC_HERO);
+ push_spell(BOOK_HARPS, MUSIC_LITE);
+ push_spell(BOOK_HARPS, MUSIC_STOP);
+
+ /* Create the Horns */
+ push_spell(BOOK_HORNS, MUSIC_AMBARKANTA);
+ push_spell(BOOK_HORNS, MUSIC_YLMIR);
+ push_spell(BOOK_HORNS, MUSIC_WIND);
+ push_spell(BOOK_HORNS, MUSIC_BLOW);
+ push_spell(BOOK_HORNS, MUSIC_STOP);
+
+ /* Book of the Player, filled in by the Library Quest */
+ push_spell(BOOK_PLAYER, -1);
+
+ /* Geomancy spells, not a real book */
+ push_spell(BOOK_GEOMANCY, ELEMENTAL_MINION);
+ push_spell(BOOK_GEOMANCY, GROW_BARRIER);
+ push_spell(BOOK_GEOMANCY, DRIPPING_TREAD);
+ push_spell(BOOK_GEOMANCY, GEOLYSIS);
+ push_spell(BOOK_GEOMANCY, VAPORIZE);
+ push_spell(BOOK_GEOMANCY, ELEMENTAL_WAVE);
+ push_spell(BOOK_GEOMANCY, CHANNEL_ELEMENTS);
+ push_spell(BOOK_GEOMANCY, CALL_THE_ELEMENTS);
+
+ if (game_module_idx == MODULE_THEME)
+ {
+ /* Aule */
+ push_spell(BOOK_AULE, AULE_CHILD);
+ push_spell(BOOK_AULE, AULE_ENCHANT_ARMOUR);
+ push_spell(BOOK_AULE, AULE_ENCHANT_WEAPON);
+ push_spell(BOOK_AULE, AULE_FIREBRAND);
+
+ /* Varda */
+ push_spell(BOOK_VARDA, VARDA_STARKINDLER);
+ push_spell(BOOK_VARDA, VARDA_EVENSTAR);
+ push_spell(BOOK_VARDA, VARDA_CALL_ALMAREN);
+ push_spell(BOOK_VARDA, VARDA_LIGHT_VALINOR);
+
+ /* Ulmo */
+ push_spell(BOOK_ULMO, ULMO_WRATH);
+ push_spell(BOOK_ULMO, ULMO_CALL_ULUMURI);
+ push_spell(BOOK_ULMO, ULMO_DRAUGHT_ULMONAN);
+ push_spell(BOOK_ULMO, ULMO_BELEGAER);
+
+ /* Mandos */
+ push_spell(BOOK_MANDOS, MANDOS_CALL_HALLS);
+ push_spell(BOOK_MANDOS, MANDOS_TALE_DOOM);
+ push_spell(BOOK_MANDOS, MANDOS_SPIRIT_FEANTURI);
+ push_spell(BOOK_MANDOS, MANDOS_TEARS_LUTHIEN);
+ }
+
+ /* Random spell book; just initialize to anything */
+ push_spell(BOOK_RANDOM, -1);
+}
+
+void random_book_setup(s16b sval, s32b spell_idx)
+{
+ if (sval == BOOK_RANDOM)
+ {
+ school_book *school_book = school_books_at(sval);
+ school_book->spell_idxs.clear();
+ school_book->spell_idxs.push_back(spell_idx);
+ }
+}
+
+static std::string spell_school_name(spell_type *spell)
+{
+ std::ostringstream buf;
+ bool first = true;
+
+ for (s32b school_idx : spell_type_get_schools(spell))
+ {
+ school_type *school = school_at(school_idx);
+ // Add separator?
+ if (first)
+ {
+ first = false; // Skip separator
+ }
+ else
+ {
+ buf << "/";
+ }
+ // Put in the school's name
+ buf << school->name;
+ }
+
+ return buf.str();
+}
+
+int print_spell(cptr label_, byte color, int y, s32b s)
+{
+ s32b level;
+ bool_ na;
+ spell_type *spell = spell_at(s);
+ cptr spell_info = spell_type_info(spell);
+ cptr label = (label_ == NULL) ? "" : label_;
+ char level_str[8] = "n/a";
+ char buf[128];
+
+ get_level_school(spell, 50, -50, &level, &na);
+
+ std::string sch_str(spell_school_name(spell));
+
+ if (!na)
+ {
+ sprintf(level_str, "%3d", (int) level);
+ }
+
+ sprintf(buf, "%s%-20s%-16s %s %4d %3d%% %s",
+ label,
+ spell_type_name(spell_at(s)),
+ sch_str.c_str(),
+ level_str,
+ get_mana(s),
+ (int) spell_chance_book(s),
+ spell_info);
+ c_prt(color, buf, y, 0);
+
+ return y + 1;
+}
+
+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)
+ {
+ 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 (!spell_type_castable_while_blind(spell) &&
+ ((p_ptr->blind > 0) || no_lite()))
+ {
+ msg_print("You cannot see!");
+ return;
+ }
+
+ /* Not when confused */
+ if (!spell_type_castable_while_confused(spell) &&
+ (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_book(s)))
+ {
+ use = (spell_type_produce_effect(spell) != NO_CAST);
+ }
+ else
+ {
+ use = TRUE;
+
+ /* failures are dangerous; we'll flush the input buffer
+ so it isn't missed. */
+ flush_on_failure();
+
+ msg_print("You failed to get the spell off!");
+ }
+ }
+ else
+ {
+ spell_type_produce_effect(spell);
+ }
+
+ /* 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_FRAME;
+ p_ptr->window |= PW_PLAYER;
+}
diff --git a/src/spells4.hpp b/src/spells4.hpp
new file mode 100644
index 00000000..02cdc3ce
--- /dev/null
+++ b/src/spells4.hpp
@@ -0,0 +1,42 @@
+#pragma once
+
+#include "h-basic.h"
+#include "object_type_fwd.hpp"
+#include "school_book_fwd.hpp"
+
+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();
+school_book *school_books_at(int sval);
+void school_book_add_spell(school_book *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 school_book_length(int sval);
+int spell_x(int sval, int spell_idx, int i);
+bool_ school_book_contains_spell(int sval, s32b spell_idx);
+void lua_cast_school_spell(s32b spell_idx, bool_ no_cost);
diff --git a/src/spells5.cc b/src/spells5.cc
new file mode 100644
index 00000000..ba2e6d05
--- /dev/null
+++ b/src/spells5.cc
@@ -0,0 +1,2370 @@
+#include "spells5.hpp"
+
+#include "spell_type.hpp"
+#include "device_allocation.hpp"
+#include "spells3.hpp"
+#include "spells4.hpp"
+#include "variable.hpp"
+#include "z-rand.hpp"
+
+#include <cassert>
+
+static s16b school_spells_count = 0;
+static struct spell_type *school_spells[SCHOOL_SPELLS_MAX];
+
+static spell_type *spell_new(s32b *index, cptr name)
+{
+ assert(school_spells_count < SCHOOL_SPELLS_MAX);
+
+ spell_type *spell = spell_type_new(name);
+ school_spells[school_spells_count] = spell;
+ *index = school_spells_count;
+ school_spells_count++;
+
+ return spell;
+}
+
+static cptr no_info()
+{
+ return "";
+}
+
+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++)
+ {
+ if (streq(spell_type_name(spell_at(i)), 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 ((spell_type_random_type(spell) == random_type) &&
+ (rand_int(spell_type_skill_level(spell) * 3) < level))
+ {
+ return spl;
+ }
+ }
+
+ return -1;
+}
+
+/*
+ * Get a spell for a device of a given tval (wand or staff).
+ */
+s16b 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 = spell_type_device_allocation(spell, tval);
+
+ if ((device_allocation != NULL) &&
+ (rand_int(spell_type_skill_level(spell) * 3) < level) &&
+ (magik(100 - device_allocation->rarity)))
+ {
+ return spell_idx;
+ }
+ }
+
+ return -1;
+}
+
+static void spells_init_tome()
+{
+ {
+ spell_type *spell = spell_new(&DEVICE_THUNDERLORDS, "Artifact Thunderlords");
+ 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,
+ no_info,
+ device_thunderlords);
+
+ 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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+}
+
+static void spells_init_theme()
+{
+ {
+ spell_type *spell = spell_new(&GROW_ATHELAS, "Grow Athelas");
+ 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,
+ no_info,
+ nature_grow_athelas);
+
+ 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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&AULE_FIREBRAND, "Firebrand");
+ 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, "Enchant Weapon");
+ 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, "Enchant Armour");
+ 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, "Child of Aule");
+ 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, "Light of Valinor");
+ 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, "Call of Almaren");
+ 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,
+ no_info,
+ varda_call_of_almaren_spell);
+ }
+
+ {
+ spell_type *spell = spell_new(&VARDA_EVENSTAR, "Evenstar");
+ 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,
+ no_info,
+ varda_evenstar_spell);
+ }
+
+ {
+ spell_type *spell = spell_new(&VARDA_STARKINDLER, "Star Kindler");
+ 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, "Song of Belegaer");
+ 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, "Draught of Ulmonan");
+ 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, "Call of the Ulumuri");
+ 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, "Wrath of Ulmo");
+ 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, "Tears of Luthien");
+ 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, "Feanturi");
+ 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, "Tale of Doom");
+ 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, "Call to the Halls");
+ 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, "Artifact Thunderlords");
+ 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,
+ no_info,
+ device_thunderlords);
+
+ 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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+}
+
+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, "Globe of Light");
+ 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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&FIREFLASH, "Fireflash");
+ 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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&FIERYAURA, "Fiery Shield");
+ 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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&FIREWALL, "Firewall");
+ 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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&FIREGOLEM, "Fire Golem");
+ 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");
+ 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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&DELCURSES, "Remove Curses");
+ 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,
+ no_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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&RESISTS, "Elemental Shield");
+ 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, "Disruption Shield");
+ 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, "Tidal Wave");
+ 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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&ICESTORM, "Ice Storm");
+ 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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&ENTPOTION, "Ent's Potion");
+ 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");
+ 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");
+ 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, "Noxious Cloud");
+ 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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&AIRWINGS, "Wings of Winds");
+ 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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&INVISIBILITY, "Invisibility");
+ 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, "Poison Blood");
+ 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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&THUNDERSTORM, "Thunderstorm");
+ 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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&STERILIZE, "Sterilize");
+ 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);
+
+ 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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&STONESKIN, "Stone Skin");
+ 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");
+ 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,
+ no_info,
+ earth_dig);
+
+ 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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&STONEPRISON, "Stone Prison");
+ 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,
+ no_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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&STRIKE, "Strike");
+ 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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&SHAKE, "Shake");
+ 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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&BLINK, "Phase Door");
+ 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(&TELEPORT, "Teleportation");
+ 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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&TELEAWAY, "Teleport Away");
+ 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,
+ no_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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&RECALL, "Recall");
+ 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");
+ 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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&GROWTREE, "Grow Trees");
+ 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");
+ 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);
+
+ 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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&RECOVERY, "Recovery");
+ 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,
+ no_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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&REGENERATION, "Regeneration");
+ 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, "Summon Animal");
+ 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);
+
+ 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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&STARIDENTIFY, "Greater Identify");
+ 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,
+ no_info,
+ divination_greater_identify);
+ }
+
+ {
+ spell_type *spell = spell_new(&IDENTIFY, "Identify");
+ 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");
+ 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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&VISION, "Vision");
+ 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,
+ no_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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&SENSEHIDDEN, "Sense Hidden");
+ 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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&REVEALWAYS, "Reveal Ways");
+ 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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&SENSEMONSTERS, "Sense Monsters");
+ 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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&MAGELOCK, "Magelock");
+ 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,
+ no_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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&SLOWMONSTER, "Slow Monster");
+ 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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&ESSENCESPEED, "Essence of Speed");
+ 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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&BANISHMENT, "Banishment");
+ 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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&RECHARGE, "Recharge");
+ 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");
+ 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, "Disperse Magic");
+ 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,
+ no_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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&TRACKER, "Tracker");
+ 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,
+ no_info,
+ meta_tracker);
+ }
+
+ {
+ spell_type *spell = spell_new(&INERTIA_CONTROL, "Inertia Control");
+ 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");
+ 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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&CONFUSE, "Confuse");
+ 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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&ARMOROFFEAR, "Armor of Fear");
+ 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");
+ 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");
+ 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,
+ no_info,
+ udun_drain);
+ }
+
+ {
+ spell_type *spell = spell_new(&GENOCIDE, "Genocide");
+ 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,
+ no_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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&WRAITHFORM, "Wraithform");
+ 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, "Flame of Udun");
+ 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");
+ 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");
+ 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,
+ no_info,
+ geomancy_channel_elements);
+ }
+
+ {
+ spell_type *spell = spell_new(&ELEMENTAL_WAVE, "Elemental Wave");
+ 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,
+ no_info,
+ geomancy_elemental_wave);
+ }
+
+ {
+ spell_type *spell = spell_new(&VAPORIZE, "Vaporize");
+ 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");
+ 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");
+ 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");
+ 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,
+ no_info,
+ geomancy_grow_barrier,
+ geomancy_grow_barrier_depends);
+ }
+
+ {
+ spell_type *spell = spell_new(&ELEMENTAL_MINION, "Elemental Minion");
+ 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, "See the Music");
+ 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, "Listen to the Music");
+ 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,
+ no_info,
+ eru_listen_to_the_music);
+ }
+
+ {
+ spell_type *spell = spell_new(&ERU_UNDERSTAND, "Know the Music");
+ 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,
+ no_info,
+ eru_know_the_music);
+ }
+
+ {
+ spell_type *spell = spell_new(&ERU_PROT, "Lay of Protection");
+ 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, "Wind Shield");
+ 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, "Avatar");
+ 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's Blessing");
+ 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's Call");
+ 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, "Divine Aim");
+ 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, "Wave of Power");
+ 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, "Whirlwind");
+ 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,
+ no_info,
+ tulkas_whirlwind);
+ }
+
+ {
+ spell_type *spell = spell_new(&MELKOR_CURSE, "Curse");
+ 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,
+ no_info,
+ melkor_curse);
+ }
+
+ {
+ spell_type *spell = spell_new(&MELKOR_CORPSE_EXPLOSION, "Corpse Explosion");
+ 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, "Mind Steal");
+ 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, "Charm Animal");
+ 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, "Grow Grass");
+ 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, "Tree Roots");
+ 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, "Water Bite");
+ 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, "Uproot");
+ 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");
+ 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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&DEMON_MADNESS, "Demon Madness");
+ 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");
+ 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");
+ 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");
+ 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");
+ 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, "Summon Demon");
+ 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");
+ 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");
+ 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, "Heal Monster");
+ 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);
+
+ 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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&DEVICE_SPEED_MONSTER, "Haste Monster");
+ 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);
+
+ 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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&DEVICE_WISH, "Wish");
+ 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,
+ no_info,
+ device_wish);
+
+ 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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&DEVICE_SUMMON, "Summon");
+ 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,
+ no_info,
+ device_summon_monster);
+
+ 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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&DEVICE_MANA, "Mana");
+ 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);
+
+ 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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&DEVICE_NOTHING, "Nothing");
+ 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,
+ no_info,
+ device_nothing);
+
+ 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);
+ spell_type_add_device_allocation(spell, 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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&DEVICE_HOLY_FIRE, "Holy Fire of Mithrandir");
+ 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);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ spell_type *spell = spell_new(&MUSIC_STOP, "Stop singing(I)");
+ 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,
+ no_info,
+ music_stop_singing_spell);
+ }
+
+ {
+ spell_type *spell = spell_new(&MUSIC_HOLD, "Holding Pattern(I)");
+ 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, "Illusion Pattern(II)");
+ 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, "Stun Pattern(IV)");
+ 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, "Song of the Sun(I)");
+ 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,
+ no_info,
+ music_song_of_the_sun_spell,
+ music_song_of_the_sun_lasting);
+ }
+
+ {
+ spell_type *spell = spell_new(&MUSIC_HEAL, "Flow of Life(II)");
+ 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, "Heroic Ballad(II)");
+ 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,
+ no_info,
+ music_heroic_ballad_spell,
+ music_heroic_ballad_lasting);
+ }
+
+ {
+ spell_type *spell = spell_new(&MUSIC_TIME, "Hobbit Melodies(III)");
+ 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, "Clairaudience(IV)");
+ 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, "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, "Blow(I)");
+ 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, "Gush of Wind(II)");
+ 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, "Horns of Ylmir(III)");
+ 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, "Ambarkanta(IV)");
+ 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,
+ no_info,
+ music_ambarkanta_spell);
+ }
+
+ /* 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/spells5.hpp b/src/spells5.hpp
new file mode 100644
index 00000000..7359fa16
--- /dev/null
+++ b/src/spells5.hpp
@@ -0,0 +1,9 @@
+#pragma once
+
+#include "h-basic.h"
+
+void school_spells_init();
+struct spell_type *spell_at(s32b index);
+s16b get_random_spell(s16b random_type, int lev);
+s16b get_random_stick(byte tval, int level);
+int find_spell(cptr name);
diff --git a/src/spells6.cc b/src/spells6.cc
new file mode 100644
index 00000000..555f252f
--- /dev/null
+++ b/src/spells6.cc
@@ -0,0 +1,407 @@
+#include "spells6.hpp"
+
+#include "game.hpp"
+#include "gods.hpp"
+#include "lua_bind.hpp"
+#include "object2.hpp"
+#include "object_type.hpp"
+#include "player_type.hpp"
+#include "skills.hpp"
+#include "skill_type.hpp"
+#include "spell_type.hpp"
+#include "spells4.hpp"
+#include "variable.hpp"
+
+#include <cassert>
+#include <vector>
+#include <type_traits>
+
+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 */
+};
+
+struct school_provider_list {
+public:
+ std::vector<school_provider> v;
+};
+
+static school_provider school_provider_new(byte deity_idx, long mul, long div)
+{
+ school_provider p;
+ p.deity_idx = deity_idx;
+ p.skill_idx = SKILL_PRAY;
+ p.mul = mul;
+ p.div = div;
+ return p;
+}
+
+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);
+
+ static_assert(std::is_pod<school_type>::value, "Cannot initialize non-POD using memset!");
+ memset(school, 0, sizeof(school_type));
+
+ school->providers = new school_provider_list();
+ 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)
+{
+ assert(school->providers != nullptr);
+
+ deity_type *deity = god_at(god);
+ assert(deity != NULL);
+
+ /* Ignore gods which aren't enabled for this module. */
+ if (god_enabled(deity))
+ {
+ school->providers->v.push_back(school_provider_new(god, mul, div));
+ }
+}
+
+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)
+{
+ auto const &s_info = game->s_info;
+
+ for (auto school_provider: school->providers->v)
+ {
+ if (school_provider.deity_idx == p_ptr->pgod)
+ {
+ return (s_info[school_provider.skill_idx].value * school_provider.mul) / school_provider.div;
+ }
+ }
+
+ return 0;
+}
+
+struct get_level_school_callback_data {
+ bool_ allow_spell_power;
+ long bonus;
+ long lvl;
+ long num;
+};
+
+static bool get_level_school_callback(struct get_level_school_callback_data *data, int school_idx)
+{
+ auto const &s_info = game->s_info;
+
+ school_type *school = school_at(school_idx);
+ 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))
+ {
+ return false;
+ }
+
+ /* Take the basic skill value */
+ r = s_info[school->skill].value;
+
+ /* Do we pass tests? */
+ if ((school->depends_satisfied != NULL) &&
+ (!school->depends_satisfied()))
+ {
+ return false;
+ }
+
+ /* 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)
+ {
+ data->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)
+ {
+ data->bonus += (school->bonus_levels() * (SKILL_STEP / 10));
+ }
+
+ /* All schools must be non-zero to be able to use it. */
+ if (ok <= 0)
+ {
+ return false;
+ }
+
+ /* Apply it */
+ data->lvl += ok;
+ data->num += 1;
+
+ /* Keep going */
+ return true;
+}
+
+void get_level_school(spell_type *spell, s32b max, s32b min, s32b *level, bool_ *na)
+{
+ assert(level != NULL);
+ assert(na != NULL);
+
+ /* 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 and count up all the
+ // levels and make sure we can actually cast the spell.
+ for (auto school_idx : spell_type_get_schools(spell))
+ {
+ if (!get_level_school_callback(&data, school_idx))
+ {
+ *level = min;
+ *na = TRUE;
+ return;
+ }
+ }
+
+ /* Add the Spellpower skill as a bonus on top */
+ if (data.allow_spell_power)
+ {
+ data.bonus += (get_skill_scale(SKILL_SPELL, 20) * (SKILL_STEP / 10));
+ }
+
+ /* Add bonus from objects */
+ 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. */
+ data.lvl = (data.lvl / data.num) / 10;
+ data.lvl = lua_get_level(spell, data.lvl, max, min, data.bonus);
+
+ /* Result */
+ *level = data.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_MUSIC, "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/spells6.hpp b/src/spells6.hpp
new file mode 100644
index 00000000..bbd32d9b
--- /dev/null
+++ b/src/spells6.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "school_type_fwd.hpp"
+
+void schools_init();
+school_type *school_at(int index);
+void mana_school_calc_mana(int *msp);
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..b06367a8
--- /dev/null
+++ b/src/squelch/automatizer.cc
@@ -0,0 +1,281 @@
+#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 "util.hpp"
+#include "z-term.h"
+
+namespace squelch {
+
+/**
+ * Parse rules from JSON array
+ */
+static std::vector< std::shared_ptr < Rule > > parse_rules(jsoncons::json const &rules_json)
+{
+ std::vector< std::shared_ptr < Rule > > rules;
+
+ if (!rules_json.is_array())
+ {
+ msg_format("Error 'rules' is not an array");
+ return rules;
+ }
+
+ auto rules_array = rules_json.array_value();
+
+ for (auto const &rule_value : rules_array)
+ {
+ auto rule = Rule::parse_rule(rule_value);
+ 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 false;
+}
+
+jsoncons::json Automatizer::to_json() const
+{
+ auto document = jsoncons::json::array();
+
+ for (auto rule : m_rules)
+ {
+ document.push_back(rule->to_json());
+ }
+
+ return document;
+}
+
+void Automatizer::load_json(jsoncons::json const &document)
+{
+ // Go through all the found rules
+ auto rules = parse_rules(document);
+
+ // 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<std::shared_ptr<Condition> ()> factory)
+{
+ m_rules.at(m_selected_rule)->add_new_condition(
+ m_cursor.get(),
+ factory);
+}
+
+std::vector<std::string> Automatizer::get_rule_names() const
+{
+ std::vector<std::string> names;
+ names.reserve(m_rules.size());
+ for (auto const &rule: m_rules)
+ {
+ names.push_back(rule->get_name());
+ }
+ return names;
+}
+
+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.
+ {
+ int rules_size = m_rules.size(); // Convert to int to avoid warnings
+
+ if (m_selected_rule < 0)
+ {
+ m_selected_rule = 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 >= 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<Rule> 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..cd7f879c
--- /dev/null
+++ b/src/squelch/condition.cc
@@ -0,0 +1,1106 @@
+#include "tome/squelch/condition_fwd.hpp"
+#include "tome/squelch/condition.hpp"
+
+#include <boost/algorithm/string/predicate.hpp>
+
+#include "tome/squelch/cursor.hpp"
+#include "tome/squelch/tree_printer.hpp"
+#include "../ability_type.hpp"
+#include "../game.hpp"
+#include "../object1.hpp"
+#include "../object2.hpp"
+#include "../object_kind.hpp"
+#include "../object_type.hpp"
+#include "../player_race.hpp"
+#include "../player_race_mod.hpp"
+#include "../player_spec.hpp"
+#include "../player_type.hpp"
+#include "../skills.hpp"
+#include "../skill_type.hpp"
+#include "../util.hpp"
+#include "../variable.hpp"
+
+namespace squelch {
+
+EnumStringMap<match_type> &match_mapping()
+{
+ // TODO: This is quite ugly and leads to valgrind complaints
+ static auto m = new EnumStringMap<match_type> {
+ { 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> &identification_state_mapping()
+{
+ // TODO: This is quite ugly and leads to valgrind complaints
+ static auto m = new EnumStringMap<identification_state> {
+ { identification_state::IDENTIFIED, "identified" },
+ { identification_state::NOT_IDENTIFIED, "not identified" } };
+ return *m;
+}
+
+jsoncons::json Condition::to_json() const
+{
+ // Start with an object with only 'type' property
+ jsoncons::json j;
+ j["type"] = match_mapping().stringify(match);
+
+ // Add sub-class properties
+ to_json(j);
+ // Return the completed JSON
+ 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> Condition::parse_condition(jsoncons::json const &condition_json)
+{
+ // Parsers for concrete types of conditions.
+ static std::map< match_type,
+ std::function<std::shared_ptr<Condition>(jsoncons::json const &)>> 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.is_null())
+ {
+ return nullptr;
+ }
+
+ cptr type_s = condition_json.get("type").as<cptr>();
+ if (!type_s)
+ {
+ 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;
+}
+
+jsoncons::json Condition::optional_to_json(std::shared_ptr<Condition> condition)
+{
+ return condition
+ ? condition->to_json()
+ : jsoncons::json::null_type();
+}
+
+bool TvalCondition::is_match(object_type *o_ptr) const
+{
+ return (o_ptr->tval == m_tval);
+}
+
+std::shared_ptr<Condition> TvalCondition::from_json(jsoncons::json const &j)
+{
+ auto tval_j = j.get("tval");
+ if (!tval_j.is_uinteger())
+ {
+ msg_print("Missing/invalid 'tval' property");
+ return nullptr;
+ }
+
+ int tval = tval_j.as_uint();
+
+ return std::make_shared<TvalCondition>(tval);
+}
+
+void TvalCondition::to_json(jsoncons::json &j) const
+{
+ j["tval"] = 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<Condition> NameCondition::from_json(jsoncons::json const &j)
+{
+ cptr s = j.get("name").as<cptr>();
+
+ if (!s)
+ {
+ msg_print("Missing/invalid 'name' property");
+ return nullptr;
+ }
+
+ return std::make_shared<NameCondition>(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(jsoncons::json &j) const
+{
+ j["name"] = m_name;
+}
+
+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<Condition> ContainCondition::from_json(jsoncons::json const &j)
+{
+ cptr s = j.get("contain").as<cptr>();
+
+ if (!s)
+ {
+ msg_print("Missing/invalid 'contain' property");
+ return nullptr;
+ }
+
+ return std::make_shared<ContainCondition>(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(jsoncons::json &j) const
+{
+ j["contain"] = m_contain;
+}
+
+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<Condition> SvalCondition::from_json(jsoncons::json const &j)
+{
+ auto min_j = j.get("min");
+ if (!min_j.is_uinteger())
+ {
+ msg_print("Missing/invalid 'min' property");
+ return nullptr;
+ }
+
+ auto max_j = j.get("max");
+ if (!max_j.is_uinteger())
+ {
+ msg_print("Missing/invalid 'max' property");
+ return nullptr;
+ }
+
+ return std::make_shared<SvalCondition>(
+ min_j.as_uint(),
+ max_j.as_uint());
+}
+
+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(jsoncons::json &j) const
+{
+ j["min"] = m_min;
+ j["max"] = 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)
+{
+ m_conditions.erase(
+ std::remove_if(
+ std::begin(m_conditions),
+ std::end(m_conditions),
+ [&] (std::shared_ptr<Condition> p) {
+ return p.get() == condition;
+ }),
+ std::end(m_conditions));
+}
+
+std::shared_ptr<Condition> GroupingCondition::first_child()
+{
+ if (!m_conditions.empty())
+ {
+ return m_conditions.front();
+ }
+ return nullptr;
+}
+
+std::shared_ptr<Condition> GroupingCondition::previous_child(Condition *current)
+{
+ std::shared_ptr<Condition> 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<Condition> 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<Condition> > GroupingCondition::parse_conditions(jsoncons::json const &j)
+{
+ auto conditions_j = j.get("conditions");
+
+ if (conditions_j.is_null())
+ {
+ return std::vector< std::shared_ptr<Condition> >();
+ }
+ else if (!conditions_j.is_array())
+ {
+ msg_print("'conditions' property has invalid type");
+ return std::vector< std::shared_ptr<Condition> >();
+ }
+ else
+ {
+ std::vector< std::shared_ptr<Condition> > subconditions;
+ for (auto const &subcondition_j: conditions_j.array_value())
+ {
+ std::shared_ptr<Condition> subcondition =
+ parse_condition(subcondition_j);
+
+ if (subcondition != nullptr)
+ {
+ subconditions.push_back(subcondition);
+ }
+ }
+ return subconditions;
+ }
+}
+
+void GroupingCondition::to_json(jsoncons::json &j) const
+{
+ // Put all the sub-conditions into an array
+ jsoncons::json::array ja;
+ for (auto condition_p : m_conditions)
+ {
+ ja.push_back(optional_to_json(condition_p));
+ }
+ // Add to JSON object
+ 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<Condition> AndCondition::from_json(jsoncons::json const &j)
+{
+ auto condition = std::make_shared<AndCondition>();
+ 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<Condition> OrCondition::from_json(jsoncons::json const &j)
+{
+ std::shared_ptr<OrCondition> condition =
+ std::make_shared<OrCondition>();
+
+ 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<Condition> StatusCondition::from_json(jsoncons::json const &j)
+{
+ cptr s = j.get("status").as<cptr>();
+
+ if (!s)
+ {
+ 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<StatusCondition>(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(jsoncons::json &j) const
+{
+ j["status"] = status_mapping().stringify(m_status);
+}
+
+bool RaceCondition::is_match(object_type *o_ptr) const
+{
+ return boost::algorithm::iequals(m_race, rp_ptr->title);
+}
+
+std::shared_ptr<Condition> RaceCondition::from_json(jsoncons::json const &j)
+{
+ cptr s = j.get("race").as<cptr>();
+
+ if (!s)
+ {
+ msg_print("Missing/invalid 'race' property");
+ return nullptr;
+ }
+
+ return std::make_shared<RaceCondition>(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(jsoncons::json &j) const
+{
+ j["race"] = m_race;
+}
+
+bool SubraceCondition::is_match(object_type *o_ptr) const
+{
+ return boost::algorithm::iequals(m_subrace, rmp_ptr->title);
+}
+
+std::shared_ptr<Condition> SubraceCondition::from_json(jsoncons::json const &j)
+{
+ cptr s = j.get("subrace").as<cptr>();
+
+ if (!s)
+ {
+ msg_print("Missing/invalid 'subrace' property");
+ return nullptr;
+ }
+
+ return std::make_shared<SubraceCondition>(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(jsoncons::json &j) const
+{
+ j["subrace"] = m_subrace;
+}
+
+bool ClassCondition::is_match(object_type *o_ptr) const
+{
+ return boost::algorithm::iequals(m_class, spp_ptr->title);
+}
+
+std::shared_ptr<Condition> ClassCondition::from_json(jsoncons::json const &j)
+{
+ cptr s = j.get("class").as<cptr>();
+
+ if (!s)
+ {
+ msg_print("Missing/invalid 'class' property");
+ return nullptr;
+ }
+
+ return std::make_shared<ClassCondition>(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(jsoncons::json &j) const
+{
+ j["class"] = m_class;
+}
+
+bool InscriptionCondition::is_match(object_type *o_ptr) const
+{
+ return boost::algorithm::icontains(
+ o_ptr->inscription,
+ m_inscription);
+}
+
+std::shared_ptr<Condition> InscriptionCondition::from_json(jsoncons::json const &j)
+{
+ cptr s = j.get("inscription").as<cptr>();
+
+ if (!s)
+ {
+ msg_print("Missing/invalid 'inscription' property");
+ return nullptr;
+ }
+
+ return std::make_shared<InscriptionCondition>(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(jsoncons::json &j) const
+{
+ j["inscription"] = m_inscription;
+}
+
+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<Condition> DiscountCondition::from_json(jsoncons::json const &j)
+{
+ auto min_j = j.get("min");
+ if (!min_j.is_integer())
+ {
+ msg_print("Missing/invalid 'min' property");
+ return nullptr;
+ }
+ int min = min_j.as_int();
+
+ auto max_j = j.get("max");
+ if (!max_j.is_integer())
+ {
+ msg_print("Missing/invalid 'max' property");
+ return nullptr;
+ }
+ int max = max_j.as_int();
+
+ return std::make_shared<DiscountCondition>(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(jsoncons::json &j) const
+{
+ j["min"] = m_min;
+ j["max"] = m_max;
+}
+
+bool LevelCondition::is_match(object_type *) const
+{
+ return ((p_ptr->lev >= m_min) &&
+ (p_ptr->lev <= m_max));
+}
+
+std::shared_ptr<Condition> LevelCondition::from_json(jsoncons::json const &j)
+{
+ auto min_j = j.get("min");
+ if (!min_j.is_integer())
+ {
+ msg_print("Missing/invalid 'min' property");
+ return nullptr;
+ }
+ int min = min_j.as_int();
+
+ auto max_j = j.get("max");
+ if (!max_j.is_integer())
+ {
+ msg_print("Missing/invalid 'max' property");
+ return nullptr;
+ }
+ int max = max_j.as_int();
+
+ return std::make_shared<LevelCondition>(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(jsoncons::json &j) const
+{
+ j["min"] = m_min;
+ j["max"] = 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<Condition> SkillCondition::from_json(jsoncons::json const &j)
+{
+ auto min_j = j.get("min");
+ if (!min_j.is_integer())
+ {
+ msg_print("Missing/invalid 'min' property");
+ return nullptr;
+ }
+ int min = min_j.as_int();
+
+ auto max_j = j.get("max");
+ if (!max_j.is_integer())
+ {
+ msg_print("Missing/invalid 'max' property");
+ return nullptr;
+ }
+ int max = max_j.as_int();
+
+ auto s = j.get("name").as<cptr>();
+ if (!s)
+ {
+ msg_print("Missing/invalid 'name' property");
+ return nullptr;
+ }
+
+ auto si = find_skill_i(s);
+ if (si < 0)
+ {
+ msg_print("Invalid 'name' property");
+ return nullptr;
+ }
+
+ return std::make_shared<SkillCondition>(si, min, max);
+}
+
+void SkillCondition::write_tree(TreePrinter *p, Cursor *, uint8_t ecol, uint8_t bcol) const
+{
+ auto const &s_descriptors = game->edit_data.s_descriptors;
+
+ p->write(ecol, "Your skill in ");
+ p->write(bcol, s_descriptors[m_skill_idx].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(jsoncons::json &j) const
+{
+ auto const &s_descriptors = game->edit_data.s_descriptors;
+
+ j["name"] = s_descriptors[m_skill_idx].name;
+ j["min"] = m_min;
+ j["max"] = 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<Condition> StateCondition::from_json(jsoncons::json const &j)
+{
+ cptr s = j.get("state").as<cptr>();
+
+ if (!s)
+ {
+ 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<StateCondition>(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(jsoncons::json &j) const
+{
+ j["state"] = identification_state_mapping().stringify(m_state);
+}
+
+bool SymbolCondition::is_match(object_type *o_ptr) const
+{
+ auto const &k_info = game->edit_data.k_info;
+
+ return k_info[o_ptr->k_idx].d_char == m_symbol;
+}
+
+std::shared_ptr<Condition> SymbolCondition::from_json(jsoncons::json const &j)
+{
+ auto s = j.get("symbol").as<std::string>();
+
+ if (s.empty())
+ {
+ msg_print("Missing/invalid 'symbol' property");
+ return nullptr;
+ }
+
+ if (s.size() > 1)
+ {
+ msg_print("Invalid 'symbol' property: Too long");
+ return nullptr;
+ }
+
+ return std::make_shared<SymbolCondition>(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(jsoncons::json &j) const
+{
+ j["symbol"] = format("%c", m_symbol);
+}
+
+bool AbilityCondition::is_match(object_type *) const
+{
+ return p_ptr->has_ability(m_ability_idx);
+}
+
+std::shared_ptr<Condition> AbilityCondition::from_json(jsoncons::json const &j)
+{
+ cptr a = j.get("ability").as<cptr>();
+
+ if (!a)
+ {
+ msg_print("Missing/invalid 'ability' property");
+ return nullptr;
+ }
+
+ auto ai = find_ability(a);
+ if (ai < 0)
+ {
+ msg_print("Invalid 'ability' property");
+ return nullptr;
+ }
+
+ return std::make_shared<AbilityCondition>(ai);
+}
+
+void AbilityCondition::write_tree(TreePrinter *p, Cursor *, uint8_t ecol, uint8_t bcol) const
+{
+ auto const &ab_info = game->edit_data.ab_info;
+
+ p->write(ecol, "You have the ");
+ p->write(bcol, ab_info[m_ability_idx].name);
+ p->write(ecol, " ability");
+ p->write(TERM_WHITE, "\n");
+}
+
+void AbilityCondition::to_json(jsoncons::json &j) const
+{
+ auto const &ab_info = game->edit_data.ab_info;
+
+ j["ability"] = ab_info[m_ability_idx].name;
+}
+
+void SingleSubconditionCondition::add_child(std::function< std::shared_ptr<Condition> () > 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<Condition> SingleSubconditionCondition::first_child()
+{
+ return m_subcondition;
+}
+
+void SingleSubconditionCondition::to_json(jsoncons::json &j) const
+{
+ j["condition"] = optional_to_json(m_subcondition);
+}
+
+std::shared_ptr<Condition> SingleSubconditionCondition::parse_single_subcondition(jsoncons::json const &in_json)
+{
+ auto condition_j = in_json.get("condition");
+
+ if (condition_j.is_null())
+ {
+ return nullptr;
+ }
+ else if (!condition_j.is_object())
+ {
+ 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<Condition> NotCondition::from_json(jsoncons::json const &j)
+{
+ return std::make_shared<NotCondition>(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<Condition> InventoryCondition::from_json(jsoncons::json const &j)
+{
+ return std::make_shared<InventoryCondition>(
+ 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:");
+ p->write(TERM_WHITE, "\n");
+ if (m_subcondition)
+ {
+ m_subcondition->display(p, c);
+ }
+}
+
+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<Condition> EquipmentCondition::from_json(jsoncons::json const &j)
+{
+ return std::make_shared<EquipmentCondition>(
+ 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:");
+ p->write(TERM_WHITE, "\n");
+ if (m_subcondition)
+ {
+ m_subcondition->display(p, c);
+ }
+}
+
+} // namespace
diff --git a/src/squelch/condition_metadata.cc b/src/squelch/condition_metadata.cc
new file mode 100644
index 00000000..f6d4370c
--- /dev/null
+++ b/src/squelch/condition_metadata.cc
@@ -0,0 +1,494 @@
+#include "tome/squelch/condition_metadata.hpp"
+#include "tome/squelch/condition.hpp"
+
+#include <vector>
+
+#include "tome/squelch/object_status.hpp"
+#include "lua_bind.hpp"
+#include "skills.hpp"
+#include "util.hpp"
+#include "util.h"
+#include "z-term.h"
+
+namespace squelch {
+
+static std::shared_ptr<Condition> create_condition_name()
+{
+ auto s = input_box_auto("Object name to match?", 79);
+ if (s.empty())
+ {
+ return nullptr;
+ }
+
+ return std::make_shared<NameCondition>(s);
+}
+
+static std::shared_ptr<Condition> create_condition_contain()
+{
+ auto s = input_box_auto("Word to find in object name?", 79);
+ if (s.empty())
+ {
+ return nullptr;
+ }
+
+ return std::make_shared<ContainCondition>(s);
+}
+
+static std::shared_ptr<Condition> create_condition_inscribed()
+{
+ auto s = input_box_auto("Word to find in object inscription?", 79);
+ if (s.empty() == 0)
+ {
+ return nullptr;
+ }
+
+ return std::make_shared<InscriptionCondition>(s);
+}
+
+static std::shared_ptr<Condition> create_condition_discount()
+{
+ int min, max;
+
+ {
+ auto s = input_box_auto("Min discount?", 79);
+ if (sscanf(s.c_str(), "%d", &min) < 1)
+ {
+ return nullptr;
+ }
+ }
+
+ {
+ auto s = input_box_auto("Max discount?", 79);
+ if (sscanf(s.c_str(), "%d", &max) < 1)
+ {
+ return nullptr;
+ }
+ }
+
+ return std::make_shared<DiscountCondition>(min, max);
+}
+
+static std::shared_ptr<Condition> create_condition_symbol()
+{
+ auto s = input_box_auto("Symbol to match?", 1);
+ if (s.empty())
+ {
+ return nullptr;
+ }
+
+ return std::make_shared<SymbolCondition>(s[0]);
+}
+
+static std::shared_ptr<Condition> create_condition_status()
+{
+ status_type status;
+
+ auto c = msg_box_auto("[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<StatusCondition>(status);
+}
+
+static std::shared_ptr<Condition> create_condition_state()
+{
+ char c = msg_box_auto("[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<StateCondition>(s);
+}
+
+static bool in_byte_range(int x)
+{
+ return (x >= 0) && (x < 256);
+}
+
+static std::shared_ptr<Condition> create_condition_tval()
+{
+ auto s = input_box_auto("Tval to match?", 79);
+ int tval;
+ if (sscanf(s.c_str(), "%d", &tval) < 1)
+ {
+ return nullptr;
+ }
+
+ if (!in_byte_range(tval))
+ {
+ return nullptr;
+ }
+
+ return std::make_shared<TvalCondition>(tval);
+}
+
+static std::shared_ptr<Condition> create_condition_sval()
+{
+ int sval_min, sval_max;
+
+ {
+ auto s = input_box_auto("Min sval?", 79);
+ if ((sscanf(s.c_str(), "%d", &sval_min) < 1) ||
+ (!in_byte_range(sval_min)))
+ {
+ return nullptr;
+ }
+ }
+
+ {
+ auto s = input_box_auto("Max sval?", 79);
+ if ((sscanf(s.c_str(), "%d", &sval_max) < 1) ||
+ (!in_byte_range(sval_max)))
+ {
+ return nullptr;
+ }
+ }
+
+ return std::make_shared<SvalCondition>(sval_min, sval_max);
+}
+
+static std::shared_ptr<Condition> create_condition_race()
+{
+ auto s = input_box_auto("Player race to match?", 79);
+ if (s.empty())
+ {
+ return nullptr;
+ }
+
+ return std::make_shared<RaceCondition>(s);
+}
+
+static std::shared_ptr<Condition> create_condition_subrace()
+{
+ auto s = input_box_auto("Player subrace to match?", 79);
+ if (s.empty())
+ {
+ return nullptr;
+ }
+
+ return std::make_shared<SubraceCondition>(s);
+}
+
+static std::shared_ptr<Condition> create_condition_class()
+{
+ auto s = input_box_auto("Player class to match?", 79);
+ if (s.empty())
+ {
+ return nullptr;
+ }
+
+ return std::make_shared<ClassCondition>(s);
+}
+
+static std::shared_ptr<Condition> create_condition_level()
+{
+ int min, max;
+
+ {
+ auto s = input_box_auto("Min player level?", 79);
+ if (sscanf(s.c_str(), "%d", &min) < 1)
+ {
+ return nullptr;
+ }
+ }
+
+ {
+ auto s = input_box_auto("Max player level?", 79);
+ if (sscanf(s.c_str(), "%d", &max) < 1)
+ {
+ return nullptr;
+ }
+ }
+
+ return std::make_shared<LevelCondition>(min, max);
+}
+
+static std::shared_ptr<Condition> create_condition_skill()
+{
+ int min, max;
+
+ {
+ auto s = input_box_auto("Min skill level?", 79);
+ if (sscanf(s.c_str(), "%d", &min) < 1)
+ {
+ return nullptr;
+ }
+ }
+
+ {
+ auto s = input_box_auto("Max skill level?", 79);
+ if (sscanf(s.c_str(), "%d", &max) < 1)
+ {
+ return nullptr;
+ }
+ }
+
+ s16b skill_idx;
+ {
+ auto s = input_box_auto("Skill name?", 79);
+ if (s.empty() == 0)
+ {
+ return nullptr;
+ }
+
+ skill_idx = find_skill_i(s.c_str());
+ if (skill_idx < 0)
+ {
+ return nullptr;
+ }
+ }
+
+ return std::make_shared<SkillCondition>(skill_idx, min, max);
+}
+
+static std::shared_ptr<Condition> create_condition_ability()
+{
+ auto s = input_box_auto("Ability name?", 79);
+ if (s.empty() == 0)
+ {
+ return nullptr;
+ }
+
+ s16b ai = find_ability(s.c_str());
+ if (ai < 0)
+ {
+ return nullptr;
+ }
+
+ return std::make_shared<AbilityCondition>(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<Condition> new_condition_interactive()
+{
+ static std::vector<match_type> 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<std::string> 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, 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 >= static_cast<int>(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<AndCondition>();
+ case match_type::OR:
+ return std::make_shared<OrCondition>();
+ case match_type::NOT:
+ return std::make_shared<NotCondition>();
+ 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<InventoryCondition>();
+ case match_type::EQUIPMENT:
+ return std::make_shared<EquipmentCondition>();
+
+ }
+ }
+ }
+ return nullptr;
+}
+
+} // namespace
diff --git a/src/squelch/cursor.cc b/src/squelch/cursor.cc
new file mode 100644
index 00000000..3a3bec46
--- /dev/null
+++ b/src/squelch/cursor.cc
@@ -0,0 +1,96 @@
+#include "tome/squelch/cursor_fwd.hpp"
+#include "tome/squelch/cursor.hpp"
+
+#include <algorithm>
+#include <cassert>
+
+#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()
+{
+ if (m_conditions.empty()) {
+ return;
+ }
+ // Go right if the currently selected condition has children.
+ std::shared_ptr<Condition> 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<Condition> 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<Condition> 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..075c0529
--- /dev/null
+++ b/src/squelch/object_status.cc
@@ -0,0 +1,153 @@
+#include "tome/squelch/object_status_fwd.hpp"
+#include "tome/squelch/object_status.hpp"
+
+#include "../inventory.hpp"
+#include "../object1.hpp"
+#include "../object2.hpp"
+#include "../object_type.hpp"
+#include "../variable.hpp"
+
+namespace squelch {
+
+EnumStringMap<status_type> &status_mapping()
+{
+ // TODO: This is quite ugly and leads to valgrind complaints
+ static auto m = new EnumStringMap<status_type> {
+ { 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..e35b3ce1
--- /dev/null
+++ b/src/squelch/rule.cc
@@ -0,0 +1,316 @@
+#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 "../modules.hpp"
+#include "../object1.hpp"
+#include "../object2.hpp"
+#include "../object_flag.hpp"
+#include "../object_type.hpp"
+#include "../tables.hpp"
+#include "../util.hpp"
+#include "../variable.hpp"
+
+namespace squelch {
+
+EnumStringMap<action_type> &action_mapping()
+{
+ static auto m = new EnumStringMap<action_type> {
+ { action_type::AUTO_DESTROY, "destroy" },
+ { action_type::AUTO_PICKUP, "pickup" },
+ { action_type::AUTO_INSCRIBE, "inscribe" } };
+ return *m;
+}
+
+void Rule::set_name(std::string const &new_name)
+{
+ m_name = new_name;
+}
+
+std::string Rule::get_name() const
+{
+ return m_name;
+}
+
+std::shared_ptr<Condition> Rule::get_condition() const
+{
+ return m_condition;
+}
+
+jsoncons::json Rule::to_json() const
+{
+ jsoncons::json j;
+
+ j["name"] = jsoncons::json::string_type(m_name);
+ j["action"] = action_mapping().stringify(m_action);
+ j["module"] = modules[m_module_idx].meta.name;
+ j["condition"] = Condition::optional_to_json(m_condition);
+
+ return j;
+}
+
+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> Rule::parse_rule(jsoncons::json const &rule_json)
+{
+ if (!rule_json.is_object())
+ {
+ msg_print("Rule is not an object");
+ return nullptr;
+ }
+
+ // Retrieve the attributes
+ char const *rule_name_s = rule_json.get("name").as<char const *>();
+ char const *rule_action_s = rule_json.get("action").as<char const *>();
+ char const *rule_module_s = rule_json.get("module").as<char const *>();
+ if ((!rule_name_s) || (!rule_action_s) || (!rule_module_s))
+ {
+ 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 =
+ Condition::parse_condition(rule_json.get("condition"));
+
+ // Parse rule
+ switch (action)
+ {
+ case action_type::AUTO_INSCRIBE:
+ {
+ auto rule_inscription_j = rule_json.get("inscription");
+
+ if (rule_inscription_j.is_null())
+ {
+ msg_print("Inscription rule missing 'inscription' attribute");
+ return nullptr;
+ }
+
+ if (!rule_inscription_j.is_string())
+ {
+ msg_print("Inscription rule 'inscription' attribute wrong type");
+ return nullptr;
+ }
+
+ std::string inscription = rule_inscription_j.as<std::string>();
+
+ return std::make_shared<InscribeRule>(
+ rule_name_s, module_idx, condition, inscription);
+ }
+
+ case action_type::AUTO_PICKUP:
+ return std::make_shared<PickUpRule>(
+ rule_name_s, module_idx, condition);
+
+ case action_type::AUTO_DESTROY:
+ return std::make_shared<DestroyRule>(
+ 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->inscription.empty())
+ {
+ return false;
+ }
+
+ // Ignore artifacts; cannot be destroyed anyway
+ if (artifact_p(o_ptr))
+ {
+ return false;
+ }
+
+ // Cannot destroy CURSE_NO_DROP objects.
+ {
+ auto const f = object_flags(o_ptr);
+ if (f & TR_CURSE_NO_DROP)
+ {
+ return false;
+ }
+ }
+
+ // Destroy
+ msg_print("<Auto-destroy>");
+ 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("<Auto-pickup>");
+ object_pickup(-item_idx);
+ return true;
+}
+
+jsoncons::json InscribeRule::to_json() const
+{
+ jsoncons::json j;
+ j["inscription"] = m_inscription;
+ 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->inscription.empty())
+ {
+ return false;
+ }
+
+ // Inscribe
+ msg_format("<Auto-Inscribe {%s}>", m_inscription.c_str());
+ o_ptr->inscription = m_inscription;
+ return true;
+}
+
+} // namespace
diff --git a/src/squelch/tree_printer.cc b/src/squelch/tree_printer.cc
new file mode 100644
index 00000000..0dbceec9
--- /dev/null
+++ b/src/squelch/tree_printer.cc
@@ -0,0 +1,94 @@
+#include "tome/squelch/tree_printer_fwd.hpp"
+#include "tome/squelch/tree_printer.hpp"
+
+#include "../z-term.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;
+ }
+ }
+}
+
+void TreePrinter::write(uint8_t color, std::string const &line)
+{
+ write(color, line.c_str());
+}
+
+} // namespace
diff --git a/src/squeltch.c b/src/squeltch.c
deleted file mode 100644
index 603eaa0e..00000000
--- a/src/squeltch.c
+++ /dev/null
@@ -1,553 +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 "lua/lua.h"
-#include "tolua.h"
-
-extern lua_State *L;
-
-/*
- * The functions here use direct lua stack manipulation for calls instead of
- * exec_lua(format()) because string manipulations are too slow for such
- * functions
- */
-
-/* Check the floor for "crap" */
-void squeltch_grid(void)
-{
- int oldtop;
- s16b this_o_idx, next_o_idx = 0;
-
- if (!automatizer_enabled) return;
-
- oldtop = lua_gettop(L);
-
- /* 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;
-
- /* Push the function */
- lua_settop(L, oldtop);
- lua_getglobal(L, "apply_rules");
-
- /* Push the args */
- tolua_pushusertype(L, o_ptr, tolua_tag(L, "object_type"));
- tolua_pushnumber(L, -this_o_idx);
-
- /* 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);
-}
-
-
-/* Check the inventory for "crap" */
-void squeltch_inventory(void)
-{
- int oldtop;
- int i;
- int num_iter = 0;
- bool_ found = TRUE;
-
- if (!automatizer_enabled) return;
-
- oldtop = lua_gettop(L);
- 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];
-
- /* Push the function */
- lua_settop(L, oldtop);
- lua_getglobal(L, "apply_rules");
-
- /* Push the args */
- tolua_pushusertype(L, o_ptr, tolua_tag(L, "object_type"));
- tolua_pushnumber(L, i);
-
- /* 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;
- }
-
- /* Did it return TRUE */
- if (tolua_getnumber(L, -(lua_gettop(L) - oldtop), 0))
- {
- found = TRUE;
- break;
- }
- }
- }
- if (num_iter >= 100)
- {
- cmsg_format(TERM_VIOLET, "'apply_rules' ran too often.");
- }
- lua_settop(L, oldtop);
-}
-
-/********************** The interface **********************/
-static cptr *get_rule_list(int *max)
-{
- cptr *list;
- int i;
-
- *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,
-};
-
-/* Create a new rule */
-static int automatizer_new_rule()
-{
- int wid, hgt, max, begin = 0, sel = 0;
- char c;
-
- /* Get the number of types */
- max = 0;
- while (types_list[max] != NULL)
- max++;
-
- while (1)
- {
- Term_clear();
- Term_get_size(&wid, &hgt);
-
- display_list(0, 0, hgt - 1, 15, "Rule types", types_list, max, begin, sel, TERM_L_GREEN);
-
- 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]));
-
- 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 sel;
- }
- }
- return -1;
-}
-
-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)++;
-}
-
-#define ACTIVE_LIST 0
-#define ACTIVE_RULE 1
-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;
-
- 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();
-
- exec_lua(format("auto_aux:adjust_current(%d)", 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);
-
- 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");
- }
- 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));
-
- 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);
- exec_lua(format("auto_aux:adjust_current(%d)", sel));
- }
- else if (c == '2')
- {
- if (!max) continue;
- sel++;
- adjust_begin(&begin, &sel, max, hgt);
- exec_lua(format("auto_aux:adjust_current(%d)", 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));
- }
- 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));
- }
- 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))
- {
- 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));
- 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();
- }
- }
- 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));
- }
-
- continue;
- }
- else if (c == 'k')
- {
- automatizer_enabled = FALSE;
- break;
- }
- else if (c == '\t')
- {
- if (!max) continue;
- active = ACTIVE_RULE;
- }
- else if (c == 'x')
- {
- exec_lua("xml.display_english = not xml.display_english");
- }
- }
- else if (active == ACTIVE_RULE)
- {
- if (c == '?')
- {
- screen_save();
- show_file("automat.txt", "Automatizer help", 0, 0);
- screen_load();
- }
- else if (c == '8')
- {
- exec_lua("auto_aux:go_up()");
- }
- else if (c == '2')
- {
- exec_lua("auto_aux:go_down()");
- }
- else if (c == '6')
- {
- exec_lua("auto_aux:go_right()");
- }
- else if (c == '4')
- {
- exec_lua(format("auto_aux:go_left(%d)", sel));
- }
- else if (c == '9')
- {
- exec_lua("auto_aux:scroll_up()");
- }
- else if (c == '3')
- {
- exec_lua("auto_aux:scroll_down()");
- }
- else if (c == '7')
- {
- exec_lua("auto_aux:scroll_left()");
- }
- else if (c == '1')
- {
- exec_lua("auto_aux: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]));
- }
- else if (c == 'd')
- {
- if (max)
- {
- int new_sel;
-
- new_sel = exec_lua(format("return auto_aux:del_self(%d)", 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));
- }
- else if (new_sel == -1)
- {
- active = ACTIVE_LIST;
- }
- }
- }
- else if (c == '\t')
- {
- 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();
-}
-
-/* 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";
-
- if (!destroy)
- {
- type = "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')
- {
- call_lua("easy_add_rule", "(s,s,d,O)", "", type, "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);
- break;
- }
-
- if (ch == 'N' || ch == 'n')
- {
- call_lua("easy_add_rule", "(s,s,d,O)", "", type, "name", do_status, o_ptr);
- break;
- }
- }
-}
diff --git a/src/squeltch.cc b/src/squeltch.cc
new file mode 100644
index 00000000..1db8ff74
--- /dev/null
+++ b/src/squeltch.cc
@@ -0,0 +1,601 @@
+/*
+ * 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 "squeltch.hpp"
+
+#include "cave_type.hpp"
+#include "files.hpp"
+#include "game.hpp"
+#include "loadsave.hpp"
+#include "lua_bind.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_kind.hpp"
+#include "object_type.hpp"
+#include "player_type.hpp"
+#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"
+#include "util.hpp"
+#include "util.h"
+#include "variable.h"
+#include "variable.hpp"
+
+#include <algorithm>
+#include <deque>
+#include <fmt/format.h>
+#include <list>
+#include <memory>
+#include <string>
+#include <vector>
+
+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()
+{
+ auto const &k_info = game->edit_data.k_info;
+
+ if (!automatizer_enabled)
+ {
+ return;
+ }
+
+ // Copy list of objects since we may modify it
+ auto const object_idxs(cave[p_ptr->py][p_ptr->px].o_idxs);
+
+ // Scan the pile of objects
+ for (auto const this_o_idx: object_idxs)
+ {
+ // 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);
+ }
+
+ // Apply rules
+ automatizer->apply_rules(o_ptr, -this_o_idx);
+ }
+}
+
+void squeltch_inventory()
+{
+ if (!automatizer_enabled)
+ {
+ return;
+ }
+
+ bool changed = true;
+ for (int num_iter = 0; changed && (num_iter < 100); num_iter++)
+ {
+ // No changes on this iteration.
+ changed = false;
+ // Traverse inventory
+ for (int i = 0; i < INVEN_PACK; i++)
+ {
+ object_type *o_ptr = &p_ptr->inventory[i];
+ if ((o_ptr->k_idx > 0) && automatizer->apply_rules(o_ptr, i))
+ {
+ // We have changes
+ changed = true;
+ // Re-traverse inventory
+ break;
+ }
+ }
+ }
+ // If we reached the iteration limit, "changed" will be true
+ if (changed)
+ {
+ cmsg_format(TERM_VIOLET, "'apply_rules' ran too often.");
+ }
+}
+
+static int create_new_rule()
+{
+ std::string name = "No name";
+
+ if (!input_box_auto("Name?", &name, 20))
+ {
+ return -1;
+ }
+
+ char typ = msg_box_auto("[D]estroy, [P]ickup, [I]nscribe?");
+
+ std::shared_ptr<Rule> rule;
+ switch (typ)
+ {
+ case 'd':
+ case 'D':
+ rule = std::make_shared<DestroyRule>(name, game_module_idx, nullptr);
+ break;
+
+ case 'p':
+ case 'P':
+ rule = std::make_shared<PickUpRule>(name, game_module_idx, nullptr);
+ break;
+
+ case 'i':
+ case 'I':
+ {
+ auto s = input_box_auto("Inscription?", 79);
+ if (s.empty())
+ {
+ return -1;
+ }
+
+ rule = std::make_shared<InscribeRule>(name, game_module_idx, nullptr, s);
+ break;
+ }
+
+ default:
+ return -1;
+ }
+
+ return automatizer->append_rule(rule);
+}
+
+static void automatizer_save_rules()
+{
+ char buf[1025];
+ char ch;
+ int hgt, wid;
+
+ Term_get_size(&wid, &hgt);
+
+ std::string name = fmt::format("{}.atm", game->player_name);
+
+ if (!input_box_auto("Save name?", &name, 30))
+ {
+ return;
+ }
+
+ // Function for showing a message
+ auto show_message = [hgt, wid](std::string text) {
+ auto n = std::max<std::size_t>(text.size(), 28);
+ while (text.size() < n)
+ {
+ text += ' ';
+ }
+ c_put_str(TERM_WHITE, text.c_str(), hgt/2, wid/2 - 14);
+ };
+
+ // Function for showing an error message
+ auto error = [show_message]() {
+ show_message("Saving rules FAILED!");
+ inkey();
+ };
+
+ // Build the filename
+ path_build(buf, 1024, ANGBAND_DIR_USER, name.c_str());
+
+ if (boost::filesystem::exists(buf))
+ {
+ show_message("File exists, continue? [y/n]");
+ ch = inkey();
+ if ((ch != 'Y') && (ch != 'y'))
+ {
+ return;
+ }
+ }
+
+ // Pretty-printing options
+ jsoncons::output_format format;
+ format.indent(2);
+
+ // Convert to a JSON document
+ auto rules_document = automatizer->to_json();
+
+ // Open output stream
+ std::ofstream of(buf, std::ios_base::out | std::ios_base::binary);
+ if (of.fail())
+ {
+ error();
+ return;
+ }
+
+ // Write JSON to output
+ of << jsoncons::pretty_print(rules_document, format);
+ if (of.fail())
+ {
+ error();
+ return;
+ }
+
+ // Success
+ show_message("Saved rules in file");
+ inkey();
+}
+
+static void rename_rule(Rule *rule)
+{
+ assert(rule != nullptr);
+
+ std::string name = rule->get_name();
+ if (input_box_auto("New name?", &name, 16))
+ {
+ rule->set_name(name.c_str());
+ }
+}
+
+#define ACTIVE_LIST 0
+#define ACTIVE_RULE 1
+void do_cmd_automatizer()
+{
+ int active = ACTIVE_LIST;
+ cptr keys;
+ cptr keys2;
+ cptr keys3;
+ std::vector<cptr> rule_names;
+
+ if (!automatizer_enabled)
+ {
+ if (msg_box_auto("Automatizer is currently disabled, enable it? (y/n)") == 'y')
+ {
+ automatizer_enabled = TRUE;
+ }
+ else
+ return;
+ }
+
+ screen_save();
+
+ automatizer->reset_view();
+
+ while (1)
+ {
+ Term_clear();
+
+ int wid, hgt;
+ Term_get_size(&wid, &hgt);
+
+ auto rule_names = automatizer->get_rule_names();
+
+ display_list(0, 0, hgt - 1, 15, "Rules", rule_names, 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");
+ 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");
+ 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(add_rule_mode mode, bool do_status, object_type *o_ptr)
+{
+ std::shared_ptr<Condition> condition;
+
+ switch (mode)
+ {
+
+ case add_rule_mode::TVAL:
+ condition = std::make_shared<TvalCondition>(o_ptr->tval);
+ break;
+
+ case add_rule_mode::TSVAL:
+ {
+ auto andCondition = std::make_shared<AndCondition>();
+
+ andCondition->add_condition(
+ std::make_shared<TvalCondition>(o_ptr->tval));
+ andCondition->add_condition(
+ std::make_shared<SvalCondition>(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<NameCondition>(buf);
+ break;
+ }
+
+ }
+
+ // Use object status?
+ if (do_status)
+ {
+ status_type status = squelch::object_status(o_ptr);
+
+ auto andCondition = std::make_shared<AndCondition>();
+
+ andCondition->add_condition(
+ std::shared_ptr<Condition>(condition)); // cycle
+ andCondition->add_condition(
+ std::make_shared<StatusCondition>(status));
+
+ // Replace condition; breaks cycle
+ condition = andCondition;
+ }
+
+ // Rule name
+ auto rule_name = action_mapping().stringify(action_type::AUTO_DESTROY);
+
+ // Append to list of rules
+ automatizer->append_rule(
+ std::make_shared<DestroyRule>(
+ rule_name, game_module_idx, condition));
+
+ 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 do_status = false;
+
+ while (true)
+ {
+ char ch;
+
+ if (!get_com(format("Destroy all of the same [T]ype, [F]amily or [N]ame, also use [S]tatus (%s)? ", (do_status) ? "Yes" : "No"), &ch))
+ {
+ break;
+ }
+
+ if (ch == 'S' || ch == 's')
+ {
+ do_status = !do_status;
+ continue;
+ }
+
+ if (ch == 'T' || ch == 't')
+ {
+ easy_add_rule(add_rule_mode::TSVAL, do_status, o_ptr);
+ break;
+ }
+
+ if (ch == 'F' || ch == 'f')
+ {
+ easy_add_rule(add_rule_mode::TVAL, do_status, o_ptr);
+ break;
+ }
+
+ if (ch == 'N' || ch == 'n')
+ {
+ easy_add_rule(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<squelch::TreePrinter>());
+ auto cursor(std::make_shared<squelch::Cursor>());
+
+ // Initialize
+ automatizer = new squelch::Automatizer(tree_printer, cursor);
+}
+
+/**
+ * Load automatizer file. Returns true iff automatizer
+ * rules were loaded successfully.
+ */
+bool automatizer_load(boost::filesystem::path const &path)
+{
+ assert(automatizer != NULL);
+
+ // Does the path exist?
+ if (!boost::filesystem::exists(path))
+ {
+ return false; // Not fatal; just skip
+ }
+
+ // Parse into memory
+ jsoncons::json rules_json;
+ try
+ {
+ rules_json = jsoncons::json::parse_file(path.string());
+ }
+ catch (jsoncons::json_exception const &exc)
+ {
+ msg_format("Error parsing automatizer rules from '%s'.", path.c_str());
+ msg_print(exc.what());
+ return false;
+ }
+
+ // We didn't return directly via an exception, so let's extract
+ // the rules.
+ automatizer->load_json(rules_json);
+ return true;
+}
diff --git a/src/squeltch.hpp b/src/squeltch.hpp
new file mode 100644
index 00000000..c4525e7d
--- /dev/null
+++ b/src/squeltch.hpp
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "h-basic.h"
+#include "object_type_fwd.hpp"
+#include <boost/filesystem.hpp>
+
+void squeltch_inventory();
+void squeltch_grid();
+void do_cmd_automatizer();
+void automatizer_add_rule(object_type *o_ptr);
+extern bool_ automatizer_create;
+void automatizer_init();
+bool automatizer_load(boost::filesystem::path const &path);
diff --git a/src/stairs_direction.hpp b/src/stairs_direction.hpp
new file mode 100644
index 00000000..b0b5f25d
--- /dev/null
+++ b/src/stairs_direction.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+typedef enum { STAIRS_UP, STAIRS_DOWN } stairs_direction;
diff --git a/src/stats.hpp b/src/stats.hpp
new file mode 100644
index 00000000..e682446c
--- /dev/null
+++ b/src/stats.hpp
@@ -0,0 +1,11 @@
+#pragma once
+
+/*
+ * Indexes of the various "stats" (hard-coded by savefiles, etc).
+ */
+#define A_STR 0
+#define A_INT 1
+#define A_WIS 2
+#define A_DEX 3
+#define A_CON 4
+#define A_CHR 5
diff --git a/src/status.c b/src/status.c
deleted file mode 100644
index 967a8323..00000000
--- a/src/status.c
+++ /dev/null
@@ -1,773 +0,0 @@
-/* File status.c */
-
-/* Purpose: Status information */
-
-/* Written by Pat Gunn <qc@apk.net> for ToME
- * This file is released into the public domain
- */
-
-/* Throughout this file, I make use of 2-d arrays called flag_arr.
- * I fill them out with esp as the 0th element because then the second
- * index is equal to the f-number that they are in the attributes, and
- * that makes it more intuitive to use. I do need to fill them out in an
- * odd order, but that's all abstracted nicely away. The 6th element is used
- * to mark if the rest of the array is filled, that is, if there's an object
- * there.
- */
-
-#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_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 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);
-static void status_trival(s32b, s32b, byte, byte);
-static void status_bival(s32b, byte, byte);
-static void status_numeric(s32b, byte, byte);
-static void status_curses(void);
-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]);
-#define STATNM_LENGTH 11
-#define SL_LENGTH 11
-
-#define INVEN_PLAYER (INVEN_TOTAL - INVEN_WIELD + 1)
-
-void status_attr(void)
-{
- u32b flag_arr[INVEN_TOTAL - INVEN_WIELD + 2][7];
- int yo = 0;
- char c;
-
- clear_from(0);
- c_put_str(TERM_L_BLUE, "Statistics", yo++, 1);
- yo += 2;
- az_line(SL_LENGTH, flag_arr);
- statline("Str", A_STR, TR1_STR, yo++, flag_arr);
- statline("Int", A_INT, TR1_INT, yo++, flag_arr);
- statline("Wis", A_INT, TR1_WIS, yo++, flag_arr);
- statline("Con", A_CON, TR1_CON, yo++, flag_arr);
- statline("Dex", A_DEX, TR1_DEX, yo++, flag_arr);
- statline("Chr", A_CHR, TR1_CHR, yo++, flag_arr);
- row_npval("Luck", 5, TR5_LUCK, yo++, flag_arr);
- yo++;
- row_npval("Life", 2, TR2_LIFE, yo++, flag_arr);
- row_npval("Mana", 1, TR1_MANA, yo++, flag_arr);
-
-
- c_put_str(TERM_WHITE, "Press ESC to continue", 23, 0);
- Term_fresh();
- while (1)
- {
- c = inkey();
- if (c == ESCAPE) break;
- }
-}
-
-void status_move(void)
-{
- u32b flag_arr[INVEN_TOTAL - INVEN_WIELD + 2][7];
- int yo = 3;
- clear_from(0);
- c_put_str(TERM_L_BLUE, "Movement", 0, 1);
- az_line(STATNM_LENGTH, flag_arr);
-
- row_trival("Fly/Lev", 4, TR4_FLY, 3, TR3_FEATHER, yo++, flag_arr);
- row_bival("Climb", 4, TR4_CLIMB, yo++, flag_arr);
- row_npval("Dig", 1, TR1_TUNNEL, yo++, flag_arr);
- row_npval("Speed", 1, TR1_SPEED, yo++, flag_arr);
- row_bival("Wraith", 3, TR3_WRAITH, yo++, flag_arr);
- yo++;
- row_npval("Stealth", 1, TR1_STEALTH, yo++, flag_arr);
- row_bival("Telep", 3, TR3_TELEPORT, yo++, flag_arr);
-
- c_put_str(TERM_WHITE, "Press ESC to continue", 23, 0);
- Term_fresh();
- while (1)
- {
- bool_ loop_exit = FALSE;
- char c;
- c = inkey();
- switch (c)
- {
- case ESCAPE:
- {
- loop_exit = TRUE;
- }
- }
- if (loop_exit)
- {
- break;
- }
- }
-}
-
-void status_sight(void)
-/* Tell player about ESP, infravision, auto-id, see invis, and similar */
-{
- u32b flag_arr[INVEN_TOTAL - INVEN_WIELD + 2][7];
- int yo = 3;
- clear_from(0);
- c_put_str(TERM_L_BLUE, "Sight", 0, 1);
- az_line(STATNM_LENGTH, flag_arr);
-
- row_bival("SeeInvis", 3, TR3_SEE_INVIS, yo++, flag_arr);
- row_npval("Invis", 2, TR2_INVIS, yo++, flag_arr);
- row_npval("Infra", 1, TR1_INFRA, yo++, flag_arr);
- row_npval("Search", 1, TR1_SEARCH, yo++, flag_arr);
- row_bival("AutoID", 4, TR4_AUTO_ID, yo++, flag_arr);
- row_count("Light", 3, TR3_LITE1, 1, 4, TR4_LITE2, 2, 4, TR4_LITE3, 3, 0, 0, 0, yo++, flag_arr);
- row_bival("Full ESP", 0, ESP_ALL, yo++, flag_arr);
- row_bival("Orc ESP", 0, ESP_ORC, yo++, flag_arr);
- row_bival("Trol ESP", 0, ESP_TROLL, yo++, flag_arr);
- row_bival("Drag ESP", 0, ESP_DRAGON, yo++, flag_arr);
- row_bival("GiantESP", 0, ESP_GIANT, yo++, flag_arr);
- row_bival("DemonESP", 0, ESP_DEMON, yo++, flag_arr);
- row_bival("Undd ESP", 0, ESP_UNDEAD, yo++, flag_arr);
- row_bival("Evil ESP", 0, ESP_EVIL, yo++, flag_arr);
- row_bival("Anim ESP", 0, ESP_ANIMAL, yo++, flag_arr);
- row_bival("Drid ESP", 0, ESP_THUNDERLORD, yo++, flag_arr);
- row_bival("Good ESP", 0, ESP_GOOD, yo++, flag_arr);
- row_bival("SpidrESP", 0, ESP_SPIDER, yo++, flag_arr);
- row_bival("NonlvESP", 0, ESP_NONLIVING, yo++, flag_arr);
- row_bival("Uniq ESP", 0, ESP_UNIQUE, yo++, flag_arr);
-
- c_put_str(TERM_WHITE, "Press ESC to continue", 23, 0);
- Term_fresh();
- while (1)
- {
- bool_ loop_exit = FALSE;
- char c;
- c = inkey();
- switch (c)
- {
- case ESCAPE:
- {
- loop_exit = TRUE;
- }
- }
- if (loop_exit)
- {
- break;
- }
- }
-}
-
-void status_item(void)
-{
- u32b flag_arr[INVEN_TOTAL - INVEN_WIELD + 2][7];
- int yo = 3;
- clear_from(0);
- c_put_str(TERM_L_BLUE, "Misc", 0, 1);
-
- row_x_start = 40;
- az_line(STATNM_LENGTH + row_x_start, flag_arr);
- row_bival("Blessed", 3, TR3_BLESSED, yo++, flag_arr);
- row_bival("Activate", 3, TR3_ACTIVATE, yo++, flag_arr);
- row_bival("EasyKnow", 3, TR3_EASY_KNOW, yo++, flag_arr);
- row_bival("HideType", 3, TR3_HIDE_TYPE, yo++, flag_arr);
- yo++;
- row_bival("SafeAcid", 3, TR3_IGNORE_ACID, yo++, flag_arr);
- row_bival("SafeElec", 3, TR3_IGNORE_ELEC, yo++, flag_arr);
- row_bival("SafeFire", 3, TR3_IGNORE_FIRE, yo++, flag_arr);
- row_bival("SafeCold", 3, TR3_IGNORE_COLD, yo++, flag_arr);
- row_bival("ResMorgul", 5, TR5_RES_MORGUL, yo++, flag_arr);
-
- yo = 3;
- row_x_start = 0;
- az_line(STATNM_LENGTH, flag_arr);
- row_bival("Sh.fire", 3, TR3_SH_FIRE, yo++, flag_arr);
- row_bival("Sh.elec", 3, TR3_SH_ELEC, yo++, flag_arr);
- row_bival("Regen", 3, TR3_REGEN, yo++, flag_arr);
- row_bival("SlowDigest", 3, TR3_SLOW_DIGEST, yo++, flag_arr);
- row_bival("Precog", 4, TR4_PRECOGNITION, yo++, flag_arr);
- row_bival("Auto.Id", 4, TR4_AUTO_ID, yo++, flag_arr);
- row_bival("Spell.In", 5, TR5_SPELL_CONTAIN, yo++, flag_arr);
-
- c_put_str(TERM_WHITE, "Press ESC to continue", 23, 0);
- Term_fresh();
- while (1)
- {
- bool_ loop_exit = FALSE;
- char c;
- c = inkey();
- switch (c)
- {
- case ESCAPE:
- loop_exit = TRUE;
- }
- if (loop_exit)
- {
- break;
- }
- }
-}
-
-void status_combat(void)
-{
- u32b flag_arr[INVEN_TOTAL - INVEN_WIELD + 2][7];
- int yo = 3;
- clear_from(0);
- c_put_str(TERM_L_BLUE, "Combat", 0, 1);
- az_line(STATNM_LENGTH, flag_arr);
-
- row_npval("Spell", 1, TR1_SPELL, yo++, flag_arr);
- row_npval("Blows", 1, TR1_BLOWS, yo++, flag_arr);
- row_npval("Crits", 5, TR5_CRIT, yo++, flag_arr);
- row_npval("Ammo_Mgt", 3, TR3_XTRA_MIGHT, yo++, flag_arr);
- row_npval("Ammo_Sht", 3, TR3_XTRA_SHOTS, yo++, flag_arr);
- row_bival("Vorpal", 1, TR1_VORPAL, yo++, flag_arr);
- row_bival("Quake", 1, TR1_IMPACT, yo++, flag_arr);
- row_bival("Chaotic", 1, TR1_CHAOTIC, yo++, flag_arr);
- row_bival("Vampiric", 1, TR1_VAMPIRIC, yo++, flag_arr);
- row_bival("Poison", 1, TR1_BRAND_POIS, yo++, flag_arr);
- row_bival("Acidic", 1, TR1_BRAND_ACID, yo++, flag_arr);
- row_bival("Shocks", 1, TR1_BRAND_ELEC, yo++, flag_arr);
- row_bival("Burns", 1, TR1_BRAND_FIRE, yo++, flag_arr);
- row_bival("Chills", 1, TR1_BRAND_COLD, yo++, flag_arr);
- row_bival("Wound", 5, TR5_WOUNDING, yo++, flag_arr);
-
- row_x_start = 40;
- yo = 3;
- az_line(row_x_start + STATNM_LENGTH, flag_arr);
- row_bival("No.Blow", 4, TR4_NEVER_BLOW, yo++, flag_arr);
- row_trival("S/K Undd", 1, TR1_SLAY_UNDEAD, 5, TR5_KILL_UNDEAD, yo++, flag_arr);
- row_trival("S/K Dmn", 1, TR1_SLAY_DEMON, 5, TR5_KILL_DEMON, yo++, flag_arr);
- row_trival("S/K Drag", 1, TR1_SLAY_DRAGON, 1, TR1_KILL_DRAGON, yo++, flag_arr);
- row_bival("Sl.Orc", 1, TR1_SLAY_ORC, yo++, flag_arr);
- row_bival("Sl.Troll", 1, TR1_SLAY_TROLL, yo++, flag_arr);
- row_bival("Sl.Giant", 1, TR1_SLAY_GIANT, yo++, flag_arr);
- row_bival("Sl.Evil", 1, TR1_SLAY_EVIL, yo++, flag_arr);
- row_bival("Sl.Animal", 1, TR1_SLAY_ANIMAL, yo++, flag_arr);
- row_hd_bon(0, yo++, flag_arr);
- row_hd_bon(1, yo++, flag_arr);
- row_x_start = 0;
-
- c_put_str(TERM_WHITE, "Press ESC to continue", 23, 0);
- Term_fresh();
- while (1)
- {
- bool_ loop_exit = FALSE;
- char c;
- c = inkey();
- switch (c)
- {
- case ESCAPE:
- loop_exit = TRUE;
- }
- if (loop_exit)
- {
- break;
- }
- }
-}
-
-void status_curses(void)
-{
- u32b flag_arr[INVEN_TOTAL - INVEN_WIELD + 2][7];
- int yo = 3;
-
- clear_from(0);
- c_put_str(TERM_L_BLUE, "Curses", 0, 1);
- az_line(STATNM_LENGTH, flag_arr);
-
- row_trival("Hvy/Nrm", 3, TR3_HEAVY_CURSE, 3, TR3_CURSED, yo++, flag_arr);
- row_bival("Perma", 3, TR3_PERMA_CURSE, yo++, flag_arr);
- row_trival("DG/Ty", 4, TR4_DG_CURSE, 3, TR3_TY_CURSE, yo++, flag_arr);
- row_trival("Prm/Auto", 3, TR3_PERMA_CURSE, 3, TR3_AUTO_CURSE, yo++, flag_arr);
- row_bival("NoDrop", 4, TR4_CURSE_NO_DROP, yo++, flag_arr);
- yo++;
- row_bival("B.Breath", 4, TR4_BLACK_BREATH, yo++, flag_arr);
- row_bival("Dr.Exp", 3, TR3_DRAIN_EXP, yo++, flag_arr);
- row_bival("Dr.Mana", 5, TR5_DRAIN_MANA, yo++, flag_arr);
- row_bival("Dr.HP", 5, TR5_DRAIN_HP, yo++, flag_arr);
- row_bival("No Hit", 4, TR4_NEVER_BLOW, yo++, flag_arr);
- row_bival("NoTelep", 3, TR3_NO_TELE, yo++, flag_arr);
- row_bival("NoMagic", 3, TR3_NO_MAGIC, yo++, flag_arr);
- row_bival("Aggrav", 3, TR3_AGGRAVATE, yo++, flag_arr);
- row_bival("Clone", 4, TR4_CLONE, yo++, flag_arr);
- row_bival("Temp", 5, TR5_TEMPORARY, yo++, flag_arr);
- yo++;
- row_count("Antimagic", 4, TR4_ANTIMAGIC_50, 5, 4, TR4_ANTIMAGIC_30, 3, 4, TR4_ANTIMAGIC_20, 2, 4, TR4_ANTIMAGIC_10, 1, yo++, flag_arr);
-
- c_put_str(TERM_WHITE, "Press ESC to continue", 23, 0);
- Term_fresh();
- while (1)
- {
- bool_ loop_exit = FALSE;
- char c;
-
- c = inkey();
- switch (c)
- {
- case ESCAPE:
- {
- loop_exit = TRUE;
- }
- }
- if (loop_exit == TRUE)
- {
- break;
- }
- }
-}
-
-void status_res(void)
-{
- u32b flag_arr[INVEN_TOTAL - INVEN_WIELD + 2][7];
- int yo = 3;
-
- clear_from(0);
- c_put_str(TERM_L_BLUE, "Resistances", 0, 1);
- az_line(STATNM_LENGTH, flag_arr);
-
- row_trival("Fire", 2, TR2_IM_FIRE, 2, TR2_RES_FIRE, yo++, flag_arr);
- row_trival("Cold", 2, TR2_IM_COLD, 2, TR2_RES_COLD, yo++, flag_arr);
- row_trival("Acid", 2, TR2_IM_ACID, 2, TR2_RES_ACID, yo++, flag_arr);
- row_trival("Lightning", 2, TR2_IM_ELEC, 2, TR2_RES_ELEC, yo++, flag_arr);
- row_bival("Poison", 2, TR2_RES_POIS, yo++, flag_arr);
- row_bival("Lite", 2, TR2_RES_LITE, yo++, flag_arr);
- row_bival("Dark", 2, TR2_RES_DARK, yo++, flag_arr);
- row_bival("Sound", 2, TR2_RES_SOUND, yo++, flag_arr);
- row_bival("Shards", 2, TR2_RES_SHARDS, yo++, flag_arr);
- row_trival("Nether", 4, TR4_IM_NETHER, 2, TR2_RES_NETHER, yo++, flag_arr);
- row_bival("Nexus", 2, TR2_RES_NEXUS, yo++, flag_arr);
- row_bival("Chaos", 2, TR2_RES_CHAOS, yo++, flag_arr);
- row_bival("Disen.", 2, TR2_RES_DISEN, yo++, flag_arr);
- row_bival("Confusion", 2, TR2_RES_CONF, yo++, flag_arr);
- row_bival("Blindness", 2, TR2_RES_BLIND, yo++, flag_arr);
- row_bival("Fear", 2, TR2_RES_FEAR, yo++, flag_arr);
- row_bival("Free Act", 2, TR2_FREE_ACT, yo++, flag_arr);
- row_bival("Reflect", 2, TR2_REFLECT, yo++, flag_arr);
- row_bival("Hold Life", 2, TR2_HOLD_LIFE, yo++, flag_arr);
-
- c_put_str(TERM_WHITE, "Press ESC to continue", 23, 0);
- Term_fresh();
- while (1)
- {
- bool_ loop_exit = FALSE;
- char c;
-
- c = inkey();
- switch (c)
- {
- case ESCAPE:
- {
- loop_exit = TRUE;
- }
- }
- if (loop_exit == TRUE)
- {
- break;
- }
- }
-}
-
-void status_main(void)
-{
- int do_quit = 0;
- char c;
-
- character_icky = TRUE;
- Term_save();
- while (1)
- {
- clear_from(0);
- c_put_str(TERM_WHITE, format("%s Character Status screen", game_module), 0, 10);
- c_put_str(TERM_WHITE, "1) Statistics", 2, 5);
- c_put_str(TERM_WHITE, "2) Movement", 3, 5);
- c_put_str(TERM_WHITE, "3) Combat", 4, 5);
- c_put_str(TERM_WHITE, "4) Resistances", 5, 5);
- c_put_str(TERM_WHITE, "5) Misc", 6, 5);
- c_put_str(TERM_WHITE, "6) Curses", 7, 5);
- c_put_str(TERM_WHITE, "7) Sight", 8, 5);
- c_put_str(TERM_WHITE, "8) Companions", 9, 5);
- c_put_str(TERM_RED, "Press 'q' to Quit", 23, 5);
- c = inkey();
- switch (c)
- {
- case '1':
- status_attr();
- break;
- case '2':
- status_move();
- break;
- case '3':
- status_combat();
- break;
- case '4':
- status_res();
- break;
- case '5':
- status_item();
- break;
- case '6':
- status_curses();
- break;
- case '7':
- status_sight();
- break;
- case '8':
- status_companion();
- break;
- case 'q':
- case ESCAPE:
- do_quit = 1; /* Schedule leaving the outer loop */
- break;
- }
- Term_fresh();
- if (do_quit) break;
- }
- Term_load();
- character_icky = FALSE;
- p_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP);
- handle_stuff();
-}
-
-void az_line(int xo, u32b flag_arr[INVEN_TOTAL - INVEN_WIELD + 2][7])
-{
- int index = xo; /* Leave room for description */
- int i;
- for (i = INVEN_WIELD; i < INVEN_TOTAL; i++)
- {
- if (p_ptr->inventory[i].k_idx) /* Wearing anything here? */
- {
- char cstrng[2];
- cstrng[0] = (i - INVEN_WIELD) + 'a'; /* Assumes ASCII */
- cstrng[1] = '\0'; /* terminate it */
- c_put_str(TERM_WHITE, cstrng, 2, index++); /* Assumes ASCII */
-
- /* DGDGDGDG */
- /* object_flags_known(&inventory[i],*/
- object_flags(&p_ptr->inventory[i], /* Help me debug */
- &flag_arr[i - INVEN_WIELD][1], /* f1 */
- &flag_arr[i - INVEN_WIELD][2], /* f2 */
- &flag_arr[i - INVEN_WIELD][3], /* f3 */
- &flag_arr[i - INVEN_WIELD][4], /* f4 */
- &flag_arr[i - INVEN_WIELD][5], /* f5 */
- &flag_arr[i - INVEN_WIELD][0]); /* esp */
- flag_arr[i - INVEN_WIELD][6] = 1; /* And mark it to display */
- }
- else flag_arr[i - INVEN_WIELD][6] = 0; /* Otherwise don't display it */
- }
- c_put_str(TERM_WHITE, "@", 2, index++);
- player_flags(
- &flag_arr[INVEN_PLAYER][1], /* f1 */
- &flag_arr[INVEN_PLAYER][2], /* f2 */
- &flag_arr[INVEN_PLAYER][3], /* f3 */
- &flag_arr[INVEN_PLAYER][4], /* f4 */
- &flag_arr[INVEN_PLAYER][5], /* f5 */
- &flag_arr[INVEN_PLAYER][0] /* esp */
- );
- flag_arr[INVEN_PLAYER][6] = 1;
-}
-
-static void status_trival(s32b val1, s32b val2, byte ypos, byte xpos)
-{
- if (val1 != 0)
- c_put_str(TERM_L_BLUE, "*", ypos, xpos);
- else if (val2 != 0)
- c_put_str(TERM_L_BLUE, "+", ypos, xpos);
- else
- c_put_str(TERM_WHITE, ".", ypos, xpos);
-}
-
-static void status_bival(s32b val, byte ypos, byte xpos)
-{
- if (val != 0)
- c_put_str(TERM_L_BLUE, "+", ypos, xpos);
- else
- c_put_str(TERM_WHITE, ".", ypos, xpos);
-}
-
-static void status_numeric(s32b val, byte ypos, byte xpos)
-{
- u32b magnitude = ABS(val);
- int color = TERM_WHITE; /* default */
- char strnum[2];
-
- if (val<0) {
- color = TERM_RED;
- };
- if (val>0) {
- color = TERM_GREEN;
- };
-
- if (magnitude == 0) {
- sprintf(strnum, ".");
- } if (magnitude > 9) {
- sprintf(strnum, "*");
- } else {
- sprintf(strnum, "%lu", (unsigned long int) magnitude);
- }
-
- c_put_str(color, strnum, ypos, xpos);
-}
-
-static void status_count(s32b val1, int v1, s32b val2, int v2, s32b val3, int v3, s32b val4, int v4, byte ypos, byte xpos)
-{
- int v = 0;
-
- if (val1 != 0) v += v1;
- if (val2 != 0) v += v2;
- if (val3 != 0) v += v3;
- if (val4 != 0) v += v4;
-
- 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])
-{
- int i;
- int x = row_x_start;
-
- c_put_str(TERM_L_GREEN, statname, yo, row_x_start);
-
- for (i = 0; i < (INVEN_TOTAL - INVEN_WIELD + 2); i++)
- {
- if (flag_arr[i][6] == 1)
- {
- status_count((flag_arr[i][row1] & flag1), v1, (flag_arr[i][row2] & flag2), v2, (flag_arr[i][row3] & flag3), v3, (flag_arr[i][row4] & flag4), v4, yo, x + STATNM_LENGTH);
- x++;
- }
- }
-}
-
-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])
-{
- int i;
- int x = row_x_start;
- c_put_str(TERM_L_GREEN, statname, yo, row_x_start);
- for (i = 0; i < (INVEN_TOTAL - INVEN_WIELD + 2); i++)
- {
- if (flag_arr[i][6] == 1)
- {
- status_trival(
- (flag_arr[i][row] & flag),
- (flag_arr[i][row2] & flag2),
- yo, x + STATNM_LENGTH);
- x++;
- }
- }
-}
-
-static void row_bival(char* statname, s16b row, u32b flag, int yo, u32b flag_arr[INVEN_TOTAL - INVEN_WIELD + 2][7])
-{
- int i;
- int x = row_x_start;
- c_put_str(TERM_L_GREEN, statname, yo, row_x_start);
- for (i = 0; i < (INVEN_TOTAL - INVEN_WIELD + 2); i++)
- {
- if (flag_arr[i][6] == 1)
- {
- status_bival((flag_arr[i][row] & flag), yo, x + STATNM_LENGTH);
- x++;
- }
- }
-}
-
-static void row_npval(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;
- int x = row_x_start;
- c_put_str(TERM_L_GREEN, statname, yo, row_x_start);
- for (i = 0; i < (INVEN_TOTAL - INVEN_WIELD + 2); i++)
- {
- if (flag_arr[i][6] == 1)
- {
- if (i == INVEN_PLAYER)
- /* Special case, player_flags */
- /* Players lack a pval, no way to calc value */
- {
- if (flag_arr[i][row] & flag)
- c_put_str(TERM_YELLOW, "*", yo, x + STATNM_LENGTH);
- else c_put_str(TERM_WHITE, ".", yo, x + STATNM_LENGTH);
- x++;
- continue;
- }
- if (flag_arr[i][row] & flag)
- status_numeric(p_ptr->inventory[i + INVEN_WIELD].pval, yo, x + STATNM_LENGTH);
- else
- c_put_str(TERM_WHITE, ".", yo, x + STATNM_LENGTH);
- x++;
- }
- }
-}
-
-static void statline(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;
- int x = row_x_start;
- char statstr[8];
- byte stat_color = TERM_L_RED;
-
- cnv_stat(p_ptr->stat_use[statidx], statstr);
-
- c_put_str(TERM_L_GREEN, statstr, yo, 4 + row_x_start);
- for (i = 0; i < (INVEN_TOTAL - INVEN_WIELD + 2); i++)
- {
- byte color = TERM_L_RED;
-
- if (flag_arr[i][6] == 1)
- {
- switch (statidx)
- {
- case A_STR:
- if (flag_arr[i][2] & TR2_SUST_STR)
- color = TERM_L_BLUE;
- break;
- case A_INT:
- if (flag_arr[i][2] & TR2_SUST_INT)
- color = TERM_L_BLUE;
- break;
- case A_WIS:
- if (flag_arr[i][2] & TR2_SUST_WIS)
- color = TERM_L_BLUE;
- break;
- case A_DEX:
- if (flag_arr[i][2] & TR2_SUST_DEX)
- color = TERM_L_BLUE;
- break;
- case A_CON:
- if (flag_arr[i][2] & TR2_SUST_CON)
- color = TERM_L_BLUE;
- break;
- case A_CHR:
- if (flag_arr[i][2] & TR2_SUST_CHR)
- color = TERM_L_BLUE;
- break;
- }
-
- if (i == INVEN_PLAYER ) /* Player flags */
- {
- if (flag_arr[i][1] & flag)
- c_put_str((color == TERM_L_RED) ? TERM_YELLOW : color, "*", yo, x + SL_LENGTH);
- else c_put_str((color == TERM_L_RED) ? TERM_WHITE : color, ".", yo, x + SL_LENGTH);
- x++;
- continue;
- }
- if (flag_arr[i][1] & flag)
- status_numeric(p_ptr->inventory[i + INVEN_WIELD].pval, yo, x + SL_LENGTH);
- else
- c_put_str((color == TERM_L_RED) ? TERM_WHITE : color, ".", yo, x + SL_LENGTH);
-
- if (color != TERM_L_RED)
- stat_color = color;
-
- x++;
- }
- }
-
- c_put_str(stat_color, statname, yo, row_x_start);
-}
-
-static void row_hd_bon(int which, int yo, u32b flag_arr[INVEN_TOTAL - INVEN_WIELD + 2][7])
-/* To-hit/dmg modifiers, selected by 1st argument */
-{
- int i;
- int x = row_x_start;
- if ((which != 0) && (which != 1)) return;
- c_put_str(TERM_L_GREEN, ((which == 0) ? "To-Hit" : "To-Dmg"), yo, row_x_start);
- for (i = 0; i < (INVEN_TOTAL - INVEN_WIELD + 2); i++)
- {
- if (flag_arr[i][6] == 1)
- {
- if (i == INVEN_PLAYER) /* Player? */
- {
- c_put_str(TERM_WHITE, ".", yo, x + STATNM_LENGTH);
- x++;
- continue;
- }
- if ( (which == 0) && (p_ptr->inventory[INVEN_WIELD + i].to_h != 0))
- {
- status_numeric(p_ptr->inventory[INVEN_WIELD + i].to_h, yo, x + STATNM_LENGTH);
- x++;
- continue;
- }
- if ( (which == 1) && (p_ptr->inventory[INVEN_WIELD + i].to_d != 0))
- {
- status_numeric(p_ptr->inventory[INVEN_WIELD + i].to_d, yo, x + STATNM_LENGTH);
- x++;
- continue;
- }
- c_put_str(TERM_WHITE, ".", yo, x + STATNM_LENGTH);
- x++;
- }
- }
-}
-
-static void status_companion(void)
-{
- int i;
-
- FILE *fff;
-
- char file_name[1024];
-
- Term_clear();
-
- /* Temporary file */
- if (path_temp(file_name, 1024)) return;
-
- /* Open a new file */
- fff = my_fopen(file_name, "w");
-
- /* Calculate companions */
- /* Process the monsters (backwards) */
- for (i = m_max - 1; i >= 1; i--)
- {
- /* Access the monster */
- monster_type *m_ptr = &m_list[i];
-
- if (m_ptr->status == MSTATUS_COMPANION)
- {
- char m_name[80];
- int b, y = 0;
-
- /* Extract monster name */
- monster_desc(m_name, m_ptr, 0x80);
-
- fprintf(fff, "#####BCompanion: %s\n", m_name);
-
- fprintf(fff, " Lev/Exp : [[[[[G%d / %ld]\n", m_ptr->level, (long int) m_ptr->exp);
- if (m_ptr->level < MONSTER_LEVEL_MAX) fprintf(fff, " Next lvl: [[[[[G%ld]\n", (long int) MONSTER_EXP((s32b)m_ptr->level + 1));
- else fprintf(fff, " Next lvl: [[[[[G****]\n");
-
- fprintf(fff, " HP : [[[[[G%ld / %ld]\n", (long int) m_ptr->hp, (long int) m_ptr->maxhp);
- fprintf(fff, " AC : [[[[[G%d]\n", m_ptr->ac);
- fprintf(fff, " Speed : [[[[[G%d]\n", m_ptr->mspeed - 110);
-
- for (b = 0; b < 4; b++)
- {
- if (!m_ptr->blow[b].d_dice) continue;
- if (!m_ptr->blow[b].d_side) continue;
-
- fprintf(fff, " Blow %1d : [[[[[G%dd%d]\n", y + 1, m_ptr->blow[b].d_dice, m_ptr->blow[b].d_side);
- y++;
- }
-
- fprintf(fff, "\n");
- }
- }
-
- /* Close the file */
- my_fclose(fff);
-
- /* Display the file contents */
- show_file(file_name, "Companion List", 0, 0);
-
- /* Remove the file */
- fd_kill(file_name);
-}
diff --git a/src/store.c b/src/store.cc
index 78120846..a11a3ea8 100644
--- a/src/store.c
+++ b/src/store.cc
@@ -1,7 +1,3 @@
-/* File: store.c */
-
-/* Purpose: Store commands */
-
/*
* Copyright (c) 1989 James E. Wilson, Robert A. Koeneke
*
@@ -10,8 +6,57 @@
* included in all such copies.
*/
-#include "angband.h"
-
+#include "store.hpp"
+
+#include "bldg.hpp"
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "cmd3.hpp"
+#include "cmd4.hpp"
+#include "cmd5.hpp"
+#include "files.hpp"
+#include "game.hpp"
+#include "hooks.hpp"
+#include "obj_theme.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_flag.hpp"
+#include "object_kind.hpp"
+#include "options.hpp"
+#include "owner_type.hpp"
+#include "player_type.hpp"
+#include "spell_type.hpp"
+#include "skills.hpp"
+#include "spells5.hpp"
+#include "stats.hpp"
+#include "store_action_type.hpp"
+#include "store_flag.hpp"
+#include "store_type.hpp"
+#include "store_info_type.hpp"
+#include "tables.hpp"
+#include "town_type.hpp"
+#include "util.hpp"
+#include "util.h"
+#include "variable.h"
+#include "variable.hpp"
+#include "xtra1.hpp"
+#include "z-rand.hpp"
+
+#include <cassert>
+#include <fmt/format.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_CONSTRUCTION_SUPPLIES "Construction Supply Store"
+#define STORE_MUSIC "Music Store"
#define RUMOR_CHANCE 8
@@ -27,59 +72,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] =
@@ -100,42 +92,17 @@ 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.
*/
-static void say_comment_1(void)
+static void say_comment_1()
{
char rumour[80];
msg_print(comment_1[rand_int(MAX_COMMENT_1)]);
- if (randint(RUMOR_CHANCE) == 1 && speak_unique)
+ if (randint(RUMOR_CHANCE) == 1)
{
msg_print("The shopkeeper whispers something into your ear:");
get_rnd_line("rumors.txt", rumour);
@@ -145,85 +112,15 @@ 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-
*/
-static void say_comment_4(void)
+static void say_comment_4()
{
msg_print(comment_4a[rand_int(MAX_COMMENT_4A)]);
msg_print(comment_4b[rand_int(MAX_COMMENT_4B)]);
}
-/*
- * 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.
@@ -281,9 +178,6 @@ static void purchase_analyze(s32b price, s32b value, s32b guess)
{
/* Comment */
msg_print(comment_7a[rand_int(MAX_COMMENT_7A)]);
-
- /* Sound */
- sound(SOUND_STORE1);
}
/* Item was cheaper than we thought, and we paid more than necessary */
@@ -291,9 +185,6 @@ static void purchase_analyze(s32b price, s32b value, s32b guess)
{
/* Comment */
msg_print(comment_7b[rand_int(MAX_COMMENT_7B)]);
-
- /* Sound */
- sound(SOUND_STORE2);
}
/* Item was a good bargain, and we got away with it */
@@ -301,9 +192,6 @@ static void purchase_analyze(s32b price, s32b value, s32b guess)
{
/* Comment */
msg_print(comment_7c[rand_int(MAX_COMMENT_7C)]);
-
- /* Sound */
- sound(SOUND_STORE3);
}
/* Item was a great bargain, and we got away with it */
@@ -311,9 +199,6 @@ static void purchase_analyze(s32b price, s32b value, s32b guess)
{
/* Comment */
msg_print(comment_7d[rand_int(MAX_COMMENT_7D)]);
-
- /* Sound */
- sound(SOUND_STORE4);
}
}
@@ -339,7 +224,7 @@ static store_type *st_ptr = NULL;
/*
* We store the current "owner type" here so everyone can access it
*/
-static owner_type *ot_ptr = NULL;
+static owner_type const *ot_ptr = NULL;
@@ -364,6 +249,8 @@ static owner_type *ot_ptr = NULL;
*/
static s32b price_item(object_type *o_ptr, int greed, bool_ flip)
{
+ auto const &st_info = game->edit_data.st_info;
+
int factor;
int adjust;
s32b price;
@@ -412,7 +299,10 @@ static s32b price_item(object_type *o_ptr, int greed, bool_ flip)
if (adjust > 100) adjust = 100;
/* Mega-Hack -- Black market sucks */
- if (st_info[st_ptr->st_idx].flags1 & SF1_ALL_ITEM) price = price / 2;
+ if (st_info[st_ptr->st_idx].flags & STF_ALL_ITEM) price = price / 2;
+
+ /* No selling means you get no money */
+ if (options->no_selling) price = 0;
}
/* Shop is selling */
@@ -425,15 +315,15 @@ static s32b price_item(object_type *o_ptr, int greed, bool_ flip)
if (adjust < 100) adjust = 100;
/* Mega-Hack -- Black market sucks */
- if (st_info[st_ptr->st_idx].flags1 & SF1_ALL_ITEM) price = price * 2;
+ if (st_info[st_ptr->st_idx].flags & STF_ALL_ITEM) price = price * 2;
+
+ /* Never give items away for free */
+ if (price <= 0L) price = 1L;
}
/* Compute the final price (with rounding) */
price = (price * adjust + 50L) / 100L;
- /* Note -- Never become "free" */
- if (price <= 0L) return (1L);
-
/* Return the price */
return (price);
}
@@ -564,9 +454,9 @@ static void mass_produce(object_type *o_ptr)
}
- if (o_ptr->art_name)
+ if (!o_ptr->artifact_name.empty())
{
- if (cheat_peek && discount)
+ if (options->cheat_peek && discount)
{
msg_print("No discount on random artifacts.");
}
@@ -592,7 +482,7 @@ static void mass_produce(object_type *o_ptr)
*
* See "object_similar()" for the same function for the "player"
*/
-static bool_ store_object_similar(object_type *o_ptr, object_type *j_ptr)
+static bool_ store_object_similar(object_type const *o_ptr, object_type *j_ptr)
{
/* Hack -- Identical items cannot be stacked */
if (o_ptr == j_ptr) return (0);
@@ -622,12 +512,11 @@ static bool_ store_object_similar(object_type *o_ptr, object_type *j_ptr)
if (o_ptr->name2b != j_ptr->name2b) return (0);
/* Random artifacts don't stack !*/
- if (o_ptr->art_name || j_ptr->art_name) return (0);
+ if (!o_ptr->artifact_name.empty()) return 0;
+ if (!j_ptr->artifact_name.empty()) return 0;
/* Hack -- Identical art_flags! */
- if ((o_ptr->art_flags1 != j_ptr->art_flags1) ||
- (o_ptr->art_flags2 != j_ptr->art_flags2) ||
- (o_ptr->art_flags3 != j_ptr->art_flags3))
+ if (o_ptr->art_flags != j_ptr->art_flags)
return (0);
/* Hack -- Never stack "powerful" items */
@@ -685,24 +574,25 @@ static void store_object_absorb(object_type *o_ptr, object_type *j_ptr)
*/
static bool_ store_check_num(object_type *o_ptr)
{
- int i;
- object_type *j_ptr;
+ auto const &st_info = game->edit_data.st_info;
/* Free space is always usable */
- if (st_ptr->stock_num < st_ptr->stock_size) return TRUE;
+ if (st_ptr->stock.size() < st_ptr->stock_size)
+ {
+ return TRUE;
+ }
/* The "home" acts like the player */
- if ((cur_store_num == 7) ||
- (st_info[st_ptr->st_idx].flags1 & SF1_MUSEUM))
+ if ((cur_store_num == 7) || (st_info[st_ptr->st_idx].flags & STF_MUSEUM))
{
/* Check all the items */
- for (i = 0; i < st_ptr->stock_num; i++)
+ for (auto const &o_ref: st_ptr->stock)
{
- /* Get the existing item */
- j_ptr = &st_ptr->stock[i];
-
/* Can the new object be combined with the old one? */
- if (object_similar(j_ptr, o_ptr)) return (TRUE);
+ if (object_similar(&o_ref, o_ptr))
+ {
+ return TRUE;
+ }
}
}
@@ -710,27 +600,25 @@ static bool_ store_check_num(object_type *o_ptr)
else
{
/* Check all the items */
- for (i = 0; i < st_ptr->stock_num; i++)
+ for (auto const &o_ref: st_ptr->stock)
{
- /* Get the existing item */
- j_ptr = &st_ptr->stock[i];
-
/* Can the new object be combined with the old one? */
- if (store_object_similar(j_ptr, o_ptr)) return (TRUE);
+ if (store_object_similar(&o_ref, o_ptr))
+ {
+ return TRUE;
+ }
}
}
/* But there was no room at the inn... */
- return (FALSE);
+ return FALSE;
}
-bool_ is_blessed(object_type *o_ptr)
+static bool is_blessed(object_type const *o_ptr)
{
- u32b f1, f2, f3, f4, f5, esp;
- object_flags_known(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
- if (f3 & TR3_BLESSED) return (TRUE);
- else return (FALSE);
+ auto flags = object_flags_known(o_ptr);
+ return bool(flags & TR_BLESSED);
}
@@ -740,24 +628,212 @@ bool_ is_blessed(object_type *o_ptr)
*
* Note that a shop-keeper must refuse to buy "worthless" items
*/
-static bool_ store_will_buy(object_type *o_ptr)
+static bool store_will_buy(object_type const *o_ptr)
{
+ auto const &st_info = game->edit_data.st_info;
+
+ auto const &store_name = st_info[st_ptr->st_idx].name;
+
/* Hack -- The Home is simple */
- if (cur_store_num == 7) return (TRUE);
+ if (cur_store_num == 7)
+ {
+ return true;
+ }
- if (st_info[st_ptr->st_idx].flags1 & SF1_MUSEUM) return TRUE;
+ if (st_info[st_ptr->st_idx].flags & STF_MUSEUM)
+ {
+ return true;
+ }
/* XXX XXX XXX Ignore "worthless" items */
- if (object_value(o_ptr) <= 0) return (FALSE);
+ if (object_value(o_ptr) <= 0)
+ {
+ return false;
+ }
+
+ /* What do stores buy? */
+ if ((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 ((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 ((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 ((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) &&
+ (spell_type_random_type(spell_at(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 ((store_name == STORE_ALCHEMY))
+ {
+ switch (o_ptr->tval)
+ {
+ case TV_SCROLL:
+ case TV_POTION2:
+ case TV_POTION:
+ case TV_BOTTLE:
+ return true;
+ }
+ }
+ else if ((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;
+ }
- /* 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))
+ if ((o_ptr->tval == TV_BOOK) &&
+ (o_ptr->sval == BOOK_RANDOM) &&
+ (spell_type_random_type(spell_at(o_ptr->pval)) == SKILL_MAGIC))
+ {
+ return true;
+ }
+ else if ((o_ptr->tval == TV_BOOK) &&
+ (o_ptr->sval != BOOK_RANDOM))
+ {
+ return true;
+ }
+ }
+ else if ((store_name == STORE_BLACK_MARKET))
{
- return process_hooks_return[0].num;
+ return true;
+ }
+ else if ((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 ((store_name == STORE_PETS))
+ {
+ return (o_ptr->tval == TV_EGG);
+ }
+ else if ((store_name == STORE_HUNTING_SUPPLIES))
+ {
+ switch (o_ptr->tval)
+ {
+ case TV_BOOMERANG:
+ case TV_SHOT:
+ case TV_BOLT:
+ case TV_ARROW:
+ case TV_BOW:
+ case TV_POTION2:
+ return true;
+ }
+ }
+ else if ((store_name == STORE_CONSTRUCTION_SUPPLIES))
+ {
+ switch (o_ptr->tval)
+ {
+ case TV_LITE:
+ case TV_DIGGING:
+ return true;
+ }
+ }
+ else if ((store_name == STORE_MUSIC))
+ {
+ return (o_ptr->tval == TV_INSTRUMENT);
}
/* Assume not okay */
- return (FALSE);
+ return false;
}
@@ -774,17 +850,13 @@ static bool_ store_will_buy(object_type *o_ptr)
*/
static int home_carry(object_type *o_ptr)
{
- int slot;
- s32b value, j_value;
- int i;
- object_type *j_ptr;
-
+ std::size_t slot;
/* Check each existing item (try to combine) */
- for (slot = 0; slot < st_ptr->stock_num; slot++)
+ for (slot = 0; slot < st_ptr->stock.size(); slot++)
{
/* Get the existing item */
- j_ptr = &st_ptr->stock[slot];
+ auto j_ptr = &st_ptr->stock[slot];
/* The home acts just like the player */
if (object_similar(j_ptr, o_ptr))
@@ -793,22 +865,24 @@ static int home_carry(object_type *o_ptr)
object_absorb(j_ptr, o_ptr);
/* All done */
- return (slot);
+ return slot;
}
}
/* No space? */
- if (st_ptr->stock_num >= st_ptr->stock_size) return ( -1);
-
+ if (st_ptr->stock.size() >= st_ptr->stock_size)
+ {
+ return -1;
+ }
/* Determine the "value" of the item */
- value = object_value(o_ptr);
+ auto const value = object_value(o_ptr);
/* Check existing slots to see if we must "slide" */
- for (slot = 0; slot < st_ptr->stock_num; slot++)
+ for (slot = 0; slot < st_ptr->stock.size(); slot++)
{
/* Get that item */
- j_ptr = &st_ptr->stock[slot];
+ auto j_ptr = &st_ptr->stock[slot];
/* Objects sort by decreasing type */
if (o_ptr->tval > j_ptr->tval) break;
@@ -838,25 +912,16 @@ static int home_carry(object_type *o_ptr)
}
/* Objects sort by decreasing value */
- j_value = object_value(j_ptr);
+ auto const j_value = object_value(j_ptr);
if (value > j_value) break;
if (value < j_value) continue;
}
- /* Slide the others up */
- for (i = st_ptr->stock_num; i > slot; i--)
- {
- st_ptr->stock[i] = st_ptr->stock[i - 1];
- }
-
- /* More stuff now */
- st_ptr->stock_num++;
-
- /* Insert the new item */
- st_ptr->stock[slot] = *o_ptr;
+ /* Insert */
+ st_ptr->stock.insert(st_ptr->stock.begin() + slot, *o_ptr);
/* Return the location */
- return (slot);
+ return slot;
}
@@ -874,28 +939,28 @@ static int home_carry(object_type *o_ptr)
*/
static int store_carry(object_type *o_ptr)
{
- int i, slot;
- s32b value, j_value;
- object_type *j_ptr;
-
+ std::size_t slot;
/* Evaluate the object */
- value = object_value(o_ptr);
+ auto const value = object_value(o_ptr);
/* Cursed/Worthless items "disappear" when sold */
- if (value <= 0) return ( -1);
+ if (value <= 0)
+ {
+ return -1;
+ }
/* All store items are fully *identified* */
o_ptr->ident |= IDENT_MENTAL;
/* Erase the inscription */
- o_ptr->note = 0;
+ o_ptr->inscription.clear();
/* Check each existing item (try to combine) */
- for (slot = 0; slot < st_ptr->stock_num; slot++)
+ for (slot = 0; slot < st_ptr->stock.size(); slot++)
{
/* Get the existing item */
- j_ptr = &st_ptr->stock[slot];
+ auto j_ptr = &st_ptr->stock[slot];
/* Can the existing items be incremented? */
if (store_object_similar(j_ptr, o_ptr))
@@ -904,19 +969,22 @@ static int store_carry(object_type *o_ptr)
store_object_absorb(j_ptr, o_ptr);
/* All done */
- return (slot);
+ return slot;
}
}
/* No space? */
- if (st_ptr->stock_num >= st_ptr->stock_size) return ( -1);
+ if (st_ptr->stock.size() >= st_ptr->stock_size)
+ {
+ return -1;
+ }
/* Check existing slots to see if we must "slide" */
- for (slot = 0; slot < st_ptr->stock_num; slot++)
+ for (slot = 0; slot < st_ptr->stock.size(); slot++)
{
/* Get that item */
- j_ptr = &st_ptr->stock[slot];
+ auto j_ptr = &st_ptr->stock[slot];
/* Objects sort by decreasing type */
if (o_ptr->tval > j_ptr->tval) break;
@@ -938,27 +1006,18 @@ static int store_carry(object_type *o_ptr)
}
/* Evaluate that slot */
- j_value = object_value(j_ptr);
+ auto const j_value = object_value(j_ptr);
/* Objects sort by decreasing value */
if (value > j_value) break;
if (value < j_value) continue;
}
- /* Slide the others up */
- for (i = st_ptr->stock_num; i > slot; i--)
- {
- st_ptr->stock[i] = st_ptr->stock[i - 1];
- }
-
- /* More stuff now */
- st_ptr->stock_num++;
-
/* Insert the new item */
- st_ptr->stock[slot] = *o_ptr;
+ st_ptr->stock.insert(st_ptr->stock.begin() + slot, *o_ptr);
/* Return the location */
- return (slot);
+ return slot;
}
@@ -968,14 +1027,11 @@ static int store_carry(object_type *o_ptr)
*/
static void store_item_increase(int item, int num)
{
- int cnt;
- object_type *o_ptr;
-
/* Get the item */
- o_ptr = &st_ptr->stock[item];
+ auto o_ptr = &st_ptr->stock[item];
/* Verify the number */
- cnt = o_ptr->number + num;
+ int cnt = o_ptr->number + num;
if (cnt > 255) cnt = 255;
else if (cnt < 0) cnt = 0;
num = cnt - o_ptr->number;
@@ -990,11 +1046,8 @@ static void store_item_increase(int item, int num)
*/
static void store_item_optimize(int item)
{
- int j;
- object_type *o_ptr;
-
/* Get the item */
- o_ptr = &st_ptr->stock[item];
+ auto const o_ptr = &st_ptr->stock[item];
/* Must exist */
if (!o_ptr->k_idx) return;
@@ -1002,17 +1055,11 @@ static void store_item_optimize(int item)
/* Must have no items */
if (o_ptr->number) return;
- /* One less item */
- st_ptr->stock_num--;
+ /* Wipe the item */
+ object_wipe(&st_ptr->stock[item]);
- /* Slide everyone */
- for (j = item; j < st_ptr->stock_num; j++)
- {
- st_ptr->stock[j] = st_ptr->stock[j + 1];
- }
-
- /* Nuke the final slot */
- object_wipe(&st_ptr->stock[j]);
+ /* Erase the item */
+ st_ptr->stock.erase(st_ptr->stock.begin() + item);
}
@@ -1023,7 +1070,7 @@ static void store_item_optimize(int item)
*/
static bool_ black_market_crap(object_type *o_ptr)
{
- int i, j;
+ auto const &st_info = game->edit_data.st_info;
/* Ego items are never crap */
if (o_ptr->name2) return (FALSE);
@@ -1034,18 +1081,16 @@ static bool_ black_market_crap(object_type *o_ptr)
if (o_ptr->to_d > 0) return (FALSE);
/* Check all stores */
- for (i = 0; i < max_st_idx; i++)
+ for (std::size_t i = 0; i < st_info.size(); i++)
{
if (i == STORE_HOME) continue;
- if (st_info[i].flags1 & SF1_MUSEUM) continue;
+ if (st_info[i].flags & STF_MUSEUM) continue;
/* Check every item in the store */
- for (j = 0; j < town_info[p_ptr->town_num].store[i].stock_num; j++)
+ for (auto const &stock_obj: town_info[p_ptr->town_num].store[i].stock)
{
- object_type *j_ptr = &town_info[p_ptr->town_num].store[i].stock[j];
-
/* Duplicate item "type", assume crappy */
- if (o_ptr->k_idx == j_ptr->k_idx) return (TRUE);
+ if (o_ptr->k_idx == stock_obj.k_idx) return (TRUE);
}
}
@@ -1058,15 +1103,13 @@ static bool_ black_market_crap(object_type *o_ptr)
* Attempt to delete (some of) a random item from the store
* Hack -- we attempt to "maintain" piles of items when possible.
*/
-static void store_delete(void)
+static void store_delete()
{
- int what, num;
-
/* Pick a random slot */
- what = rand_int(st_ptr->stock_num);
+ int const what = rand_int(st_ptr->stock.size());
/* Determine how many items are here */
- num = st_ptr->stock[what].number;
+ int num = st_ptr->stock[what].number;
/* Hack -- sometimes, only destroy half the items */
if (rand_int(100) < 50) num = (num + 1) / 2;
@@ -1088,19 +1131,22 @@ static void store_delete(void)
/* Analyze store flags and return a level */
int return_level()
{
- store_info_type *sti_ptr = &st_info[st_ptr->st_idx];
+ auto const &st_info = game->edit_data.st_info;
+
+ auto sti_ptr = &st_info[st_ptr->st_idx];
+
int level;
- if (sti_ptr->flags1 & SF1_RANDOM) level = 0;
+ if (sti_ptr->flags & STF_RANDOM) level = 0;
else level = rand_range(1, STORE_OBJ_LEVEL);
- if (sti_ptr->flags1 & SF1_DEPEND_LEVEL) level += dun_level;
+ if (sti_ptr->flags & STF_DEPEND_LEVEL) level += dun_level;
- if (sti_ptr->flags1 & SF1_SHALLOW_LEVEL) level += 5 + rand_int(5);
- if (sti_ptr->flags1 & SF1_MEDIUM_LEVEL) level += 25 + rand_int(25);
- if (sti_ptr->flags1 & SF1_DEEP_LEVEL) level += 45 + rand_int(45);
+ if (sti_ptr->flags & STF_SHALLOW_LEVEL) level += 5 + rand_int(5);
+ if (sti_ptr->flags & STF_MEDIUM_LEVEL) level += 25 + rand_int(25);
+ if (sti_ptr->flags & STF_DEEP_LEVEL) level += 45 + rand_int(45);
- if (sti_ptr->flags1 & SF1_ALL_ITEM) level += p_ptr->lev;
+ if (sti_ptr->flags & STF_ALL_ITEM) level += p_ptr->lev;
return (level);
}
@@ -1113,12 +1159,14 @@ static int store_tval = 0, store_level = 0;
*/
static bool_ kind_is_storeok(int k_idx)
{
- object_kind *k_ptr = &k_info[k_idx];
+ auto const &k_info = game->edit_data.k_info;
- if (k_info[k_idx].flags3 & TR3_NORM_ART)
+ auto k_ptr = &k_info[k_idx];
+
+ if (k_info[k_idx].flags & TR_NORM_ART)
return ( FALSE );
- if (k_info[k_idx].flags3 & TR3_INSTA_ART)
+ if (k_info[k_idx].flags & TR_INSTA_ART)
return ( FALSE );
if (!kind_is_legal(k_idx)) return FALSE;
@@ -1139,9 +1187,13 @@ static bool_ kind_is_storeok(int k_idx)
*
* Should we check for "permission" to have the given item?
*/
-static void store_create(void)
+static void store_create()
{
- int i = 0, tries, level = 0, chance, item;
+ auto const &st_info = game->edit_data.st_info;
+ auto const &k_info = game->edit_data.k_info;
+ auto &alloc = game->alloc;
+
+ int i = 0, tries, level = 0;
object_type forge;
object_type *q_ptr = NULL;
@@ -1149,7 +1201,10 @@ static void store_create(void)
/* Paranoia -- no room left */
- if (st_ptr->stock_num >= st_ptr->stock_size) return;
+ if (st_ptr->stock.size() >= st_ptr->stock_size)
+ {
+ return;
+ }
/* Hack -- consider up to four items */
@@ -1157,24 +1212,43 @@ static void store_create(void)
{
obj_all_done = FALSE;
- /* Lua can define things to buy */
- if (process_hooks_ret(HOOK_STORE_STOCK, "O", "(d,s,d)", st_ptr->st_idx, st_info[st_ptr->st_idx].name + st_name, return_level()))
+ /* Magic Shop */
+ if ((st_info[st_ptr->st_idx].name == STORE_MAGIC) &&
+ 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;
- q_ptr = process_hooks_return[0].o_ptr;
}
- /* Black Market */
- else if (st_info[st_ptr->st_idx].flags1 & SF1_ALL_ITEM)
+ /* Temple */
+ else if ((st_info[st_ptr->st_idx].name == STORE_TEMPLE) &&
+ magik(20))
{
- obj_theme theme;
+ 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].flags & STF_ALL_ITEM)
+ {
/* No themes */
- theme.treasure = 100;
- theme.combat = 100;
- theme.magic = 100;
- theme.tools = 100;
- init_match_theme(theme);
+ init_match_theme(obj_theme::no_theme());
/*
* Even in Black Markets, illegal objects can be
@@ -1192,7 +1266,7 @@ static void store_create(void)
i = get_obj_num(level);
/* Invalidate the cached allocation table */
- alloc_kind_table_valid = FALSE;
+ alloc.kind_table_valid = false;
/* Handle failure */
if (!i) continue;
@@ -1203,12 +1277,12 @@ static void store_create(void)
else
{
/* Hack -- Pick an item to sell */
- item = rand_int(st_info[st_ptr->st_idx].table_num);
- i = st_info[st_ptr->st_idx].table[item][0];
- chance = st_info[st_ptr->st_idx].table[item][1];
+ auto const &item = st_info[st_ptr->st_idx].items[rand_int(st_info[st_ptr->st_idx].items.size())];
+ i = item.kind;
+ auto chance = item.chance;
/* Don't allow k_info artifacts */
- if ((i <= 10000) && (k_info[i].flags3 & TR3_NORM_ART))
+ if ((i <= 10000) && (k_info[i].flags & TR_NORM_ART))
continue;
/* Does it passes the rarity check ? */
@@ -1220,22 +1294,22 @@ static void store_create(void)
/* Hack -- i > 10000 means it's a tval and all svals are allowed */
if (i > 10000)
{
- obj_theme theme;
-
/* No themes */
- theme.treasure = 100;
- theme.combat = 100;
- theme.magic = 100;
- theme.tools = 100;
- init_match_theme(theme);
+ init_match_theme(obj_theme::no_theme());
/* Activate restriction */
get_obj_num_hook = kind_is_storeok;
store_tval = i - 10000;
/* Do we forbid too shallow items ? */
- if (st_info[st_ptr->st_idx].flags1 & SF1_FORCE_LEVEL) store_level = level;
- else store_level = 0;
+ if (st_info[st_ptr->st_idx].flags & STF_FORCE_LEVEL)
+ {
+ store_level = level;
+ }
+ else
+ {
+ store_level = 0;
+ }
/* Prepare allocation table */
get_obj_num_prep();
@@ -1244,7 +1318,7 @@ static void store_create(void)
i = get_obj_num(level);
/* Invalidate the cached allocation table */
- alloc_kind_table_valid = FALSE;
+ alloc.kind_table_valid = false;
}
if (!i) continue;
@@ -1254,11 +1328,11 @@ static void store_create(void)
if (!obj_all_done)
{
/* Don't allow k_info artifacts */
- if (k_info[i].flags3 & TR3_NORM_ART)
+ if (k_info[i].flags & TR_NORM_ART)
continue;
/* Don't allow artifacts */
- if (k_info[i].flags3 & TR3_INSTA_ART)
+ if (k_info[i].flags & TR_INSTA_ART)
continue;
/* Get local object */
@@ -1273,11 +1347,11 @@ static void store_create(void)
/* Hack -- Charge lite's */
if (q_ptr->tval == TV_LITE)
{
- u32b f1, f2, f3, f4, f5, esp;
-
- object_flags(q_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
-
- if (f4 & TR4_FUEL_LITE) q_ptr->timeout = k_info[q_ptr->k_idx].pval2;
+ auto const flags = object_flags(q_ptr);
+ if (flags & TR_FUEL_LITE)
+ {
+ q_ptr->timeout = k_info[q_ptr->k_idx].pval2;
+ }
}
}
@@ -1292,7 +1366,7 @@ static void store_create(void)
if (q_ptr->tval == TV_CHEST) continue;
/* Prune the black market */
- if (st_info[st_ptr->st_idx].flags1 & SF1_ALL_ITEM)
+ if (st_info[st_ptr->st_idx].flags & STF_ALL_ITEM)
{
/* Hack -- No "crappy" items */
if (black_market_crap(q_ptr)) continue;
@@ -1319,7 +1393,7 @@ static void store_create(void)
}
/* Attempt to carry the (known) item */
- (void)store_carry(q_ptr);
+ store_carry(q_ptr);
/* Definitely done */
break;
@@ -1329,89 +1403,25 @@ 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
*/
static void display_entry(int pos)
{
- int i, cur_col;
- object_type *o_ptr;
- s32b x;
-
- char o_name[80];
- char out_val[160];
-
-
- int maxwid = 75;
+ auto const &st_info = game->edit_data.st_info;
/* Get the item */
- o_ptr = &st_ptr->stock[pos];
+ auto o_ptr = &st_ptr->stock[pos];
/* Get the "offset" */
- i = (pos % 12);
+ auto const i = (pos % 12);
/* Label it, clear the line --(-- */
+ char out_val[160];
strnfmt(out_val, 160, "%c) ", I2A(i));
c_prt(get_item_letter_color(o_ptr), out_val, i + 6, 0);
- cur_col = 3;
- if (show_store_graph)
+ int cur_col = 3;
{
byte a = object_attr(o_ptr);
char c = object_char(o_ptr);
@@ -1419,31 +1429,25 @@ static void display_entry(int pos)
if (!o_ptr->k_idx) c = ' ';
Term_draw(cur_col, i + 6, a, c);
- if (use_bigtile)
- {
- cur_col++;
- if (a & 0x80)
- Term_draw(cur_col, i + 6, 255, 255);
- }
cur_col += 2;
}
/* Describe an item in the home */
if ((cur_store_num == 7) ||
- (st_info[st_ptr->st_idx].flags1 & SF1_MUSEUM))
+ (st_info[st_ptr->st_idx].flags & STF_MUSEUM))
{
- maxwid = 75;
+ int maxwid = 75;
- /* Leave room for weights, if necessary -DRS- */
- if (show_weights) maxwid -= 10;
+ /* Leave room for weights */
+ maxwid -= 10;
/* Describe the object */
+ char o_name[80];
object_desc(o_name, o_ptr, TRUE, 3);
o_name[maxwid] = '\0';
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;
@@ -1458,18 +1462,18 @@ static void display_entry(int pos)
byte color = TERM_WHITE;
/* Must leave room for the "price" */
- maxwid = 65;
+ int maxwid = 65;
- /* Leave room for weights, if necessary -DRS- */
- if (show_weights) maxwid -= 7;
+ /* Leave room for weights */
+ maxwid -= 7;
/* Describe the object (fully) */
+ char o_name[80];
object_desc_store(o_name, o_ptr, TRUE, 3);
o_name[maxwid] = '\0';
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;
@@ -1477,50 +1481,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;
-
- /* Actually draw the price (with tax) */
- strnfmt(out_val, 160, "%9ld ", (long)x);
- c_put_str(color, out_val, i + 6, 68);
- }
-
- /* Display a "haggle" cost */
- else
- {
- /* Extrect the "maximum" price */
- x = price_item(o_ptr, ot_ptr->max_inflate, FALSE);
+ /* Extract the "minimum" price */
+ auto const x = price_item(o_ptr, ot_ptr->inflation, FALSE);
- /* Can we buy one ? */
- if (x > p_ptr->au) color = TERM_L_DARK;
+ /* 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 ", static_cast<long>(x));
+ c_put_str(color, out_val, i + 6, 68);
}
}
@@ -1529,28 +1498,31 @@ static void display_entry(int pos)
* Displays a store's inventory -RAK-
* All prices are listed as "per individual object". -BEN-
*/
-static void display_inventory(void)
+static void display_inventory()
{
- int i, k;
+ int k;
/* Display the next 12 items */
for (k = 0; k < 12; k++)
{
/* Do not display "dead" items */
- if (store_top + k >= st_ptr->stock_num) break;
+ if (store_top + k >= static_cast<int>(st_ptr->stock.size()))
+ {
+ break;
+ }
/* Display that line */
display_entry(store_top + k);
}
/* Erase the extra lines and the "more" prompt */
- for (i = k; i < 13; i++) prt("", i + 6, 0);
+ for (int i = k; i < 13; i++) prt("", i + 6, 0);
/* Assume "no current page" */
put_str(" ", 5, 20);
/* Visual reminder of "more items" */
- if (st_ptr->stock_num > 12)
+ if (st_ptr->stock.size() > 12)
{
/* Show "more" reminder (after the last item) */
prt("-more-", k + 6, 3);
@@ -1564,13 +1536,13 @@ static void display_inventory(void)
/*
* Displays players gold -RAK-
*/
-void store_prt_gold(void)
+void store_prt_gold()
{
char out_val[64];
prt("Gold Remaining: ", 19, 53);
- strnfmt(out_val, 64, "%9ld", (long)p_ptr->au);
+ strnfmt(out_val, 64, "%9ld", static_cast<long>(p_ptr->au));
prt(out_val, 19, 68);
}
@@ -1578,8 +1550,10 @@ void store_prt_gold(void)
/*
* Displays store (after clearing screen) -RAK-
*/
-void display_store(void)
+void display_store()
{
+ auto const &st_info = game->edit_data.st_info;
+
char buf[80];
@@ -1595,52 +1569,36 @@ 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)
+ else if (st_info[st_ptr->st_idx].flags & STF_MUSEUM)
{
- cptr store_name = (st_name + st_info[cur_store_num].name);
-
/* Show the name of the store */
- strnfmt(buf, 80, "%s", store_name);
- prt(buf, 3, 30);
+ prt(st_info[cur_store_num].name, 3, 30);
/* Label the item descriptions */
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 */
else
{
- cptr store_name = (st_name + st_info[cur_store_num].name);
- cptr owner_name = (ow_name + ot_ptr->name);
-
/* Put the owner name and race */
- strnfmt(buf, 80, "%s", owner_name);
+ strnfmt(buf, 80, "%s", ot_ptr->name.c_str());
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));
- prt(buf, 3, 50);
+ prt(fmt::format("{:s} ({:d})", st_info[cur_store_num].name, ot_ptr->max_cost), 3, 50);
/* Label the item descriptions */
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);
@@ -1722,220 +1680,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;
+ cptr allowed = "yn\r\n";
+ cptr yes = "y\r\n";
+ char buf[128];
+ bool_ ret;
+ /* Build prompt */
+ snprintf(buf, sizeof(buf), "%s [y/n/RET/ESC] ", prompt);
- /* 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)));
- }
-
- /* 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);
- }
-
-
- /* 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) || options->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-
*
@@ -1943,176 +1738,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;
+ /* Describe the object (fully) */
+ object_desc_store(o_name, o_ptr, TRUE, 3);
- /* 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;
-
- /* 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);
}
@@ -2123,235 +1784,101 @@ 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;
-
- /* No offer yet */
- offer = 0;
+ /* Describe the object */
+ object_desc(o_name, o_ptr, TRUE, 3);
- /* 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);
}
/*
* Will the owner retire?
*/
-static bool_ retire_owner_p(void)
+static bool retire_owner_p()
{
- store_info_type *sti_ptr = &st_info[town_info[p_ptr->town_num].store[cur_store_num].st_idx];
+ auto const &st_info = game->edit_data.st_info;
- if ((sti_ptr->owners[0] == sti_ptr->owners[1]) &&
- (sti_ptr->owners[0] == sti_ptr->owners[2]) &&
- (sti_ptr->owners[0] == sti_ptr->owners[3]))
+ auto sti_ptr = &st_info[town_info[p_ptr->town_num].store[cur_store_num].st_idx];
+
+ if (sti_ptr->owners.size() > 1)
{
- /* there is no other owner */
- return FALSE;
+ return false; // No other possible owner
}
if (rand_int(STORE_SHUFFLE) != 0)
{
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
/*
- * Stole an item from a store -DG-
+ * Adjust store_top to account for a removed item
*/
-void store_stole(void)
+static void adjust_store_top_item_removed()
{
- int i, amt;
- int item, item_new;
-
- object_type forge;
- object_type *j_ptr;
+ /* Nothing left? */
+ if (st_ptr->stock.empty() == 0)
+ {
+ store_top = 0;
+ }
- object_type *o_ptr;
+ /* Already at the top beginning? */
+ else if (store_top == 0)
+ {
+ /* Nothing to do */
+ }
- char o_name[80];
+ /* Nothing left on current screen? */
+ else if (store_top >= static_cast<int>(st_ptr->stock.size()))
+ {
+ store_top -= 12;
+ }
+}
- char out_val[160];
+/*
+ * Stole an item from a store -DG-
+ */
+void store_stole()
+{
if (cur_store_num == 7)
{
msg_print("You can't steal from your home!");
@@ -2359,7 +1886,7 @@ void store_stole(void)
}
/* Empty? */
- if (st_ptr->stock_num <= 0)
+ if (st_ptr->stock.empty())
{
msg_print("There is no item to steal.");
return;
@@ -2367,30 +1894,31 @@ void store_stole(void)
/* Find the number of objects on this and following pages */
- i = (st_ptr->stock_num - store_top);
+ int i = (st_ptr->stock.size() - store_top);
/* And then restrict it to the current page */
if (i > 12) i = 12;
/* Prompt */
+ char out_val[160];
strnfmt(out_val, 160, "Which item do you want to steal? ");
/* Get the item number to be bought */
+ int item;
if (!get_stock(&item, out_val, 0, i - 1)) return;
/* Get the actual index */
item = item + store_top;
/* Get the actual item */
- o_ptr = &st_ptr->stock[item];
+ object_type *o_ptr = &st_ptr->stock[item];
/* Assume the player wants just one of them */
- amt = 1;
-
- /* Get local object */
- j_ptr = &forge;
+ int amt = 1;
/* Get a copy of the object */
+ object_type forge;
+ object_type *j_ptr = &forge;
object_copy(j_ptr, o_ptr);
/* Modify quantity */
@@ -2441,9 +1969,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
@@ -2457,16 +1982,17 @@ void store_stole(void)
}
/* Describe the transaction */
+ char o_name[80];
object_desc(o_name, j_ptr, TRUE, 3);
/* Message */
msg_format("You steal %s.", o_name);
/* Erase the inscription */
- j_ptr->note = 0;
+ j_ptr->inscription.clear();
/* Give it to the player */
- item_new = inven_carry(j_ptr, FALSE);
+ int const item_new = inven_carry(j_ptr, FALSE);
/* Describe the final result */
object_desc(o_name, &p_ptr->inventory[item_new], TRUE, 3);
@@ -2479,14 +2005,14 @@ void store_stole(void)
handle_stuff();
/* Note how many slots the store used to have */
- i = st_ptr->stock_num;
+ auto prev_stock_size = st_ptr->stock.size();
/* Remove the bought items from the store */
store_item_increase(item, -amt);
store_item_optimize(item);
/* Store is empty */
- if (st_ptr->stock_num == 0)
+ if (st_ptr->stock.empty())
{
/* Shuffle */
if (retire_owner_p())
@@ -2506,7 +2032,7 @@ void store_stole(void)
}
/* New inventory */
- for (i = 0; i < 10; i++)
+ for (int k = 0; k < 10; k++)
{
/* Maintain the store */
store_maint(p_ptr->town_num, cur_store_num);
@@ -2520,10 +2046,9 @@ void store_stole(void)
}
/* The item is gone */
- else if (st_ptr->stock_num != i)
+ else if (st_ptr->stock.size() != prev_stock_size)
{
- /* Pick the correct screen */
- if (store_top >= st_ptr->stock_num) store_top -= 12;
+ adjust_store_top_item_removed();
/* Redraw everything */
display_inventory();
@@ -2541,11 +2066,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);
}
@@ -2557,31 +2077,19 @@ void store_stole(void)
/*
* Buy an item from a store -RAK-
*/
-void store_purchase(void)
+void store_purchase()
{
- int i, amt = 1, choice;
- int item, item_new;
-
- s32b price, best;
-
- object_type forge;
- object_type *j_ptr;
-
- object_type *o_ptr;
-
- char o_name[80];
-
- char out_val[160];
+ auto const &st_info = game->edit_data.st_info;
/* Museum? */
- if (st_info[st_ptr->st_idx].flags1 & SF1_MUSEUM)
+ if (st_info[st_ptr->st_idx].flags & STF_MUSEUM)
{
msg_print("You cannot take items from the museum!");
return;
}
/* Empty? */
- if (st_ptr->stock_num <= 0)
+ if (st_ptr->stock.empty())
{
if (cur_store_num == 7) msg_print("Your home is empty.");
else msg_print("I am currently out of stock.");
@@ -2590,12 +2098,13 @@ void store_purchase(void)
/* Find the number of objects on this and following pages */
- i = (st_ptr->stock_num - store_top);
+ int i = (st_ptr->stock.size() - store_top);
/* And then restrict it to the current page */
if (i > 12) i = 12;
/* Prompt */
+ char out_val[160];
if (cur_store_num == 7)
{
strnfmt(out_val, 160, "Which item do you want to take? ");
@@ -2606,18 +2115,18 @@ void store_purchase(void)
}
/* Get the item number to be bought */
+ int item;
if (!get_stock(&item, out_val, 0, i - 1)) return;
/* Get the actual index */
item = item + store_top;
/* Get the actual item */
- o_ptr = &st_ptr->stock[item];
-
- /* Get local object */
- j_ptr = &forge;
+ auto o_ptr = &st_ptr->stock[item];
/* Get a copy of one object to determine the price */
+ object_type forge;
+ auto j_ptr = &forge;
object_copy(j_ptr, o_ptr);
/* Modify quantity */
@@ -2637,20 +2146,15 @@ void store_purchase(void)
}
/* Determine the "best" price (per item) */
- best = price_item(j_ptr, ot_ptr->min_inflate, FALSE);
+ auto const best = price_item(j_ptr, ot_ptr->inflation, FALSE);
/* Find out how many the player wants */
+ int amt = 1;
if (o_ptr->number > 1)
{
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)
{
@@ -2662,10 +2166,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;
}
if (o_ptr->number < q)
q = o_ptr->number;
@@ -2684,10 +2185,8 @@ void store_purchase(void)
if (amt <= 0) return;
}
- /* Get local object */
- j_ptr = &forge;
-
/* Get desired object */
+ j_ptr = &forge;
object_copy(j_ptr, o_ptr);
/* Modify quantity */
@@ -2711,52 +2210,23 @@ 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 */
+ s32b price;
+ auto const 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)
+ if (!choice)
{
- /* 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)
{
/* Say "okay" */
say_comment_1();
- /* Make a sound */
- sound(SOUND_BUY);
-
- /* Be happy */
- decrease_insults();
-
/* Spend the money */
p_ptr->au -= price;
@@ -2770,17 +2240,15 @@ 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 */
+ char o_name[80];
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;
+ j_ptr->inscription.clear();
/* Hack -- If a rod or wand, allocate total maximum
* timeouts or charges between those picked up and
@@ -2793,7 +2261,7 @@ void store_purchase(void)
}
/* Give it to the player */
- item_new = inven_carry(j_ptr, FALSE);
+ int const item_new = inven_carry(j_ptr, FALSE);
/* Describe the final result */
object_desc(o_name, &p_ptr->inventory[item_new], TRUE, 3);
@@ -2806,14 +2274,14 @@ void store_purchase(void)
handle_stuff();
/* Note how many slots the store used to have */
- i = st_ptr->stock_num;
+ auto prev_stock_size = st_ptr->stock.size();
/* Remove the bought items from the store */
store_item_increase(item, -amt);
store_item_optimize(item);
/* Store is empty */
- if (st_ptr->stock_num == 0)
+ if (st_ptr->stock.empty())
{
/* Shuffle */
if (retire_owner_p())
@@ -2833,7 +2301,7 @@ void store_purchase(void)
}
/* New inventory */
- for (i = 0; i < 10; i++)
+ for (int k = 0; k < 10; k++)
{
/* Maintain the store */
store_maint(p_ptr->town_num, cur_store_num);
@@ -2844,10 +2312,9 @@ void store_purchase(void)
}
/* The item is gone */
- else if (st_ptr->stock_num != i)
+ else if (st_ptr->stock.size() != prev_stock_size)
{
- /* Pick the correct screen */
- if (store_top >= st_ptr->stock_num) store_top -= 12;
+ adjust_store_top_item_removed();
}
/* Redraw everything */
@@ -2877,9 +2344,10 @@ void store_purchase(void)
}
/* Give it to the player */
- item_new = inven_carry(j_ptr, FALSE);
+ int const item_new = inven_carry(j_ptr, FALSE);
/* Describe just the result */
+ char o_name[80];
object_desc(o_name, &p_ptr->inventory[item_new], TRUE, 3);
/* Message */
@@ -2889,14 +2357,14 @@ void store_purchase(void)
handle_stuff();
/* Take note if we take the last one */
- i = st_ptr->stock_num;
+ std::size_t prev_stock_size = st_ptr->stock.size();
/* Remove the items from the home */
store_item_increase(item, -amt);
store_item_optimize(item);
/* Hack -- Item is still here */
- if (i == st_ptr->stock_num)
+ if (prev_stock_size == st_ptr->stock.size())
{
/* Redraw the item */
display_entry(item);
@@ -2905,11 +2373,7 @@ void store_purchase(void)
/* The item is gone */
else
{
- /* Nothing left */
- if (st_ptr->stock_num == 0) store_top = 0;
-
- /* Nothing left on that screen */
- else if (store_top >= st_ptr->stock_num) store_top -= 12;
+ adjust_store_top_item_removed();
/* Redraw everything */
display_inventory();
@@ -2924,8 +2388,10 @@ void store_purchase(void)
/*
* Sell an item to the store (or home)
*/
-void store_sell(void)
+void store_sell()
{
+ auto const &st_info = game->edit_data.st_info;
+
int choice;
int item, item_pos;
int amt;
@@ -2935,43 +2401,38 @@ void store_sell(void)
object_type forge;
object_type *q_ptr;
- object_type *o_ptr;
-
- cptr q, s;
-
char o_name[80];
- u32b f1, f2, f3, f4, f5, esp;
-
- bool_ museum = (st_info[st_ptr->st_idx].flags1 & SF1_MUSEUM) ? TRUE : FALSE;
-
- /* Prepare a prompt */
- if (cur_store_num == 7) q = "Drop which item? ";
- else if (museum) q = "Donate which item?";
- else q = "Sell which item? ";
-
- /* Only allow items the store will buy */
- item_tester_hook = store_will_buy;
+ bool museum = bool(st_info[st_ptr->st_idx].flags & STF_MUSEUM);
- /* Get an item */
+ /* Prepare prompt */
+ cptr q, s;
if (cur_store_num == STORE_HOME)
{
+ q = "Drop which item? ";
s = "You have nothing to drop.";
}
else if (museum)
{
+ q = "Donate which item?";
s = "You have nothing to donate.";
}
else
{
+ q = "Sell which item? ";
s = "You have nothing that I want.";
}
- if (!get_item(&item, q, s, (USE_EQUIP | USE_INVEN))) return;
+
+ /* Get an item */
+ if (!get_item(&item, q, s, (USE_EQUIP | USE_INVEN), store_will_buy))
+ {
+ return;
+ }
/* Get the item */
- o_ptr = get_object(item);
+ auto o_ptr = get_object(item);
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ auto const flags = object_flags(o_ptr);
/* Hack -- Cannot remove cursed items */
if (cursed_p(o_ptr))
@@ -2986,7 +2447,7 @@ void store_sell(void)
}
else
{
- if (f4 & TR4_CURSE_NO_DROP)
+ if (flags & TR_CURSE_NO_DROP)
{
/* Oops */
msg_print("Hmmm, you seem to be unable to drop it.");
@@ -3034,7 +2495,7 @@ void store_sell(void)
/* Remove any inscription for stores */
if ((cur_store_num != 7) && !museum)
{
- q_ptr->note = 0;
+ q_ptr->inscription.clear();
}
/* Is there room in the store (or the home?) */
@@ -3050,10 +2511,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);
@@ -3066,12 +2523,6 @@ void store_sell(void)
/* Say "okay" */
say_comment_1();
- /* Make a sound */
- sound(SOUND_SELL);
-
- /* Be happy */
- decrease_insults();
-
/* Get some money */
p_ptr->au += price;
@@ -3116,7 +2567,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);
@@ -3238,45 +2689,38 @@ void store_sell(void)
/*
* Examine an item in a store -JDL-
*/
-void store_examine(void)
+void store_examine()
{
- int i;
- int item;
-
- object_type *o_ptr;
-
- char o_name[80];
-
- char out_val[160];
-
+ auto const &st_info = game->edit_data.st_info;
/* Empty? */
- if (st_ptr->stock_num <= 0)
+ if (st_ptr->stock.empty())
{
if (cur_store_num == 7) msg_print("Your home is empty.");
- else if (st_info[st_ptr->st_idx].flags1 & SF1_MUSEUM) msg_print("The museum is empty.");
+ else if (st_info[st_ptr->st_idx].flags & STF_MUSEUM) msg_print("The museum is empty.");
else msg_print("I am currently out of stock.");
return;
}
/* Find the number of objects on this and following pages */
- i = (st_ptr->stock_num - store_top);
+ int i = (st_ptr->stock.size() - store_top);
/* And then restrict it to the current page */
- if (i > 12) i = 12;
-
- /* Prompt */
- strnfmt(out_val, 160, "Which item do you want to examine? ");
+ if (i > 12)
+ {
+ i = 12;
+ }
/* Get the item number to be examined */
- if (!get_stock(&item, out_val, 0, i - 1)) return;
+ int item;
+ if (!get_stock(&item, "Which item do you want to examine? ", 0, i - 1)) return;
/* Get the actual index */
item = item + store_top;
/* Get the actual item */
- o_ptr = &st_ptr->stock[item];
+ auto o_ptr = &st_ptr->stock[item];
/* Debug hack */
if (wizard)
@@ -3293,6 +2737,7 @@ void store_examine(void)
}
/* Description */
+ char o_name[80];
object_desc(o_name, o_ptr, TRUE, 3);
/* Describe */
@@ -3325,6 +2770,34 @@ static bool_ leave_store = FALSE;
/*
+ * Find building action for command. Returns nullptr if no matching
+ * action is found.
+ */
+static store_action_type const *find_store_action(s16b command_cmd)
+{
+ auto const &st_info = game->edit_data.st_info;
+ auto const &ba_info = game->edit_data.ba_info;
+
+ for (std::size_t i = 0; i < st_info[st_ptr->st_idx].actions.size(); i++)
+ {
+ auto ba_ptr = &ba_info[st_info[st_ptr->st_idx].actions[i]];
+
+ if (ba_ptr->letter && (ba_ptr->letter == command_cmd))
+ {
+ return ba_ptr;
+ }
+
+ if (ba_ptr->letter_aux && (ba_ptr->letter_aux == command_cmd))
+ {
+ return ba_ptr;
+ }
+ }
+
+ return nullptr;
+}
+
+
+/*
* Process a command in a store
*
* Note that we must allow the use of a few "special" commands
@@ -3332,41 +2805,18 @@ static bool_ leave_store = FALSE;
* must disable some commands which are allowed in the dungeon
* but not in the stores, to prevent chaos.
*/
-static bool_ store_process_command(void)
+static bool_ store_process_command()
{
- bool_ validcmd = FALSE;
- int i;
- store_action_type *ba_ptr;
bool_ recreate = FALSE;
/* Handle repeating the last command */
repeat_check();
- for (i = 0; i < 6; i++)
- {
- ba_ptr = &ba_info[st_info[st_ptr->st_idx].actions[i]];
+ auto ba_ptr = find_store_action(command_cmd);
- if (ba_ptr->letter)
- {
- if (ba_ptr->letter == command_cmd)
- {
- validcmd = TRUE;
- break;
- }
- }
- if (ba_ptr->letter_aux)
- {
- if (ba_ptr->letter_aux == command_cmd)
- {
- validcmd = TRUE;
- break;
- }
- }
- }
-
- if (validcmd)
+ if (ba_ptr)
{
- recreate = bldg_process_command(st_ptr, i);
+ recreate = bldg_process_command(st_ptr, ba_ptr);
}
else
{
@@ -3383,14 +2833,17 @@ static bool_ store_process_command(void)
/* Browse */
case ' ':
{
- if (st_ptr->stock_num <= 12)
+ if (st_ptr->stock.size() <= 12)
{
msg_print("Entire inventory is shown.");
}
else
{
store_top += 12;
- if (store_top >= st_ptr->stock_num) store_top = 0;
+ if (store_top >= static_cast<int>(st_ptr->stock.size()))
+ {
+ store_top = 0;
+ }
display_inventory();
}
break;
@@ -3399,7 +2852,7 @@ static bool_ store_process_command(void)
/* Browse backwards */
case '-':
{
- if (st_ptr->stock_num <= 12)
+ if (st_ptr->stock.size() <= 12)
{
msg_print("Entire inventory is shown.");
}
@@ -3408,7 +2861,7 @@ static bool_ store_process_command(void)
store_top -= 12;
if (store_top < 0)
{
- store_top = ((st_ptr->stock_num - 1) / 12) * 12;
+ store_top = ((st_ptr->stock.size() - 1) / 12) * 12;
}
display_inventory();
}
@@ -3538,13 +2991,6 @@ static bool_ store_process_command(void)
/*** System Commands ***/
- /* Hack -- User interface */
- case '!':
- {
- (void)Term_user(0);
- break;
- }
-
/* Single line from a pref file */
case '"':
{
@@ -3667,8 +3113,12 @@ static bool_ store_process_command(void)
* into other commands, normally, we convert "p" (pray) and "m"
* (cast magic) into "g" (get), and "s" (search) into "d" (drop).
*/
-void do_cmd_store(void)
+void do_cmd_store()
{
+ auto const &ow_info = game->edit_data.ow_info;
+ auto const &ba_info = game->edit_data.ba_info;
+ auto const &st_info = game->edit_data.st_info;
+
int which;
int maintain_num;
int tmp_chr;
@@ -3750,13 +3200,11 @@ void do_cmd_store(void)
display_store();
/* Mega-Hack -- Ignore keymaps on store action letters */
- for (i = 0; i < 6; i++)
+ for (std::size_t i = 0; i < st_info[st_ptr->st_idx].actions.size(); i++)
{
- store_action_type *ba_ptr =
- &ba_info[st_info[st_ptr->st_idx].actions[i]];
+ auto ba_ptr = &ba_info[st_info[st_ptr->st_idx].actions[i]];
request_command_ignore_keymaps[2*i] = ba_ptr->letter;
request_command_ignore_keymaps[2*i+1] = ba_ptr->letter_aux;
-
}
/* Do not leave */
@@ -3780,7 +3228,7 @@ void do_cmd_store(void)
prt(") Exit.", 22, 4);
/* Browse if necessary */
- if (st_ptr->stock_num > 12)
+ if (st_ptr->stock.size() > 12)
{
c_prt(TERM_YELLOW, " SPACE", 23, 0);
prt(") Next page", 23, 6);
@@ -3921,7 +3369,7 @@ void do_cmd_store(void)
p_ptr->update |= (PU_MONSTERS);
/* Redraw entire screen */
- p_ptr->redraw |= (PR_BASIC | PR_EXTRA);
+ p_ptr->redraw |= (PR_FRAME);
/* Redraw map */
p_ptr->redraw |= (PR_MAP);
@@ -3937,14 +3385,14 @@ void do_cmd_store(void)
*/
void store_shuffle(int which)
{
- int i, j;
-
+ auto const &ow_info = game->edit_data.ow_info;
+ auto const &st_info = game->edit_data.st_info;
/* Ignore home */
if (which == STORE_HOME) return;
/* Ignoer Museum */
- if (st_info[st_ptr->st_idx].flags1 & SF1_MUSEUM) return;
+ if (st_info[st_ptr->st_idx].flags & STF_MUSEUM) return;
/* Save the store index */
@@ -3954,9 +3402,9 @@ void store_shuffle(int which)
st_ptr = &town_info[p_ptr->town_num].store[cur_store_num];
/* Pick a new owner */
- for (j = st_ptr->owner; j == st_ptr->owner; )
+ for (auto j = st_ptr->owner; j == st_ptr->owner; )
{
- st_ptr->owner = st_info[st_ptr->st_idx].owners[rand_int(4)];
+ st_ptr->owner = *uniform_element(st_info[st_ptr->st_idx].owners);
}
/* Activate the new owner */
@@ -3964,29 +3412,20 @@ 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 */
- for (i = 0; i < st_ptr->stock_num; i++)
+ for (auto &o_ref: st_ptr->stock)
{
- object_type *o_ptr;
-
- /* Get the item */
- o_ptr = &st_ptr->stock[i];
+ auto o_ptr = &o_ref;
/* Hack -- Sell all old items for "half price" */
- if (!(o_ptr->art_name))
+ if (o_ptr->artifact_name.empty())
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");
+ o_ptr->inscription = "on sale";
}
}
@@ -3996,9 +3435,10 @@ void store_shuffle(int which)
*/
void store_maint(int town_num, int store_num)
{
- int j, tries = 100;
+ auto const &ow_info = game->edit_data.ow_info;
+ auto const &st_info = game->edit_data.st_info;
- int old_rating = rating;
+ int const old_rating = rating;
cur_store_num = store_num;
@@ -4009,19 +3449,16 @@ void store_maint(int town_num, int store_num)
st_ptr = &town_info[town_num].store[store_num];
/* Ignoer Museum */
- if (st_info[st_ptr->st_idx].flags1 & SF1_MUSEUM) return;
+ if (st_info[st_ptr->st_idx].flags & STF_MUSEUM) return;
/* 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)
+ if (st_info[st_ptr->st_idx].flags & STF_ALL_ITEM)
{
/* Destroy crappy black market items */
- for (j = st_ptr->stock_num - 1; j >= 0; j--)
+ for (int j = st_ptr->stock.size() - 1; j >= 0; j--)
{
object_type *o_ptr = &st_ptr->stock[j];
@@ -4037,7 +3474,7 @@ void store_maint(int town_num, int store_num)
/* Choose the number of slots to keep */
- j = st_ptr->stock_num;
+ int j = st_ptr->stock.size();
/* Sell a few items */
j = j - randint(STORE_TURNOVER);
@@ -4052,11 +3489,13 @@ void store_maint(int town_num, int store_num)
if (j < 0) j = 0;
/* Destroy objects until only "j" slots are left */
- while (st_ptr->stock_num > j) store_delete();
-
+ while (j < static_cast<int>(st_ptr->stock.size()))
+ {
+ store_delete();
+ }
/* Choose the number of slots to fill */
- j = st_ptr->stock_num;
+ j = st_ptr->stock.size();
/* Buy some more items */
j = j + randint(STORE_TURNOVER);
@@ -4068,13 +3507,15 @@ void store_maint(int town_num, int store_num)
if (j < STORE_MIN_KEEP) j = STORE_MIN_KEEP;
/* Hack -- prevent "overflow" */
- if (j >= st_ptr->stock_size) j = st_ptr->stock_size - 1;
+ if (j >= st_ptr->stock_size)
+ {
+ j = st_ptr->stock_size - 1;
+ }
/* Acquire some new items */
- while ((st_ptr->stock_num < j) && tries)
+ for (int tries = 0; (tries < 100) && (static_cast<int>(st_ptr->stock.size()) < j); tries++)
{
store_create();
- tries--;
}
/* Hack -- Restore the rating */
@@ -4087,52 +3528,37 @@ void store_maint(int town_num, int store_num)
*/
void store_init(int town_num, int store_num)
{
- int k;
+ auto const &ow_info = game->edit_data.ow_info;
+ auto const &st_info = game->edit_data.st_info;
cur_store_num = store_num;
- /* Activate that store */
+ // Activate store
st_ptr = &town_info[town_num].store[store_num];
+ // Pick an owner. We use 0 for st_info[] which haven't been
+ // initialized, i.e. where there's no entry in st_info.txt.
+ st_ptr->owner = st_info[st_ptr->st_idx].owners.empty()
+ ? 0
+ : *uniform_element(st_info[st_ptr->st_idx].owners)
+ ;
- /* Pick an owner */
- st_ptr->owner = st_info[st_ptr->st_idx].owners[rand_int(4)];
-
- /* Activate the new owner */
+ // Activate the new owner
ot_ptr = &ow_info[st_ptr->owner];
-
- /* Initialize the store */
+ // 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;
+ // Nothing in stock
+ st_ptr->stock.reserve(st_ptr->stock_size);
+ st_ptr->stock.clear();
- /*
- * MEGA-HACK - Last visit to store is
- * BEFORE player birth to enable store restocking
- */
+ // MEGA-HACK - Last visit to store is BEFORE player
+ // birth to enable store restocking.
st_ptr->last_visit = -100L * STORE_TURNS;
-
- /* Clear any old items */
- for (k = 0; k < st_ptr->stock_size; k++)
- {
- object_wipe(&st_ptr->stock[k]);
- }
}
-void move_to_black_market(object_type * o_ptr)
-{
- st_ptr = &town_info[p_ptr->town_num].store[6];
- o_ptr->ident |= IDENT_STOREB;
- (void)store_carry(o_ptr);
- object_wipe(o_ptr); /* Don't leave a bogus object behind... */
-}
-
/*
* Enter the home, and interact with it from the dungeon (trump magic).
*
@@ -4143,12 +3569,15 @@ void move_to_black_market(object_type * o_ptr)
* into other commands, normally, we convert "p" (pray) and "m"
* (cast magic) into "g" (get), and "s" (search) into "d" (drop).
*/
-void do_cmd_home_trump(void)
+void do_cmd_home_trump()
{
+ auto const &ow_info = game->edit_data.ow_info;
+ auto const &ba_info = game->edit_data.ba_info;
+ auto const &st_info = game->edit_data.st_info;
+
int which;
int maintain_num;
int tmp_chr;
- int i;
int town_num;
/* Extract the store code */
@@ -4173,8 +3602,10 @@ void do_cmd_home_trump(void)
if (maintain_num)
{
/* Maintain the store */
- for (i = 0; i < maintain_num; i++)
+ for (int i = 0; i < maintain_num; i++)
+ {
store_maint(town_num, which);
+ }
/* Save the visit */
town_info[town_num].store[which].last_visit = turn;
@@ -4216,10 +3647,10 @@ void do_cmd_home_trump(void)
display_store();
/* Mega-Hack -- Ignore keymaps on store action letters */
- for (i = 0; i < 6; i++)
+ auto const &st_actions = st_info[st_ptr->st_idx].actions;
+ for (std::size_t i = 0; (i < (MAX_IGNORE_KEYMAPS/2)) && (i < st_actions.size()); i++)
{
- store_action_type *ba_ptr =
- &ba_info[st_info[st_ptr->st_idx].actions[i]];
+ auto ba_ptr = &ba_info[st_actions[i]];
request_command_ignore_keymaps[2*i] = ba_ptr->letter;
request_command_ignore_keymaps[2*i+1] = ba_ptr->letter_aux;
}
@@ -4244,7 +3675,7 @@ void do_cmd_home_trump(void)
prt(" ESC) Exit from Building.", 22, 0);
/* Browse if necessary */
- if (st_ptr->stock_num > 12)
+ if (st_ptr->stock.size() > 12)
{
prt(" SPACE) Next page of stock", 23, 0);
}
@@ -4386,7 +3817,7 @@ void do_cmd_home_trump(void)
p_ptr->update |= (PU_MONSTERS);
/* Redraw entire screen */
- p_ptr->redraw |= (PR_BASIC | PR_EXTRA);
+ p_ptr->redraw |= (PR_FRAME);
/* Redraw map */
p_ptr->redraw |= (PR_MAP);
@@ -4394,65 +3825,3 @@ void do_cmd_home_trump(void)
/* Window stuff */
p_ptr->window |= (PW_OVERHEAD);
}
-
-static void pay_for_requested_item(int value, object_type *q_ptr)
-{
- msg_format("It'll cost %i gold pieces. ", value);
-
- if (get_check("Do you wish to pay?"))
- {
- if (p_ptr->au < value)
- msg_print("You don't have enough money for it.");
- else
- {
- if (store_carry(q_ptr) != -1)
- {
- msg_print("The item has arrived in the Black Market.");
- p_ptr->au -= value;
-
- p_ptr->redraw |= PR_GOLD;
- }
- else
- msg_print("There isn't enough room for it.");
- }
- }
-}
-
-/*
- * Request item for merchants
- */
-void store_request_item(void)
-{
- char buf[80], name[80];
- object_type forge, *q_ptr = &forge;
- store_type *ost_ptr = st_ptr;
-
- /* Get the Black Market */
- st_ptr = &town_info[p_ptr->town_num].store[6];
-
- /* Make an empty string */
- buf[0] = 0;
-
- /* Ask for the wish */
- if (!get_string("Request what? ", buf, 80))
- {
- st_ptr = ost_ptr;
- return;
- }
-
- clean_wish_name(buf, name);
-
- if (test_object_wish(name, q_ptr, &forge, "request"))
- {
- int value = object_value_real(q_ptr) * 5;
-
- /* Pay for the delivery */
- pay_for_requested_item(value, q_ptr);
-
- /* Don't search any more */
- st_ptr = ost_ptr;
- return;
- }
-
- st_ptr = ost_ptr;
-}
diff --git a/src/store.hpp b/src/store.hpp
new file mode 100644
index 00000000..0f189167
--- /dev/null
+++ b/src/store.hpp
@@ -0,0 +1,12 @@
+#pragma once
+
+void do_cmd_store();
+void store_shuffle(int which);
+void store_maint(int town_num, int store_num);
+void store_init(int town_num, int store_num);
+void do_cmd_home_trump();
+void store_sell();
+void store_purchase();
+void store_examine();
+void store_stole();
+void store_prt_gold();
diff --git a/src/store_action_type.hpp b/src/store_action_type.hpp
new file mode 100644
index 00000000..ee479375
--- /dev/null
+++ b/src/store_action_type.hpp
@@ -0,0 +1,17 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * Store/building actions.
+ */
+struct store_action_type
+{
+ std::string name; /* Name */
+
+ std::array<s16b, 3> costs { }; /* Costs for liked people */
+ char letter = '\0'; /* Action letter */
+ char letter_aux = '\0'; /* Action letter */
+ s16b action = 0; /* Action code */
+ s16b action_restr = 0; /* Action restriction */
+};
diff --git a/src/store_action_type_fwd.hpp b/src/store_action_type_fwd.hpp
new file mode 100644
index 00000000..e1746dad
--- /dev/null
+++ b/src/store_action_type_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct store_action_type;
diff --git a/src/store_flag.hpp b/src/store_flag.hpp
new file mode 100644
index 00000000..6844bd84
--- /dev/null
+++ b/src/store_flag.hpp
@@ -0,0 +1,12 @@
+#pragma once
+
+#include "store_flag_set.hpp"
+#include <boost/preprocessor/cat.hpp>
+
+//
+// Define flag set for each flag.
+//
+#define STF(tier, index, name) \
+ DECLARE_FLAG(store_flag_set, BOOST_PP_CAT(STF_,name), tier, index)
+#include "store_flag_list.hpp"
+#undef STF
diff --git a/src/store_flag_list.hpp b/src/store_flag_list.hpp
new file mode 100644
index 00000000..f8e4b177
--- /dev/null
+++ b/src/store_flag_list.hpp
@@ -0,0 +1,17 @@
+/**
+ * X-macro list of all the store flags
+ */
+
+/* STF(<tier>, <index>, <name>) */
+
+STF(1, 0, DEPEND_LEVEL )
+STF(1, 1, SHALLOW_LEVEL)
+STF(1, 2, MEDIUM_LEVEL )
+STF(1, 3, DEEP_LEVEL )
+STF(1, 4, RARE )
+STF(1, 5, VERY_RARE )
+STF(1, 6, COMMON )
+STF(1, 7, ALL_ITEM )
+STF(1, 8, RANDOM )
+STF(1, 9, FORCE_LEVEL )
+STF(1, 10, MUSEUM )
diff --git a/src/store_flag_set.hpp b/src/store_flag_set.hpp
new file mode 100644
index 00000000..0529baed
--- /dev/null
+++ b/src/store_flag_set.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "flag_set.hpp"
+
+constexpr std::size_t STF_MAX_TIERS = 1;
+
+typedef flag_set<STF_MAX_TIERS> store_flag_set;
diff --git a/src/store_info_type.hpp b/src/store_info_type.hpp
new file mode 100644
index 00000000..78aa071e
--- /dev/null
+++ b/src/store_info_type.hpp
@@ -0,0 +1,31 @@
+#pragma once
+
+#include "h-basic.h"
+#include "store_flag_set.hpp"
+#include "store_item.hpp"
+
+#include <vector>
+
+/**
+ * Store descriptor.
+ */
+struct store_info_type
+{
+ std::string name; /* Name */
+
+ std::vector<store_item> items; /* Table -- Legal item kinds */
+
+ s16b max_obj = 0; /* Number of items this store can hold */
+
+ std::vector<u16b> owners; /* List of owners; refers to ow_info */
+
+ std::vector<u16b> actions; /* Actions; refers to ba_info */
+
+ byte d_attr = 0; /* Default building attribute */
+ char d_char = '\0'; /* Default building character */
+
+ byte x_attr = 0; /* Desired building attribute */
+ char x_char = '\0'; /* Desired building character */
+
+ store_flag_set flags; /* Flags */
+};
diff --git a/src/store_item.hpp b/src/store_item.hpp
new file mode 100644
index 00000000..62d3f2a9
--- /dev/null
+++ b/src/store_item.hpp
@@ -0,0 +1,18 @@
+#pragma once
+
+#include "h-basic.h"
+
+struct store_item
+{
+ /**
+ * Legal item kinds; if > 10000, designates (TVAL - 10000) and any SVAL.
+ * Otherwise designates an entry in k_info.txt.
+ */
+ s16b kind = 0;
+
+ /**
+ * Percentage chance of generation if the entry is chosen.
+ */
+ s16b chance = 0;
+
+};
diff --git a/src/store_type.hpp b/src/store_type.hpp
new file mode 100644
index 00000000..5fb4ac7f
--- /dev/null
+++ b/src/store_type.hpp
@@ -0,0 +1,40 @@
+#pragma once
+
+#include "h-basic.h"
+#include "object_type_fwd.hpp"
+
+#include <vector>
+
+/**
+ * A store, with an owner, various state flags, a current stock
+ * of items, and a table of items that are often purchased.
+ */
+struct store_type
+{
+ u16b st_idx = 0;
+
+ /**
+ * Owner index
+ */
+ u16b owner = 0;
+
+ /**
+ * Closed until this turn.
+ */
+ s32b store_open = 0;
+
+ /**
+ * Last visited on this turn.
+ */
+ s32b last_visit = 0;
+
+ /**
+ * Stock: Total size of array
+ */
+ u16b stock_size = 0;
+
+ /**
+ * Stock: Actual stock items
+ */
+ std::vector<object_type> stock;
+};
diff --git a/src/store_type_fwd.hpp b/src/store_type_fwd.hpp
new file mode 100644
index 00000000..15410563
--- /dev/null
+++ b/src/store_type_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct store_type;
diff --git a/src/tables.c b/src/tables.cc
index e976e234..1caa4bcf 100644
--- a/src/tables.c
+++ b/src/tables.cc
@@ -1,7 +1,3 @@
-/* File: tables.c */
-
-/* Purpose: Angband Tables */
-
/*
* Copyright (c) 1989 James E. Wilson, Robert A. Koeneke
*
@@ -10,8 +6,43 @@
* included in all such copies.
*/
-#include "angband.h"
-
+#include "tables.hpp"
+#include "tables.h"
+
+#include "modules.hpp"
+#include "monster_race_flag.hpp"
+#include "monster_spell_flag.hpp"
+#include "object_flag.hpp"
+#include "options.hpp"
+#include "q_library.hpp"
+#include "q_fireprof.hpp"
+#include "q_bounty.hpp"
+#include "q_thrain.hpp"
+#include "q_narsil.hpp"
+#include "q_evil.hpp"
+#include "q_betwen.hpp"
+#include "q_haunted.hpp"
+#include "q_invas.hpp"
+#include "q_nirna.hpp"
+#include "q_eol.hpp"
+#include "q_god.hpp"
+#include "q_dragons.hpp"
+#include "q_poison.hpp"
+#include "q_spider.hpp"
+#include "q_wolves.hpp"
+#include "q_shroom.hpp"
+#include "q_nazgul.hpp"
+#include "q_wight.hpp"
+#include "q_troll.hpp"
+#include "q_hobbit.hpp"
+#include "q_thief.hpp"
+#include "q_ultrae.hpp"
+#include "q_ultrag.hpp"
+#include "q_one.hpp"
+#include "q_main.hpp"
+#include "q_rand.hpp"
+#include "stats.hpp"
+#include "variable.hpp"
@@ -53,52 +84,6 @@ char hexsym[16] =
/*
- * Stat Table (INT/WIS) -- Number of half-spells per level
- */
-byte adj_mag_study[] =
-{
- 0 /* 3 */,
- 0 /* 4 */,
- 0 /* 5 */,
- 0 /* 6 */,
- 0 /* 7 */,
- 1 /* 8 */,
- 1 /* 9 */,
- 1 /* 10 */,
- 1 /* 11 */,
- 2 /* 12 */,
- 2 /* 13 */,
- 2 /* 14 */,
- 2 /* 15 */,
- 2 /* 16 */,
- 2 /* 17 */,
- 2 /* 18/00-18/09 */,
- 2 /* 18/10-18/19 */,
- 2 /* 18/20-18/29 */,
- 2 /* 18/30-18/39 */,
- 2 /* 18/40-18/49 */,
- 3 /* 18/50-18/59 */,
- 3 /* 18/60-18/69 */,
- 3 /* 18/70-18/79 */,
- 3 /* 18/80-18/89 */,
- 4 /* 18/90-18/99 */,
- 4 /* 18/100-18/109 */,
- 4 /* 18/110-18/119 */,
- 5 /* 18/120-18/129 */,
- 5 /* 18/130-18/139 */,
- 5 /* 18/140-18/149 */,
- 5 /* 18/150-18/159 */,
- 5 /* 18/160-18/169 */,
- 5 /* 18/170-18/179 */,
- 5 /* 18/180-18/189 */,
- 5 /* 18/190-18/199 */,
- 5 /* 18/200-18/209 */,
- 6 /* 18/210-18/219 */,
- 6 /* 18/220+ */
-};
-
-
-/*
* Stat Table (INT/WIS) -- extra half-mana-points per level
*/
byte adj_mag_mana[] =
@@ -283,52 +268,6 @@ byte adj_chr_gold[] =
/*
- * Stat Table (INT) -- Magic devices
- */
-byte adj_int_dev[] =
-{
- 0 /* 3 */,
- 0 /* 4 */,
- 0 /* 5 */,
- 0 /* 6 */,
- 0 /* 7 */,
- 1 /* 8 */,
- 1 /* 9 */,
- 1 /* 10 */,
- 1 /* 11 */,
- 1 /* 12 */,
- 1 /* 13 */,
- 1 /* 14 */,
- 2 /* 15 */,
- 2 /* 16 */,
- 2 /* 17 */,
- 3 /* 18/00-18/09 */,
- 3 /* 18/10-18/19 */,
- 4 /* 18/20-18/29 */,
- 4 /* 18/30-18/39 */,
- 5 /* 18/40-18/49 */,
- 5 /* 18/50-18/59 */,
- 6 /* 18/60-18/69 */,
- 6 /* 18/70-18/79 */,
- 7 /* 18/80-18/89 */,
- 7 /* 18/90-18/99 */,
- 8 /* 18/100-18/109 */,
- 9 /* 18/110-18/119 */,
- 10 /* 18/120-18/129 */,
- 11 /* 18/130-18/139 */,
- 12 /* 18/140-18/149 */,
- 13 /* 18/150-18/159 */,
- 14 /* 18/160-18/169 */,
- 15 /* 18/170-18/179 */,
- 16 /* 18/180-18/189 */,
- 17 /* 18/190-18/199 */,
- 18 /* 18/200-18/209 */,
- 19 /* 18/210-18/219 */,
- 20 /* 18/220+ */
-};
-
-
-/*
* Stat Table (WIS) -- Saving throw
*/
byte adj_wis_sav[] =
@@ -375,98 +314,6 @@ byte adj_wis_sav[] =
/*
- * Stat Table (DEX) -- disarming
- */
-byte adj_dex_dis[] =
-{
- 0 /* 3 */,
- 0 /* 4 */,
- 0 /* 5 */,
- 0 /* 6 */,
- 0 /* 7 */,
- 0 /* 8 */,
- 0 /* 9 */,
- 0 /* 10 */,
- 0 /* 11 */,
- 0 /* 12 */,
- 1 /* 13 */,
- 1 /* 14 */,
- 1 /* 15 */,
- 2 /* 16 */,
- 2 /* 17 */,
- 4 /* 18/00-18/09 */,
- 4 /* 18/10-18/19 */,
- 4 /* 18/20-18/29 */,
- 4 /* 18/30-18/39 */,
- 5 /* 18/40-18/49 */,
- 5 /* 18/50-18/59 */,
- 5 /* 18/60-18/69 */,
- 6 /* 18/70-18/79 */,
- 6 /* 18/80-18/89 */,
- 7 /* 18/90-18/99 */,
- 8 /* 18/100-18/109 */,
- 8 /* 18/110-18/119 */,
- 8 /* 18/120-18/129 */,
- 8 /* 18/130-18/139 */,
- 8 /* 18/140-18/149 */,
- 9 /* 18/150-18/159 */,
- 9 /* 18/160-18/169 */,
- 9 /* 18/170-18/179 */,
- 9 /* 18/180-18/189 */,
- 9 /* 18/190-18/199 */,
- 10 /* 18/200-18/209 */,
- 10 /* 18/210-18/219 */,
- 10 /* 18/220+ */
-};
-
-
-/*
- * Stat Table (INT) -- disarming
- */
-byte adj_int_dis[] =
-{
- 0 /* 3 */,
- 0 /* 4 */,
- 0 /* 5 */,
- 0 /* 6 */,
- 0 /* 7 */,
- 1 /* 8 */,
- 1 /* 9 */,
- 1 /* 10 */,
- 1 /* 11 */,
- 1 /* 12 */,
- 1 /* 13 */,
- 1 /* 14 */,
- 2 /* 15 */,
- 2 /* 16 */,
- 2 /* 17 */,
- 3 /* 18/00-18/09 */,
- 3 /* 18/10-18/19 */,
- 3 /* 18/20-18/29 */,
- 4 /* 18/30-18/39 */,
- 4 /* 18/40-18/49 */,
- 5 /* 18/50-18/59 */,
- 6 /* 18/60-18/69 */,
- 7 /* 18/70-18/79 */,
- 8 /* 18/80-18/89 */,
- 9 /* 18/90-18/99 */,
- 10 /* 18/100-18/109 */,
- 10 /* 18/110-18/119 */,
- 11 /* 18/120-18/129 */,
- 12 /* 18/130-18/139 */,
- 13 /* 18/140-18/149 */,
- 14 /* 18/150-18/159 */,
- 15 /* 18/160-18/169 */,
- 16 /* 18/170-18/179 */,
- 17 /* 18/180-18/189 */,
- 18 /* 18/190-18/199 */,
- 19 /* 18/200-18/209 */,
- 19 /* 18/210-18/219 */,
- 20 /* 18/220+ */
-};
-
-
-/*
* Stat Table (DEX) -- bonus to ac (plus 128)
*/
byte adj_dex_ta[] =
@@ -1088,15 +935,6 @@ byte blows_table[12][12] =
};
-s16b arena_monsters[MAX_ARENA_MONS] =
-{
- 30, 43, 102, 118, 126, 149, 173,
- 183, 188, 191, 216, 230, 238, 244,
- 255, 262, 293, 297, 321, 349, 372,
- 401, 415, 454, 464, 485, 538, 631,
- 641
-};
-
/*
* This table allows quick conversion from "speed" to "energy"
@@ -1217,29 +1055,6 @@ s32b player_exp[PY_MAX_LEVEL] =
/*
- * Player Sexes
- *
- * Title,
- * Winner
- */
-player_sex sex_info[MAX_SEXES] =
-{
- {
- "Female",
- "Queen"
- },
-
-{
-"Male",
-"King"
-},
-{
-"Neuter",
-"Ruler"
-}
-};
-
-/*
* Hack -- the "basic" color names (see "TERM_xxx")
*/
cptr color_names[16] =
@@ -1331,522 +1146,6 @@ cptr window_flag_desc[32] =
};
-/*
- * Available Options
- *
- * Option Screen Sets:
- *
- * Set 1: User Interface
- * Set 2: Disturbance
- * Set 3: Inventory
- * Set 4: Game Play
- * Set 5: ToME
- * Set 6: Birth
- *
- * Note that bits 28-31 of set 0 are currently unused.
- */
-option_type option_info[] =
-{
- /*** User-Interface ***/
-
- { &rogue_like_commands, FALSE, 1, 0,
- "rogue_like_commands", "Rogue-like commands" },
-
- { &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" },
-
- { &use_old_target, FALSE, 1, 4,
- "use_old_target", "Use old target by default" },
-
- { &always_pickup, FALSE, 1, 5,
- "always_pickup", "Pick things up by default" },
-
- { &prompt_pickup_heavy, TRUE, 1, 6,
- "prompt_pickup_heavy", "Prompt before picking up heavy objects" },
-
- { &always_repeat, TRUE, 1, 7,
- "always_repeat", "Repeat obvious commands" },
-
- { &depth_in_feet, FALSE, 1, 8,
- "depth_in_feet", "Show dungeon level in feet" },
-
- { &stack_force_notes, TRUE, 1, 9,
- "stack_force_notes", "Merge inscriptions when stacking" },
-
- { &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_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" },
-
- { &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" },
-
- { &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" },
-
- { &ring_bell, FALSE, 1, 18,
- "ring_bell", "Audible bell (on errors, etc)" },
- /* Changed to default to FALSE -- it's so extremely annoying!!! -TY */
-
- /*** Disturbance ***/
-
- { &find_ignore_stairs, FALSE, 2, 0,
- "find_ignore_stairs", "Run past stairs" },
-
- { &find_ignore_doors, TRUE, 2, 1,
- "find_ignore_doors", "Run through open doors" },
-
- { &find_cut, FALSE, 2, 2,
- "find_cut", "Run past known corners" },
-
- { &find_examine, TRUE, 2, 3,
- "find_examine", "Run into potential corners" },
-
- { &disturb_move, FALSE, 2, 4,
- "disturb_move", "Disturb whenever any monster moves" },
-
- { &disturb_near, TRUE, 2, 5,
- "disturb_near", "Disturb whenever viewable monster moves" },
-
- { &disturb_panel, TRUE, 2, 6,
- "disturb_panel", "Disturb whenever map panel changes" },
-
- { &disturb_detect, TRUE, 2, 21,
- "disturb_detect", "Disturb whenever leaving trap-detected area" },
-
- { &disturb_state, TRUE, 2, 7,
- "disturb_state", "Disturb whenever player state changes" },
-
- { &disturb_minor, TRUE, 2, 8,
- "disturb_minor", "Disturb whenever boring things happen" },
-
- { &disturb_other, FALSE, 2, 9,
- "disturb_other", "Disturb whenever random things happen" },
-
- { &alert_hitpoint, FALSE, 2, 10,
- "alert_hitpoint", "Alert user to critical hitpoints" },
-
- { &alert_failure, FALSE, 2, 11,
- "alert_failure", "Alert user to various failures" },
-
- { &last_words, TRUE, 2, 12,
- "last_words", "Get last words when the character dies" },
-
- { &speak_unique, TRUE, 2, 13,
- "speak_unique", "Allow shopkeepers and uniques to speak" },
-
- { &auto_destroy, TRUE, 2, 14,
- "auto_destroy", "No query to destroy known worthless items" },
-
- { &wear_confirm, TRUE, 2, 15,
- "confirm_wear", "Confirm to wear/wield known cursed items" },
-
- { &confirm_stairs, FALSE, 2, 16,
- "confirm_stairs", "Prompt before exiting a dungeon level" },
-
- { &disturb_pets, FALSE, 2, 17,
- "disturb_pets", "Disturb when visible pets move" },
-
- { &easy_open, TRUE, 2, 18,
- "easy_open", "Automatically open doors" },
-
- { &easy_disarm, TRUE, 2, 19,
- "easy_disarm", "Automatically disarm traps" },
-
- { &easy_tunnel, FALSE, 2, 20,
- "easy_tunnel", "Automatically tunnel walls" },
-
- /*** 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" },
-
- { &stack_allow_items, TRUE, 3, 2,
- "stack_allow_items", "Allow weapons and armour to stack" },
-
- { &stack_allow_wands, TRUE, 3, 3,
- "stack_allow_wands", "Allow wands/staffs/rods to stack" },
-
- { &expand_look, FALSE, 3, 4,
- "expand_look", "Expand the power of the look command" },
-
- { &expand_list, FALSE, 3, 5,
- "expand_list", "Expand the power of the list commands" },
-
- { &view_perma_grids, TRUE, 3, 6,
- "view_perma_grids", "Map remembers all perma-lit grids" },
-
- { &view_torch_grids, FALSE, 3, 7,
- "view_torch_grids", "Map remembers all torch-lit grids" },
-
- { &monster_lite, TRUE, 3, 19,
- "monster_lite", "Allow some monsters to carry light" },
-
- { &dungeon_align, TRUE, 3, 8,
- "dungeon_align", "Generate dungeons with aligned rooms" },
-
- { &dungeon_stair, TRUE, 3, 9,
- "dungeon_stair", "Generate dungeons with connected stairs" },
-
- { &flow_by_sound, FALSE, 3, 10,
- "flow_by_sound", "Monsters chase current location (v.slow)" },
-
- { &player_symbols, FALSE, 3, 12,
- "player_symbols", "Use special symbols for the player char"},
-
- { &plain_descriptions, TRUE, 3, 13,
- "plain_descriptions", "Plain object descriptions" },
-
- { &smart_learn, FALSE, 3, 14,
- "smart_learn", "Monsters learn from their mistakes" },
-
- { &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" },
-
- { &empty_levels, TRUE, 3, 18,
- "empty_levels", "Allow empty 'arena' levels" },
-
- /*** Efficiency ***/
-
- { &view_reduce_lite, FALSE, 4, 0,
- "view_reduce_lite", "Reduce lite-radius when running" },
-
- { &view_reduce_view, FALSE, 4, 1,
- "view_reduce_view", "Reduce view-radius in town" },
-
- { &avoid_abort, FALSE, 4, 2,
- "avoid_abort", "Avoid checking for user abort" },
-
- { &avoid_shimmer, FALSE, 4, 17,
- "avoid_shimmer", "Avoid extra shimmering (fast)" },
-
- { &avoid_other, FALSE, 4, 3,
- "avoid_other", "Avoid processing special colors (fast)" },
-
- { &flush_failure, TRUE, 4, 4,
- "flush_failure", "Flush input on various failures" },
-
- { &flush_disturb, FALSE, 4, 5,
- "flush_disturb", "Flush input whenever disturbed" },
-
- { &flush_command, FALSE, 4, 6,
- "flush_command", "Flush input before every command" },
-
- { &fresh_before, TRUE, 4, 7,
- "fresh_before", "Flush output before every command" },
-
- { &fresh_after, FALSE, 4, 8,
- "fresh_after", "Flush output after every command" },
-
- { &fresh_message, FALSE, 4, 9,
- "fresh_message", "Flush output after every message" },
-
- { &hilite_player, FALSE, 4, 11,
- "hilite_player", "Hilite the player with the cursor" },
-
- { &view_yellow_lite, FALSE, 4, 12,
- "view_yellow_lite", "Use special colors for torch-lit grids" },
-
- { &view_bright_lite, FALSE, 4, 13,
- "view_bright_lite", "Use special colors for 'viewable' grids" },
-
- { &view_granite_lite, FALSE, 4, 14,
- "view_granite_lite", "Use special colors for wall grids (slow)" },
-
- { &view_special_lite, FALSE, 4, 15,
- "view_special_lite", "Use special colors for floor grids (slow)" },
-
- { &center_player, FALSE, 4, 16,
- "center_player", "Center the view on the player (very slow)" },
-
- /*** ToME options ***/
-
- { &option_ingame_help, TRUE, 5, 1,
- "ingame_help", "Ingame contextual help" },
-
- { &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" },
-
- { &player_char_health, TRUE, 5, 6,
- "player_char_health", "Player char represent his/her health" },
-
- { &linear_stats, TRUE, 5, 7,
- "linear_stats", "Stats are represented in a linear way" },
-
- { &inventory_no_move, FALSE, 5, 8,
- "inventory_no_move", "In option windows, just omit the select char" },
-
-
- /*** Birth Options ***/
-
- { &maximize, TRUE, 6, 1,
- "maximize", "Maximise stats" },
-
- { &preserve, TRUE, 6, 2,
- "preserve", "Preserve artifacts" },
-
- { &autoroll, TRUE, 6, 3,
- "autoroll", "Specify 'minimal' stats" },
-
- { &point_based, FALSE, 6, 17,
- "point_based", "Generate character using a point system" },
-
- { &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" },
-
- { &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" },
-
- /* XXX */
-
- { &always_small_level, FALSE, 6, 16,
- "always_small_level", "Always make small levels" },
-
- { &fate_option, TRUE, 6, 18,
- "fate_option", "You can receive fates, good or bad" },
-
- /* XXX 17 is used BEFORE */
-
- /*** Stacking ***/
-
- { &testing_stack, TRUE, 7, 0,
- "testing_stack", "Allow objects to stack on floor" },
-
- { &testing_carry, TRUE, 7, 1,
- "testing_carry", "Allow monsters to carry objects" },
-
-
- /*** End of Table ***/
-
- { NULL, 0, 0, 0,
- NULL, NULL }
-};
-
-
-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 =
"adanedhel\n"
@@ -2568,9 +1867,9 @@ magic_power mindcraft_powers[MAX_MINDCRAFT_POWERS] =
"Telekinetic Wave",
"Powerful wave of pure telekinetic forces."
},
- };
+};
- magic_power necro_powers[MAX_NECRO_POWERS] =
+magic_power necro_powers[MAX_NECRO_POWERS] =
{
/* Level gained, cost, %fail, name, desc */
{
@@ -2698,50 +1997,14 @@ magic_power symbiotic_powers[MAX_SYMBIOTIC_POWERS] =
/*
- * Textual translation of your god's "niceness".
- */
-
-cptr deity_niceness[10] =
-{
- "a lovable deity",
- "a friendly deity",
- "an easygoing deity",
- "a forgiving deity",
- "an uncaring deity",
- "a wary deity",
- "an unforgiving deity",
- "an impatient deity",
- "a wrathful deity",
- "an easily angered deity"
-};
-
-/*
- * Textual translation of your standing with your god.
- */
-
-cptr deity_standing[11] =
-{
- "cursed",
- "persecuted",
- "punished",
- "despised",
- "disliked",
- "watched",
- "unnoticed",
- "noticed",
- "rewarded",
- "favored",
- "championed"
-};
-
-/*
* Name and description (max. 10 lines) of the gods.
* 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 +2020,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 +2036,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 +2052,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 +2068,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,10 +2084,73 @@ 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 "
- "Middle-earth.",
+ "She is the Vala of nature, protectress of the great forests of Middle-earth.",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ },
+ },
+ {
+ { 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.",
"",
"",
"",
@@ -2839,16 +2169,16 @@ deity_type deity_info_init[MAX_GODS_INIT] =
/* as far as I know. */
tactic_info_type tactic_info[9] =
{
- /* hit dam ac stl dis sav */
- { -10, -10, + 15, + 3, + 15, + 14, "coward"}, /* 4-4 */
- { -8, -8, + 10, + 2, + 9, + 9, "meek"}, /* 4-3 */
- { -4, -4, + 5, + 1, + 5, + 5, "wary"}, /* 4-2 */
- { -2, -2, + 2, + 1, + 2, + 2, "careful"}, /* 4-1 */
- { 0, 0, 0, 0, 0, 0, "normal"}, /* 4+0 */
- { 2, 2, -2, -1, -2, -3, "confident"}, /* 4+1 */
- { 4, 4, -5, -2, -5, -7, "aggressive"}, /* 4+2 */
- { 6, 6, -10, -3, -11, -12, "furious"}, /* 4+3 */
- { 8, 12, -25, -5, -18, -18, "berserker"} /* 4+4 */
+ /* hit dam ac stl sav */
+ { -10, -10, +15, +3, +14, "coward" },
+ { -8, -8, +10, +2, +9, "meek" },
+ { -4, -4, +5, +1, +5, "wary" },
+ { -2, -2, +2, +1, +2, "careful" },
+ { 0, 0, 0, 0, 0, "normal" },
+ { 2, 2, -2, -1, -3, "confident" },
+ { 4, 4, -5, -2, -7, "aggressive" },
+ { 6, 6, -10, -3, -12, "furious" },
+ { 8, 12, -25, -5, -18, "berserker" }
};
/*
@@ -2931,52 +2261,44 @@ move_info_type move_info[9] =
*/
inscription_info_type inscription_info[MAX_INSCRIPTIONS] =
{
- { /* Nothing */
+ { /* Padding; 0 index is used to signify "no inscription" */
"",
0,
- TRUE,
0,
},
{ /* Light up the room(Adunaic) */
"ure nimir", /* sun shine */
INSCRIP_EXEC_ENGRAVE | INSCRIP_EXEC_WALK | INSCRIP_EXEC_MONST_WALK,
- FALSE,
30,
},
{ /* Darkness in room(Adunaic) */
"lomi gimli", /* night stars */
INSCRIP_EXEC_ENGRAVE | INSCRIP_EXEC_WALK | INSCRIP_EXEC_MONST_WALK,
- FALSE,
10,
},
{ /* Storm(Adunaic) */
"dulgi bawiba", /* black winds */
INSCRIP_EXEC_ENGRAVE | INSCRIP_EXEC_WALK | INSCRIP_EXEC_MONST_WALK,
- FALSE,
40,
},
{ /* Protection(Sindarin) */
"pedo mellon a minno", /* say friend and enter */
INSCRIP_EXEC_MONST_WALK,
- FALSE,
8,
},
{ /* Dwarves summoning(Khuzdul) */
"Baruk Khazad! Khazad aimenu!", /* Axes of the Dwarves, the Dwarves are upon you! */
INSCRIP_EXEC_ENGRAVE,
- FALSE,
100,
},
{ /* Open Chasm(Nandorin) */
"dunna hrassa", /* black precipice */
INSCRIP_EXEC_MONST_WALK,
- FALSE,
50,
},
{ /* Blast of Black Fire(Orcish) */
"burz ghash ronk", /* black fire pool */
INSCRIP_EXEC_ENGRAVE | INSCRIP_EXEC_WALK | INSCRIP_EXEC_MONST_WALK,
- FALSE,
60,
},
};
@@ -3010,132 +2332,107 @@ cptr sense_desc[] =
* Flags 4,
* ESP,
*/
-flags_group flags_groups[MAX_FLAG_GROUP] =
+std::vector<flags_group> const &flags_groups()
{
- {
- "Fire",
- TERM_L_RED,
- 1,
- TR1_SLAY_UNDEAD | TR1_BRAND_FIRE,
- TR2_RES_FIRE,
- TR3_SH_FIRE | TR3_LITE1 | TR3_IGNORE_FIRE,
- 0,
- 0,
- },
- {
- "Cold",
- TERM_WHITE,
- 1,
- TR1_SLAY_DRAGON | TR1_SLAY_DEMON | TR1_BRAND_COLD,
- TR2_RES_COLD | TR2_INVIS,
- TR3_SLOW_DIGEST | TR3_IGNORE_COLD,
- 0,
- 0,
- },
- {
- "Acid",
- TERM_GREEN,
- 3,
- TR1_SLAY_ANIMAL | TR1_IMPACT | TR1_TUNNEL | TR1_BRAND_ACID,
- TR2_RES_ACID,
- TR3_IGNORE_ACID,
- 0,
- 0,
- },
- {
- "Lightning",
- TERM_L_BLUE,
- 1,
- TR1_SLAY_EVIL | TR1_BRAND_ELEC,
- TR2_RES_ELEC,
- TR3_IGNORE_ELEC | TR3_SH_ELEC | TR3_TELEPORT,
- 0,
- 0,
- },
- {
- "Poison",
- TERM_L_GREEN,
- 2,
- TR1_CHR | TR1_VAMPIRIC | TR1_SLAY_ANIMAL | TR1_BRAND_POIS,
- TR2_SUST_CHR | TR2_RES_POIS,
- TR3_DRAIN_EXP,
- 0,
- ESP_TROLL | ESP_GIANT,
- },
- {
- "Air",
- TERM_BLUE,
- 5,
- TR1_WIS | TR1_STEALTH | TR1_INFRA | TR1_SPEED,
- TR2_RES_LITE | TR2_RES_DARK | TR2_RES_BLIND | TR2_SUST_WIS,
- TR3_FEATHER | TR3_SEE_INVIS | TR3_BLESSED,
- 0,
- ESP_GOOD,
- },
- {
- "Earth",
- TERM_L_UMBER,
- 5,
- TR1_STR | TR1_CON | TR1_TUNNEL | TR1_BLOWS | TR1_SLAY_TROLL | TR1_SLAY_GIANT | TR1_IMPACT,
- TR2_SUST_STR | TR2_SUST_CON | TR2_FREE_ACT | TR2_RES_FEAR | TR2_RES_SHARDS,
- TR3_REGEN,
- 0,
- ESP_TROLL | ESP_GIANT,
- },
- {
- "Mind",
- TERM_YELLOW,
- 7,
- TR1_INT | TR1_SEARCH,
- TR2_SUST_INT | TR2_RES_CONF | TR2_RES_FEAR,
- 0,
- 0,
- ESP_ORC | ESP_TROLL | ESP_GIANT | ESP_ANIMAL | ESP_UNIQUE | ESP_SPIDER | ESP_DEMON,
- },
- {
- "Shield",
- TERM_RED,
- 7,
- TR1_DEX,
- TR2_SUST_DEX | TR2_INVIS | TR2_REFLECT | TR2_HOLD_LIFE | TR2_RES_SOUND | TR2_RES_NEXUS,
- TR3_REGEN,
- 0,
- 0,
- },
- {
- "Chaos",
- TERM_VIOLET,
- 7,
- TR1_CHAOTIC | TR1_IMPACT,
- TR2_RES_CHAOS | TR2_RES_DISEN,
- TR3_REGEN,
- 0,
- ESP_ALL,
- },
- {
- "Magic",
- TERM_L_BLUE,
- 10,
- TR1_MANA | TR1_SPELL,
- TR2_RES_CHAOS | TR2_RES_DISEN,
- TR3_WRAITH,
- TR4_PRECOGNITION | TR4_FLY | TR4_CLONE,
- 0,
- },
- {
- "Antimagic",
- TERM_L_DARK,
- 10,
- TR1_VAMPIRIC | TR1_CHAOTIC | TR1_BLOWS | TR1_SPEED,
- TR2_LIFE | TR2_REFLECT | TR2_FREE_ACT | TR2_HOLD_LIFE,
- TR3_NO_MAGIC | TR3_NO_TELE | TR3_SEE_INVIS,
- TR4_ANTIMAGIC_10 | TR4_ANTIMAGIC_20,
- 0,
- },
+ static auto *instance = new std::vector<flags_group> {
+ flags_group {
+ "Fire",
+ TERM_L_RED,
+ 1,
+ TR_SLAY_UNDEAD | TR_BRAND_FIRE | TR_RES_FIRE |
+ TR_SH_FIRE | TR_LITE1 | TR_IGNORE_FIRE,
+ },
+ flags_group {
+ "Cold",
+ TERM_WHITE,
+ 1,
+ TR_SLAY_DRAGON | TR_SLAY_DEMON | TR_BRAND_COLD | TR_RES_COLD |
+ TR_INVIS | TR_SLOW_DIGEST | TR_IGNORE_COLD,
+ },
+ flags_group {
+ "Acid",
+ TERM_GREEN,
+ 3,
+ TR_SLAY_ANIMAL | TR_IMPACT | TR_TUNNEL |
+ TR_BRAND_ACID | TR_RES_ACID | TR_IGNORE_ACID,
+ },
+ flags_group {
+ "Lightning",
+ TERM_L_BLUE,
+ 1,
+ TR_SLAY_EVIL | TR_BRAND_ELEC | TR_RES_ELEC |
+ TR_IGNORE_ELEC | TR_SH_ELEC | TR_TELEPORT,
+ },
+ flags_group {
+ "Poison",
+ TERM_L_GREEN,
+ 2,
+ TR_CHR | TR_VAMPIRIC | TR_SLAY_ANIMAL | TR_BRAND_POIS |
+ TR_SUST_CHR | TR_RES_POIS | TR_DRAIN_EXP |
+ ESP_TROLL | ESP_GIANT,
+ },
+ flags_group {
+ "Air",
+ TERM_BLUE,
+ 5,
+ TR_WIS | TR_STEALTH | TR_INFRA | TR_SPEED |
+ TR_RES_LITE | TR_RES_DARK | TR_RES_BLIND | TR_SUST_WIS |
+ TR_FEATHER | TR_SEE_INVIS | TR_BLESSED |
+ ESP_GOOD,
+ },
+ flags_group {
+ "Earth",
+ TERM_L_UMBER,
+ 5,
+ TR_STR | TR_CON | TR_TUNNEL | TR_BLOWS | TR_SLAY_TROLL |
+ TR_SLAY_GIANT | TR_IMPACT | TR_SUST_STR | TR_SUST_CON |
+ TR_FREE_ACT | TR_RES_FEAR | TR_RES_SHARDS | TR_REGEN |
+ ESP_TROLL | ESP_GIANT,
+ },
+ flags_group {
+ "Mind",
+ TERM_YELLOW,
+ 7,
+ TR_INT | TR_SUST_INT | TR_RES_CONF | TR_RES_FEAR |
+ ESP_ORC | ESP_TROLL | ESP_GIANT | ESP_ANIMAL | ESP_UNIQUE | ESP_SPIDER | ESP_DEMON,
+ },
+ flags_group {
+ "Shield",
+ TERM_RED,
+ 7,
+ TR_DEX | TR_SUST_DEX | TR_INVIS | TR_REFLECT |
+ TR_HOLD_LIFE | TR_RES_SOUND | TR_RES_NEXUS |
+ TR_REGEN,
+ },
+ flags_group {
+ "Chaos",
+ TERM_VIOLET,
+ 7,
+ TR_CHAOTIC | TR_IMPACT | TR_RES_CHAOS | TR_RES_DISEN | TR_REGEN |
+ ESP_ALL,
+ },
+ flags_group {
+ "Magic",
+ TERM_L_BLUE,
+ 10,
+ TR_MANA | TR_SPELL | TR_RES_CHAOS | TR_RES_DISEN | TR_WRAITH |
+ TR_PRECOGNITION | TR_FLY | TR_CLONE,
+ },
+ flags_group {
+ "Antimagic",
+ TERM_L_DARK,
+ 10,
+ TR_VAMPIRIC | TR_CHAOTIC | TR_BLOWS | TR_SPEED | TR_LIFE |
+ TR_REFLECT | TR_FREE_ACT | TR_HOLD_LIFE | TR_NO_MAGIC |
+ TR_NO_TELE | TR_SEE_INVIS | TR_ANTIMAGIC_50,
+ }
+ };
+
+ return *instance;
};
/* Powers */
-power_type powers_type_init[POWER_MAX_INIT] =
+power_type powers_type[POWER_MAX] =
{
{
"spit acid",
@@ -3537,10 +2834,12 @@ power_type powers_type_init[POWER_MAX_INIT] =
1, 1, A_DEX, 1,
},
{
- "Merchant abilities",
- "You can request items and get loans.",
- "From now on you can use the merchant abilities.",
- "You can no longer use the merchant abilities.",
+ "notused", /* Merchant abilities; no longer used, but want to
+ * avoid having to move all potential places where
+ * we're indexing into this table. */
+ "notused",
+ "notused",
+ "notused",
0, 0, 0, 0,
},
{
@@ -3571,16 +2870,36 @@ 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,
+ },
};
/*
* The Quests
*/
-quest_type quest_init_tome[MAX_Q_IDX_INIT] =
+quest_type quest[MAX_Q_IDX] =
{
{
FALSE,
- FALSE,
"",
{
"",
@@ -3598,14 +2917,12 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
0,
NULL,
- HOOK_TYPE_C,
- quest_null_hook,
+ NULL,
{0, 0},
NULL,
},
{
FALSE,
- FALSE,
"Dol Guldur",
{
"The forest of Mirkwood is a very dangerous place to go, mainly due to",
@@ -3623,14 +2940,12 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
70,
&plots[PLOT_MAIN],
- HOOK_TYPE_C,
quest_necro_init_hook,
{0, 0},
NULL,
},
{
FALSE,
- FALSE,
"Sauron",
{
"It is time to take the battle to Morgoth. But, before you can",
@@ -3648,14 +2963,12 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
99,
&plots[PLOT_MAIN],
- HOOK_TYPE_C,
quest_sauron_init_hook,
{0, 0},
NULL,
},
{
FALSE,
- FALSE,
"Morgoth",
{
"Your final quest is the ultimate quest that has always been",
@@ -3673,7 +2986,6 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
100,
&plots[PLOT_MAIN],
- HOOK_TYPE_C,
quest_morgoth_init_hook,
{0, 0},
NULL,
@@ -3682,7 +2994,6 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
/* Bree plot */
{
FALSE,
- FALSE,
"Thieves!",
{
"There are thieves robbing my people! They live in a small",
@@ -3700,7 +3011,6 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
5,
&plots[PLOT_BREE],
- HOOK_TYPE_C,
quest_thieves_init_hook,
{0, 0},
NULL,
@@ -3708,7 +3018,6 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
{
FALSE,
- TRUE,
"Random Quest",
{
"",
@@ -3726,7 +3035,6 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
5,
NULL,
- HOOK_TYPE_C,
quest_random_init_hook,
{0, 0},
quest_random_describe,
@@ -3734,7 +3042,6 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
{
FALSE,
- FALSE,
"Lost Hobbit",
{
"Merton Proudfoot, a young hobbit, seems to have disappeared.",
@@ -3752,7 +3059,6 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
25,
&plots[PLOT_OTHER],
- HOOK_TYPE_C,
quest_hobbit_init_hook,
{0, 0},
NULL,
@@ -3760,7 +3066,6 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
{
FALSE,
- FALSE,
"The Dark Horseman",
{
"A dark-cloaked horseman has been spotted several times in town.",
@@ -3778,7 +3083,6 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
40,
&plots[PLOT_BREE],
- HOOK_TYPE_C,
quest_nazgul_init_hook,
{0, 0},
NULL,
@@ -3786,7 +3090,6 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
{
FALSE,
- FALSE,
"The Trolls Glade",
{
"A group of Forest Trolls settled in an abandoned forest in the",
@@ -3804,7 +3107,6 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
30,
&plots[PLOT_BREE],
- HOOK_TYPE_C,
quest_troll_init_hook,
{FALSE, 0},
NULL,
@@ -3812,7 +3114,6 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
{
FALSE,
- FALSE,
"The Wight Grave",
{
"The Barrow-Downs hides many mysteries and dangers.",
@@ -3830,7 +3131,6 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
30,
&plots[PLOT_BREE],
- HOOK_TYPE_C,
quest_wight_init_hook,
{FALSE, 0},
NULL,
@@ -3839,7 +3139,6 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
/* Lorien plot */
{
FALSE,
- FALSE,
"Spiders of Mirkwood",
{
"Powers lurk deep within Mirkwood. Spiders have blocked the",
@@ -3857,14 +3156,12 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
25,
&plots[PLOT_LORIEN],
- HOOK_TYPE_C,
quest_spider_init_hook,
{0, 0},
NULL,
},
{
FALSE,
- FALSE,
"Poisoned Water",
{
"A curse has beset Lothlorien. All trees along the shorelines of Nimrodel",
@@ -3882,7 +3179,6 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
30,
&plots[PLOT_LORIEN],
- HOOK_TYPE_C,
quest_poison_init_hook,
{0, 0},
NULL,
@@ -3890,7 +3186,6 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
/* Other quests */
{
FALSE,
- FALSE,
"The Broken Sword",
{
"You have found Narsil, a broken sword. It is said that the sword that",
@@ -3908,7 +3203,6 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
20,
&plots[PLOT_OTHER],
- HOOK_TYPE_C,
quest_narsil_init_hook,
{0, 0},
NULL,
@@ -3916,7 +3210,6 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
/* Gondolin plot */
{
FALSE,
- FALSE,
"Eol the Dark Elf",
{
"We have disturbing tidings. Eol the Dark Elf has come seeking his kin in",
@@ -3934,14 +3227,12 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
30,
&plots[PLOT_GONDOLIN],
- HOOK_TYPE_C,
quest_eol_init_hook,
{0, 0},
NULL,
},
{
FALSE,
- FALSE,
"Nirnaeth Arnoediad",
{
"The fortunes of war in the north turn against us.",
@@ -3959,14 +3250,12 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
37,
&plots[PLOT_GONDOLIN],
- HOOK_TYPE_C,
quest_nirnaeth_init_hook,
{0, 0},
NULL,
},
{
FALSE,
- FALSE,
"Invasion of Gondolin",
{
"Morgoth is upon us! Dragons and Balrogs have poured over secret",
@@ -3984,7 +3273,6 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
80,
&plots[PLOT_GONDOLIN],
- HOOK_TYPE_C,
quest_invasion_init_hook,
{0, 0},
NULL,
@@ -3992,7 +3280,6 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
/* Minas Anor Plot*/
{
FALSE,
- FALSE,
"The Last Alliance",
{
"The armies of Morgoth are closing in on the last remaining strongholds",
@@ -4010,14 +3297,12 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
80,
&plots[PLOT_MINAS],
- HOOK_TYPE_C,
quest_between_init_hook,
{0, 0},
NULL,
},
{
FALSE,
- FALSE,
"The One Ring",
{
"Find the One Ring, then bring it to Mount Doom, in Mordor, to drop",
@@ -4035,7 +3320,6 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
99,
&plots[PLOT_MAIN],
- HOOK_TYPE_C,
quest_one_init_hook,
{0, 0},
NULL,
@@ -4043,7 +3327,6 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
{
FALSE,
- FALSE,
"Mushroom supplies",
{
"Farmer Maggot asked you to bring him back his mushrooms.",
@@ -4061,7 +3344,6 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
3,
&plots[PLOT_OTHER],
- HOOK_TYPE_C,
quest_shroom_init_hook,
{0, 0},
NULL,
@@ -4069,7 +3351,6 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
{
FALSE,
- FALSE,
"The prisoner of Dol Guldur",
{
"You keep hearing distress cries in the dark tower of",
@@ -4087,7 +3368,6 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
60,
&plots[PLOT_OTHER],
- HOOK_TYPE_C,
quest_thrain_init_hook,
{0, 0},
NULL,
@@ -4096,7 +3376,6 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
/* The 2 ultra endings go here */
{
FALSE,
- FALSE,
"Falling Toward Apotheosis",
{
"You must enter the Void where Melkor spirit lurks to destroy",
@@ -4114,14 +3393,12 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
150,
&plots[PLOT_MAIN],
- HOOK_TYPE_C,
quest_ultra_good_init_hook,
{0, 0},
NULL,
},
{
FALSE,
- FALSE,
"Falling Toward Apotheosis",
{
"You must now launch an onslaught on Valinor itself to eliminate",
@@ -4139,7 +3416,6 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
150,
&plots[PLOT_MAIN],
- HOOK_TYPE_C,
quest_ultra_evil_init_hook,
{0, 0},
NULL,
@@ -4147,7 +3423,6 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
/* More Lorien */
{
FALSE,
- FALSE,
"Wolves!",
{
"There are wolves pestering my people! They gather in a hut",
@@ -4165,7 +3440,6 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
15,
&plots[PLOT_LORIEN],
- HOOK_TYPE_C,
quest_wolves_init_hook,
{0, 0},
NULL,
@@ -4173,7 +3447,6 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
/* More Gondolin */
{
FALSE,
- FALSE,
"Dragons!",
{
"There are dragons pestering my people! They gather in a",
@@ -4191,7 +3464,6 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
25,
&plots[PLOT_GONDOLIN],
- HOOK_TYPE_C,
quest_dragons_init_hook,
{0, 0},
NULL,
@@ -4199,7 +3471,6 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
/* More Minas Anor */
{
FALSE,
- FALSE,
"Haunted House!",
{
"There are undead pestering my people! They gather in a hut",
@@ -4217,7 +3488,6 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
45,
&plots[PLOT_MINAS],
- HOOK_TYPE_C,
quest_haunted_init_hook,
{0, 0},
NULL,
@@ -4225,7 +3495,6 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
/* Khazad-Dum Plot*/
{
FALSE,
- FALSE,
"Evil!",
{
"We have burrowed too deep, and let out some creatures of",
@@ -4243,137 +3512,232 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
60,
&plots[PLOT_KHAZAD],
- HOOK_TYPE_C,
quest_evil_init_hook,
{0, 0},
NULL,
},
+ /* Bounty */
+ {
+ FALSE,
+ "Bounty quest",
+ {
+ "", /* dynamic desc */
+ },
+ QUEST_STATUS_UNTAKEN,
+ -1,
+ NULL,
+ quest_bounty_init_hook,
+ {0, 0, 0, 0},
+ quest_bounty_describe,
+ },
+ /* Fireproofing */
+ {
+ FALSE,
+ "Old Mages quest",
+ {
+ "", /* dynamic desc */
+ },
+ QUEST_STATUS_UNTAKEN,
+ 20,
+ NULL,
+ quest_fireproof_init_hook,
+ {0, 0, 0, 0},
+ quest_fireproof_describe,
+ },
+ /* Library */
+ {
+ FALSE,
+ "Library quest",
+ {
+ "", /* dynamic desc */
+ },
+ QUEST_STATUS_UNTAKEN,
+ 35,
+ NULL,
+ quest_library_init_hook,
+ { -1, -1, -1, -1 },
+ quest_library_describe,
+ },
+ /* God quest */
+ {
+ FALSE,
+ "God quest",
+ {
+ "", /* dynamic desc */
+ },
+ QUEST_STATUS_UNTAKEN,
+ -1,
+ NULL,
+ 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,
+ },
};
/* List of powers for Symbiants/Powers */
-monster_power monster_powers[96] =
- {
- { RF4_SHRIEK, "Aggravate Monster", 1, FALSE },
- { RF4_MULTIPLY, "Multiply", 10, FALSE },
- { RF4_S_ANIMAL, "Summon Animal", 30, FALSE },
- { RF4_ROCKET, "Fire a Rocket", 40, TRUE },
- { RF4_ARROW_1, "Light Arrow", 1, FALSE },
- { RF4_ARROW_2, "Minor Arrow", 3, FALSE },
- { RF4_ARROW_3, "Major Arrow", 7, TRUE },
- { RF4_ARROW_4, "Great Arrow", 9, TRUE },
- { RF4_BR_ACID, "Breathe Acid", 10, FALSE },
- { RF4_BR_ELEC, "Breathe Lightning", 10, FALSE },
- { RF4_BR_FIRE, "Breathe Fire", 10, FALSE },
- { RF4_BR_COLD, "Breathe Cold", 10, FALSE },
- { RF4_BR_POIS, "Breathe Poison", 15, TRUE },
- { RF4_BR_NETH, "Breathe Nether", 30, TRUE },
- { RF4_BR_LITE, "Breathe Light", 20, TRUE },
- { RF4_BR_DARK, "Breathe Dark", 20, TRUE },
- { RF4_BR_CONF, "Breathe Confusion", 15, TRUE },
- { RF4_BR_SOUN, "Breathe Sound", 30, TRUE },
- { RF4_BR_CHAO, "Breathe Chaos", 30, TRUE },
- { RF4_BR_DISE, "Breathe Disenchantment", 30, TRUE },
- { RF4_BR_NEXU, "Breathe Nexus", 30, TRUE },
- { RF4_BR_TIME, "Breathe Time", 30, TRUE },
- { RF4_BR_INER, "Breathe Inertia", 30, TRUE },
- { RF4_BR_GRAV, "Breathe Gravity", 30, TRUE },
- { RF4_BR_SHAR, "Breathe Shards", 30, TRUE },
- { RF4_BR_PLAS, "Breathe Plasma", 30, TRUE },
- { RF4_BR_WALL, "Breathe Force", 30, TRUE },
- { RF4_BR_MANA, "Breathe Mana", 40, TRUE },
- { RF4_BA_NUKE, "Nuke Ball", 30, TRUE },
- { RF4_BR_NUKE, "Breathe Nuke", 40, TRUE },
- { RF4_BA_CHAO, "Chaos Ball", 30, TRUE },
- { RF4_BR_DISI, "Breathe Disintegration", 40, TRUE },
+monster_power monster_powers[] =
+ {
+ { SF_SHRIEK_IDX, "Aggravate Monster", 1, FALSE },
+ { SF_MULTIPLY_IDX, "Multiply", 10, FALSE },
+ { SF_S_ANIMAL_IDX, "Summon Animal", 30, FALSE },
+ { SF_ROCKET_IDX, "Fire a Rocket", 40, TRUE },
+ { SF_ARROW_1_IDX, "Light Arrow", 1, FALSE },
+ { SF_ARROW_2_IDX, "Minor Arrow", 3, FALSE },
+ { SF_ARROW_3_IDX, "Major Arrow", 7, TRUE },
+ { SF_ARROW_4_IDX, "Great Arrow", 9, TRUE },
+ { SF_BR_ACID_IDX, "Breathe Acid", 10, FALSE },
+ { SF_BR_ELEC_IDX, "Breathe Lightning", 10, FALSE },
+ { SF_BR_FIRE_IDX, "Breathe Fire", 10, FALSE },
+ { SF_BR_COLD_IDX, "Breathe Cold", 10, FALSE },
+ { SF_BR_POIS_IDX, "Breathe Poison", 15, TRUE },
+ { SF_BR_NETH_IDX, "Breathe Nether", 30, TRUE },
+ { SF_BR_LITE_IDX, "Breathe Light", 20, TRUE },
+ { SF_BR_DARK_IDX, "Breathe Dark", 20, TRUE },
+ { SF_BR_CONF_IDX, "Breathe Confusion", 15, TRUE },
+ { SF_BR_SOUN_IDX, "Breathe Sound", 30, TRUE },
+ { SF_BR_CHAO_IDX, "Breathe Chaos", 30, TRUE },
+ { SF_BR_DISE_IDX, "Breathe Disenchantment", 30, TRUE },
+ { SF_BR_NEXU_IDX, "Breathe Nexus", 30, TRUE },
+ { SF_BR_TIME_IDX, "Breathe Time", 30, TRUE },
+ { SF_BR_INER_IDX, "Breathe Inertia", 30, TRUE },
+ { SF_BR_GRAV_IDX, "Breathe Gravity", 30, TRUE },
+ { SF_BR_SHAR_IDX, "Breathe Shards", 30, TRUE },
+ { SF_BR_PLAS_IDX, "Breathe Plasma", 30, TRUE },
+ { SF_BR_WALL_IDX, "Breathe Force", 30, TRUE },
+ { SF_BR_MANA_IDX, "Breathe Mana", 40, TRUE },
+ { SF_BA_NUKE_IDX, "Nuke Ball", 30, TRUE },
+ { SF_BR_NUKE_IDX, "Breathe Nuke", 40, TRUE },
+ { SF_BA_CHAO_IDX, "Chaos Ball", 30, TRUE },
+ { SF_BR_DISI_IDX, "Breathe Disintegration", 40, TRUE },
+ { SF_BA_ACID_IDX, "Acid Ball", 8, FALSE },
+ { SF_BA_ELEC_IDX, "Lightning Ball", 8, FALSE },
+ { SF_BA_FIRE_IDX, "Fire Ball", 8, FALSE },
+ { SF_BA_COLD_IDX, "Cold Ball", 8, FALSE },
+ { SF_BA_POIS_IDX, "Poison Ball", 20, TRUE },
+ { SF_BA_NETH_IDX, "Nether Ball", 20, TRUE },
+ { SF_BA_WATE_IDX, "Water Ball", 20, TRUE },
+ { SF_BA_MANA_IDX, "Mana Ball", 50, TRUE },
+ { SF_BA_DARK_IDX, "Darkness Ball", 20, TRUE },
+ { SF_CAUSE_1_IDX, "Cause Light Wounds", 20, FALSE },
+ { SF_CAUSE_2_IDX, "Cause Medium Wounds", 30, FALSE },
+ { SF_CAUSE_3_IDX, "Cause Critical Wounds", 35, TRUE },
+ { SF_CAUSE_4_IDX, "Cause Mortal Wounds", 45, TRUE },
+ { SF_BO_ACID_IDX, "Acid Bolt", 5, FALSE },
+ { SF_BO_ELEC_IDX, "Lightning Bolt", 5, FALSE },
+ { SF_BO_FIRE_IDX, "Fire Bolt", 5, FALSE },
+ { SF_BO_COLD_IDX, "Cold Bolt", 5, FALSE },
+ { SF_BO_POIS_IDX, "Poison Bolt", 10, TRUE },
+ { SF_BO_NETH_IDX, "Nether Bolt", 15, TRUE },
+ { SF_BO_WATE_IDX, "Water Bolt", 20, TRUE },
+ { SF_BO_MANA_IDX, "Mana Bolt", 25, TRUE },
+ { SF_BO_PLAS_IDX, "Plasma Bolt", 20, TRUE },
+ { SF_BO_ICEE_IDX, "Ice Bolt", 20, TRUE },
+ { SF_MISSILE_IDX, "Magic Missile", 1, FALSE },
+ { SF_SCARE_IDX, "Scare", 4, FALSE },
+ { SF_BLIND_IDX, "Blindness", 6, FALSE },
+ { SF_CONF_IDX, "Confusion", 7, FALSE },
+ { SF_SLOW_IDX, "Slowness", 10, FALSE },
+ { SF_HOLD_IDX, "Paralyse", 10, FALSE },
+ { SF_HASTE_IDX, "Haste Self", 50, FALSE },
+ { SF_HAND_DOOM_IDX, "Hand of Doom", 30, TRUE },
+ { SF_HEAL_IDX, "Healing", 60, FALSE },
+ { SF_S_ANIMALS_IDX, "Summon Animals", 60, TRUE },
+ { SF_BLINK_IDX, "Phase Door", 2, FALSE },
+ { SF_TPORT_IDX, "Teleport", 10, FALSE },
+ { SF_TELE_TO_IDX, "Teleport To", 20, TRUE },
+ { SF_TELE_AWAY_IDX, "Teleport Away", 20, FALSE },
+ { SF_TELE_LEVEL_IDX, "Teleport Level", 20, TRUE },
+ { SF_DARKNESS_IDX, "Darkness", 3, FALSE },
+ { SF_RAISE_DEAD_IDX, "Raise the Dead", 400, TRUE },
+ { SF_S_THUNDERLORD_IDX, "Summon Thunderlords", 90, TRUE },
+ { SF_S_KIN_IDX, "Summon Kin", 80, FALSE },
+ { SF_S_HI_DEMON_IDX, "Summon Greater Demons", 90, TRUE },
+ { SF_S_MONSTER_IDX, "Summon Monster", 50, FALSE },
+ { SF_S_MONSTERS_IDX, "Summon Monsters", 60, TRUE },
+ { SF_S_ANT_IDX, "Summon Ants", 30, FALSE },
+ { SF_S_SPIDER_IDX, "Summon Spider", 30, FALSE },
+ { SF_S_HOUND_IDX, "Summon Hound", 50, TRUE },
+ { SF_S_HYDRA_IDX, "Summon Hydra", 40, TRUE },
+ { SF_S_ANGEL_IDX, "Summon Angel", 60, TRUE },
+ { SF_S_DEMON_IDX, "Summon Demon", 60, TRUE },
+ { SF_S_UNDEAD_IDX, "Summon Undead", 70, TRUE },
+ { SF_S_DRAGON_IDX, "Summon Dragon", 70, TRUE },
+ { SF_S_HI_UNDEAD_IDX, "Summon High Undead", 90, TRUE },
+ { SF_S_HI_DRAGON_IDX, "Summon High Dragon", 90, TRUE },
+ { SF_S_WRAITH_IDX, "Summon Wraith", 90, TRUE },
+ };
- { RF5_BA_ACID, "Acid Ball", 8, FALSE },
- { RF5_BA_ELEC, "Lightning Ball", 8, FALSE },
- { RF5_BA_FIRE, "Fire Ball", 8, FALSE },
- { RF5_BA_COLD, "Cold Ball", 8, FALSE },
- { RF5_BA_POIS, "Poison Ball", 20, TRUE },
- { RF5_BA_NETH, "Nether Ball", 20, TRUE },
- { RF5_BA_WATE, "Water Ball", 20, TRUE },
- { RF5_BA_MANA, "Mana Ball", 50, TRUE },
- { RF5_BA_DARK, "Darkness Ball", 20, TRUE },
- { 0, "(none)", 0, FALSE },
- { 0, "(none)", 0, FALSE },
- { 0, "(none)", 0, FALSE },
- { RF5_CAUSE_1, "Cause Light Wounds", 20, FALSE },
- { RF5_CAUSE_2, "Cause Medium Wounds", 30, FALSE },
- { RF5_CAUSE_3, "Cause Critical Wounds", 35, TRUE },
- { RF5_CAUSE_4, "Cause Mortal Wounds", 45, TRUE },
- { RF5_BO_ACID, "Acid Bolt", 5, FALSE },
- { RF5_BO_ELEC, "Lightning Bolt", 5, FALSE },
- { RF5_BO_FIRE, "Fire Bolt", 5, FALSE },
- { RF5_BO_COLD, "Cold Bolt", 5, FALSE },
- { RF5_BO_POIS, "Poison Bolt", 10, TRUE },
- { RF5_BO_NETH, "Nether Bolt", 15, TRUE },
- { RF5_BO_WATE, "Water Bolt", 20, TRUE },
- { RF5_BO_MANA, "Mana Bolt", 25, TRUE },
- { RF5_BO_PLAS, "Plasma Bolt", 20, TRUE },
- { RF5_BO_ICEE, "Ice Bolt", 20, TRUE },
- { RF5_MISSILE, "Magic Missile", 1, FALSE },
- { RF5_SCARE, "Scare", 4, FALSE },
- { RF5_BLIND, "Blindness", 6, FALSE },
- { RF5_CONF, "Confusion", 7, FALSE },
- { RF5_SLOW, "Slowness", 10, FALSE },
- { RF5_HOLD, "Paralyse", 10, FALSE },
- { RF6_HASTE, "Haste Self", 50, FALSE },
- { RF6_HAND_DOOM, "Hand of Doom", 30, TRUE },
- { RF6_HEAL, "Healing", 60, FALSE },
- { RF6_S_ANIMALS, "Summon Animals", 60, TRUE },
- { RF6_BLINK, "Phase Door", 2, FALSE },
- { RF6_TPORT, "Teleport", 10, FALSE },
- { RF6_TELE_TO, "Teleport To", 20, TRUE },
- { RF6_TELE_AWAY, "Teleport Away", 20, FALSE },
- { RF6_TELE_LEVEL, "Teleport Level", 20, TRUE },
- { RF6_DARKNESS, "Darkness", 3, FALSE },
- { RF6_TRAPS, "Create Traps", 10, TRUE },
- { 0, "(none)", 0, FALSE },
- { RF6_RAISE_DEAD, "Raise the Dead", 400, TRUE },
- { 0, "(none)", 0, FALSE },
- { 0, "(none)", 0, FALSE },
- { RF6_S_THUNDERLORD, "Summon Thunderlords", 90, TRUE },
- { RF6_S_KIN, "Summon Kin", 80, FALSE },
- { RF6_S_HI_DEMON, "Summon Greater Demons", 90, TRUE },
- { RF6_S_MONSTER, "Summon Monster", 50, FALSE },
- { RF6_S_MONSTERS, "Summon Monsters", 60, TRUE },
- { RF6_S_ANT, "Summon Ants", 30, FALSE },
- { RF6_S_SPIDER, "Summon Spider", 30, FALSE },
- { RF6_S_HOUND, "Summon Hound", 50, TRUE },
- { RF6_S_HYDRA, "Summon Hydra", 40, TRUE },
- { RF6_S_ANGEL, "Summon Angel", 60, TRUE },
- { RF6_S_DEMON, "Summon Demon", 60, TRUE },
- { RF6_S_UNDEAD, "Summon Undead", 70, TRUE },
- { RF6_S_DRAGON, "Summon Dragon", 70, TRUE },
- { RF6_S_HI_UNDEAD, "Summon High Undead", 90, TRUE },
- { RF6_S_HI_DRAGON, "Summon High Dragon", 90, TRUE },
- { RF6_S_WRAITH, "Summon Wraith", 90, TRUE },
- { 0, "(none)", 0, FALSE },
- };
+/*
+ * A list of tvals and their textual names
+ */
+tval_desc tvals[] =
+{
+ { TV_SWORD, "Sword" },
+ { TV_POLEARM, "Polearm" },
+ { TV_HAFTED, "Hafted Weapon" },
+ { TV_AXE, "Axe" },
+ { TV_BOW, "Bow" },
+ { TV_BOOMERANG, "Boomerang" },
+ { TV_ARROW, "Arrows" },
+ { TV_BOLT, "Bolts" },
+ { TV_SHOT, "Shots" },
+ { TV_SHIELD, "Shield" },
+ { TV_CROWN, "Crown" },
+ { TV_HELM, "Helm" },
+ { TV_GLOVES, "Gloves" },
+ { TV_BOOTS, "Boots" },
+ { TV_CLOAK, "Cloak" },
+ { TV_DRAG_ARMOR, "Dragon Scale Mail" },
+ { TV_HARD_ARMOR, "Hard Armor" },
+ { TV_SOFT_ARMOR, "Soft Armor" },
+ { TV_RING, "Ring" },
+ { TV_AMULET, "Amulet" },
+ { TV_LITE, "Lite" },
+ { TV_POTION, "Potion" },
+ { TV_POTION2, "Potion" },
+ { TV_SCROLL, "Scroll" },
+ { TV_WAND, "Wand" },
+ { TV_STAFF, "Staff" },
+ { TV_ROD_MAIN, "Rod" },
+ { TV_ROD, "Rod Tip" },
+ { TV_BOOK, "Schools Spellbook", },
+ { TV_SYMBIOTIC_BOOK, "Symbiotic Spellbook", },
+ { TV_DRUID_BOOK, "Elemental Stone" },
+ { TV_MUSIC_BOOK, "Music Book" },
+ { TV_DAEMON_BOOK, "Daemon Book" },
+ { TV_SPIKE, "Spikes" },
+ { TV_DIGGING, "Digger" },
+ { TV_CHEST, "Chest" },
+ { TV_FOOD, "Food" },
+ { TV_FLASK, "Flask" },
+ { TV_MSTAFF, "Mage Staff" },
+ { TV_PARCHMENT, "Parchment" },
+ { TV_INSTRUMENT, "Musical Instrument" },
+ { TV_JUNK, "Junk" },
+ { 0, NULL }
+};
/* Tval descriptions */
tval_desc tval_descs[] =
{
{
- TV_BATERIE,
- "Essences contain primitive magic forces which users of the "
- "Alchemy skill can use to create powerful magic items from "
- "other magic items."
- },
- {
TV_MSTAFF,
"Mage Staves are the spellcaster's weapons of choice. "
"They all reduce spellcasting time to 80% of "
"normal time and some will yield even greater powers."
},
{
- 3,
- "XXX"
- },
- {
TV_PARCHMENT,
"Parchments can contain useful information ... or useless "
"junk."
@@ -4464,11 +3828,6 @@ tval_desc tval_descs[] =
"arcane magics."
},
{
- TV_TRAPKIT,
- "Trapping kits are used with the trapping ability to set "
- "deadly monster traps."
- },
- {
TV_STAFF,
"Staves are objects imbued with mystical powers."
},
@@ -4525,14 +3884,6 @@ tval_desc tval_descs[] =
"they can be activated for great or strange effects..."
},
{
- TV_RUNE1,
- "Runes are used with the Runecraft skill to create brand new spells."
- },
- {
- TV_RUNE2,
- "Runes are used with the Runecraft skill to create brand new spells."
- },
- {
TV_JUNK,
"Junk is usually worthless, though experienced archers can "
"create ammo with them."
@@ -4543,7 +3894,7 @@ tval_desc tval_descs[] =
},
{
TV_BOTTLE,
- "An empty bottle. Maybe an alchemist could refill it."
+ "An empty bottle."
},
{
TV_SPIKE,
@@ -4560,8 +3911,7 @@ tval_desc tval_descs[] =
{
TV_GLOVES,
"Handgear is used to protect hands, but nonmagical ones "
- "can sometimes hinder spellcasting. Alchemists need "
- "gloves in order to do alchemy."
+ "can sometimes hinder spellcasting."
},
{
TV_HELM,
@@ -4639,43 +3989,14 @@ between_exit between_exits[MAX_BETWEEN_EXITS] =
10, 35,
0, 0
},
-};
-
-/*
- * Months
- */
-int month_day[9] =
-{
- 0, /* 1 day */
-
- 1, /* 54 days */
- 55, /* 72 days */
- 127, /* 54 days */
-
- 181, /* 3 days */
-
- 184, /* 54 days */
- 238, /* 72 days */
- 310, /* 54 days */
-
- 364, /* 1 day */
-};
-
-cptr month_name[9] =
-{
- "Yestare",
-
- "Tuile",
- "Laire",
- "Yavie",
-
- "Enderi",
-
- "Quelle",
- "Hrive",
- "Coire",
-
- "Mettare",
+ /* Theme: Minas Tirith -> Gondolin link */
+ {
+ 0,
+ FALSE,
+ 3, 11,
+ 119, 25,
+ 0, 0
+ },
};
/*
@@ -4728,10 +4049,8 @@ gf_name_type gf_names[] =
{ GF_GRAVITY, "gravity" },
{ GF_KILL_WALL, "wall destruction" },
{ GF_KILL_DOOR, "door destruction" },
- { GF_KILL_TRAP, "trap destruction" },
{ GF_MAKE_WALL, "wall creation" },
{ GF_MAKE_DOOR, "door creation" },
- { GF_MAKE_TRAP, "trap creation" },
{ GF_OLD_CLONE, "clone" },
{ GF_OLD_POLY, "polymorph" },
{ GF_OLD_HEAL, "healing" },
@@ -4770,7 +4089,6 @@ gf_name_type gf_names[] =
{ GF_JAM_DOOR, "door jamming" },
{ GF_DOMINATION, "domination" },
{ GF_DISP_GOOD, "dispel good" },
- { GF_IDENTIFY, "identification" },
{ GF_RAISE, "raise dead" },
{ GF_STAR_IDENTIFY, "*identification*" },
{ GF_DESTRUCTION, "destruction" },
@@ -4790,3 +4108,51 @@ gf_name_type gf_names[] =
{ GF_ATTACK, "projected melee attacks" },
{ -1, NULL },
};
+
+/**
+ * Modules
+ */
+module_type modules[MAX_MODULES] =
+{
+ {
+ { "ToME",
+ { 2, 4, 0 },
+ { "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 },
+ /* Skills: */
+ { 6, 4, },
+ /* Intro function */
+ tome_intro,
+ /* Race status function: ToME requires no special handling */
+ NULL
+ },
+
+ {
+ { "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 },
+ /* Skill overage: */
+ { 6, 5, },
+ /* Intro function */
+ theme_intro,
+ /* Race status function */
+ theme_race_status
+ }
+
+};
+
diff --git a/src/tables.h b/src/tables.h
new file mode 100644
index 00000000..9a5cfb58
--- /dev/null
+++ b/src/tables.h
@@ -0,0 +1,12 @@
+#pragma once
+
+// C linkage required for these functions since main-* code uses them.
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern char hexsym[16];
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/src/tables.hpp b/src/tables.hpp
new file mode 100644
index 00000000..613dbddb
--- /dev/null
+++ b/src/tables.hpp
@@ -0,0 +1,80 @@
+#pragma once
+
+#include "angband.h"
+#include "activation.hpp"
+#include "between_exit.hpp"
+#include "body.hpp"
+#include "cli_comm_fwd.hpp"
+#include "flags_group.hpp"
+#include "gf_name_type.hpp"
+#include "inscription_info_type.hpp"
+#include "magic_power.hpp"
+#include "martial_arts.hpp"
+#include "module_type.hpp"
+#include "monster_power.hpp"
+#include "move_info_type.hpp"
+#include "option_type.hpp"
+#include "player_defs.hpp"
+#include "power_type.hpp"
+#include "powers.hpp"
+#include "quest_type.hpp"
+#include "tactic_info_type.hpp"
+#include "tval_desc.hpp"
+
+#include <vector>
+
+extern s16b ddd[9];
+extern s16b ddx[10];
+extern s16b ddy[10];
+extern s16b ddx_ddd[9];
+extern s16b ddy_ddd[9];
+extern byte adj_mag_mana[];
+extern byte adj_mag_fail[];
+extern byte adj_mag_stat[];
+extern byte adj_chr_gold[];
+extern byte adj_wis_sav[];
+extern byte adj_dex_ta[];
+extern byte adj_str_td[];
+extern byte adj_dex_th[];
+extern byte adj_str_th[];
+extern byte adj_str_wgt[];
+extern byte adj_str_hold[];
+extern byte adj_str_dig[];
+extern byte adj_str_blow[];
+extern byte adj_dex_blow[];
+extern byte adj_dex_safe[];
+extern byte adj_con_fix[];
+extern byte adj_con_mhp[];
+extern byte blows_table[12][12];
+extern byte extract_energy[300];
+extern s32b player_exp[PY_MAX_LEVEL];
+extern cptr color_names[16];
+extern cptr stat_names[6];
+extern cptr stat_names_reduced[6];
+extern cptr window_flag_desc[32];
+extern martial_arts bear_blows[MAX_BEAR];
+extern martial_arts ma_blows[MAX_MA];
+extern magic_power mindcraft_powers[MAX_MINDCRAFT_POWERS];
+extern magic_power necro_powers[MAX_NECRO_POWERS];
+extern magic_power mimic_powers[MAX_MIMIC_POWERS];
+extern magic_power symbiotic_powers[MAX_SYMBIOTIC_POWERS];
+extern move_info_type move_info[9];
+extern tactic_info_type tactic_info[9];
+extern activation activation_info[MAX_T_ACT];
+extern inscription_info_type inscription_info[MAX_INSCRIPTIONS];
+extern cptr sense_desc[];
+std::vector<flags_group> const &flags_groups();
+extern power_type powers_type[POWER_MAX];
+extern cptr artifact_names_list;
+extern monster_power monster_powers[MONSTER_POWERS_MAX];
+extern tval_desc tvals[];
+extern tval_desc tval_descs[];
+extern between_exit between_exits[MAX_BETWEEN_EXITS];
+extern int month_day[9];
+extern cptr month_name[9];
+extern cli_comm *cli_info;
+extern int cli_total;
+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];
diff --git a/src/tactic_info_type.hpp b/src/tactic_info_type.hpp
new file mode 100644
index 00000000..4cb330f4
--- /dev/null
+++ b/src/tactic_info_type.hpp
@@ -0,0 +1,16 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * Tactics descriptor.
+ */
+struct tactic_info_type
+{
+ s16b to_hit;
+ s16b to_dam;
+ s16b to_ac;
+ s16b to_stealth;
+ s16b to_saving;
+ cptr name;
+};
diff --git a/src/terrain.hpp b/src/terrain.hpp
new file mode 100644
index 00000000..118a877a
--- /dev/null
+++ b/src/terrain.hpp
@@ -0,0 +1,19 @@
+#pragma once
+
+/*
+ * Wilderness terrains
+ */
+#define TERRAIN_EDGE 0 /* Edge of the World */
+#define TERRAIN_TOWN 1 /* Town */
+#define TERRAIN_DEEP_WATER 2 /* Deep water */
+#define TERRAIN_SHALLOW_WATER 3 /* Shallow water */
+#define TERRAIN_SWAMP 4 /* Swamp */
+#define TERRAIN_DIRT 5 /* Dirt */
+#define TERRAIN_GRASS 6 /* Grass */
+#define TERRAIN_TREES 7 /* Trees */
+#define TERRAIN_DESERT 8 /* Desert */
+#define TERRAIN_SHALLOW_LAVA 9 /* Shallow lava */
+#define TERRAIN_DEEP_LAVA 10 /* Deep lava */
+#define TERRAIN_MOUNTAIN 11 /* Mountain */
+
+#define MAX_WILD_TERRAIN 18
diff --git a/src/timer_type.hpp b/src/timer_type.hpp
new file mode 100644
index 00000000..d682b3bd
--- /dev/null
+++ b/src/timer_type.hpp
@@ -0,0 +1,81 @@
+#pragma once
+
+#include "h-basic.h"
+
+#include <functional>
+
+/*
+ * Timer descriptor and runtime data.
+ */
+struct timer_type
+{
+private:
+ std::function<void ()> m_callback;
+
+public:
+ //
+ // XXX Currently need public access for loading and saving.
+ //
+ bool m_enabled;
+ s32b m_delay = 0;
+ s32b m_countdown = 0;
+
+public:
+ /**
+ * Create a new timer
+ */
+ timer_type(std::function<void()> callback, s32b delay)
+ : m_callback(callback)
+ , m_enabled(false)
+ , m_delay(delay)
+ , m_countdown(delay)
+ {
+ }
+
+ timer_type(timer_type const &other) = delete;
+ timer_type &operator =(timer_type const &other) = delete;
+
+ /**
+ * Enable the timer.
+ */
+ void enable()
+ {
+ m_enabled = true;
+ }
+
+ /**
+ * Disable the timer.
+ */
+ void disable()
+ {
+ m_enabled = false;
+ }
+
+ /**
+ * Change delay and reset.
+ */
+ void set_delay_and_reset(s32b delay)
+ {
+ m_delay = delay;
+ m_countdown = delay;
+ }
+
+ /**
+ * Count down.
+ */
+ void count_down()
+ {
+ if (!m_enabled)
+ {
+ return;
+ }
+
+ m_countdown--;
+ if (m_countdown <= 0)
+ {
+ m_countdown = m_delay;
+ m_callback();
+ }
+ }
+
+};
diff --git a/src/timer_type_fwd.hpp b/src/timer_type_fwd.hpp
new file mode 100644
index 00000000..bda03716
--- /dev/null
+++ b/src/timer_type_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct timer_type;
diff --git a/src/town_type.hpp b/src/town_type.hpp
new file mode 100644
index 00000000..0b903138
--- /dev/null
+++ b/src/town_type.hpp
@@ -0,0 +1,25 @@
+#pragma once
+
+#include "h-basic.h"
+#include "seed.hpp"
+#include "store_type_fwd.hpp"
+
+#include <vector>
+
+/**
+ * Town descriptor.
+ */
+struct town_type
+{
+ cptr name = nullptr;
+
+ seed_t seed = seed_t::system(); /* Seed for RNG */
+
+ std::vector<store_type> store; /* The stores [max_st_idx] */
+
+ byte flags = 0; /* Town flags */
+
+ bool_ stocked = FALSE; /* Is the town actualy stocked ? */
+
+ bool_ destroyed = FALSE; /* Is the town destroyed? */
+};
diff --git a/src/town_type_fwd.hpp b/src/town_type_fwd.hpp
new file mode 100644
index 00000000..9de8c448
--- /dev/null
+++ b/src/town_type_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct town_type;
diff --git a/src/traps.c b/src/traps.c
deleted file mode 100644
index 1c8e36c9..00000000
--- a/src/traps.c
+++ /dev/null
@@ -1,3169 +0,0 @@
-/* File: traps.c */
-
-/* Purpose: handle traps */
-
-/* the below copyright probably still applies, but it is heavily changed
- * copied, adapted & re-engineered by JK.
- * 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"
-
-bool_ do_player_trap_call_out(void)
-{
- s16b i, sn, cx, cy;
- s16b h_index = 0;
- s16b h_level = 0;
- monster_type *m_ptr;
- char m_name[80];
- bool_ ident = FALSE;
-
- for (i = 1; i < m_max; i++)
- {
- m_ptr = &m_list[i];
-
- /* Paranoia -- Skip dead monsters */
- if (!m_ptr->r_idx) continue;
-
- if (m_ptr->level >= h_level)
- {
- h_level = m_ptr->level;
- h_index = i;
- }
- }
-
- /* if the level is empty of monsters, h_index will be 0 */
- if (!h_index) return (FALSE);
-
- m_ptr = &m_list[h_index];
-
- sn = 0;
- for (i = 0; i < 8; i++)
- {
- cx = p_ptr->px + ddx[i];
- cy = p_ptr->py + ddy[i];
-
- /* Skip non-empty grids */
- if (!cave_valid_bold(cy, cx)) continue;
- if (cave[cy][cx].feat == FEAT_GLYPH) continue;
- if ((cx == p_ptr->px) && (cy == p_ptr->py)) continue;
- sn++;
-
- /* Randomize choice */
- if (rand_int(sn) > 0) continue;
- cave[cy][cx].m_idx = h_index;
- cave[m_ptr->fy][m_ptr->fx].m_idx = 0;
- m_ptr->fx = cx;
- m_ptr->fy = cy;
-
- /* we do not change the sublevel! */
- ident = TRUE;
- update_mon(h_index, TRUE);
- monster_desc(m_name, m_ptr, 0x08);
- msg_format("You hear a rapid-shifting wail, and %s appears!", m_name);
- break;
- }
-
- return (ident);
-}
-
-static bool_ do_trap_teleport_away(object_type *i_ptr, s16b y, s16b x)
-{
- bool_ ident = FALSE;
- char o_name[80];
-
- s16b o_idx = 0;
- object_type *o_ptr;
- cave_type *c_ptr;
-
- s16b x1;
- s16b y1;
-
- if (i_ptr == NULL) return (FALSE);
-
- if (i_ptr->name1 == ART_POWER) return (FALSE);
-
- while (o_idx == 0)
- {
- x1 = rand_int(cur_wid);
- y1 = rand_int(cur_hgt);
-
- /* Obtain grid */
- c_ptr = &cave[y1][x1];
-
- /* Require floor space (or shallow terrain) -KMW- */
- if (!(f_info[c_ptr->feat].flags1 & FF1_FLOOR)) continue;
-
- o_idx = drop_near(i_ptr, 0, y1, x1);
- }
-
- o_ptr = &o_list[o_idx];
-
- x1 = o_ptr->ix;
- y1 = o_ptr->iy;
-
- if (!p_ptr->blind)
- {
- note_spot(y, x);
- lite_spot(y, x);
- ident = TRUE;
- object_desc(o_name, i_ptr, FALSE, 0);
- if (player_has_los_bold(y1, x1))
- {
- lite_spot(y1, x1);
- msg_format("The %s suddenly stands elsewhere.", o_name);
-
- }
- else
- {
- msg_format("You suddenly don't see the %s any more!", o_name);
- }
- }
- else
- {
- msg_print("You hear something move.");
- }
- return (ident);
-}
-
-/*
- * this handles a trap that places walls around the player
- */
-static bool_ player_handle_trap_of_walls(void)
-{
- bool_ ident;
-
- s16b dx, dy, cx, cy;
- s16b sx = 0, sy = 0, sn, i;
- cave_type *cv_ptr;
- bool_ map[5][5] =
- {
- {FALSE, FALSE, FALSE, FALSE, FALSE},
- {FALSE, FALSE, FALSE, FALSE, FALSE},
- {FALSE, FALSE, FALSE, FALSE, FALSE},
- {FALSE, FALSE, FALSE, FALSE, FALSE},
- {FALSE, FALSE, FALSE, FALSE, FALSE}
- };
-
- for (dy = -2; dy <= 2; dy++)
- for (dx = -2; dx <= 2; dx++)
- {
- /* Extract the location */
- cx = p_ptr->px + dx;
- cy = p_ptr->py + dy;
-
- if (!in_bounds(cy, cx)) continue;
-
- cv_ptr = &cave[cy][cx];
-
- if (cv_ptr->m_idx) continue;
-
- /* Lose room and vault */
- cv_ptr->info &= ~(CAVE_ROOM | CAVE_ICKY);
- /* Lose light and knowledge */
- cv_ptr->info &= ~(CAVE_GLOW | CAVE_MARK);
-
- /* Skip the center */
- if (!dx && !dy) continue;
-
- /* test for dungeon level */
- if (randint(100) > 10 + max_dlv[dungeon_type]) continue;
-
- /* Damage this grid */
- map[2 + dx][2 + dy] = TRUE;
- }
-
- for (dy = -2; dy <= 2; dy++)
- for (dx = -2; dx <= 2; dx++)
- {
- /* Extract the location */
- cx = p_ptr->px + dx;
- cy = p_ptr->py + dy;
-
- /* Skip unaffected grids */
- if (!map[2 + dx][2 + dy]) continue;
-
- cv_ptr = &cave[cy][cx];
-
- if (cv_ptr->m_idx)
- {
- monster_type *m_ptr = &m_list[cv_ptr->m_idx];
- monster_race *r_ptr = race_inf(m_ptr);
-
- /* Most monsters cannot co-exist with rock */
- if ((!(r_ptr->flags2 & RF2_KILL_WALL)) &&
- (!(r_ptr->flags2 & RF2_PASS_WALL)))
- {
- char m_name[80];
-
- /* Assume not safe */
- sn = 0;
-
- /* Monster can move to escape the wall */
- if (!(r_ptr->flags1 & RF1_NEVER_MOVE))
- {
- /* Look for safety */
- for (i = 0; i < 8; i++)
- {
- /* Access the grid */
- cy = p_ptr->py + ddy[i];
- cx = p_ptr->px + ddx[i];
-
- /* Skip non-empty grids */
- if (!cave_clean_bold(cy, cx)) continue;
-
- /* Hack -- no safety on glyph of warding */
- if (cave[cy][cx].feat == FEAT_GLYPH) continue;
-
- /* Important -- Skip "quake" grids */
- if (map[2 + (cx - p_ptr->px)][2 + (cy - p_ptr->py)]) continue;
-
- /* Count "safe" grids */
- sn++;
-
- /* Randomize choice */
- if (rand_int(sn) > 0) continue;
-
- /* Save the safe grid */
- sx = cx;
- sy = cy;
-
- ident = TRUE;
-
- break; /* discontinue for loop - safe grid found */
- }
- }
-
- /* Describe the monster */
- monster_desc(m_name, m_ptr, 0);
-
- /* Scream in pain */
- msg_format("%^s wails out in pain!", m_name);
-
- /* Monster is certainly awake */
- m_ptr->csleep = 0;
-
- /* Apply damage directly */
- m_ptr->hp -= (sn ? damroll(4, 8) : 200);
-
- /* Delete (not kill) "dead" monsters */
- if (m_ptr->hp < 0)
- {
- /* Message */
- msg_format("%^s is entombed in the rock!", m_name);
-
- /* Delete the monster */
- delete_monster_idx(cave[cy][cx].m_idx);
-
- /* No longer safe */
- sn = 0;
- }
-
- /* Hack -- Escape from the rock */
- if (sn)
- {
- s16b m_idx = cave[cy][cx].m_idx;
-
- /* Update the new location */
- cave[sy][sx].m_idx = m_idx;
-
- /* Update the old location */
- cave[cy][cx].m_idx = 0;
-
- /* Move the monster */
- m_ptr->fy = sy;
- m_ptr->fx = sx;
-
- /* do not change fz */
- /* don't make rock on that square! */
- if ((sx >= (p_ptr->px - 2)) && (sx <= (p_ptr->px + 2)) &&
- (sy >= (p_ptr->py - 2)) && (sy <= (p_ptr->py + 2)))
- {
- map[2 + (sx - p_ptr->px)][2 + (sy - p_ptr->py)] = FALSE;
- }
-
- /* Update the monster (new location) */
- update_mon(m_idx, TRUE);
-
- /* Redraw the old grid */
- lite_spot(cy, cx);
-
- /* Redraw the new grid */
- lite_spot(sy, sx);
- } /* if sn */
- } /* if monster can co-exist with rock */
- } /* if monster on square */
- }
-
- /* Examine the quaked region */
- for (dy = -2; dy <= 2; dy++)
- for (dx = -2; dx <= 2; dx++)
- {
- /* Extract the location */
- cx = p_ptr->px + dx;
- cy = p_ptr->py + dy;
-
- /* Skip unaffected grids */
- if (!map[2 + dx][2 + dy]) continue;
-
- /* Access the cave grid */
- cv_ptr = &cave[cy][cx];
-
- /* Paranoia -- never affect player */
- if (!dy && !dx) continue;
-
- /* Destroy location (if valid) */
- if ((cx < cur_wid) && (cy < cur_hgt) && cave_valid_bold(cy, cx))
- {
- bool_ floor = (f_info[cave[cy][cx].feat].flags1 & FF1_FLOOR);
-
- /* Delete any object that is still there */
- delete_object(cy, cx);
-
- if (floor)
- {
- cave_set_feat(cy, cx, FEAT_WALL_OUTER);
- }
- else
- {
- /* Clear previous contents, add floor */
- cave_set_feat(cy, cx, FEAT_FLOOR);
- }
- }
- }
-
- /* Mega-Hack -- Forget the view and lite */
- p_ptr->update |= PU_UN_VIEW;
-
- /* Update stuff */
- p_ptr->update |= (PU_VIEW | PU_FLOW | PU_MON_LITE);
-
- /* Update the monsters */
- p_ptr->update |= (PU_DISTANCE);
-
- /* Update the health bar */
- p_ptr->redraw |= (PR_HEALTH);
-
- /* Redraw map */
- p_ptr->redraw |= (PR_MAP);
-
- /* Window stuff */
- p_ptr->window |= (PW_OVERHEAD);
- handle_stuff();
-
- msg_print("Suddenly the cave shifts around you. The air is getting stale!");
-
- ident = TRUE;
-
- return (ident);
-}
-
-
-/*
- * this function handles arrow & dagger traps, in various types.
- * num = number of missiles
- * tval, sval = kind of missiles
- * dd,ds = damage roll for missiles
- * poison_dam = additional poison damage
- * name = name given if you should die from it...
- *
- * return value = ident (always TRUE)
- */
-static bool_ player_handle_missile_trap(s16b num, s16b tval, s16b sval, s16b dd, s16b ds,
- s16b pdam, cptr name)
-{
- object_type *o_ptr, forge;
- s16b i, k_idx = lookup_kind(tval, sval);
- char i_name[80];
-
- o_ptr = &forge;
- object_prep(o_ptr, k_idx);
- o_ptr->number = num;
- apply_magic(o_ptr, max_dlv[dungeon_type], FALSE, FALSE, FALSE);
- object_desc(i_name, o_ptr, TRUE, 0);
-
- msg_format("Suddenly %s hit%s you!", i_name,
- ((num == 1) ? "" : "s"));
-
- for (i = 0; i < num; i++)
- {
- take_hit(damroll(dd, ds), name);
-
- redraw_stuff();
-
- if (pdam > 0)
- {
- if (!(p_ptr->resist_pois || p_ptr->oppose_pois))
- {
- (void)set_poisoned(p_ptr->poisoned + pdam);
- }
- }
- }
-
- drop_near(o_ptr, -1, p_ptr->py, p_ptr->px);
-
- return TRUE;
-}
-
-/*
- * this function handles a "breath" type trap - acid bolt, lightning balls etc.
- */
-static bool_ player_handle_breath_trap(s16b rad, s16b type, u16b trap)
-{
- trap_type *t_ptr = &t_info[trap];
- bool_ ident;
- s16b my_dd, my_ds, dam;
-
- my_dd = t_ptr->dd;
- my_ds = t_ptr->ds;
-
- /* these traps gets nastier as levels progress */
- if (max_dlv[dungeon_type] > (2 * t_ptr->minlevel))
- {
- my_dd += (max_dlv[dungeon_type] / 15);
- my_ds += (max_dlv[dungeon_type] / 15);
- }
- dam = damroll(my_dd, my_ds);
-
- ident = project( -2, rad, p_ptr->py, p_ptr->px, dam, type, PROJECT_KILL | PROJECT_JUMP);
-
- return (ident);
-}
-
-/*
- * This function damages the player by a trap
- */
-static void trap_hit(s16b trap)
-{
- s16b dam;
- trap_type *t_ptr = &t_info[trap];
-
- dam = damroll(t_ptr->dd, t_ptr->ds);
-
- take_hit(dam, t_name + t_ptr->name);
-}
-
-/*
- * this function activates one trap type, and returns
- * a bool_ indicating if this trap is now identified
- */
-bool_ player_activate_trap_type(s16b y, s16b x, object_type *i_ptr, s16b item)
-{
- bool_ ident = FALSE;
- s16b trap;
-
- s16b k, l;
-
- trap = cave[y][x].t_idx;
-
- if (i_ptr != NULL)
- {
- trap = i_ptr->pval;
- }
-
- if ((i_ptr == NULL) && (cave[y][x].o_idx != 0))
- {
- i_ptr = &o_list[cave[y][x].o_idx];
- }
-
- switch (trap)
- {
- /* stat traps */
- case TRAP_OF_WEAKNESS_I:
- ident = do_dec_stat(A_STR, STAT_DEC_TEMPORARY);
- break;
- case TRAP_OF_WEAKNESS_II:
- ident = do_dec_stat(A_STR, STAT_DEC_NORMAL);
- break;
- case TRAP_OF_WEAKNESS_III:
- ident = do_dec_stat(A_STR, STAT_DEC_PERMANENT);
- break;
- case TRAP_OF_INTELLIGENCE_I:
- ident = do_dec_stat(A_INT, STAT_DEC_TEMPORARY);
- break;
- case TRAP_OF_INTELLIGENCE_II:
- ident = do_dec_stat(A_INT, STAT_DEC_NORMAL);
- break;
- case TRAP_OF_INTELLIGENCE_III:
- ident = do_dec_stat(A_INT, STAT_DEC_PERMANENT);
- break;
- case TRAP_OF_WISDOM_I:
- ident = do_dec_stat(A_WIS, STAT_DEC_TEMPORARY);
- break;
- case TRAP_OF_WISDOM_II:
- ident = do_dec_stat(A_WIS, STAT_DEC_NORMAL);
- break;
- case TRAP_OF_WISDOM_III:
- ident = do_dec_stat(A_WIS, STAT_DEC_PERMANENT);
- break;
- case TRAP_OF_FUMBLING_I:
- ident = do_dec_stat(A_DEX, STAT_DEC_TEMPORARY);
- break;
- case TRAP_OF_FUMBLING_II:
- ident = do_dec_stat(A_DEX, STAT_DEC_NORMAL);
- break;
- case TRAP_OF_FUMBLING_III:
- ident = do_dec_stat(A_DEX, STAT_DEC_PERMANENT);
- break;
- case TRAP_OF_WASTING_I:
- ident = do_dec_stat(A_CON, STAT_DEC_TEMPORARY);
- break;
- case TRAP_OF_WASTING_II:
- ident = do_dec_stat(A_CON, STAT_DEC_NORMAL);
- break;
- case TRAP_OF_WASTING_III:
- ident = do_dec_stat(A_CON, STAT_DEC_PERMANENT);
- break;
- case TRAP_OF_BEAUTY_I:
- ident = do_dec_stat(A_CHR, STAT_DEC_TEMPORARY);
- break;
- case TRAP_OF_BEAUTY_II:
- ident = do_dec_stat(A_CHR, STAT_DEC_NORMAL);
- break;
- case TRAP_OF_BEAUTY_III:
- ident = do_dec_stat(A_CHR, STAT_DEC_PERMANENT);
- break;
-
- /* Trap of Curse Weapon */
- case TRAP_OF_CURSE_WEAPON:
- {
- ident = curse_weapon();
- break;
- }
-
- /* Trap of Curse Armor */
- case TRAP_OF_CURSE_ARMOR:
- {
- ident = curse_armor();
- break;
- }
-
- /* Earthquake Trap */
- case TRAP_OF_EARTHQUAKE:
- {
- msg_print("As you touch the trap, the ground starts to shake.");
- earthquake(y, x, 10);
- ident = TRUE;
- break;
- }
-
- /* Poison Needle Trap */
- case TRAP_OF_POISON_NEEDLE:
- {
- if (!(p_ptr->resist_pois || p_ptr->oppose_pois))
- {
- msg_print("You prick yourself on a poisoned needle.");
- (void)set_poisoned(p_ptr->poisoned + rand_int(15) + 10);
- ident = TRUE;
- }
- else
- {
- msg_print("You prick yourself on a needle.");
- }
- break;
- }
-
- /* Summon Monster Trap */
- case TRAP_OF_SUMMON_MONSTER:
- {
- msg_print("A spell hangs in the air.");
- for (k = 0; k < randint(3); k++)
- {
- ident |= summon_specific(y, x, max_dlv[dungeon_type], 0);
- }
- break;
- }
-
- /* Summon Undead Trap */
- case TRAP_OF_SUMMON_UNDEAD:
- {
- msg_print("A mighty spell hangs in the air.");
- for (k = 0; k < randint(3); k++)
- {
- ident |= summon_specific(y, x, max_dlv[dungeon_type],
- SUMMON_UNDEAD);
- }
- break;
- }
-
- /* Summon Greater Undead Trap */
- case TRAP_OF_SUMMON_GREATER_UNDEAD:
- {
- msg_print("An old and evil spell hangs in the air.");
- for (k = 0; k < randint(3); k++)
- {
- ident |= summon_specific(y, x, max_dlv[dungeon_type],
- SUMMON_HI_UNDEAD);
- }
- break;
- }
-
- /* Teleport Trap */
- case TRAP_OF_TELEPORT:
- {
- msg_print("The world whirls around you.");
- teleport_player(RATIO * 67);
- ident = TRUE;
- break;
- }
-
- /* Paralyzing Trap */
- case TRAP_OF_PARALYZING:
- {
- 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);
- ident = TRUE;
- }
- else
- {
- msg_print("You prick yourself on a needle.");
- }
- break;
- }
-
- /* Explosive Device */
- case TRAP_OF_EXPLOSIVE_DEVICE:
- {
- msg_print("A hidden explosive device explodes in your face.");
- take_hit(damroll(5, 8), "an explosion");
- ident = TRUE;
- break;
- }
-
- /* Teleport Away Trap */
- case TRAP_OF_TELEPORT_AWAY:
- {
- int item, amt;
- object_type *o_ptr;
-
- /* teleport away all items */
- while (cave[y][x].o_idx != 0)
- {
- item = cave[y][x].o_idx;
-
- o_ptr = &o_list[item];
-
- amt = o_ptr->number;
-
- ident = do_trap_teleport_away(o_ptr, y, x);
-
- floor_item_increase(item, -amt);
- floor_item_optimize(item);
- }
- break;
- }
-
- /* Lose Memory Trap */
- case TRAP_OF_LOSE_MEMORY:
- {
- lose_exp(p_ptr->exp / 4);
-
- ident |= dec_stat(A_WIS, rand_int(20) + 10, STAT_DEC_NORMAL);
- ident |= dec_stat(A_INT, rand_int(20) + 10, STAT_DEC_NORMAL);
-
- if (!p_ptr->resist_conf)
- {
- ident |= set_confused(p_ptr->confused + rand_int(100) + 50);
- }
-
- if (ident)
- {
- msg_print("You suddenly don't remember what you were doing.");
- }
- else
- {
- msg_print("You feel an alien force probing your mind.");
- }
- break;
- }
- /* Bitter Regret Trap */
- case TRAP_OF_BITTER_REGRET:
- {
- msg_print("An age-old and hideous-sounding spell reverberates off the walls.");
-
- ident |= dec_stat(A_DEX, 25, TRUE);
- ident |= dec_stat(A_WIS, 25, TRUE);
- ident |= dec_stat(A_CON, 25, TRUE);
- ident |= dec_stat(A_STR, 25, TRUE);
- ident |= dec_stat(A_CHR, 25, TRUE);
- ident |= dec_stat(A_INT, 25, TRUE);
- break;
- }
-
- /* Bowel Cramps Trap */
- case TRAP_OF_BOWEL_CRAMPS:
- {
- msg_print("A wretched-smelling gas cloud upsets your stomach.");
-
- (void)set_food(PY_FOOD_STARVE - 1);
- (void)set_poisoned(0);
-
- if (!p_ptr->free_act)
- {
- (void)set_paralyzed(p_ptr->paralyzed + rand_int(dun_level) + 6);
- }
- ident = TRUE;
- break;
- }
-
- /* Blindness/Confusion Trap */
- case TRAP_OF_BLINDNESS_CONFUSION:
- {
- msg_print("A powerful magic protected this.");
-
- if (!p_ptr->resist_blind)
- {
- ident |= set_blind(p_ptr->blind + rand_int(100) + 100);
- }
- if (!p_ptr->resist_conf)
- {
- ident |= set_confused(p_ptr->confused + rand_int(20) + 15);
- }
- break;
- }
-
- /* Aggravation Trap */
- case TRAP_OF_AGGRAVATION:
- {
- msg_print("You hear a hollow noise echoing through the dungeons.");
- aggravate_monsters(1);
- break;
- }
-
- /* Multiplication Trap */
- case TRAP_OF_MULTIPLICATION:
- {
- msg_print("You hear a loud click.");
- for (k = -1; k <= 1; k++)
- for (l = -1; l <= 1; l++)
- {
- if ((in_bounds(p_ptr->py + l, p_ptr->px + k)) &&
- (!cave[p_ptr->py + l][p_ptr->px + k].t_idx))
- {
- place_trap(p_ptr->py + l, p_ptr->px + k);
- }
- }
- ident = TRUE;
- break;
- }
-
- /* Steal Item Trap */
- case TRAP_OF_STEAL_ITEM:
- {
- /*
- * please note that magical stealing is not so
- * easily circumvented
- */
- if (!p_ptr->paralyzed &&
- (rand_int(160) < (adj_dex_safe[p_ptr->stat_ind[A_DEX]] +
- p_ptr->lev)))
- {
- /* Saving throw message */
- msg_print("Your backpack seems to vibrate strangely!");
- break;
- }
-
- /* Find an item */
- for (k = 0; k < rand_int(10); k++)
- {
- char i_name[80];
- object_type *j_ptr, *q_ptr, forge;
-
- /* Pick an item */
- s16b i = rand_int(INVEN_PACK);
-
- /* Obtain the item */
- j_ptr = &p_ptr->inventory[i];
-
- /* Accept real items */
- if (!j_ptr->k_idx) continue;
-
- /* Don't steal artifacts -CFT */
- if (artifact_p(j_ptr)) continue;
-
- /* Get a description */
- object_desc(i_name, j_ptr, FALSE, 3);
-
- /* Message */
- msg_format("%sour %s (%c) was stolen!",
- ((j_ptr->number > 1) ? "One of y" : "Y"),
- i_name, index_to_label(i));
-
- /* Create the item */
- q_ptr = &forge;
- object_copy(q_ptr, j_ptr);
- q_ptr->number = 1;
-
- /* Drop it somewhere */
- do_trap_teleport_away(q_ptr, y, x);
-
- inc_stack_size_ex(i, -1, OPTIMIZE, NO_DESCRIBE);
-
- ident = TRUE;
- }
- break;
- }
-
- /* Summon Fast Quylthulgs Trap */
- case TRAP_OF_SUMMON_FAST_QUYLTHULGS:
- {
- for (k = 0; k < randint(3); k++)
- {
- ident |= summon_specific(y, x, max_dlv[dungeon_type], SUMMON_QUYLTHULG);
- }
-
- if (ident)
- {
- msg_print("You suddenly have company.");
- (void)set_slow(p_ptr->slow + randint(25) + 15);
- }
- break;
- }
-
- /* Trap of Sinking */
- case TRAP_OF_SINKING:
- {
- msg_print("You fell through a trap door!");
-
- if (p_ptr->ffall)
- {
- if (dungeon_flags1 & DF1_TOWER)
- {
- msg_print("You float gently down to the previous level.");
- }
- else
- {
- msg_print("You float gently down to the next level.");
- }
- }
- else
- {
- take_hit(damroll(2, 8), "a trap door");
- }
-
- /* Still alive and autosave enabled */
- if (p_ptr->chp >= 0)
- {
- autosave_checkpoint();
- }
-
- if (dungeon_flags1 & DF1_TOWER) dun_level--;
- else dun_level++;
-
- /* Leaving */
- p_ptr->leaving = TRUE;
- break;
- }
-
- /* Trap of Mana Drain */
- case TRAP_OF_MANA_DRAIN:
- {
- if (p_ptr->csp > 0)
- {
- p_ptr->csp = 0;
- p_ptr->csp_frac = 0;
- p_ptr->redraw |= (PR_MANA);
- msg_print("You sense a great loss.");
- ident = TRUE;
- }
- else if (p_ptr->msp == 0)
- {
- /* no sense saying this unless you never have mana */
- msg_format("Suddenly you feel glad you're a mere %s",
- spp_ptr->title + c_name);
- }
- else
- {
- msg_print("Your head feels dizzy for a moment.");
- }
- break;
- }
- /* Trap of Missing Money */
- case TRAP_OF_MISSING_MONEY:
- {
- s32b gold = (p_ptr->au / 10) + randint(25);
-
- if (gold < 2) gold = 2;
- if (gold > 5000) gold = (p_ptr->au / 20) + randint(3000);
- if (gold > p_ptr->au) gold = p_ptr->au;
-
- p_ptr->au -= gold;
- if (gold <= 0)
- {
- msg_print("You feel something touching you.");
- }
- else if (p_ptr->au)
- {
- msg_print("Your purse feels lighter.");
- msg_format("%ld coins were stolen!", (long)gold);
- ident = TRUE;
- }
- else
- {
- msg_print("Your purse feels empty.");
- msg_print("All of your coins were stolen!");
- ident = TRUE;
- }
- p_ptr->redraw |= (PR_GOLD);
- break;
- }
-
- /* Trap of No Return */
- case TRAP_OF_NO_RETURN:
- {
- object_type *j_ptr;
- s16b j;
-
- for (j = 0; j < INVEN_WIELD; j++)
- {
- if (!p_ptr->inventory[j].k_idx) continue;
-
- j_ptr = &p_ptr->inventory[j];
-
- if ((j_ptr->tval == TV_SCROLL) &&
- (j_ptr->sval == SV_SCROLL_WORD_OF_RECALL))
- {
- inc_stack_size_ex(j, -j_ptr->number, OPTIMIZE, NO_DESCRIBE);
-
- combine_pack();
- reorder_pack();
-
- if (!ident)
- {
- msg_print("A small fire works its way through your backpack. "
- "Some scrolls are burnt.");
- }
- else
- {
- msg_print("The fire hasn't finished.");
- }
- ident = TRUE;
- }
- else if ((j_ptr->tval == TV_ROD_MAIN) &&
- (j_ptr->pval == SV_ROD_RECALL))
- {
- j_ptr->timeout = 0; /* a long time */
- if (!ident) msg_print("You feel the air stabilise around you.");
- ident = TRUE;
- }
- }
- if ((!ident) && (p_ptr->word_recall))
- {
- msg_print("You feel like staying around.");
- p_ptr->word_recall = 0;
- ident = TRUE;
- }
- break;
- }
-
- /* Trap of Silent Switching */
- case TRAP_OF_SILENT_SWITCHING:
- {
- s16b i, j, slot1, slot2;
- object_type *j_ptr, *k_ptr;
- u32b f1, f2, f3, f4, f5, esp;
-
- for (i = INVEN_WIELD; i < INVEN_TOTAL; i++)
- {
- j_ptr = &p_ptr->inventory[i];
-
- if (!j_ptr->k_idx) continue;
-
- /* Do not allow this trap to touch the One Ring */
- object_flags(j_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
- if(f3 & TR3_PERMA_CURSE) continue;
-
- slot1 = wield_slot(j_ptr);
-
- for (j = 0; j < INVEN_WIELD; j++)
- {
- k_ptr = &p_ptr->inventory[j];
-
- if (!k_ptr->k_idx) continue;
-
- /* Do not allow this trap to touch the One Ring */
- object_flags(k_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
- if(f3 & TR3_PERMA_CURSE) continue;
-
- /* this is a crude hack, but it prevent wielding 6 torches... */
- if (k_ptr->number > 1) continue;
-
- slot2 = wield_slot(k_ptr);
-
- /* a chance of 4 in 5 of switching something, then 2 in 5 to do it again */
- if ((slot1 == slot2) &&
- (rand_int(100) < (80 - (ident * 40))))
- {
- object_type tmp_obj;
-
- if (p_ptr->inventory[j].name1)
- wield_set(p_ptr->inventory[j].name1, a_info[p_ptr->inventory[j].name1].set, FALSE);
- if (p_ptr->inventory[i].name1)
- takeoff_set(p_ptr->inventory[i].name1, a_info[p_ptr->inventory[i].name1].set);
-
- tmp_obj = p_ptr->inventory[j];
- p_ptr->inventory[j] = p_ptr->inventory[i];
- p_ptr->inventory[i] = tmp_obj;
- ident = TRUE;
- }
- }
- }
-
- if (ident)
- {
- p_ptr->update |= (PU_BONUS);
- p_ptr->update |= (PU_TORCH);
- p_ptr->update |= (PU_MANA);
- msg_print("You somehow feel like another person.");
- }
- else
- {
- msg_print("You feel a lack of useful items.");
- }
- break;
- }
-
- /* Trap of Walls */
- case TRAP_OF_WALLS:
- {
- ident = player_handle_trap_of_walls();
- break;
- }
-
- /* Trap of Calling Out */
- case TRAP_OF_CALLING_OUT:
- {
- ident = do_player_trap_call_out();
-
- if (!ident)
- {
- /* Increase "afraid" */
- if (p_ptr->resist_fear)
- {
- msg_print("You feel as if you had a nightmare!");
- }
- else if (rand_int(100) < p_ptr->skill_sav)
- {
- msg_print("You remember having a nightmare!");
- }
- else
- {
- if (set_afraid(p_ptr->afraid + 3 + randint(40)))
- {
- msg_print("You have a vision of a powerful enemy.");
- }
- }
- }
- break;
- }
-
- /* Trap of Sliding */
- case TRAP_OF_SLIDING:
- break;
-
- /* Trap of Charges Drain */
- case TRAP_OF_CHARGES_DRAIN:
- {
- /* Find an item */
- for (k = 0; k < 10; k++)
- {
- s16b i = rand_int(INVEN_PACK);
-
- object_type *j_ptr = &p_ptr->inventory[i];
-
- /* Drain charged wands/staffs
- Hack -- don't let artifacts get drained */
- if (((j_ptr->tval == TV_STAFF) ||
- (j_ptr->tval == TV_WAND)) &&
- (j_ptr->pval) &&
- !artifact_p(j_ptr))
- {
- ident = TRUE;
- j_ptr->pval = j_ptr->pval / (randint(4) + 1);
-
- /* 60% chance of only 1 */
- if (randint(10) > 3) break;
- }
- }
-
- if (ident)
- {
- /* Window stuff */
- p_ptr->window |= PW_INVEN;
- /* Combine / Reorder the pack */
- p_ptr->notice |= (PN_COMBINE | PN_REORDER);
-
- msg_print("Your backpack seems to be turned upside down.");
- }
- else
- {
- msg_print("You hear a wail of great disappointment.");
- }
- break;
- }
-
- /* Trap of Stair Movement */
- case TRAP_OF_STAIR_MOVEMENT:
- {
- s16b cx, cy, i, j;
- s16b cnt = 0;
- s16b cnt_seen = 0;
- s16b tmps, tmpx;
- s16b tmpspecial, tmpspecial2;
- u32b tmpf;
- bool_ seen = FALSE;
- s16b index_x[20], index_y[20]; /* 20 stairs per level is enough? */
- cave_type *cv_ptr;
-
- if (max_dlv[dungeon_type] == 99)
- {
- /* no sense in relocating that stair! */
- msg_print("You have a feeling that this trap could be dangerous.");
- break;
- }
-
- for (cx = 0; cx < cur_wid; cx++)
- for (cy = 0; cy < cur_hgt; cy++)
- {
- cv_ptr = &cave[cy][cx];
-
- if ((cv_ptr->feat != FEAT_LESS) &&
- (cv_ptr->feat != FEAT_MORE) &&
- (cv_ptr->feat != FEAT_SHAFT_UP) &&
- (cv_ptr->feat != FEAT_SHAFT_DOWN)) continue;
-
- index_x[cnt] = cx;
- index_y[cnt] = cy;
- cnt++;
- }
-
- if (cnt == 0)
- {
- if (wizard) msg_print("Executing moving stairs trap on level with no stairs!");
- break;
- }
-
- for (i = 0; i < cnt; i++)
- {
- seen = FALSE;
-
- for (j = 0; j < 10; j++) /* try 10 times to relocate */
- {
- cave_type *cv_ptr = &cave[index_y[i]][index_x[i]];
- cave_type *cv_ptr2;
-
- cx = rand_int(cur_wid);
- cy = rand_int(cur_hgt);
-
- if ((cx == index_x[i]) || (cy == index_y[i])) continue;
-
- cv_ptr2 = &cave[cy][cx];
-
- if (!cave_valid_bold(cy, cx) || cv_ptr2->o_idx != 0) continue;
-
- /* don't put anything in vaults */
- if (cv_ptr2->info & CAVE_ICKY) continue;
-
- tmpx = cv_ptr2->mimic;
- tmps = cv_ptr2->info;
- tmpf = cv_ptr2->feat;
- tmpspecial = cv_ptr2->special;
- tmpspecial2 = cv_ptr2->special2;
- cave[cy][cx].mimic = cv_ptr->mimic;
- cave[cy][cx].info = cv_ptr->info;
- cave[cy][cx].special = cv_ptr->special;
- cave[cy][cx].special2 = cv_ptr->special2;
- cave_set_feat(cy, cx, cv_ptr->feat);
- cv_ptr->mimic = tmpx;
- cv_ptr->info = tmps;
- cv_ptr->special = tmpspecial;
- cv_ptr->special2 = tmpspecial2;
- cave_set_feat(index_y[i], index_x[i], tmpf);
-
- /* if we are placing walls in rooms, make them rubble instead */
- if ((cv_ptr->info & CAVE_ROOM) &&
- (cv_ptr->feat >= FEAT_WALL_EXTRA) &&
- (cv_ptr->feat <= FEAT_PERM_SOLID))
- {
- cave_set_feat(index_y[i], index_x[i], FEAT_RUBBLE);
- }
-
- if (player_has_los_bold(cy, cx))
- {
- note_spot(cy, cx);
- lite_spot(cy, cx);
- seen = TRUE;
- }
- else
- {
- cv_ptr2->info &= ~CAVE_MARK;
- }
-
- if (player_has_los_bold(index_y[i], index_x[i]))
- {
- note_spot(index_y[i], index_x[i]);
- lite_spot(index_y[i], index_x[i]);
- seen = TRUE;
- }
- else
- {
- cv_ptr->info &= ~CAVE_MARK;
- }
- break;
- }
-
- if (seen) cnt_seen++;
- }
-
- ident = (cnt_seen > 0);
-
- if ((ident) && (cnt_seen > 1))
- {
- msg_print("You see some stairs move.");
- }
- else if (ident)
- {
- msg_print("You see a stair move.");
- }
- else
- {
- msg_print("You hear distant scraping noises.");
- }
- p_ptr->redraw |= PR_MAP;
- break;
- }
-
- /* Trap of New Trap */
- case TRAP_OF_NEW:
- {
- /* if we're on a floor or on a door, place a new trap */
- if ((item == -1) || (item == -2))
- {
- place_trap(y, x);
- if (player_has_los_bold(y, x))
- {
- note_spot(y, x);
- lite_spot(y, x);
- }
- }
- else
- {
- /* re-trap the chest */
- place_trap(y, x);
- }
- msg_print("You hear a noise, and then its echo.");
- ident = FALSE;
- break;
- }
-
- /* Trap of Acquirement */
- case TRAP_OF_ACQUIREMENT:
- {
- /* Get a nice thing */
- msg_print("You notice something falling off the trap.");
- acquirement(y, x, 1, TRUE, FALSE);
-
- /* If we're on a floor or on a door, place a new trap */
- if ((item == -1) || (item == -2))
- {
- place_trap(y, x);
- if (player_has_los_bold(y, x))
- {
- note_spot(y, x);
- lite_spot(y, x);
- }
- }
- else
- {
- /* Re-trap the chest */
- place_trap(y, x);
- }
- msg_print("You hear a noise, and then its echo.");
-
- /* Never known */
- ident = FALSE;
- }
- break;
-
- /* Trap of Scatter Items */
- case TRAP_OF_SCATTER_ITEMS:
- {
- s16b i, j;
- bool_ message = FALSE;
-
- for (i = 0; i < INVEN_PACK; i++)
- {
-
- if (!p_ptr->inventory[i].k_idx) continue;
-
- if (rand_int(10) < 3) continue;
-
- for (j = 0; j < 10; j++)
- {
- object_type tmp_obj, *j_ptr = &tmp_obj;
- s16b cx = x + 15 - rand_int(30);
- s16b cy = y + 15 - rand_int(30);
-
- if (!in_bounds(cy, cx)) continue;
-
- if (!cave_floor_bold(cy, cx)) continue;
-
- object_copy(j_ptr, &p_ptr->inventory[i]);
-
- inc_stack_size_ex(i, -999, OPTIMIZE, NO_DESCRIBE);
-
- p_ptr->notice |= (PN_COMBINE | PN_REORDER);
-
- (void)floor_carry(cy, cx, j_ptr);
-
- if (!message)
- {
- msg_print("You feel light-footed.");
- message = TRUE;
- }
-
- if (player_has_los_bold(cy, cx))
- {
- char i_name[80];
-
- object_desc(i_name, &tmp_obj, TRUE, 3);
- note_spot(cy, cx);
- lite_spot(cy, cx);
- ident = TRUE;
- msg_format("Suddenly %s appear%s!", i_name,
- (j_ptr->number > 1) ? "" : "s");
- }
- break;
- }
- }
- ident = message;
- break;
- }
-
- /* Trap of Decay */
- case TRAP_OF_DECAY:
- break;
-
- /* Trap of Wasting Wands */
- case TRAP_OF_WASTING_WANDS:
- {
- s16b i;
- object_type *j_ptr;
-
- for (i = 0; i < INVEN_PACK; i++)
- {
- if (!p_ptr->inventory[i].k_idx) continue;
-
- j_ptr = &p_ptr->inventory[i];
-
- if ((j_ptr->tval == TV_WAND) && (rand_int(5) == 1))
- {
- if (object_known_p(j_ptr)) ident = TRUE;
-
- /* Create a Wand of Nothing */
- object_prep(j_ptr, lookup_kind(TV_WAND, SV_WAND_NOTHING));
- hack_apply_magic_power = -99;
- apply_magic(j_ptr, 0, FALSE, FALSE, FALSE);
- j_ptr->ident &= ~IDENT_KNOWN;
- p_ptr->notice |= (PN_COMBINE | PN_REORDER);
- }
- else if ((j_ptr->tval == TV_STAFF) && (rand_int(5) == 1))
- {
- if (object_known_p(j_ptr)) ident = TRUE;
-
- /* Create a Staff of Nothing */
- object_prep(j_ptr, lookup_kind(TV_STAFF, SV_STAFF_NOTHING));
- hack_apply_magic_power = -99;
- apply_magic(j_ptr, 0, FALSE, FALSE, FALSE);
- j_ptr->ident &= ~IDENT_KNOWN;
- p_ptr->notice |= (PN_COMBINE | PN_REORDER);
- }
- }
- if (ident)
- {
- msg_print("You have lost trust in your backpack!");
- }
- else
- {
- msg_print("You hear an echoing cry of rage.");
- }
- break;
- }
-
- /* Trap of Filling */
- case TRAP_OF_FILLING:
- {
- s16b nx, ny;
-
- for (nx = x - 8; nx <= x + 8; nx++)
- for (ny = y - 8; ny <= y + 8; ny++)
- {
- if (!in_bounds (ny, nx)) continue;
-
- if (rand_int(distance(ny, nx, y, x)) > 3)
- {
- place_trap(ny, nx);
- }
- }
-
- msg_print("The floor vibrates in a strange way.");
- ident = FALSE;
- break;
- }
-
- case TRAP_OF_DRAIN_SPEED:
- {
- object_type *j_ptr;
- s16b j, chance = 75;
- u32b f1, f2, f3, f4, f5, esp;
-
- for (j = 0; j < INVEN_TOTAL; j++)
- {
- /* don't bother the overflow slot */
- if (j == INVEN_PACK) continue;
-
- if (!p_ptr->inventory[j].k_idx) continue;
-
- j_ptr = &p_ptr->inventory[j];
- object_flags(j_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
-
- /* is it a non-artifact speed item? */
- if ((!j_ptr->name1) && (f1 & TR1_SPEED))
- {
- if (randint(100) < chance)
- {
- j_ptr->pval = j_ptr->pval / 2;
- if (j_ptr->pval == 0)
- {
- j_ptr->pval--;
- }
- chance /= 2;
- ident = TRUE;
- }
- inven_item_optimize(j);
- }
- }
- if (!ident)
- {
- msg_print("You feel some things in your pack vibrating.");
- }
- else
- {
- combine_pack();
- reorder_pack();
- msg_print("You suddenly feel you have time for self-reflection.");
-
- /* 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);
- }
- break;
- }
-
- /*
- * single missile traps
- */
- case TRAP_OF_ARROW_I:
- ident = player_handle_missile_trap(1, TV_ARROW, SV_AMMO_NORMAL, 4, 8, 0, "Arrow Trap");
- break;
- case TRAP_OF_ARROW_II:
- ident = player_handle_missile_trap(1, TV_BOLT, SV_AMMO_NORMAL, 5, 8, 0, "Bolt Trap");
- break;
- case TRAP_OF_ARROW_III:
- ident = player_handle_missile_trap(1, TV_ARROW, SV_AMMO_HEAVY, 6, 8, 0, "Seeker Arrow Trap");
- break;
- case TRAP_OF_ARROW_IV:
- ident = player_handle_missile_trap(1, TV_BOLT, SV_AMMO_HEAVY, 8, 10, 0, "Seeker Bolt Trap");
- break;
- case TRAP_OF_POISON_ARROW_I:
- ident = player_handle_missile_trap(1, TV_ARROW, SV_AMMO_NORMAL, 4, 8, 10 + randint(20), "Poison Arrow Trap");
- break;
- case TRAP_OF_POISON_ARROW_II:
- ident = player_handle_missile_trap(1, TV_BOLT, SV_AMMO_NORMAL, 5, 8, 15 + randint(30), "Poison Bolt Trap");
- break;
- case TRAP_OF_POISON_ARROW_III:
- ident = player_handle_missile_trap(1, TV_ARROW, SV_AMMO_HEAVY, 6, 8, 30 + randint(50), "Poison Seeker Arrow Trap");
- break;
- case TRAP_OF_POISON_ARROW_IV:
- ident = player_handle_missile_trap(1, TV_BOLT, SV_AMMO_HEAVY, 8, 10, 40 + randint(70), "Poison Seeker Bolt Trap");
- break;
- case TRAP_OF_DAGGER_I:
- ident = player_handle_missile_trap(1, TV_SWORD, SV_BROKEN_DAGGER, 2, 8, 0, "Dagger Trap");
- break;
- case TRAP_OF_DAGGER_II:
- ident = player_handle_missile_trap(1, TV_SWORD, SV_DAGGER, 3, 8, 0, "Dagger Trap");
- break;
- case TRAP_OF_POISON_DAGGER_I:
- ident = player_handle_missile_trap(1, TV_SWORD, SV_BROKEN_DAGGER, 2, 8, 15 + randint(20), "Poison Dagger Trap");
- break;
- case TRAP_OF_POISON_DAGGER_II:
- ident = player_handle_missile_trap(1, TV_SWORD, SV_DAGGER, 3, 8, 20 + randint(30), "Poison Dagger Trap");
- break;
-
- /*
- * multiple missile traps
- * numbers range from 2 (level 0 to 14) to 10 (level 120 and up)
- */
- case TRAP_OF_ARROWS_I:
- ident = player_handle_missile_trap(2 + (max_dlv[dungeon_type] / 15), TV_ARROW, SV_AMMO_NORMAL, 4, 8, 0, "Arrow Trap");
- break;
- case TRAP_OF_ARROWS_II:
- ident = player_handle_missile_trap(2 + (max_dlv[dungeon_type] / 15), TV_BOLT, SV_AMMO_NORMAL, 5, 8, 0, "Bolt Trap");
- break;
- case TRAP_OF_ARROWS_III:
- ident = player_handle_missile_trap(2 + (max_dlv[dungeon_type] / 15), TV_ARROW, SV_AMMO_HEAVY, 6, 8, 0, "Seeker Arrow Trap");
- break;
- case TRAP_OF_ARROWS_IV:
- ident = player_handle_missile_trap(2 + (max_dlv[dungeon_type] / 15), TV_BOLT, SV_AMMO_HEAVY, 8, 10, 0, "Seeker Bolt Trap");
- break;
- case TRAP_OF_POISON_ARROWS_I:
- ident = player_handle_missile_trap(2 + (max_dlv[dungeon_type] / 15), TV_ARROW, SV_AMMO_NORMAL, 4, 8, 10 + randint(20), "Poison Arrow Trap");
- break;
- case TRAP_OF_POISON_ARROWS_II:
- ident = player_handle_missile_trap(2 + (max_dlv[dungeon_type] / 15), TV_BOLT, SV_AMMO_NORMAL, 5, 8, 15 + randint(30), "Poison Bolt Trap");
- break;
- case TRAP_OF_POISON_ARROWS_III:
- ident = player_handle_missile_trap(2 + (max_dlv[dungeon_type] / 15), TV_ARROW, SV_AMMO_HEAVY, 6, 8, 30 + randint(50), "Poison Seeker Arrow Trap");
- break;
- case TRAP_OF_POISON_ARROWS_IV:
- ident = player_handle_missile_trap(2 + (max_dlv[dungeon_type] / 15), TV_BOLT, SV_AMMO_HEAVY, 8, 10, 40 + randint(70), "Poison Seeker Bolt Trap");
- break;
- case TRAP_OF_DAGGERS_I:
- ident = player_handle_missile_trap(2 + (max_dlv[dungeon_type] / 15), TV_SWORD, SV_BROKEN_DAGGER, 2, 8, 0, "Dagger Trap");
- break;
- case TRAP_OF_DAGGERS_II:
- ident = player_handle_missile_trap(2 + (max_dlv[dungeon_type] / 15), TV_SWORD, SV_DAGGER, 3, 8, 0, "Dagger Trap");
- break;
- case TRAP_OF_POISON_DAGGERS_I:
- ident = player_handle_missile_trap(2 + (max_dlv[dungeon_type] / 15), TV_SWORD, SV_BROKEN_DAGGER, 2, 8, 15 + randint(20), "Poison Dagger Trap");
- break;
- case TRAP_OF_POISON_DAGGERS_II:
- ident = player_handle_missile_trap(2 + (max_dlv[dungeon_type] / 15), TV_SWORD, SV_DAGGER, 3, 8, 20 + randint(30), "Poison Dagger Trap");
- break;
-
- case TRAP_OF_DROP_ITEMS:
- {
- s16b i;
- bool_ message = FALSE;
-
- for (i = 0; i < INVEN_PACK; i++)
- {
- object_type tmp_obj;
-
- if (!p_ptr->inventory[i].k_idx) continue;
- if (randint(100) < 80) continue;
- if (p_ptr->inventory[i].name1 == ART_POWER) continue;
-
- tmp_obj = p_ptr->inventory[i];
-
- /* drop carefully */
- drop_near(&tmp_obj, 0, y, x);
-
- inc_stack_size_ex(i, -999, OPTIMIZE, NO_DESCRIBE);
-
- p_ptr->notice |= (PN_COMBINE | PN_REORDER);
-
- if (!message)
- {
- msg_print("You are startled by a sudden sound.");
- message = TRUE;
- }
- ident = TRUE;
- }
- if (!ident)
- {
- msg_print("You hear a sudden, strange sound.");
- }
- break;
- }
-
- case TRAP_OF_DROP_ALL_ITEMS:
- {
- s16b i;
- bool_ message = FALSE;
-
- for (i = 0; i < INVEN_PACK; i++)
- {
- object_type tmp_obj;
-
- if (!p_ptr->inventory[i].k_idx) continue;
- if (randint(100) < 10) continue;
- if (p_ptr->inventory[i].name1 == ART_POWER) continue;
-
- tmp_obj = p_ptr->inventory[i];
-
- /* drop carefully */
- drop_near(&tmp_obj, 0, y, x);
-
- inc_stack_size_ex(i, -999, OPTIMIZE, NO_DESCRIBE);
-
- p_ptr->notice |= (PN_COMBINE | PN_REORDER);
-
- if (!message)
- {
- msg_print("You are greatly startled by a sudden sound.");
- message = TRUE;
- }
- ident = TRUE;
- }
- if (!ident)
- {
- msg_print("You hear a sudden, strange sound.");
- }
- break;
- }
-
- case TRAP_OF_DROP_EVERYTHING:
- {
- s16b i;
- bool_ message = FALSE;
-
- for (i = 0; i < INVEN_TOTAL; i++)
- {
- object_type tmp_obj;
- if (!p_ptr->inventory[i].k_idx) continue;
- if (randint(100) < 30) continue;
- if (p_ptr->inventory[i].name1 == ART_POWER) continue;
-
- tmp_obj = p_ptr->inventory[i];
- /* drop carefully */
-
- drop_near(&tmp_obj, 0, y, x);
-
- inc_stack_size_ex(i, -999, OPTIMIZE, NO_DESCRIBE);
-
- p_ptr->notice |= (PN_COMBINE | PN_REORDER);
-
- if (!message)
- {
- msg_print("You are completely startled by a sudden sound.");
- message = TRUE;
- }
- ident = TRUE;
- }
- if (!ident)
- {
- msg_print("You hear a sudden, strange sound.");
- }
- break;
- }
-
- /* Bolt Trap */
- case TRAP_G_ELEC_BOLT:
- ident = player_handle_breath_trap(1, GF_ELEC, TRAP_G_ELEC_BOLT);
- break;
- case TRAP_G_POIS_BOLT:
- ident = player_handle_breath_trap(1, GF_POIS, TRAP_G_POIS_BOLT);
- break;
- case TRAP_G_ACID_BOLT:
- ident = player_handle_breath_trap(1, GF_ACID, TRAP_G_ACID_BOLT);
- break;
- case TRAP_G_COLD_BOLT:
- ident = player_handle_breath_trap(1, GF_COLD, TRAP_G_COLD_BOLT);
- break;
- case TRAP_G_FIRE_BOLT:
- ident = player_handle_breath_trap(1, GF_FIRE, TRAP_G_FIRE_BOLT);
- break;
- case TRAP_OF_ELEC_BOLT:
- ident = player_handle_breath_trap(1, GF_ELEC, TRAP_OF_ELEC_BOLT);
- break;
- case TRAP_OF_POIS_BOLT:
- ident = player_handle_breath_trap(1, GF_POIS, TRAP_OF_POIS_BOLT);
- break;
- case TRAP_OF_ACID_BOLT:
- ident = player_handle_breath_trap(1, GF_ACID, TRAP_OF_ACID_BOLT);
- break;
- case TRAP_OF_COLD_BOLT:
- ident = player_handle_breath_trap(1, GF_COLD, TRAP_OF_COLD_BOLT);
- break;
- case TRAP_OF_FIRE_BOLT:
- ident = player_handle_breath_trap(1, GF_FIRE, TRAP_OF_FIRE_BOLT);
- break;
- case TRAP_OF_PLASMA_BOLT:
- ident = player_handle_breath_trap(1, GF_PLASMA, TRAP_OF_PLASMA_BOLT);
- break;
- case TRAP_OF_WATER_BOLT:
- ident = player_handle_breath_trap(1, GF_WATER, TRAP_OF_WATER_BOLT);
- break;
- case TRAP_OF_LITE_BOLT:
- ident = player_handle_breath_trap(1, GF_LITE, TRAP_OF_LITE_BOLT);
- break;
- case TRAP_OF_DARK_BOLT:
- ident = player_handle_breath_trap(1, GF_DARK, TRAP_OF_DARK_BOLT);
- break;
- case TRAP_OF_SHARDS_BOLT:
- ident = player_handle_breath_trap(1, GF_SHARDS, TRAP_OF_SHARDS_BOLT);
- break;
- case TRAP_OF_SOUND_BOLT:
- ident = player_handle_breath_trap(1, GF_SOUND, TRAP_OF_SOUND_BOLT);
- break;
- case TRAP_OF_CONFUSION_BOLT:
- ident = player_handle_breath_trap(1, GF_CONFUSION, TRAP_OF_CONFUSION_BOLT);
- break;
- case TRAP_OF_FORCE_BOLT:
- ident = player_handle_breath_trap(1, GF_FORCE, TRAP_OF_FORCE_BOLT);
- break;
- case TRAP_OF_INERTIA_BOLT:
- ident = player_handle_breath_trap(1, GF_INERTIA, TRAP_OF_INERTIA_BOLT);
- break;
- case TRAP_OF_MANA_BOLT:
- ident = player_handle_breath_trap(1, GF_MANA, TRAP_OF_MANA_BOLT);
- break;
- case TRAP_OF_ICE_BOLT:
- ident = player_handle_breath_trap(1, GF_ICE, TRAP_OF_ICE_BOLT);
- break;
- case TRAP_OF_CHAOS_BOLT:
- ident = player_handle_breath_trap(1, GF_CHAOS, TRAP_OF_CHAOS_BOLT);
- break;
- case TRAP_OF_NETHER_BOLT:
- ident = player_handle_breath_trap(1, GF_NETHER, TRAP_OF_NETHER_BOLT);
- break;
- case TRAP_OF_DISENCHANT_BOLT:
- ident = player_handle_breath_trap(1, GF_DISENCHANT, TRAP_OF_DISENCHANT_BOLT);
- break;
- case TRAP_OF_NEXUS_BOLT:
- ident = player_handle_breath_trap(1, GF_NEXUS, TRAP_OF_NEXUS_BOLT);
- break;
- case TRAP_OF_TIME_BOLT:
- ident = player_handle_breath_trap(1, GF_TIME, TRAP_OF_TIME_BOLT);
- break;
- case TRAP_OF_GRAVITY_BOLT:
- ident = player_handle_breath_trap(1, GF_GRAVITY, TRAP_OF_GRAVITY_BOLT);
- break;
-
- /* Ball Trap */
- case TRAP_OF_ELEC_BALL:
- ident = player_handle_breath_trap(3, GF_ELEC, TRAP_OF_ELEC_BALL);
- break;
- case TRAP_OF_POIS_BALL:
- ident = player_handle_breath_trap(3, GF_POIS, TRAP_OF_POIS_BALL);
- break;
- case TRAP_OF_ACID_BALL:
- ident = player_handle_breath_trap(3, GF_ACID, TRAP_OF_ACID_BALL);
- break;
- case TRAP_OF_COLD_BALL:
- ident = player_handle_breath_trap(3, GF_COLD, TRAP_OF_COLD_BALL);
- break;
- case TRAP_OF_FIRE_BALL:
- ident = player_handle_breath_trap(3, GF_FIRE, TRAP_OF_FIRE_BALL);
- break;
- case TRAP_OF_PLASMA_BALL:
- ident = player_handle_breath_trap(3, GF_PLASMA, TRAP_OF_PLASMA_BALL);
- break;
- case TRAP_OF_WATER_BALL:
- ident = player_handle_breath_trap(3, GF_WATER, TRAP_OF_WATER_BALL);
- break;
- case TRAP_OF_LITE_BALL:
- ident = player_handle_breath_trap(3, GF_LITE, TRAP_OF_LITE_BALL);
- break;
- case TRAP_OF_DARK_BALL:
- ident = player_handle_breath_trap(3, GF_DARK, TRAP_OF_DARK_BALL);
- break;
- case TRAP_OF_SHARDS_BALL:
- ident = player_handle_breath_trap(3, GF_SHARDS, TRAP_OF_SHARDS_BALL);
- break;
- case TRAP_OF_SOUND_BALL:
- ident = player_handle_breath_trap(3, GF_SOUND, TRAP_OF_SOUND_BALL);
- break;
- case TRAP_OF_CONFUSION_BALL:
- ident = player_handle_breath_trap(3, GF_CONFUSION, TRAP_OF_CONFUSION_BALL);
- break;
- case TRAP_OF_FORCE_BALL:
- ident = player_handle_breath_trap(3, GF_FORCE, TRAP_OF_FORCE_BALL);
- break;
- case TRAP_OF_INERTIA_BALL:
- ident = player_handle_breath_trap(3, GF_INERTIA, TRAP_OF_INERTIA_BALL);
- break;
- case TRAP_OF_MANA_BALL:
- ident = player_handle_breath_trap(3, GF_MANA, TRAP_OF_MANA_BALL);
- break;
- case TRAP_OF_ICE_BALL:
- ident = player_handle_breath_trap(3, GF_ICE, TRAP_OF_ICE_BALL);
- break;
- case TRAP_OF_CHAOS_BALL:
- ident = player_handle_breath_trap(3, GF_CHAOS, TRAP_OF_CHAOS_BALL);
- break;
- case TRAP_OF_NETHER_BALL:
- ident = player_handle_breath_trap(3, GF_NETHER, TRAP_OF_NETHER_BALL);
- break;
- case TRAP_OF_DISENCHANT_BALL:
- ident = player_handle_breath_trap(3, GF_DISENCHANT, TRAP_OF_DISENCHANT_BALL);
- break;
- case TRAP_OF_NEXUS_BALL:
- ident = player_handle_breath_trap(3, GF_NEXUS, TRAP_OF_NEXUS_BALL);
- break;
- case TRAP_OF_TIME_BALL:
- ident = player_handle_breath_trap(3, GF_TIME, TRAP_OF_TIME_BALL);
- break;
- case TRAP_OF_GRAVITY_BALL:
- ident = player_handle_breath_trap(3, GF_GRAVITY, TRAP_OF_GRAVITY_BALL);
- break;
-
- /* -SC- */
- case TRAP_OF_FEMINITY:
- {
- msg_print("Gas sprouts out... you feel yourself transmute.");
- p_ptr->psex = SEX_FEMALE;
- sp_ptr = &sex_info[p_ptr->psex];
- ident = TRUE;
- trap_hit(trap);
- break;
- }
-
- case TRAP_OF_MASCULINITY:
- {
- msg_print("Gas sprouts out... you feel yourself transmute.");
- p_ptr->psex = SEX_MALE;
- sp_ptr = &sex_info[p_ptr->psex];
- ident = TRUE;
- trap_hit(trap);
- break;
- }
-
- case TRAP_OF_NEUTRALITY:
- {
- msg_print("Gas sprouts out... you feel yourself transmute.");
- p_ptr->psex = SEX_NEUTER;
- sp_ptr = &sex_info[p_ptr->psex];
- ident = TRUE;
- trap_hit(trap);
- break;
- }
-
- case TRAP_OF_AGING:
- {
- msg_print("Colors are scintillating around you. "
- "You see your past running before your eyes.");
- p_ptr->age += randint((rp_ptr->b_age + rmp_ptr->b_age) / 2);
- ident = TRUE;
- trap_hit(trap);
- break;
- }
-
- case TRAP_OF_GROWING:
- {
- s16b tmp;
-
- msg_print("Heavy fumes sprout out... you feel yourself transmute.");
- if (p_ptr->psex == SEX_FEMALE) tmp = rp_ptr->f_b_ht + rmp_ptr->f_b_ht;
- else tmp = rp_ptr->m_b_ht + rmp_ptr->m_b_ht;
-
- p_ptr->ht += randint(tmp / 4);
- ident = TRUE;
- trap_hit(trap);
- break;
- }
-
- case TRAP_OF_SHRINKING:
- {
- s16b tmp;
-
- msg_print("Heavy fumes sprout out... you feel yourself transmute.");
- if (p_ptr->psex == SEX_FEMALE) tmp = rp_ptr->f_b_ht + rmp_ptr->f_b_ht;
- else tmp = rp_ptr->m_b_ht + rmp_ptr->m_b_ht;
-
- p_ptr->ht -= randint(tmp / 4);
- if (p_ptr->ht <= tmp / 4) p_ptr->ht = tmp / 4;
- ident = TRUE;
- trap_hit(trap);
- break;
- }
-
- /* Trap of Divine Anger */
- case TRAP_OF_DIVINE_ANGER:
- {
- if (p_ptr->pgod == 0)
- {
- msg_format("Suddenly you feel glad you're a mere %s", spp_ptr->title + c_name);
- }
- else
- {
- cptr name;
-
- name = deity_info[p_ptr->pgod].name;
- msg_format("You feel you have angered %s.", name);
- inc_piety(p_ptr->pgod, -3000);
- }
- break;
- }
-
- /* Trap of Divine Wrath */
- case TRAP_OF_DIVINE_WRATH:
- {
- if (p_ptr->pgod == 0)
- {
- msg_format("Suddenly you feel glad you're a mere %s", spp_ptr->title + c_name);
- }
- else
- {
- cptr name;
-
- name = deity_info[p_ptr->pgod].name;
-
- msg_format("%s quakes in rage: ``Thou art supremely insolent, mortal!!''", name);
- inc_piety(p_ptr->pgod, -500 * p_ptr->lev);
- }
- break;
- }
-
- /* Trap of hallucination */
- case TRAP_OF_HALLUCINATION:
- {
- msg_print("Scintillating colors hypnotise you for a moment.");
-
- set_image(80);
- }
- break;
-
- /* Bolt Trap */
- case TRAP_OF_ROCKET:
- ident = player_handle_breath_trap(1, GF_ROCKET, trap);
- break;
- case TRAP_OF_NUKE_BOLT:
- ident = player_handle_breath_trap(1, GF_NUKE, trap);
- break;
- case TRAP_OF_HOLY_FIRE:
- ident = player_handle_breath_trap(1, GF_HOLY_FIRE, trap);
- break;
- case TRAP_OF_HELL_FIRE:
- ident = player_handle_breath_trap(1, GF_HELL_FIRE, trap);
- break;
- case TRAP_OF_PSI_BOLT:
- ident = player_handle_breath_trap(1, GF_PSI, trap);
- break;
- case TRAP_OF_PSI_DRAIN:
- ident = player_handle_breath_trap(1, GF_PSI_DRAIN, trap);
- break;
-
- /* Ball Trap */
- case TRAP_OF_NUKE_BALL:
- ident = player_handle_breath_trap(3, GF_NUKE, TRAP_OF_NUKE_BALL);
- break;
- case TRAP_OF_PSI_BALL:
- ident = player_handle_breath_trap(3, GF_PSI, TRAP_OF_NUKE_BALL);
- break;
-
- default:
- {
- msg_print(format("Executing unknown trap %d", trap));
- }
- }
- return ident;
-}
-
-void player_activate_door_trap(s16b y, s16b x)
-{
- cave_type *c_ptr;
- bool_ ident = FALSE;
-
- c_ptr = &cave[y][x];
-
- /* Return if trap or door not found */
- if ((c_ptr->t_idx == 0) ||
- !(f_info[c_ptr->feat].flags1 & FF1_DOOR)) return;
-
- /* Disturb */
- disturb(0, 0);
-
- /* Message */
- msg_print("You found a trap!");
-
- /* Pick a trap */
- pick_trap(y, x);
-
- /* Hit the trap */
- ident = player_activate_trap_type(y, x, NULL, -1);
- if (ident)
- {
- t_info[c_ptr->t_idx].ident = TRUE;
- msg_format("You identified that trap as %s.",
- t_name + t_info[c_ptr->t_idx].name);
- }
-}
-
-
-/*
- * Places a random trap at the given location.
- *
- * The location must be a valid, empty, clean, floor grid.
- */
-void place_trap(int y, int x)
-{
- s16b trap;
- trap_type *t_ptr;
- int cnt;
- u32b flags;
- cave_type *c_ptr = &cave[y][x];
- dungeon_info_type *d_ptr = &d_info[dungeon_type];
-
- /* No traps in town or on first level */
- if (dun_level <= 1) return;
-
- /*
- * Avoid open doors -- because DOOR flag is added to make much more
- * important processing faster
- */
- if (c_ptr->feat == FEAT_OPEN) return;
- if (c_ptr->feat == FEAT_BROKEN) return;
-
- /* Traps only appears on empty floor */
- if (!cave_floor_grid(c_ptr) &&
- !(f_info[c_ptr->feat].flags1 & (FF1_DOOR))) return;
-
- /* Set flags */
- if (f_info[c_ptr->feat].flags1 & FF1_DOOR) flags = FTRAP_DOOR;
- else flags = FTRAP_FLOOR;
-
- /* Try 100 times */
- cnt = 100;
- while (cnt--)
- {
- trap = randint(max_t_idx - 1);
- t_ptr = &t_info[trap];
-
- /* No traps below their minlevel */
- if (t_ptr->minlevel > dun_level) continue;
-
- /* is this a correct trap now? */
- if (!(t_ptr->flags & flags)) continue;
-
- /*
- * Hack -- No trap door at the bottom of dungeon or in flat
- * (non dungeon) places or on quest levels
- */
- if ((trap == TRAP_OF_SINKING) &&
- ((d_ptr->maxdepth == dun_level) ||
- (dungeon_flags1 & DF1_FLAT) || (is_quest(dun_level))) )
- {
- continue;
- }
-
- /* How probable is this trap */
- if (rand_int(100) < t_ptr->probability)
- {
- c_ptr->t_idx = trap;
- break;
- }
- }
-
- return;
-}
-
-
-/*
- * Places a random trap on the given chest.
- *
- * The object must be a valid chest.
- */
-void place_trap_object(object_type *o_ptr)
-{
- s16b trap;
- trap_type *t_ptr;
- int cnt;
-
- /* No traps in town or on first level */
- if (dun_level <= 1)
- {
- /* empty chest were already looted, therefore known */
- o_ptr->ident |= IDENT_KNOWN;
- return;
- }
-
- /* Try 100 times */
- cnt = 100;
- while (cnt--)
- {
- trap = randint(max_t_idx - 1);
- t_ptr = &t_info[trap];
-
- /* no traps below their minlevel */
- if (t_ptr->minlevel > dun_level) continue;
-
- /* Is this a correct trap now? */
- if (!(t_ptr->flags & FTRAP_CHEST)) continue;
-
- /* How probable is this trap */
- if (rand_int(100) < t_ptr->probability)
- {
- o_ptr->pval = trap;
- break;
- }
- }
-
- return;
-}
-
-/* Dangerous trap placing function */
-void wiz_place_trap(int y, int x, int idx)
-{
- cave_type *c_ptr = &cave[y][x];
-
- /* Dangerous enough as it is... */
- if (!cave_floor_grid(c_ptr) && (!(f_info[c_ptr->feat].flags1 & FF1_DOOR))) return;
-
- c_ptr->t_idx = idx;
-}
-
-/*
- * Here begin monster traps code
- */
-
-/*
- * Hook to determine if an object is a device
- */
-static bool_ item_tester_hook_device(object_type *o_ptr)
-{
- if (((o_ptr->tval == TV_ROD_MAIN) && (o_ptr->pval != 0)) ||
- (o_ptr->tval == TV_STAFF) ||
- (o_ptr->tval == TV_WAND)) return (TRUE);
-
- /* Assume not */
- return (FALSE);
-}
-
-/*
- * Hook to determine if an object is a potion
- */
-static bool_ item_tester_hook_potion(object_type *o_ptr)
-{
- if ((o_ptr->tval == TV_POTION) ||
- (o_ptr->tval == TV_POTION2)) return (TRUE);
-
- /* Assume not */
- return (FALSE);
-}
-
-/*
- * The trap setting code for rogues -MWK-
- *
- * Also, it will fail or give weird results if the tvals are resorted!
- */
-void do_cmd_set_trap(void)
-{
- int item_kit, item_load, i;
- int num;
-
- object_type *o_ptr, *j_ptr, *i_ptr;
-
- cptr q, s, c;
-
- object_type object_type_body;
-
- u32b f1, f2, f3, f4, f5, esp;
-
- /* Check some conditions */
- if (p_ptr->blind)
- {
- msg_print("You can't see anything.");
- return;
- }
- if (no_lite())
- {
- msg_print("You don't dare to set a trap in the darkness.");
- return;
- }
- if (p_ptr->confused)
- {
- msg_print("You are too confused!");
- return;
- }
-
- /* Only set traps on clean floor grids */
- if (!cave_clean_bold(p_ptr->py, p_ptr->px))
- {
- msg_print("You cannot set a trap on this.");
- return;
- }
-
- /* Restrict choices to trapkits */
- item_tester_tval = TV_TRAPKIT;
-
- /* Get an item */
- q = "Use which trapping kit? ";
- s = "You have no trapping kits.";
- if (!get_item(&item_kit, q, s, USE_INVEN)) return;
-
- o_ptr = &p_ptr->inventory[item_kit];
-
- /* Trap kits need a second object */
- switch (o_ptr->sval)
- {
- case SV_TRAPKIT_BOW:
- item_tester_tval = TV_ARROW;
- break;
- case SV_TRAPKIT_XBOW:
- item_tester_tval = TV_BOLT;
- break;
- case SV_TRAPKIT_SLING:
- item_tester_tval = TV_SHOT;
- break;
- case SV_TRAPKIT_POTION:
- item_tester_hook = item_tester_hook_potion;
- break;
- case SV_TRAPKIT_SCROLL:
- item_tester_tval = TV_SCROLL;
- break;
- case SV_TRAPKIT_DEVICE:
- item_tester_hook = item_tester_hook_device;
- break;
- default:
- msg_print("Unknown trapping kit type!");
- break;
- }
-
- /* Get the second item */
- q = "Load with what? ";
- s = "You have nothing to load that trap with.";
- if (!get_item(&item_load, q, s, USE_INVEN)) return;
-
- /* Get the second object */
- j_ptr = &p_ptr->inventory[item_load];
-
- /* Assume a single object */
- num = 1;
-
- /* In some cases, take multiple objects to load */
- if (o_ptr->sval != SV_TRAPKIT_DEVICE)
- {
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
-
- if ((f3 & TR3_XTRA_SHOTS) && (o_ptr->pval > 0)) num += o_ptr->pval;
-
- if (f2 & (TRAP2_AUTOMATIC_5 | TRAP2_AUTOMATIC_99)) num = 99;
-
- if (num > j_ptr->number) num = j_ptr->number;
-
- c = format("How many (1-%d)? ", num);
-
- /* Ask for number of items to use */
- num = get_quantity(c, num);
- }
-
- /* Canceled */
- if (!num) return;
-
- /* Take a turn */
- energy_use = 100;
-
- /* Get local object */
- i_ptr = &object_type_body;
-
- /* Obtain local object for trap content */
- object_copy(i_ptr, j_ptr);
-
- /* Set number */
- i_ptr->number = num;
-
- /* Drop it here */
- cave[p_ptr->py][p_ptr->px].special = floor_carry(p_ptr->py, p_ptr->px, i_ptr);
-
- /* Obtain local object for trap trigger kit */
- object_copy(i_ptr, o_ptr);
-
- /* Set number */
- i_ptr->number = 1;
-
- /* Drop it here */
- cave[p_ptr->py][p_ptr->px].special2 = floor_carry(p_ptr->py, p_ptr->px, i_ptr);
-
- /* Modify, Describe, Optimize */
- inc_stack_size_ex(item_kit, -1, NO_OPTIMIZE, DESCRIBE);
- inc_stack_size_ex(item_load, -num, NO_OPTIMIZE, DESCRIBE);
-
- for (i = 0; i < INVEN_WIELD; i++)
- {
- if (inven_item_optimize(i)) break;
- }
- for (i = 0; i < INVEN_WIELD; i++)
- {
- inven_item_optimize(i);
- }
-
- /* Actually set the trap */
- cave_set_feat(p_ptr->py, p_ptr->px, FEAT_MON_TRAP);
-}
-
-/*
- * Monster hitting a rod trap -MWK-
- *
- * Return TRUE if the monster died
- */
-bool_ mon_hit_trap_aux_rod(int m_idx, object_type *o_ptr)
-{
- int dam = 0, typ = 0;
- int rad = 0;
- monster_type *m_ptr = &m_list[m_idx];
- int y = m_ptr->fy;
- int x = m_ptr->fx;
-
- /* Depend on rod type */
- switch (o_ptr->pval)
- {
- case SV_ROD_DETECT_TRAP:
- m_ptr->smart |= SM_NOTE_TRAP;
- break;
- case SV_ROD_DETECTION:
- m_ptr->smart |= SM_NOTE_TRAP;
- break;
- case SV_ROD_ILLUMINATION:
- typ = GF_LITE_WEAK;
- dam = damroll(2, 15);
- rad = 3;
- lite_room(y, x);
- break;
- case SV_ROD_CURING:
- typ = GF_OLD_HEAL;
- dam = damroll(3, 4); /* and heal conf? */
- break;
- case SV_ROD_HEALING:
- typ = GF_OLD_HEAL;
- dam = 300;
- break;
- case SV_ROD_SPEED:
- typ = GF_OLD_SPEED;
- dam = 50;
- break;
- case SV_ROD_TELEPORT_AWAY:
- typ = GF_AWAY_ALL;
- dam = MAX_SIGHT * 5;
- break;
- case SV_ROD_DISARMING:
- break;
- case SV_ROD_LITE:
- typ = GF_LITE_WEAK;
- dam = damroll(6, 8);
- break;
- case SV_ROD_SLEEP_MONSTER:
- typ = GF_OLD_SLEEP;
- dam = 50;
- break;
- case SV_ROD_SLOW_MONSTER:
- typ = GF_OLD_SLOW;
- dam = 50;
- break;
- case SV_ROD_DRAIN_LIFE:
- typ = GF_OLD_DRAIN;
- dam = 75;
- break;
- case SV_ROD_POLYMORPH:
- typ = GF_OLD_POLY;
- dam = 50;
- break;
- case SV_ROD_ACID_BOLT:
- typ = GF_ACID;
- dam = damroll(6, 8);
- break;
- case SV_ROD_ELEC_BOLT:
- typ = GF_ELEC;
- dam = damroll(3, 8);
- break;
- case SV_ROD_FIRE_BOLT:
- typ = GF_FIRE;
- dam = damroll(8, 8);
- break;
- case SV_ROD_COLD_BOLT:
- typ = GF_COLD;
- dam = damroll(5, 8);
- break;
- case SV_ROD_ACID_BALL:
- typ = GF_ACID;
- dam = 60;
- rad = 2;
- break;
- case SV_ROD_ELEC_BALL:
- typ = GF_ELEC;
- dam = 32;
- rad = 2;
- break;
- case SV_ROD_FIRE_BALL:
- typ = GF_FIRE;
- dam = 72;
- rad = 2;
- break;
- case SV_ROD_COLD_BALL:
- typ = GF_COLD;
- dam = 48;
- rad = 2;
- break;
- default:
- return (FALSE);
- }
-
- /* Actually hit the monster */
- if (typ) (void) project( -2, rad, y, x, dam, typ, PROJECT_KILL | PROJECT_ITEM | PROJECT_JUMP);
- return (cave[y][x].m_idx == 0 ? TRUE : FALSE);
-}
-
-/*
- * Monster hitting a staff trap -MWK-
- *
- * Return TRUE if the monster died
- */
-bool_ mon_hit_trap_aux_staff(int m_idx, object_type *o_ptr)
-{
- return (FALSE);
-}
-
-/*
- * Monster hitting a scroll trap -MWK-
- *
- * Return TRUE if the monster died
- */
-bool_ mon_hit_trap_aux_scroll(int m_idx, int sval)
-{
- monster_type *m_ptr = &m_list[m_idx];
- int dam = 0, typ = 0;
- int rad = 0;
- int y = m_ptr->fy;
- int x = m_ptr->fx;
- int k;
-
- /* Depend on scroll type */
- switch (sval)
- {
- case SV_SCROLL_CURSE_ARMOR:
- case SV_SCROLL_CURSE_WEAPON:
- case SV_SCROLL_TRAP_CREATION: /* these don't work :-( */
- case SV_SCROLL_WORD_OF_RECALL: /* should these? */
- case SV_SCROLL_IDENTIFY:
- case SV_SCROLL_STAR_IDENTIFY:
- case SV_SCROLL_MAPPING:
- case SV_SCROLL_DETECT_GOLD:
- case SV_SCROLL_DETECT_ITEM:
- case SV_SCROLL_REMOVE_CURSE:
- case SV_SCROLL_STAR_REMOVE_CURSE:
- case SV_SCROLL_ENCHANT_ARMOR:
- case SV_SCROLL_ENCHANT_WEAPON_TO_HIT:
- case SV_SCROLL_ENCHANT_WEAPON_TO_DAM:
- case SV_SCROLL_STAR_ENCHANT_ARMOR:
- case SV_SCROLL_STAR_ENCHANT_WEAPON:
- case SV_SCROLL_RECHARGING:
- case SV_SCROLL_DETECT_DOOR:
- case SV_SCROLL_DETECT_INVIS:
- case SV_SCROLL_SATISFY_HUNGER:
- case SV_SCROLL_RUNE_OF_PROTECTION:
- case SV_SCROLL_TRAP_DOOR_DESTRUCTION:
- case SV_SCROLL_PROTECTION_FROM_EVIL:
- return (FALSE);
- case SV_SCROLL_DARKNESS:
- unlite_room(y, x);
- typ = GF_DARK_WEAK;
- dam = 10;
- rad = 3;
- break;
- case SV_SCROLL_AGGRAVATE_MONSTER:
- aggravate_monsters(m_idx);
- return (FALSE);
- case SV_SCROLL_SUMMON_MONSTER:
- for (k = 0; k < randint(3) ; k++) summon_specific(y, x, dun_level, 0);
- return (FALSE);
- case SV_SCROLL_SUMMON_UNDEAD:
- for (k = 0; k < randint(3) ; k++) summon_specific(y, x, dun_level, SUMMON_UNDEAD);
- return (FALSE);
- case SV_SCROLL_PHASE_DOOR:
- typ = GF_AWAY_ALL;
- dam = 10;
- break;
- case SV_SCROLL_TELEPORT:
- typ = GF_AWAY_ALL;
- dam = 100;
- break;
- case SV_SCROLL_TELEPORT_LEVEL:
- delete_monster(y, x);
- return (TRUE);
- case SV_SCROLL_LIGHT:
- lite_room(y, x);
- typ = GF_LITE_WEAK;
- dam = damroll(2, 8);
- rad = 2;
- break;
- case SV_SCROLL_DETECT_TRAP:
- m_ptr->smart |= SM_NOTE_TRAP;
- return (FALSE);
- case SV_SCROLL_BLESSING:
- typ = GF_HOLY_FIRE;
- dam = damroll(1, 4);
- break;
- case SV_SCROLL_HOLY_CHANT:
- typ = GF_HOLY_FIRE;
- dam = damroll(2, 4);
- break;
- case SV_SCROLL_HOLY_PRAYER:
- typ = GF_HOLY_FIRE;
- dam = damroll(4, 4);
- break;
- case SV_SCROLL_MONSTER_CONFUSION:
- typ = GF_OLD_CONF;
- dam = damroll(5, 10);
- break;
- case SV_SCROLL_STAR_DESTRUCTION:
- destroy_area(y, x, 15, TRUE, FALSE);
- return (FALSE);
- case SV_SCROLL_DISPEL_UNDEAD:
- typ = GF_DISP_UNDEAD;
- rad = 5;
- dam = 60;
- break;
- case SV_SCROLL_GENOCIDE:
- {
- monster_race *r_ptr = &r_info[m_ptr->r_idx];
- genocide_aux(FALSE, r_ptr->d_char);
- /* although there's no point in a multiple genocide trap... */
- return (!(r_ptr->flags1 & RF1_UNIQUE));
- }
- case SV_SCROLL_MASS_GENOCIDE:
- for (k = 0; k < 8; k++)
- delete_monster(y + ddy[k], x + ddx[k]);
- delete_monster(y, x);
- return (TRUE);
- case SV_SCROLL_ACQUIREMENT:
- acquirement(y, x, 1, TRUE, FALSE);
- return (FALSE);
- case SV_SCROLL_STAR_ACQUIREMENT:
- acquirement(y, x, randint(2) + 1, TRUE, FALSE);
- return (FALSE);
- default:
- return (FALSE);
- }
-
- /* Actually hit the monster */
- (void) project( -2, rad, y, x, dam, typ, PROJECT_KILL | PROJECT_ITEM | PROJECT_JUMP);
- return (cave[y][x].m_idx == 0 ? TRUE : FALSE);
-}
-
-/*
- * Monster hitting a wand trap -MWK-
- *
- * Return TRUE if the monster died
- */
-bool_ mon_hit_trap_aux_wand(int m_idx, object_type *o_ptr)
-{
- return (FALSE);
-}
-
-/*
- * Monster hitting a potions trap -MWK-
- *
- * Return TRUE if the monster died
- */
-bool_ mon_hit_trap_aux_potion(int m_idx, object_type *o_ptr)
-{
- monster_type *m_ptr = &m_list[m_idx];
- int dam = 0, typ = 0;
- int y = m_ptr->fy;
- int x = m_ptr->fx;
- int sval = o_ptr->sval;
-
- /* Depend on potion type */
- if (o_ptr->tval == TV_POTION)
- {
- switch (sval)
- {
- /* Nothing happens */
- case SV_POTION_WATER:
- case SV_POTION_APPLE_JUICE:
- case SV_POTION_SLIME_MOLD:
- case SV_POTION_SALT_WATER:
- case SV_POTION_DEC_STR:
- case SV_POTION_DEC_INT:
- case SV_POTION_DEC_WIS:
- case SV_POTION_DEC_DEX:
- case SV_POTION_DEC_CON:
- case SV_POTION_DEC_CHR:
- case SV_POTION_INFRAVISION:
- case SV_POTION_DETECT_INVIS:
- case SV_POTION_SLOW_POISON:
- case SV_POTION_CURE_POISON:
- case SV_POTION_RESIST_HEAT:
- case SV_POTION_RESIST_COLD:
- case SV_POTION_RESTORE_MANA:
- case SV_POTION_RESTORE_EXP:
- case SV_POTION_RES_STR:
- case SV_POTION_RES_INT:
- case SV_POTION_RES_WIS:
- case SV_POTION_RES_DEX:
- case SV_POTION_RES_CON:
- case SV_POTION_RES_CHR:
- case SV_POTION_INC_STR:
- case SV_POTION_INC_INT:
- case SV_POTION_INC_WIS:
- case SV_POTION_INC_DEX:
- case SV_POTION_INC_CON:
- case SV_POTION_INC_CHR:
- case SV_POTION_AUGMENTATION:
- case SV_POTION_RUINATION: /* ??? */
- case SV_POTION_ENLIGHTENMENT:
- case SV_POTION_STAR_ENLIGHTENMENT:
- case SV_POTION_SELF_KNOWLEDGE:
- return (FALSE);
-
- case SV_POTION_EXPERIENCE:
- if (m_ptr->level < MONSTER_LEVEL_MAX)
- {
- m_ptr->exp = MONSTER_EXP(m_ptr->level + 1);
- monster_check_experience(m_idx, FALSE);
- }
- return (FALSE);
- case SV_POTION_SLOWNESS:
- typ = GF_OLD_SLOW;
- dam = damroll(4, 6);
- break;
- case SV_POTION_POISON:
- typ = GF_POIS;
- dam = damroll(8, 6);
- break;
- case SV_POTION_CONFUSION:
- typ = GF_CONFUSION;
- dam = damroll(4, 6);
- break;
- case SV_POTION_BLINDNESS:
- typ = GF_DARK;
- dam = 10;
- break;
- case SV_POTION_SLEEP:
- typ = GF_OLD_SLEEP;
- dam = damroll (4, 6);
- break;
- case SV_POTION_LOSE_MEMORIES:
- typ = GF_OLD_CONF;
- dam = damroll(10, 10);
- break;
- case SV_POTION_DETONATIONS:
- typ = GF_DISINTEGRATE;
- dam = damroll(20, 20);
- break;
- case SV_POTION_DEATH:
- typ = GF_NETHER;
- dam = damroll(100, 20);
- break;
- case SV_POTION_BOLDNESS:
- m_ptr->monfear = 0;
- return (FALSE);
- case SV_POTION_SPEED:
- typ = GF_OLD_SPEED;
- dam = damroll(5, 10);
- break;
- case SV_POTION_HEROISM:
- case SV_POTION_BESERK_STRENGTH:
- m_ptr->monfear = 0;
- typ = GF_OLD_HEAL;
- dam = damroll(2, 10);
- break;
- case SV_POTION_CURE_LIGHT:
- typ = GF_OLD_HEAL;
- dam = damroll(3, 4);
- break;
- case SV_POTION_CURE_SERIOUS:
- typ = GF_OLD_HEAL;
- dam = damroll(4, 6);
- break;
- case SV_POTION_CURE_CRITICAL:
- typ = GF_OLD_HEAL;
- dam = damroll(6, 8);
- break;
- case SV_POTION_HEALING:
- typ = GF_OLD_HEAL;
- dam = 300;
- break;
- case SV_POTION_STAR_HEALING:
- typ = GF_OLD_HEAL;
- dam = 1000;
- break;
- case SV_POTION_LIFE:
- {
- monster_race *r_ptr = &r_info[m_ptr->r_idx];
- if (r_ptr->flags3 & RF3_UNDEAD)
- {
- typ = GF_HOLY_FIRE;
- dam = damroll(20, 20);
- }
- else
- {
- typ = GF_OLD_HEAL;
- dam = 5000;
- }
- break;
- }
- default:
- return (FALSE);
-
- }
- }
- else
- {}
-
- /* Actually hit the monster */
- (void) project_m( -2, 0, y, x, dam, typ);
- return (cave[y][x].m_idx == 0 ? TRUE : FALSE);
-}
-
-/*
- * Monster hitting a monster trap -MWK-
- * Returns True if the monster died, false otherwise
- */
-bool_ mon_hit_trap(int m_idx)
-{
- monster_type *m_ptr = &m_list[m_idx];
- monster_race *r_ptr = &r_info[m_ptr->r_idx];
-
- object_type *kit_o_ptr, *load_o_ptr, *j_ptr;
-
- u32b f1, f2, f3, f4, f5, esp;
-
- object_type object_type_body;
-
- int mx = m_ptr->fx;
- int my = m_ptr->fy;
-
- int difficulty;
- int smartness;
-
- char m_name[80];
-
- bool_ notice = FALSE;
- bool_ disarm = FALSE;
- bool_ remove = FALSE;
- bool_ dead = FALSE;
- bool_ fear = FALSE;
- s32b special = 0;
-
- int dam, chance, shots;
- int mul = 0;
- int breakage = -1;
-
- int cost = 0;
-
- /* Get the trap objects */
- kit_o_ptr = &o_list[cave[my][mx].special2];
- load_o_ptr = &o_list[cave[my][mx].special];
- j_ptr = &object_type_body;
-
- /* Get trap properties */
- object_flags(kit_o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
-
- /* Can set off check */
- /* Ghosts only set off Ghost traps */
- if ((r_ptr->flags2 & RF2_PASS_WALL) && !(f2 & TRAP2_KILL_GHOST)) return (FALSE);
-
- /* Some traps are specialized to some creatures */
- if (f2 & TRAP2_ONLY_MASK)
- {
- bool_ affect = FALSE;
- if ((f2 & TRAP2_ONLY_DRAGON) && (r_ptr->flags3 & RF3_DRAGON)) affect = TRUE;
- if ((f2 & TRAP2_ONLY_DEMON) && (r_ptr->flags3 & RF3_DEMON)) affect = TRUE;
- if ((f2 & TRAP2_ONLY_UNDEAD) && (r_ptr->flags3 & RF3_UNDEAD)) affect = TRUE;
- if ((f2 & TRAP2_ONLY_EVIL) && (r_ptr->flags3 & RF3_EVIL)) affect = TRUE;
- if ((f2 & TRAP2_ONLY_ANIMAL) && (r_ptr->flags3 & RF3_ANIMAL)) affect = TRUE;
-
- /* Don't set it off if forbidden */
- if (!affect) return (FALSE);
- }
-
- /* Get detection difficulty */
- difficulty = 25;
-
- /* Some traps are well-hidden */
- if (f1 & TR1_STEALTH)
- {
- difficulty += 10 * (kit_o_ptr->pval);
- }
-
- /* Get monster smartness for trap detection */
- /* Higher level monsters are smarter */
- smartness = r_ptr->level;
-
- /* Smart monsters are better at detecting traps */
- if (r_ptr->flags2 & RF2_SMART) smartness += 10;
-
- /* Some monsters have already noticed one of out traps */
- if (m_ptr->smart & SM_NOTE_TRAP) smartness += 20;
-
- /* Stupid monsters are no good at detecting traps */
- if (r_ptr->flags2 & (RF2_STUPID | RF2_EMPTY_MIND)) smartness = -150;
-
- /* Check if the monster notices the trap */
- if (randint(300) > (difficulty - smartness + 150)) notice = TRUE;
-
- /* Disarm check */
- if (notice)
- {
- /* The next traps will be easier to spot! */
- m_ptr->smart |= SM_NOTE_TRAP;
-
- /* Get trap disarming difficulty */
- difficulty = (kit_o_ptr->ac + kit_o_ptr->to_a);
-
- /* Get monster disarming ability */
- /* Higher level monsters are better */
- smartness = r_ptr->level / 5;
-
- /* Smart monsters are better at disarming */
- if (r_ptr->flags2 & RF2_SMART) smartness *= 2;
-
- /* Stupid monsters never disarm traps */
- if (r_ptr->flags2 & RF2_STUPID) smartness = -150;
-
- /* Nonsmart animals never disarm traps */
- if ((r_ptr->flags3 & RF3_ANIMAL) && !(r_ptr->flags2 & RF2_SMART)) smartness = -150;
-
- /* Check if the monster disarms the trap */
- if (randint(120) > (difficulty - smartness + 80)) disarm = TRUE;
- }
-
- /* If disarmed, remove the trap and print a message */
- if (disarm)
- {
- remove = TRUE;
-
- if (m_ptr->ml)
- {
- /* Get the name */
- monster_desc(m_name, m_ptr, 0);
-
- /* Print a message */
- msg_format("%^s disarms a trap!", m_name);
- }
- }
-
- /* Otherwise, activate the trap! */
- else
- {
- /* Message for visible monster */
- if (m_ptr->ml)
- {
- /* Get the name */
- monster_desc(m_name, m_ptr, 0);
-
- /* Print a message */
- msg_format("%^s sets off a trap!", m_name);
- }
- else
- {
- /* No message if monster isn't visible ? */
- }
-
- /* Next time be more careful */
- if (randint(100) < 80) m_ptr->smart |= SM_NOTE_TRAP;
-
- /* Actually activate the trap */
- switch (kit_o_ptr->sval)
- {
- case SV_TRAPKIT_BOW:
- case SV_TRAPKIT_XBOW:
- case SV_TRAPKIT_SLING:
- {
- /* Get number of shots */
- shots = 1;
- if (f3 & TR3_XTRA_SHOTS) shots += kit_o_ptr->pval;
- if (shots <= 0) shots = 1;
- if (shots > load_o_ptr->number) shots = load_o_ptr->number;
-
- while (shots-- && !dead)
- {
- /* Total base damage */
- dam = damroll(load_o_ptr->dd, load_o_ptr->ds) + load_o_ptr->to_d + kit_o_ptr->to_d;
-
- /* Total hit probability */
- chance = (kit_o_ptr->to_h + load_o_ptr->to_h + 20) * BTH_PLUS_ADJ;
-
- /* Damage multiplier */
- if (kit_o_ptr->sval == SV_TRAPKIT_BOW) mul = 3;
- if (kit_o_ptr->sval == SV_TRAPKIT_XBOW) mul = 4;
- if (kit_o_ptr->sval == SV_TRAPKIT_SLING) mul = 2;
- if (f3 & TR3_XTRA_MIGHT) mul += kit_o_ptr->pval;
- if (mul < 0) mul = 0;
-
- /* Multiply damage */
- dam *= mul;
-
- /* Check if we hit the monster */
- if (test_hit_fire(chance, r_ptr->ac, TRUE))
- {
- /* 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.";
- }
-
- /* Message if visible */
- if (m_ptr->ml)
- {
- /* describe the monster (again, just in case :-) */
- monster_desc(m_name, m_ptr, 0);
-
- /* Print a message */
- msg_format("%^s is hit by a missile.", m_name);
- }
-
- /* Apply slays, brand, critical hits */
- dam = tot_dam_aux(load_o_ptr, dam, m_ptr, &special);
- dam = critical_shot(load_o_ptr->weight, load_o_ptr->to_h, dam, SKILL_ARCHERY);
-
- /* No negative damage */
- if (dam < 0) dam = 0;
-
- /* Hit the monster, check for death */
- if (mon_take_hit(m_idx, dam, &fear, note_dies))
- {
- /* Dead monster */
- dead = TRUE;
- }
-
- /* No death */
- else
- {
- /* Message */
- message_pain(m_idx, dam);
-
- if (special) attack_special(m_ptr, special, dam);
-
- /* Take note */
- if (fear && m_ptr->ml)
- {
- /* Message */
- msg_format("%^s flees in terror!", m_name);
- }
- }
-
- }
-
- /* Exploding ammo */
- if (load_o_ptr->pval2 != 0)
- {
- int rad = 0;
- int dam = (damroll(load_o_ptr->dd, load_o_ptr->ds) + load_o_ptr->to_d)*2;
- int flag = PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL |
- PROJECT_JUMP;
-
- switch (load_o_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, my, mx, dam, load_o_ptr->pval2, flag);
-
- breakage = 100;
- }
- else
- {
- breakage = breakage_chance(load_o_ptr);
- }
-
- /* Copy and decrease ammo */
- object_copy(j_ptr, load_o_ptr);
-
- j_ptr->number = 1;
-
- load_o_ptr->number--;
-
- if (load_o_ptr->number <= 0)
- {
- remove = TRUE;
- delete_object_idx(kit_o_ptr->next_o_idx);
- kit_o_ptr->next_o_idx = 0;
- }
-
- /* Drop (or break) near that location */
- drop_near(j_ptr, breakage, my, mx);
-
- }
-
- break;
- }
-
- case SV_TRAPKIT_POTION:
- {
- /* Get number of shots */
- shots = 1;
- if (f3 & TR3_XTRA_SHOTS) shots += kit_o_ptr->pval;
- if (shots <= 0) shots = 1;
- if (shots > load_o_ptr->number) shots = load_o_ptr->number;
-
- while (shots-- && !dead)
- {
-
- /* Message if visible */
- if (m_ptr->ml)
- {
- /* describe the monster (again, just in case :-) */
- monster_desc(m_name, m_ptr, 0);
-
- /* Print a message */
- msg_format("%^s is hit by fumes.", m_name);
- }
-
- /* Get the potion effect */
- dead = mon_hit_trap_aux_potion(m_idx, load_o_ptr);
-
- /* Copy and decrease ammo */
- object_copy(j_ptr, load_o_ptr);
-
- j_ptr->number = 1;
-
- load_o_ptr->number--;
-
- if (load_o_ptr->number <= 0)
- {
- remove = TRUE;
- delete_object_idx(kit_o_ptr->next_o_idx);
- kit_o_ptr->next_o_idx = 0;
- }
- }
-
- break;
- }
-
- case SV_TRAPKIT_SCROLL:
- {
- /* Get number of shots */
- shots = 1;
- if (f3 & TR3_XTRA_SHOTS) shots += kit_o_ptr->pval;
- if (shots <= 0) shots = 1;
- if (shots > load_o_ptr->number) shots = load_o_ptr->number;
-
- while (shots-- && !dead)
- {
-
- /* Message if visible */
- if (m_ptr->ml)
- {
- /* describe the monster (again, just in case :-) */
- monster_desc(m_name, m_ptr, 0);
-
- /* Print a message */
- msg_format("%^s activates a spell!", m_name);
- }
-
- /* Get the potion effect */
- dead = mon_hit_trap_aux_scroll(m_idx, load_o_ptr->sval);
-
- /* Copy and decrease ammo */
- object_copy(j_ptr, load_o_ptr);
-
- j_ptr->number = 1;
-
- load_o_ptr->number--;
-
- if (load_o_ptr->number <= 0)
- {
- remove = TRUE;
- delete_object_idx(kit_o_ptr->next_o_idx);
- kit_o_ptr->next_o_idx = 0;
- }
- }
-
- break;
- }
-
- case SV_TRAPKIT_DEVICE:
- {
- if (load_o_ptr->tval == TV_ROD_MAIN)
- {
- /* Extract mana cost of the rod tip */
- u32b tf1, tf2, tf3, tf4, tf5, tesp;
- object_kind *tip_o_ptr = &k_info[lookup_kind(TV_ROD, load_o_ptr->pval)];
- object_flags(load_o_ptr, &tf1, &tf2, &tf3, &tf4, &tf5, &tesp);
- cost = (tf4 & TR4_CHEAPNESS) ? tip_o_ptr->pval / 2 : tip_o_ptr->pval;
- if (cost <= 0) cost = 1;
- }
-
- /* Get number of shots */
- shots = 1;
- if (f3 & TR3_XTRA_SHOTS) shots += kit_o_ptr->pval;
- if (shots <= 0) shots = 1;
-
- if (load_o_ptr->tval == TV_ROD_MAIN)
- {
- if (shots > load_o_ptr->timeout / cost) shots = load_o_ptr->timeout / cost;
- }
- else
- {
- if (shots > load_o_ptr->pval) shots = load_o_ptr->pval;
- }
-
- while (shots-- && !dead)
- {
- /* Get the effect effect */
- switch (load_o_ptr->tval)
- {
- case TV_ROD_MAIN:
- dead = mon_hit_trap_aux_rod(m_idx, load_o_ptr);
- break;
- case TV_WAND:
- dead = mon_hit_trap_aux_wand(m_idx, load_o_ptr);
- break;
- case TV_STAFF:
- dead = mon_hit_trap_aux_staff(m_idx, load_o_ptr);
- break;
- }
-
- if (load_o_ptr->tval == TV_ROD_MAIN)
- {
- /* decrease stored mana (timeout) for rods */
- load_o_ptr->timeout -= cost;
- }
- else
- {
- /* decrease charges for wands and staves */
- load_o_ptr->pval--;
- }
- }
-
- break;
- }
-
- default:
- msg_print("oops! nonexistant trap!");
-
- }
-
- /* Non-automatic traps are removed */
- if (!(f2 & (TRAP2_AUTOMATIC_5 | TRAP2_AUTOMATIC_99)))
- {
- remove = TRUE;
- }
- else if (f2 & TRAP2_AUTOMATIC_5) remove = (randint(5) == 1);
-
- }
-
- /* Special trap effect -- teleport to */
- if ((f2 & TRAP2_TELEPORT_TO) && (!disarm) && (!dead))
- {
- teleport_monster_to(m_idx, p_ptr->py, p_ptr->px);
- }
-
- /* Remove the trap if inactive now */
- if (remove) place_floor_convert_glass(my, mx);
-
- /* did it die? */
- return (dead);
-}
-
diff --git a/src/tval_desc.hpp b/src/tval_desc.hpp
new file mode 100644
index 00000000..abf0b5e2
--- /dev/null
+++ b/src/tval_desc.hpp
@@ -0,0 +1,17 @@
+#pragma once
+
+/**
+ * TVal description entry.
+ */
+struct tval_desc
+{
+ /**
+ * TVal
+ */
+ int tval;
+
+ /**
+ * Description
+ */
+ char const *desc;
+};
diff --git a/src/types.h b/src/types.h
deleted file mode 100644
index 49acb383..00000000
--- a/src/types.h
+++ /dev/null
@@ -1,2522 +0,0 @@
-/* File: types.h */
-
-/* Purpose: global type declarations */
-
-/*
- * 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.
- */
-
-
-/*
- * This file should ONLY be included by "angband.h"
- */
-
-
-/*
- * Note that "char" may or may not be signed, and that "signed char"
- * may or may not work on all machines. So always use "s16b" or "s32b"
- * for signed values. Also, note that unsigned values cause math problems
- * in many cases, so try to only use "u16b" and "u32b" for "bit flags",
- * unless you really need the extra bit of information, or you really
- * need to restrict yourself to a single byte for storage reasons.
- *
- * Also, if possible, attempt to restrict yourself to sub-fields of
- * known size (use "s16b" or "s32b" instead of "int", and "byte" instead
- * of "bool"), and attempt to align all fields along four-byte words, to
- * optimize storage issues on 32-bit machines. Also, avoid "bit flags"
- * since these increase the code size and slow down execution. When
- * you need to store bit flags, use one byte per flag, or, where space
- * is an issue, use a "byte" or "u16b" or "u32b", and add special code
- * to access the various bit flags.
- *
- * Many of these structures were developed to reduce the number of global
- * variables, facilitate structured program design, allow the use of ascii
- * template files, simplify access to indexed data, or facilitate efficient
- * clearing of many variables at once.
- *
- * Certain data is saved in multiple places for efficient access, currently,
- * this includes the tval/sval/weight fields in "object_type", various fields
- * in "header_type", and the "m_idx" and "o_idx" fields in "cave_type". All
- * of these could be removed, but this would, in general, slow down the game
- * and increase the complexity of the code.
- */
-
-
-
-
-
-/*
- * Template file header information (see "init.c"). 16 bytes.
- *
- * Note that the sizes of many of the "arrays" are between 32768 and
- * 65535, and so we must use "unsigned" values to hold the "sizes" of
- * these arrays below. Normally, I try to avoid using unsigned values,
- * since they can cause all sorts of bizarre problems, but I have no
- * choice here, at least, until the "race" array is split into "normal"
- * and "unique" monsters, which may or may not actually help.
- *
- * Note that, on some machines, for example, the Macintosh, the standard
- * "read()" and "write()" functions cannot handle more than 32767 bytes
- * at one time, so we need replacement functions, see "util.c" for details.
- *
- * Note that, on some machines, for example, the Macintosh, the standard
- * "malloc()" function cannot handle more than 32767 bytes at one time,
- * but we may assume that the "ralloc()" function can handle up to 65535
- * butes at one time. We should not, however, assume that the "ralloc()"
- * function can handle more than 65536 bytes at a time, since this might
- * result in segmentation problems on certain older machines, and in fact,
- * we should not assume that it can handle exactly 65536 bytes at a time,
- * since the internal functions may use an unsigned short to specify size.
- *
- * In general, these problems occur only on machines (such as most personal
- * computers) which use 2 byte "int" values, and which use "int" for the
- * arguments to the relevent functions.
- */
-
-typedef struct header header;
-
-struct header
-{
- u16b info_num; /* Number of "info" records */
-
- u32b name_size; /* Size of the "name" array in bytes */
-
- u32b text_size; /* Size of the "text" array in bytes */
-};
-
-
-/*
- * "Themed" objects.
- * Probability in percent for each class of objects to be dropped.
- * This could perhaps be an array - but that wouldn't be as clear.
- */
-typedef struct obj_theme obj_theme;
-struct obj_theme
-{
- byte treasure;
- byte combat;
- byte magic;
- byte tools;
-};
-
-
-/*
- * Information about terrain "features"
- */
-
-typedef struct feature_type feature_type;
-
-struct feature_type
-{
- u32b name; /* Name (offset) */
- u32b text; /* Text (offset) */
- u32b tunnel; /* Text for tunneling */
- u32b block; /* Text for blocking */
-
- byte mimic; /* Feature to mimic */
-
- u32b flags1; /* First set of flags */
-
- byte extra; /* Extra byte (unused) */
-
- s16b unused; /* Extra bytes (unused) */
-
- byte d_attr; /* Default feature attribute */
- char d_char; /* Default feature character */
-
-
- byte x_attr; /* Desired feature attribute */
- char x_char; /* Desired feature character */
-
- byte shimmer[7]; /* Shimmer colors */
-
- int d_dice[4]; /* Number of dices */
- int d_side[4]; /* Number of sides */
- int d_frequency[4]; /* Frequency of damage (1 is the minimum) */
- int d_type[4]; /* Type of damage */
-};
-
-
-/*
- * Information about object "kinds", including player knowledge.
- *
- * Only "aware" and "tried" are saved in the savefile
- */
-
-typedef struct object_kind object_kind;
-
-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 activate; /* Activation number */
-
- s16b ac; /* Base armor */
-
- byte dd, 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 */
-
- u32b oflags1; /* Obvious Flags, set 1 */
- u32b oflags2; /* Obvious Flags, set 2 */
- u32b oflags3; /* Obvious Flags, set 3 */
- u32b oflags4; /* Obvious Flags, set 4 */
- u32b oflags5; /* Obvious 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 */
- u32b oesp; /* Obvious 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) */
-};
-
-
-
-/*
- * Information about "artifacts".
- *
- * Note that the save-file only writes "cur_num" to the savefile.
- *
- * Note that "max_num" is always "1" (if that artifact "exists")
- */
-
-typedef struct artifact_type artifact_type;
-
-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 activate; /* Activation Number */
-
- s16b ac; /* Base armor */
-
- byte dd, 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 */
-
- u32b oflags1; /* Obvious Flags, set 1 */
- u32b oflags2; /* Obvious Flags, set 2 */
- u32b oflags3; /* Obvious Flags, set 3 */
- u32b oflags4; /* Obvious Flags, set 4 */
- u32b oflags5; /* Obvious 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 */
- u32b oesp; /* ESP flags */
-
- s16b power; /* Power granted(if any) */
-
- s16b set; /* Does it belongs to a set ?*/
-};
-
-
-/*
- * Information about "ego-items".
- */
-
-typedef struct ego_item_type ego_item_type;
-
-struct ego_item_type
-{
- u32b name; /* Name (offset) */
- u32b text; /* Text (offset) */
-
- bool_ before; /* Before or after the object name ? */
-
- byte tval[10];
- byte min_sval[10];
- byte max_sval[10];
-
- 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 */
-
- s16b activate; /* Activation Number */
-
- 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 oflags1[5]; /* Ego-Item Obvious Flags, set 1 */
- u32b oflags2[5]; /* Ego-Item Obvious Flags, set 2 */
- u32b oflags3[5]; /* Ego-Item Obvious Flags, set 3 */
- u32b oflags4[5]; /* Ego-Item Obvious Flags, set 4 */
- u32b oflags5[5]; /* Ego-Item Obvious Flags, set 5 */
- u32b oesp[5]; /* Obvious ESP flags */
- u32b fego[5]; /* ego flags */
-
- u32b need_flags1; /* Ego-Item Flags, set 1 */
- u32b need_flags2; /* Ego-Item Flags, set 2 */
- u32b need_flags3; /* Ego-Item Flags, set 3 */
- u32b need_flags4; /* Ego-Item Flags, set 4 */
- u32b need_flags5; /* Ego-Item Flags, set 5 */
- u32b need_esp; /* ESP flags */
- u32b forbid_flags1; /* Ego-Item Flags, set 1 */
- u32b forbid_flags2; /* Ego-Item Flags, set 2 */
- u32b forbid_flags3; /* Ego-Item Flags, set 3 */
- u32b forbid_flags4; /* Ego-Item Flags, set 4 */
- u32b forbid_flags5; /* Ego-Item Flags, set 5 */
- u32b forbid_esp; /* ESP flags */
-
- s16b power; /* Power granted(if any) */
-};
-
-
-/*
- * Information about "random artifacts parts".
- */
-typedef struct randart_part_type randart_part_type;
-struct randart_part_type
-{
- byte tval[20];
- byte min_sval[20];
- byte max_sval[20];
-
- 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 value; /* power value */
- s16b max; /* Number of time it can appear on a single item */
-
- u32b flags1; /* Ego-Item Flags, set 1 */
- u32b flags2; /* Ego-Item Flags, set 2 */
- u32b flags3; /* Ego-Item Flags, set 3 */
- u32b flags4; /* Ego-Item Flags, set 4 */
- u32b flags5; /* Ego-Item Flags, set 5 */
- u32b esp; /* ESP flags */
- u32b fego; /* ego flags */
-
- u32b aflags1; /* Ego-Item Flags, set 1 */
- u32b aflags2; /* Ego-Item Flags, set 2 */
- u32b aflags3; /* Ego-Item Flags, set 3 */
- u32b aflags4; /* Ego-Item Flags, set 4 */
- u32b aflags5; /* Ego-Item Flags, set 5 */
- u32b aesp; /* ESP flags */
-
- s16b power; /* Power granted(if any) */
-};
-
-typedef struct randart_gen_type randart_gen_type;
-struct randart_gen_type
-{
- int chance; /* Chance to have that number of powers */
- int dd;
- int ds;
- int plus; /* xdy+plus power */
-};
-
-
-/*
- * Monster blow structure
- *
- * - Method (RBM_*)
- * - Effect (RBE_*)
- * - Damage Dice
- * - Damage Sides
- */
-
-typedef struct monster_blow monster_blow;
-
-struct monster_blow
-{
- byte method;
- byte effect;
- byte d_dice;
- byte d_side;
-};
-
-
-
-/*
- * Monster "race" information, including racial memories
- *
- * Note that "d_attr" and "d_char" are used for MORE than "visual" stuff.
- *
- * Note that "x_attr" and "x_char" are used ONLY for "visual" stuff.
- *
- * Note that "cur_num" (and "max_num") represent the number of monsters
- * of the given race currently on (and allowed on) the current level.
- * This information yields the "dead" flag for Unique monsters.
- *
- * Note that "max_num" is reset when a new player is created.
- * Note that "cur_num" is reset when a new level is created.
- *
- * Note that several of these fields, related to "recall", can be
- * scrapped if space becomes an issue, resulting in less "complete"
- * monster recall (no knowledge of spells, etc). All of the "recall"
- * fields have a special prefix to aid in searching for them.
- */
-
-
-typedef struct monster_race monster_race;
-
-struct monster_race
-{
- u32b name; /* Name (offset) */
- u32b text; /* Text (offset) */
-
- u16b hdice; /* Creatures hit dice count */
- u16b hside; /* Creatures hit dice sides */
-
- s16b ac; /* Armour Class */
-
- s16b sleep; /* Inactive counter (base) */
- byte aaf; /* Area affect radius (1-100) */
- byte speed; /* Speed (normally 110) */
-
- s32b mexp; /* Exp value for kill */
-
- s32b weight; /* Weight of the monster */
-
- byte freq_inate; /* Inate spell frequency */
- byte freq_spell; /* Other spell frequency */
-
- u32b flags1; /* Flags 1 (general) */
- u32b flags2; /* Flags 2 (abilities) */
- u32b flags3; /* Flags 3 (race/resist) */
- u32b flags4; /* Flags 4 (inate/breath) */
- u32b flags5; /* Flags 5 (normal spells) */
- u32b flags6; /* Flags 6 (special spells) */
- u32b flags7; /* Flags 7 (movement related abilities) */
- u32b flags8; /* Flags 8 (wilderness info) */
- u32b flags9; /* Flags 9 (drops info) */
-
- monster_blow blow[4]; /* Up to four blows per round */
-
- byte body_parts[BODY_MAX]; /* To help to decide what to use when body changing */
-
- byte level; /* Level of creature */
- byte rarity; /* Rarity of creature */
-
-
- byte d_attr; /* Default monster attribute */
- char d_char; /* Default monster character */
-
-
- byte x_attr; /* Desired monster attribute */
- char x_char; /* Desired monster character */
-
-
- s16b max_num; /* Maximum population allowed per level */
-
- byte cur_num; /* Monster population on current level */
-
-
- s16b r_sights; /* Count sightings of this monster */
- s16b r_deaths; /* Count deaths from this monster */
-
- s16b r_pkills; /* Count monsters killed in this life */
- s16b r_tkills; /* Count monsters killed in all lives */
-
- byte r_wake; /* Number of times woken up (?) */
- byte r_ignore; /* Number of times ignored (?) */
-
- byte r_xtra1; /* Something (unused) */
- byte r_xtra2; /* Something (unused) */
-
- byte r_drop_gold; /* Max number of gold dropped at once */
- byte r_drop_item; /* Max number of item dropped at once */
-
- byte r_cast_inate; /* Max number of inate spells seen */
- byte r_cast_spell; /* Max number of other spells seen */
-
- byte r_blows[4]; /* Number of times each blow type was seen */
-
- u32b r_flags1; /* Observed racial flags */
- u32b r_flags2; /* Observed racial flags */
- u32b r_flags3; /* Observed racial flags */
- u32b r_flags4; /* Observed racial flags */
- u32b r_flags5; /* Observed racial flags */
- u32b r_flags6; /* Observed racial flags */
- u32b r_flags7; /* Observed racial flags */
- u32b r_flags8; /* Observed racial flags */
- u32b r_flags9; /* Observed racial flags */
-
- bool_ on_saved; /* Is the (unique) on a saved level ? */
-
- byte total_visible; /* Amount of this race that are visible */
-
- obj_theme drops; /* The drops type */
-};
-
-
-typedef struct monster_ego monster_ego;
-
-struct monster_ego
-{
- u32b name; /* Name (offset) */
- bool_ before; /* Display ego before or after */
-
- monster_blow blow[4]; /* Up to four blows per round */
- byte blowm[4][2];
-
- s16b hdice; /* Creatures hit dice count */
- s16b hside; /* Creatures hit dice sides */
-
- s16b ac; /* Armour Class */
-
- s16b sleep; /* Inactive counter (base) */
- s16b aaf; /* Area affect radius (1-100) */
- s16b speed; /* Speed (normally 110) */
-
- s32b mexp; /* Exp value for kill */
-
- s32b weight; /* Weight of the monster */
-
- byte freq_inate; /* Inate spell frequency */
- byte freq_spell; /* Other spell frequency */
-
- /* Ego flags */
- u32b flags1; /* Flags 1 */
- u32b flags2; /* Flags 1 */
- u32b flags3; /* Flags 1 */
- u32b flags7; /* Flags 1 */
- u32b flags8; /* Flags 1 */
- u32b flags9; /* Flags 1 */
- u32b hflags1; /* Flags 1 */
- u32b hflags2; /* Flags 1 */
- u32b hflags3; /* Flags 1 */
- u32b hflags7; /* Flags 1 */
- u32b hflags8; /* Flags 1 */
- u32b hflags9; /* Flags 1 */
-
- /* Monster flags */
- u32b mflags1; /* Flags 1 (general) */
- u32b mflags2; /* Flags 2 (abilities) */
- u32b mflags3; /* Flags 3 (race/resist) */
- u32b mflags4; /* Flags 4 (inate/breath) */
- u32b mflags5; /* Flags 5 (normal spells) */
- u32b mflags6; /* Flags 6 (special spells) */
- u32b mflags7; /* Flags 7 (movement related abilities) */
- u32b mflags8; /* Flags 8 (wilderness info) */
- u32b mflags9; /* Flags 9 (drops info) */
-
- /* Negative Flags, to be removed from the monster flags */
- u32b nflags1; /* Flags 1 (general) */
- u32b nflags2; /* Flags 2 (abilities) */
- u32b nflags3; /* Flags 3 (race/resist) */
- u32b nflags4; /* Flags 4 (inate/breath) */
- u32b nflags5; /* Flags 5 (normal spells) */
- u32b nflags6; /* Flags 6 (special spells) */
- u32b nflags7; /* Flags 7 (movement related abilities) */
- u32b nflags8; /* Flags 8 (wilderness info) */
- u32b nflags9; /* Flags 9 (drops info) */
-
- s16b level; /* Level of creature */
- s16b rarity; /* Rarity of creature */
-
-
- byte d_attr; /* Default monster attribute */
- char d_char; /* Default monster character */
-
- byte g_attr; /* Overlay graphic attribute */
- char g_char; /* Overlay graphic character */
-
- char r_char[5]; /* Monster race allowed */
- char nr_char[5]; /* Monster race not allowed */
-};
-
-
-
-/*
- * Information about "vault generation"
- */
-
-typedef struct vault_type vault_type;
-
-struct vault_type
-{
- u32b name; /* Name (offset) */
- u32b text; /* Text (offset) */
-
- byte typ; /* Vault type */
-
- byte rat; /* Vault rating */
-
- byte hgt; /* Vault height */
- byte wid; /* Vault width */
-
- s16b lvl; /* level of special (if any) */
- byte dun_type; /* Dungeon type where the level will show up */
-
- s16b mon[10]; /* special monster */
- int item[3]; /* number of item (usually artifact) */
-};
-
-
-/* jk */
-/* name and description are in some other arrays */
-typedef struct trap_type trap_type;
-
-struct trap_type
-{
- s16b probability; /* probability of existence */
- s16b another; /* does this trap easily combine */
- s16b p1valinc; /* how much does this trap attribute to p1val */
- byte difficulty; /* how difficult to disarm */
- byte minlevel; /* what is the minimum level on which the traps should be */
- byte color; /* what is the color on screen */
- u32b flags; /* where can these traps go - and perhaps other flags */
- bool_ ident; /* do we know the name */
- s16b known; /* how well is this trap known */
- s16b name; /* normal name like weakness */
- s16b dd, ds; /* base damage */
- s16b text; /* longer description once you've met this trap */
- byte g_attr; /* Overlay graphic attribute */
- char g_char; /* Overlay graphic character */
-};
-
-
-
-/*
- * A single "grid" in a Cave
- *
- * Note that several aspects of the code restrict the actual cave
- * to a max size of 256 by 256. In partcular, locations are often
- * saved as bytes, limiting each coordinate to the 0-255 range.
- *
- * The "o_idx" and "m_idx" fields are very interesting. There are
- * many places in the code where we need quick access to the actual
- * monster or object(s) in a given cave grid. The easiest way to
- * do this is to simply keep the index of the monster and object
- * (if any) with the grid, but this takes 198*66*4 bytes of memory.
- * Several other methods come to mind, which require only half this
- * amound of memory, but they all seem rather complicated, and would
- * probably add enough code that the savings would be lost. So for
- * these reasons, we simply store an index into the "o_list" and
- * "m_list" arrays, using "zero" when no monster/object is present.
- *
- * Note that "o_idx" is the index of the top object in a stack of
- * objects, using the "next_o_idx" field of objects (see below) to
- * create the singly linked list of objects. If "o_idx" is zero
- * then there are no objects in the grid.
- */
-
-typedef struct cave_type cave_type;
-
-struct cave_type
-{
- u16b info; /* Hack -- cave flags */
-
- byte feat; /* Hack -- feature type */
-
- s16b o_idx; /* Object in this grid */
-
- s16b m_idx; /* Monster in this grid */
-
- s16b t_idx; /* trap index (in t_list) or zero */
-
- s16b special, special2; /* Special cave info */
-
- s16b inscription; /* Inscription of the grid */
-
- byte mana; /* Magical energy of the grid */
-
- byte mimic; /* Feature to mimic */
-
- byte cost; /* Hack -- cost of flowing */
- byte when; /* Hack -- when cost was computed */
-
- s16b effect; /* The lasting effects */
-};
-
-/* Lasting spell effects(clouds, ..) */
-typedef struct effect_type effect_type;
-struct effect_type
-{
- s16b time; /* For how long */
- s16b dam; /* How much damage */
- s16b type; /* Of which type */
- s16b cy; /* Center of the cast*/
- s16b cx; /* Center of the cast*/
- s16b rad; /* Radius -- if needed */
- u32b flags; /* Flags */
-};
-
-/*
- * Object information, for a specific object.
- *
- * Note that a "discount" on an item is permanent and never goes away.
- *
- * Note that inscriptions are now handled via the "quark_str()" function
- * applied to the "note" field, which will return NULL if "note" is zero.
- *
- * Note that "object" records are "copied" on a fairly regular basis,
- * and care must be taken when handling such objects.
- *
- * Note that "object flags" must now be derived from the object kind,
- * the artifact and ego-item indexes, and the two "xtra" fields.
- *
- * Each cave grid points to one (or zero) objects via the "o_idx"
- * field (above). Each object then points to one (or zero) objects
- * via the "next_o_idx" field, forming a singly linked list, which
- * in game terms, represents a "stack" of objects in the same grid.
- *
- * Each monster points to one (or zero) objects via the "hold_o_idx"
- * field (below). Each object then points to one (or zero) objects
- * via the "next_o_idx" field, forming a singly linked list, which
- * in game terms, represents a pile of objects held by the monster.
- *
- * The "held_m_idx" field is used to indicate which monster, if any,
- * is holding the object. Objects being held have "ix=0" and "iy=0".
- */
-
-typedef struct object_type object_type;
-
-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, 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 */
-
- u32b art_oflags1; /* Obvious Flags, set 1 */
- u32b art_oflags2; /* Obvious Flags, set 2 */
- u32b art_oflags3; /* Obvious Flags, set 3 */
- u32b art_oflags4; /* Obvious Flags, set 4 */
- u32b art_oflags5; /* Obvious Flags, set 5 */
- u32b art_oesp; /* Obvious Flags, set esp */
-
- 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 */
- s16b found_aux3; /* Stores info for found */
- s16b found_aux4; /* Stores info for found */
-};
-
-
-/*
- * 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.
- *
- * Note: fy, fx constrain dungeon size to 256x256
- *
- * The "hold_o_idx" field points to the first object of a stack
- * of objects (if any) being carried by the monster (see above).
- */
-
-typedef struct monster_type monster_type;
-
-struct monster_type
-{
- s16b r_idx; /* Monster race index */
-
- u16b ego; /* Ego monster type */
-
- byte fy; /* Y location on map */
- byte fx; /* X location on map */
-
- s32b hp; /* Current Hit points */
- s32b maxhp; /* Max Hit points */
-
- monster_blow blow[4]; /* Up to four blows per round */
-
- byte speed; /* Speed (normally 110) */
- byte level; /* Level of creature */
- s16b ac; /* Armour Class */
- u32b exp; /* Experience */
-
- s16b csleep; /* Inactive counter */
-
- byte mspeed; /* Monster "speed" */
- byte energy; /* Monster "energy" */
-
- byte stunned; /* Monster is stunned */
- byte confused; /* Monster is confused */
- byte monfear; /* Monster is afraid */
-
- s16b bleeding; /* Monster is bleeding */
- s16b poisoned; /* Monster is poisoned */
-
- byte cdis; /* Current dis from player */
-
- s32b mflag; /* Extra monster flags */
-
- bool_ ml; /* Monster is "visible" */
-
- s16b hold_o_idx; /* Object being held (if any) */
-
- u32b smart; /* Field for "smart_learn" */
-
- s16b status; /* Status(friendly, pet, companion, ..) */
-
- 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) */
-
- monster_mind *mind; /* Does it have a mind? */
-};
-
-
-
-
-/*
- * An entry for the object/monster allocation functions
- *
- * Pass 1 is determined from allocation information
- * Pass 2 is determined from allocation restriction
- * Pass 3 is determined from allocation calculation
- */
-
-typedef struct alloc_entry alloc_entry;
-
-struct alloc_entry
-{
- s16b index; /* The actual index */
-
- byte level; /* Base dungeon level */
- byte prob1; /* Probability, pass 1 */
- byte prob2; /* Probability, pass 2 */
- byte prob3; /* Probability, pass 3 */
-
- u16b total; /* Unused for now */
-};
-
-
-
-/*
- * Available "options"
- *
- * - Address of actual option variable (or NULL)
- *
- * - Normal Value (TRUE or FALSE)
- *
- * - Option Page Number (or zero)
- *
- * - Savefile Set (or zero)
- * - Savefile Bit in that set
- *
- * - Textual name (or NULL)
- * - Textual description
- */
-
-typedef struct option_type option_type;
-
-struct option_type
-{
- bool_ *o_var;
-
- byte o_norm;
-
- byte o_page;
-
- byte o_bit;
-
- cptr o_text;
- cptr o_desc;
-};
-
-/*
- * A store owner
- */
-typedef struct owner_type owner_type;
-
-struct owner_type
-{
- u32b name; /* Name (offset) */
-
- s16b max_cost; /* Purse limit */
-
- byte max_inflate; /* Inflation (max) */
- byte min_inflate; /* Inflation (min) */
-
- byte haggle_per; /* Haggle unit */
-
- byte insult_max; /* Insult limit */
-
- u32b races[2][2]; /* Liked/hated races */
- u32b classes[2][2]; /* Liked/hated classes */
-
- s16b costs[3]; /* Costs for liked people */
-};
-
-
-
-
-/*
- * A store, with an owner, various state flags, a current stock
- * of items, and a table of items that are often purchased.
- */
-typedef struct store_type store_type;
-
-struct store_type
-{
- u16b st_idx;
-
- 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 */
-
- byte stock_num; /* Stock -- Number of entries */
- s16b stock_size; /* Stock -- Total Size of Array */
- object_type *stock; /* Stock -- Actual stock items */
-};
-
-/*
- * A store/building type
- */
-typedef struct store_info_type store_info_type;
-
-struct store_info_type
-{
- u32b name; /* Name (offset) */
-
- s16b table[STORE_CHOICES][2]; /* Table -- Legal item kinds */
- byte table_num; /* Number of items */
- s16b max_obj; /* Number of items this store can hold */
-
- u16b owners[4]; /* List of owners(refers to ow_info) */
-
- u16b actions[6]; /* Actions(refers to ba_info) */
-
- byte d_attr; /* Default building attribute */
- char d_char; /* Default building character */
-
- byte x_attr; /* Desired building attribute */
- char x_char; /* Desired building character */
-
- u32b flags1; /* Flags */
-};
-
-/*
- * Stores/buildings actions
- */
-typedef struct store_action_type store_action_type;
-
-struct store_action_type
-{
- u32b name; /* Name (offset) */
-
- s16b costs[3]; /* Costs for liked people */
- char letter; /* Action letter */
- char letter_aux; /* Action letter */
- s16b action; /* Action code */
- s16b action_restr; /* Action restriction */
-};
-
-/*
- * the spell function must provide the desc
- */
-typedef struct magic_type magic_type;
-
-struct magic_type
-{
- byte slevel; /* Required level (to learn) */
- byte smana; /* Required mana (to cast) */
- byte sfail; /* Minimum chance of failure */
- byte sexp; /* Encoded experience bonus */
-};
-
-/*
- * Player sex info
- */
-
-typedef struct player_sex player_sex;
-
-struct player_sex
-{
- cptr title; /* Type of sex */
-
- cptr winner; /* Name of winner */
-};
-
-
-/*
- * Player racial info
- */
-
-typedef struct player_race player_race;
-
-struct player_race
-{
- s32b title; /* Type of race */
- s32b desc;
-
- s16b r_adj[6]; /* Racial stat bonuses */
-
- char luck; /* Luck */
-
- s16b r_dis; /* disarming */
- s16b r_dev; /* magic devices */
- s16b r_sav; /* saving throw */
- s16b r_stl; /* stealth */
- s16b r_srh; /* search ability */
- s16b r_fos; /* search frequency */
- s16b r_thn; /* combat (normal) */
- s16b r_thb; /* combat (shooting) */
-
- byte r_mhp; /* Race hit-dice modifier */
- u16b r_exp; /* Race experience factor */
-
- byte b_age; /* base age */
- byte m_age; /* mod age */
-
- byte m_b_ht; /* base height (males) */
- byte m_m_ht; /* mod height (males) */
- byte m_b_wt; /* base weight (males) */
- byte m_m_wt; /* mod weight (males) */
-
- byte f_b_ht; /* base height (females) */
- byte f_m_ht; /* mod height (females) */
- byte f_b_wt; /* base weight (females) */
- byte f_m_wt; /* mod weight (females) */
-
- byte infra; /* Infra-vision range */
-
- u32b choice[2]; /* Legal class choices */
-
- s16b powers[4]; /* Powers of the race */
-
- byte body_parts[BODY_MAX]; /* To help to decide what to use when body changing */
-
- s16b chart; /* Chart history */
-
- u32b flags1;
- u32b flags2; /* flags */
-
- u32b oflags1[PY_MAX_LEVEL + 1];
- u32b oflags2[PY_MAX_LEVEL + 1];
- u32b oflags3[PY_MAX_LEVEL + 1];
- u32b oflags4[PY_MAX_LEVEL + 1];
- u32b oflags5[PY_MAX_LEVEL + 1];
- u32b oesp[PY_MAX_LEVEL + 1];
- s16b opval[PY_MAX_LEVEL + 1];
-
- char skill_basem[MAX_SKILLS];
- u32b skill_base[MAX_SKILLS];
- char skill_modm[MAX_SKILLS];
- s16b skill_mod[MAX_SKILLS];
-
- s16b obj_tval[5];
- s16b obj_sval[5];
- s16b obj_pval[5];
- s16b obj_dd[5];
- s16b obj_ds[5];
- s16b obj_num;
-
- struct
- {
- s16b ability;
- s16b level;
- } abilities[10]; /* Abilitiers to be gained by level(doesnt take prereqs in account) */
-};
-
-typedef struct player_race_mod player_race_mod;
-
-struct player_race_mod
-{
- s32b title; /* Type of race mod */
- s32b desc; /* Desc */
- bool_ place; /* TRUE = race race modifier, FALSE = Race modifier race */
-
- s16b r_adj[6]; /* (+) Racial stat bonuses */
-
- char luck; /* Luck */
- s16b mana; /* Mana % */
-
- s16b r_dis; /* (+) disarming */
- s16b r_dev; /* (+) magic devices */
- s16b r_sav; /* (+) saving throw */
- s16b r_stl; /* (+) stealth */
- s16b r_srh; /* (+) search ability */
- s16b r_fos; /* (+) search frequency */
- s16b r_thn; /* (+) combat (normal) */
- s16b r_thb; /* (+) combat (shooting) */
-
- char r_mhp; /* (+) Race mod hit-dice modifier */
- s16b r_exp; /* (+) Race mod experience factor */
-
- char b_age; /* (+) base age */
- char m_age; /* (+) mod age */
-
- char m_b_ht; /* (+) base height (males) */
- char m_m_ht; /* (+) mod height (males) */
- char m_b_wt; /* (+) base weight (males) */
- char m_m_wt; /* (+) mod weight (males) */
-
- char f_b_ht; /* (+) base height (females) */
- char f_m_ht; /* (+) mod height (females) */
- char f_b_wt; /* (+) base weight (females) */
- char f_m_wt; /* (+) mod weight (females) */
-
- char infra; /* (+) Infra-vision range */
-
- u32b choice[2]; /* Legal race choices */
-
- u32b pclass[2]; /* Classes allowed */
- u32b mclass[2]; /* Classes restricted */
-
- s16b powers[4]; /* Powers of the subrace */
-
- char body_parts[BODY_MAX]; /* To help to decide what to use when body changing */
-
- u32b flags1;
- u32b flags2; /* flags */
-
- u32b oflags1[PY_MAX_LEVEL + 1];
- u32b oflags2[PY_MAX_LEVEL + 1];
- u32b oflags3[PY_MAX_LEVEL + 1];
- u32b oflags4[PY_MAX_LEVEL + 1];
- u32b oflags5[PY_MAX_LEVEL + 1];
- u32b oesp[PY_MAX_LEVEL + 1];
- s16b opval[PY_MAX_LEVEL + 1];
-
- byte g_attr; /* Overlay graphic attribute */
- char g_char; /* Overlay graphic character */
-
- char skill_basem[MAX_SKILLS];
- u32b skill_base[MAX_SKILLS];
- char skill_modm[MAX_SKILLS];
- s16b skill_mod[MAX_SKILLS];
-
- s16b obj_tval[5];
- s16b obj_sval[5];
- s16b obj_pval[5];
- s16b obj_dd[5];
- s16b obj_ds[5];
- s16b obj_num;
-
- struct
- {
- s16b ability;
- s16b level;
- } abilities[10]; /* Abilitiers to be gained by level(doesnt take prereqs in account) */
-};
-
-
-/*
- * Player class info
- */
-
-typedef struct player_spec player_spec;
-
-struct player_spec
-{
- s32b title; /* Type of class spec */
- s32b desc; /* Small desc of the class spec */
-
- char skill_basem[MAX_SKILLS]; /* Mod for value */
- u32b skill_base[MAX_SKILLS]; /* value */
- char skill_modm[MAX_SKILLS]; /* mod for mod */
- s16b skill_mod[MAX_SKILLS]; /* mod */
-
- u32b skill_ideal[MAX_SKILLS]; /* Ideal skill levels at level 50 */
-
- s16b obj_tval[5];
- s16b obj_sval[5];
- s16b obj_pval[5];
- s16b obj_dd[5];
- s16b obj_ds[5];
- s16b obj_num;
-
- u32b gods;
-
- u32b flags1;
- u32b flags2; /* flags */
-
- struct
- {
- s16b ability;
- s16b level;
- } abilities[10]; /* Abilitiers to be gained by level(doesnt take prereqs in account) */
-};
-
-typedef struct player_class player_class;
-
-struct player_class
-{
- s32b title; /* Type of class */
- s32b desc; /* Small desc of the class */
- s32b titles[PY_MAX_LEVEL / 5];
-
- s16b c_adj[6]; /* Class stat modifier */
-
- s16b c_dis; /* class disarming */
- s16b c_dev; /* class magic devices */
- s16b c_sav; /* class saving throws */
- s16b c_stl; /* class stealth */
- s16b c_srh; /* class searching ability */
- s16b c_fos; /* class searching frequency */
- s16b c_thn; /* class to hit (normal) */
- s16b c_thb; /* class to hit (bows) */
-
- s16b x_dis; /* extra disarming */
- s16b x_dev; /* extra magic devices */
- s16b x_sav; /* extra saving throws */
- s16b x_stl; /* extra stealth */
- s16b x_srh; /* extra searching ability */
- s16b x_fos; /* extra searching frequency */
- s16b x_thn; /* extra to hit (normal) */
- s16b x_thb; /* extra to hit (bows) */
-
- s16b c_mhp; /* Class hit-dice adjustment */
- s16b c_exp; /* Class experience factor */
-
- s16b powers[4]; /* Powers of the class */
-
- s16b spell_book; /* Tval of spell books (if any) */
- s16b spell_stat; /* Stat for spells (if any) */
- s16b spell_lev; /* The higher it is the higher the spells level are */
- s16b spell_fail; /* The higher it is the higher the spells failure are */
- s16b spell_mana; /* The higher it is the higher the spells mana are */
- s16b spell_first; /* Level of first spell */
- s16b spell_weight; /* Weight that hurts spells */
- byte max_spell_level; /* Maximun spell level */
- byte magic_max_spell; /* Maximun numbner of spells one can learn by natural means */
-
- u32b flags1; /* flags */
- u32b flags2; /* flags */
-
- s16b mana;
- s16b blow_num;
- s16b blow_wgt;
- s16b blow_mul;
- s16b extra_blows;
-
- s32b sense_base;
- s32b sense_pl;
- s32b sense_plus;
- byte sense_heavy;
- byte sense_heavy_magic;
-
- s16b obj_tval[5];
- s16b obj_sval[5];
- s16b obj_pval[5];
- s16b obj_dd[5];
- s16b obj_ds[5];
- s16b obj_num;
-
- char body_parts[BODY_MAX]; /* To help to decide what to use when body changing */
-
- u32b oflags1[PY_MAX_LEVEL + 1];
- u32b oflags2[PY_MAX_LEVEL + 1];
- u32b oflags3[PY_MAX_LEVEL + 1];
- u32b oflags4[PY_MAX_LEVEL + 1];
- u32b oflags5[PY_MAX_LEVEL + 1];
- u32b oesp[PY_MAX_LEVEL + 1];
- s16b opval[PY_MAX_LEVEL + 1];
-
- char skill_basem[MAX_SKILLS];
- u32b skill_base[MAX_SKILLS];
- char skill_modm[MAX_SKILLS];
- s16b skill_mod[MAX_SKILLS];
-
- u32b gods;
-
- player_spec spec[MAX_SPEC];
-
- struct
- {
- s16b ability;
- s16b level;
- } abilities[10]; /* Abilitiers to be gained by level(doesnt take prereqs in account) */
-};
-
-typedef struct meta_class_type meta_class_type;
-struct meta_class_type
-{
- char name[80]; /* Name */
- byte color;
- s16b *classes; /* list of classes */
-};
-
-/* Help type */
-typedef struct help_info help_info;
-struct help_info
-{
- bool_ enabled; /* ingame help enabled */
-
- u32b help1; /* help flags 1 */
-};
-
-
-/*
- * Most of the "player" information goes here.
- *
- * This stucture gives us a large collection of player variables.
- *
- * This structure contains several "blocks" of information.
- * (1) the "permanent" info
- * (2) the "variable" info
- * (3) the "transient" info
- *
- * All of the "permanent" info, and most of the "variable" info,
- * is saved in the savefile. The "transient" info is recomputed
- * whenever anything important changes.
- */
-
-typedef struct player_type player_type;
-
-struct player_type
-{
- s32b lives; /* How many times we resurected */
-
- s16b oldpy; /* Previous player location -KMW- */
- s16b oldpx; /* Previous player location -KMW- */
-
- s16b py; /* Player location */
- s16b px; /* Player location */
-
- byte psex; /* Sex index */
- byte prace; /* Race index */
- byte pracem; /* Race Mod index */
- byte pclass; /* Class index */
- byte pspec; /* Class spec index */
- byte mimic_form; /* Actualy transformation */
- s16b mimic_level; /* Level of the mimic effect */
- byte oops; /* Unused */
-
- object_type inventory[INVEN_TOTAL]; /* Player inventory */
-
- byte hitdie; /* Hit dice (sides) */
- u16b expfact; /* Experience factor */
-
- byte maximize; /* Maximize stats */
- byte preserve; /* Preserve artifacts */
- byte special; /* Special levels */
- byte allow_one_death; /* Blood of life */
-
- s16b age; /* Characters age */
- s16b ht; /* Height */
- s16b wt; /* Weight */
- s16b sc; /* Social Class */
-
-
- s32b au; /* Current Gold */
-
- s32b max_exp; /* Max experience */
- s32b exp; /* Cur experience */
- u16b exp_frac; /* Cur exp frac (times 2^16) */
-
- s16b lev; /* Level */
-
- s16b town_num; /* Current town number */
- s16b arena_number; /* monster number in arena -KMW- */
- s16b inside_arena; /* Is character inside arena? */
- s16b inside_quest; /* Inside quest level */
- bool_ exit_bldg; /* Goal obtained in arena? -KMW- */
-
- s32b wilderness_x; /* Coordinates in the wilderness */
- s32b wilderness_y;
- bool_ wild_mode; /* TRUE = Small map, FLASE = Big map */
- bool_ old_wild_mode; /* TRUE = Small map, FLASE = Big map */
-
- s16b mhp; /* Max hit pts */
- s16b chp; /* Cur hit pts */
- u16b chp_frac; /* Cur hit frac (times 2^16) */
- s16b hp_mod; /* A modificator(permanent) */
-
- s16b msp; /* Max mana pts */
- s16b csp; /* Cur mana pts */
- u16b csp_frac; /* Cur mana frac (times 2^16) */
-
- s16b msane; /* Max sanity */
- s16b csane; /* Cur sanity */
- u16b csane_frac; /* Cur sanity frac */
-
- s32b grace; /* Your God's appreciation factor. */
- byte pgod; /* Your God. */
- bool_ praying; /* Praying to your god. */
- s16b melkor_sacrifice; /* How much hp has been sacrified for damage */
-
- s16b max_plv; /* Max Player Level */
-
- s16b stat_max[6]; /* Current "maximal" stat values */
- s16b stat_cur[6]; /* Current "natural" stat values */
-
- s16b luck_cur; /* Current "natural" luck value (range -30 <> 30) */
- s16b luck_max; /* Current "maximal base" luck value (range -30 <> 30) */
- s16b luck_base; /* Current "base" luck value (range -30 <> 30) */
-
- s16b speed_factor; /* Timed -- Fast */
- s16b fast; /* Timed -- Fast */
- s16b lightspeed; /* Timed -- Light Speed */
- s16b slow; /* Timed -- Slow */
- s16b blind; /* Timed -- Blindness */
- s16b paralyzed; /* Timed -- Paralysis */
- s16b confused; /* Timed -- Confusion */
- s16b afraid; /* Timed -- Fear */
- s16b image; /* Timed -- Hallucination */
- s16b poisoned; /* Timed -- Poisoned */
- s16b cut; /* Timed -- Cut */
- s16b stun; /* Timed -- Stun */
-
- s16b protevil; /* Timed -- Protection from Evil*/
- s16b protgood; /* Timed -- Protection from Good*/
- s16b protundead; /* Timed -- Protection from Undead*/
- s16b invuln; /* Timed -- Invulnerable */
- s16b hero; /* Timed -- Heroism */
- s16b shero; /* Timed -- Super Heroism */
- s16b shield; /* Timed -- Shield Spell */
- s16b shield_power; /* Timed -- Shield Spell Power */
- s16b shield_opt; /* Timed -- Shield Spell options */
- s16b shield_power_opt; /* Timed -- Shield Spell Power */
- s16b shield_power_opt2; /* Timed -- Shield Spell Power */
- s16b blessed; /* Timed -- Blessed */
- s16b tim_invis; /* Timed -- See Invisible */
- s16b tim_infra; /* Timed -- Infra Vision */
-
- s16b oppose_acid; /* Timed -- oppose acid */
- s16b oppose_elec; /* Timed -- oppose lightning */
- s16b oppose_fire; /* Timed -- oppose heat */
- s16b oppose_cold; /* Timed -- oppose cold */
- s16b oppose_pois; /* Timed -- oppose poison */
- s16b oppose_ld; /* Timed -- oppose light & dark */
- s16b oppose_cc; /* Timed -- oppose chaos & confusion */
- s16b oppose_ss; /* Timed -- oppose sound & shards */
- s16b oppose_nex; /* Timed -- oppose nexus */
-
- s16b rush; /* Rush and Bush */
-
- s16b tim_esp; /* Timed ESP */
- s16b tim_wraith; /* Timed wraithform */
- s16b tim_ffall; /* Timed Levitation */
- s16b tim_fly; /* Timed Levitation */
- s16b tim_fire_aura; /* Timed Fire Aura */
- s16b tim_poison; /* Timed poison hands */
- s16b tim_thunder; /* Timed thunderstorm */
- s16b tim_thunder_p1; /* Timed thunderstorm */
- s16b tim_thunder_p2; /* Timed thunderstorm */
-
- s16b tim_project; /* Timed project upon melee blow */
- s16b tim_project_dam;
- s16b tim_project_gf;
- s16b tim_project_rad;
- s16b tim_project_flag;
-
- s16b tim_roots; /* Timed roots */
- s16b tim_roots_ac;
- s16b tim_roots_dam;
-
- s16b resist_magic; /* Timed Resist Magic (later) */
- s16b tim_invisible; /* Timed Invisibility */
- s16b tim_inv_pow; /* Power of timed invisibility */
- s16b tim_mimic; /* Timed Mimic */
- s16b tim_lite; /* Timed Lite */
- s16b tim_regen; /* Timed extra regen */
- s16b tim_regen_pow; /* Timed extra regen power */
- s16b holy; /* Holy Aura */
- s16b walk_water; /* Walk over water as a god */
- s16b tim_mental_barrier; /* Sustain Int&Wis */
- s16b strike; /* True Strike(+25 hit) */
- s16b meditation; /* Meditation(+50 mana -25 to hit/to dam) */
- s16b tim_reflect; /* Timed Reflection */
- s16b tim_res_time; /* Timed Resistance to Time */
- s16b tim_deadly; /* Timed deadly blow */
- s16b prob_travel; /* Timed probability travel */
- s16b disrupt_shield;/* Timed disruption shield */
- s16b parasite; /* Timed parasite */
- s16b parasite_r_idx;/* Timed parasite monster */
- s32b loan; /* Amount of loan */
- s32b loan_time; /* Timer -- time to payback loan */
- 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 immov_cntr; /* Timed -- Last ``immovable'' command. */
-
- s16b chaos_patron;
-
- s16b recall_dungeon; /* Recall in which dungeon */
- s16b word_recall; /* Word of recall counter */
-
- s32b energy; /* Current energy */
-
- s16b food; /* Current nutrition */
-
- byte confusing; /* Glowing hands */
- byte searching; /* Currently searching */
-
- s16b new_spells; /* Number of spells available */
-
- s16b old_spells;
-
- s16b xtra_spells; /* Number of xtra spell learned(via potion) */
-
- bool_ old_cumber_armor;
- bool_ old_cumber_glove;
- bool_ old_heavy_wield;
- bool_ old_heavy_shoot;
- bool_ old_icky_wield;
-
- s16b old_lite; /* Old radius of lite (if any) */
- s16b old_view; /* Old radius of view (if any) */
-
- s16b old_food_aux; /* Old value of food */
-
-
- bool_ cumber_armor; /* Mana draining armor */
- bool_ cumber_glove; /* Mana draining gloves */
- bool_ heavy_wield; /* Heavy weapon */
- bool_ heavy_shoot; /* Heavy shooter */
- bool_ icky_wield; /* Icky weapon */
- bool_ immovable; /* Immovable character */
-
- s16b cur_lite; /* Radius of lite (if any) */
-
-
- u32b notice; /* Special Updates (bit flags) */
- u32b update; /* Pending Updates (bit flags) */
- u32b redraw; /* Normal Redraws (bit flags) */
- u32b window; /* Window Redraws (bit flags) */
-
- s16b stat_use[6]; /* Current modified stats */
- s16b stat_top[6]; /* Maximal modified stats */
-
- s16b stat_add[6]; /* Modifiers to stat values */
- s16b stat_ind[6]; /* Indexes into stat tables */
- s16b stat_cnt[6]; /* Counter for temporary drains */
- s16b stat_los[6]; /* Amount of temporary drains */
-
- bool_ immune_acid; /* Immunity to acid */
- bool_ immune_elec; /* Immunity to lightning */
- bool_ immune_fire; /* Immunity to fire */
- bool_ immune_cold; /* Immunity to cold */
- bool_ immune_neth; /* Immunity to nether */
-
- bool_ resist_acid; /* Resist acid */
- bool_ resist_elec; /* Resist lightning */
- bool_ resist_fire; /* Resist fire */
- bool_ resist_cold; /* Resist cold */
- bool_ resist_pois; /* Resist poison */
-
- bool_ resist_conf; /* Resist confusion */
- bool_ resist_sound; /* Resist sound */
- bool_ resist_lite; /* Resist light */
- bool_ resist_dark; /* Resist darkness */
- bool_ resist_chaos; /* Resist chaos */
- bool_ resist_disen; /* Resist disenchant */
- bool_ resist_shard; /* Resist shards */
- bool_ resist_nexus; /* Resist nexus */
- bool_ resist_blind; /* Resist blindness */
- bool_ resist_neth; /* Resist nether */
- bool_ resist_fear; /* Resist fear */
- bool_ resist_continuum; /* Resist space-time continuum disruption */
-
- bool_ sensible_fire; /* Fire does more damage on the player */
- bool_ sensible_lite; /* Lite does more damage on the player and blinds her/him */
-
- bool_ reflect; /* Reflect 'bolt' attacks */
- bool_ sh_fire; /* Fiery 'immolation' effect */
- bool_ sh_elec; /* Electric 'immolation' effect */
- bool_ wraith_form; /* wraithform */
-
- bool_ anti_magic; /* Anti-magic */
- bool_ anti_tele; /* Prevent teleportation */
-
- bool_ sustain_str; /* Keep strength */
- bool_ sustain_int; /* Keep intelligence */
- bool_ sustain_wis; /* Keep wisdom */
- bool_ sustain_dex; /* Keep dexterity */
- bool_ sustain_con; /* Keep constitution */
- bool_ sustain_chr; /* Keep charisma */
-
- bool_ aggravate; /* Aggravate monsters */
- bool_ teleport; /* Random teleporting */
-
- bool_ exp_drain; /* Experience draining */
- byte drain_mana; /* mana draining */
- byte drain_life; /* hp draining */
-
- bool_ magical_breath; /* Magical breathing -- can breath anywhere */
- bool_ water_breath; /* Water breathing -- can breath underwater */
- bool_ climb; /* Can climb mountains */
- bool_ fly; /* Can fly over some features */
- bool_ ffall; /* No damage falling */
- bool_ lite; /* Permanent light */
- bool_ free_act; /* Never paralyzed */
- bool_ see_inv; /* Can see invisible */
- bool_ regenerate; /* Regenerate hit pts */
- bool_ hold_life; /* Resist life draining */
- u32b telepathy; /* Telepathy */
- bool_ slow_digest; /* Slower digestion */
- bool_ bless_blade; /* Blessed blade */
- byte xtra_might; /* Extra might bow */
- bool_ impact; /* Earthquake blows */
- bool_ auto_id; /* Auto id items */
-
- s16b invis; /* Invisibility */
-
- s16b dis_to_h; /* Known bonus to hit */
- s16b dis_to_d; /* Known bonus to dam */
- s16b dis_to_a; /* Known bonus to ac */
-
- s16b dis_ac; /* Known base ac */
-
- s16b to_l; /* Bonus to life */
- s16b to_m; /* Bonus to mana */
- s16b to_s; /* Bonus to spell */
- s16b to_h; /* Bonus to hit */
- s16b to_d; /* Bonus to dam */
- s16b to_h_melee; /* Bonus to hit for melee */
- s16b to_d_melee; /* Bonus to dam for melee */
- s16b to_h_ranged; /* Bonus to hit for ranged */
- s16b to_d_ranged; /* Bonus to dam for ranged */
- s16b to_a; /* Bonus to ac */
-
- s16b ac; /* Base ac */
-
- byte antimagic; /* Power of the anti magic field */
- byte antimagic_dis; /* Radius of the anti magic field */
-
- s16b see_infra; /* Infravision range */
-
- s16b skill_dis; /* Skill: Disarming */
- s16b skill_dev; /* Skill: Magic Devices */
- s16b skill_sav; /* Skill: Saving throw */
- s16b skill_stl; /* Skill: Stealth factor */
- s16b skill_srh; /* Skill: Searching ability */
- s16b skill_fos; /* Skill: Searching frequency */
- s16b skill_thn; /* Skill: To hit (normal) */
- s16b skill_thb; /* Skill: To hit (shooting) */
- s16b skill_tht; /* Skill: To hit (throwing) */
- s16b skill_dig; /* Skill: Digging */
-
- s16b num_blow; /* Number of blows */
- s16b num_fire; /* Number of shots */
- s16b xtra_crit; /* % of increased crits */
-
- byte throw_mult; /* Multiplier for throw damage */
-
- byte tval_xtra; /* Correct xtra tval */
-
- byte tval_ammo; /* Correct ammo tval */
-
- s16b pspeed; /* Current speed */
-
- u32b mimic_extra; /* Mimicry powers use that */
- u32b antimagic_extra; /* Antimagic powers */
- u32b druid_extra; /* Druid powers */
- u32b druid_extra2; /* Druid powers */
- u32b druid_extra3; /* Druid powers */
- u32b music_extra; /* Music songs */
- u32b music_extra2; /* Music songs */
- u32b necro_extra; /* Necro powers */
- u32b necro_extra2; /* Necro powers */
-
- u32b race_extra1; /* Variable for race */
- u32b race_extra2; /* Variable for race */
- u32b race_extra3; /* Variable for race */
- u32b race_extra4; /* Variable for race */
- u32b race_extra5; /* Variable for race */
- u32b race_extra6; /* Variable for race */
- u32b race_extra7; /* Variable for race */
-
- s16b dodge_chance; /* Dodging chance */
-
- u32b maintain_sum; /* Do we have partial summons */
-
- byte spellbinder_num; /* Number of spells bound */
- u32b spellbinder[4]; /* Spell bounds */
- byte spellbinder_trigger; /* Spellbinder trigger condition */
-
- cptr mimic_name;
-
- char tactic; /* from 128-4 extremely coward to */
- /* 128+4 berserker */
- char movement; /* base movement way */
-
- s16b companion_killed; /* Number of companion death */
-
- bool_ no_mortal; /* Fated to never die by the hand of a mortal being */
-
- bool_ black_breath; /* The Tolkien's Black Breath */
-
- bool_ precognition; /* Like the cheat mode */
-
- /*** Extra flags -- used for lua and easying stuff ***/
- u32b xtra_f1;
- u32b xtra_f2;
- u32b xtra_f3;
- u32b xtra_f4;
- u32b xtra_f5;
- u32b xtra_esp;
-
- /* Corruptions */
- bool_ *corruptions;
-
- /*** Pet commands ***/
- byte pet_follow_distance; /* Length of the imaginary "leash" for pets */
- byte pet_open_doors; /* flag - allow pets to open doors */
- byte pet_pickup_items; /* flag - allow pets to pickup items */
-
- s16b control; /* Controlled monster */
- byte control_dir; /* Controlled monster */
-
- /*** Body changing variables ***/
- u16b body_monster; /* In which body is the player */
- bool_ disembodied; /* Is the player in a body ? */
- byte body_parts[INVEN_TOTAL - INVEN_WIELD]; /* Which body parts does he have ? */
-
- /* Astral */
- bool_ astral; /* We started at the bottom ? */
-
- /* Powers */
- bool_ *powers; /* Actual powers */
- bool_ powers_mod[POWER_MAX_INIT]; /* Intrinsinc powers */
-
- /* Skills */
- s16b skill_points;
- s16b skill_last_level; /* Prevents gaining skills by losing level and regaining them */
- s16b melee_style; /* How are */
- s16b use_piercing_shots; /* for archery */
-
- /* Help */
- help_info help;
-
- /*** Temporary fields ***/
-
- bool_ did_nothing; /* True if the last action wasnt a real action */
- bool_ leaving; /* True if player is leaving */
-};
-
-
-/* For Monk martial arts */
-
-typedef struct martial_arts martial_arts;
-
-struct martial_arts
-{
- cptr desc; /* A verbose attack description */
- int min_level; /* Minimum level to use */
- int chance; /* Chance of 'success' */
- int dd; /* Damage dice */
- int ds; /* Damage sides */
- s16b effect; /* Special effects */
- s16b power; /* Special effects power */
-};
-
-
-
-/* Powers - used by Mindcrafters and Necromancers */
-typedef struct magic_power magic_power;
-
-struct magic_power
-{
- int min_lev;
- int mana_cost;
- int fail;
- cptr name;
- cptr desc;
-};
-
-/* Border */
-typedef struct border_type border_type;
-
-struct border_type
-{
- byte north[MAX_WID];
- byte south[MAX_WID];
- byte east[MAX_HGT];
- byte west[MAX_HGT];
- byte north_west;
- byte north_east;
- byte south_west;
- byte south_east;
-};
-
-
-/*
- * A structure describing a wilderness area
- * with a terrain, a town or a dungeon entrance
- */
-typedef struct wilderness_type_info wilderness_type_info;
-
-struct wilderness_type_info
-{
- u32b name; /* Name (offset) */
- u32b text; /* Text (offset) */
- u16b entrance; /* Which town is there(<1000 i's a town, >=1000 it a dungeon) */
- s32b wild_x; /* Map coordinates (backed out while parsing map) */
- s32b wild_y;
- byte road; /* Flags of road */
- int level; /* Difficulty level */
- u32b flags1; /* Some flags */
- byte feat; /* The feature of f_info.txt that is used to allow passing, ... and to get a char/color/graph */
- byte terrain_idx; /* Terrain index(defined in defines.h) */
-
- byte terrain[MAX_WILD_TERRAIN];/* Feature types for the plasma generator */
-};
-
-/*
- * A structure describing a wilderness map
- */
-typedef struct wilderness_map wilderness_map;
-
-struct wilderness_map
-{
- int feat; /* Wilderness feature */
- u32b seed; /* Seed for the RNG */
- u16b entrance; /* Entrance for dungeons */
-
- bool_ known; /* Is it seen by the player ? */
-};
-
-/*
- * A structure describing a town with
- * stores and buildings
- */
-typedef struct town_type town_type;
-struct town_type
-{
- cptr name;
- u32b seed; /* Seed for RNG */
- store_type *store; /* The stores [max_st_idx] */
- byte numstores;
-
- byte flags; /* Town flags */
- /* Left this for the sake of compatibility */
- bool_ stocked; /* Is the town actualy stocked ? */
-
- bool_ destroyed; /* Is the town destroyed? */
-};
-
-
-/* Alchemists */
-
-typedef struct tval_desc2
-{
- int tval;
- cptr desc;
-} tval_desc2;
-
-typedef struct alchemist_recipe alchemist_recipe;
-struct alchemist_recipe
-{
- int sval_essence;
- byte tval;
- byte sval;
- byte qty;
-};
-
-typedef struct artifact_select_flag artifact_select_flag;
-struct artifact_select_flag {
- byte group; /* Flag group to display it in */
- int flag; /* item flag to set */
- byte level; /* Player skill level to start at */
- int desc; /* Display this description to select flag */
- u32b xp; /* xp cost for this flag */
- bool_ pval; /* indicates this flag benifits from pval */
- int item_desc; /* Description of required item */
- int item_descp; /* Description of required item */
- byte rtval; /* Required items' tval */
- byte rsval; /* Required items' sval */
- int rpval; /* Required items' pval (zero for no req) */
- int rflag[6]; /* Monster Race flags for required Corpses */
-};
-
-/*
- A structure for deity information.
- */
-typedef struct deity_type deity_type;
-struct deity_type
-{
- cptr name;
- char desc[10][80];
-};
-
-/* A structure for tactics */
-typedef struct tactic_info_type tactic_info_type;
-
-struct tactic_info_type
-{
- s16b to_hit;
- s16b to_dam;
- s16b to_ac;
- s16b to_stealth;
- s16b to_disarm;
- s16b to_saving;
- cptr name;
-};
-
-/* A structure to describe a random artifact. */
-typedef struct random_artifact random_artifact;
-
-struct random_artifact
-{
- char name_full[80]; /* Full name for the artifact */
- char name_short[80]; /* Un-Id'd name */
- byte level; /* Level of the artifact */
- byte attr; /* Color that is used on the screen */
- u32b cost; /* Object's value */
- byte activation; /* Activation. */
- s16b timeout; /* Timeout. */
- byte generated; /* Does it exist already? */
-};
-
-/* A structure to describe an activation. */
-typedef struct activation activation;
-
-struct activation
-{
- char desc[80]; /* Desc of the activation */
- u32b cost; /* costs value */
- s16b spell; /* Spell. */
-};
-
-/* A structure to describe a music. */
-typedef struct music music;
-
-struct music
-{
- char desc[80]; /* Desc of the music */
- s16b music; /* Music. */
- s16b dur; /* Duration(if any) */
- s16b init_recharge; /* Minimal recharge time */
- s16b turn_recharge; /* Recharge time for each more turn */
- byte min_inst; /* Minimum instrument for the music */
- byte rarity; /* Rarity of the music(use 100 to unallow to be randomly generated) */
-};
-
-/* A structure to describe the random spells of the Power Mages */
-typedef struct random_spell random_spell;
-
-struct random_spell
-{
- char desc[30]; /* Desc of the spell */
- char name[30]; /* Name of the spell */
- s16b mana; /* Mana cost */
- s16b fail; /* Failure rate */
- u32b proj_flags; /* Project function flags */
- byte GF; /* Type of the projection */
- byte radius;
- byte dam_sides;
- byte dam_dice;
- byte level; /* Level needed */
- bool_ untried; /* Is the spell was tried? */
-};
-
-/* A structure to describe the fate of the player */
-typedef struct fate fate;
-
-struct fate
-{
- byte fate; /* Which fate */
- byte level; /* On which level */
- byte serious; /* Is it sure? */
- s16b o_idx; /* Object to find */
- s16b e_idx; /* Ego-Item to find */
- s16b a_idx; /* Artifact to find */
- s16b v_idx; /* Vault to find */
- s16b r_idx; /* Monster to find */
- s16b count; /* Number of things */
- s16b time; /* Turn before */
- bool_ know; /* Has it been predicted? */
- bool_ icky; /* Hackish runtime-only flag */
-};
-
-/* A structure for movements */
-typedef struct move_info_type move_info_type;
-
-struct move_info_type
-{
- s16b to_speed;
- s16b to_search;
- s16b to_stealth;
- s16b to_percep;
- cptr name;
-};
-
-/* Define monster generation rules */
-typedef struct rule_type rule_type;
-struct rule_type
-{
- byte mode; /* Mode of combination of the monster flags */
- byte percent; /* Percent of monsters affected by the rule */
-
- u32b mflags1; /* The monster flags that are allowed */
- u32b mflags2;
- u32b mflags3;
- u32b mflags4;
- u32b mflags5;
- u32b mflags6;
- u32b mflags7;
- u32b mflags8;
- u32b mflags9;
-
- char r_char[5]; /* Monster race allowed */
-};
-
-/* A structure for the != dungeon types */
-typedef struct dungeon_info_type dungeon_info_type;
-struct dungeon_info_type
-{
- u32b name; /* Name */
- u32b text; /* Description */
- char short_name[3]; /* Short name */
-
- char generator[30]; /* Name of the level generator */
-
- s16b floor1; /* Floor tile 1 */
- byte floor_percent1[2]; /* Chance of type 1 */
- s16b floor2; /* Floor tile 2 */
- byte floor_percent2[2]; /* Chance of type 2 */
- s16b floor3; /* Floor tile 3 */
- byte floor_percent3[2]; /* Chance of type 3 */
- s16b outer_wall; /* Outer wall tile */
- s16b inner_wall; /* Inner wall tile */
- s16b fill_type1; /* Cave tile 1 */
- byte fill_percent1[2]; /* Chance of type 1 */
- s16b fill_type2; /* Cave tile 2 */
- byte fill_percent2[2]; /* Chance of type 2 */
- s16b fill_type3; /* Cave tile 3 */
- byte fill_percent3[2]; /* Chance of type 3 */
- byte fill_method; /* Smoothing parameter for the above */
-
- s16b mindepth; /* Minimal depth */
- s16b maxdepth; /* Maximal depth */
-
- bool_ principal; /* If it's a part of the main dungeon */
- byte next; /* The next part of the main dungeon */
- byte min_plev; /* Minimal plev needed to enter -- it's an anti-cheating mesure */
-
- int min_m_alloc_level; /* Minimal number of monsters per level */
- int max_m_alloc_chance; /* There is a 1/max_m_alloc_chance chance per round of creating a new monster */
-
- u32b flags1; /* Flags 1 */
- u32b flags2; /* Flags 1 */
-
- int size_x, size_y; /* Desired numers of panels */
-
- byte rule_percents[100]; /* Flat rule percents */
- rule_type rules[5]; /* Monster generation rules */
-
- int final_object; /* The object you'll find at the bottom */
- int final_artifact; /* The artifact you'll find at the bottom */
- int final_guardian; /* The artifact's guardian. If an artifact is specified, then it's NEEDED */
-
- int ix, iy, ox, oy; /* Wilderness coordinates of the entrance/output of the dungeon */
-
- obj_theme objs; /* The drops type */
-
- int d_dice[4]; /* Number of dices */
- int d_side[4]; /* Number of sides */
- int d_frequency[4]; /* Frequency of damage (1 is the minimum) */
- int d_type[4]; /* Type of damage */
-
- s16b t_idx[TOWN_DUNGEON]; /* The towns */
- s16b t_level[TOWN_DUNGEON]; /* The towns levels */
- s16b t_num; /* Number of towns */
-};
-
-/* A structure for inscriptions */
-typedef struct inscription_info_type inscription_info_type;
-struct inscription_info_type
-{
- char text[40]; /* The inscription itself */
- byte when; /* When it is executed */
- bool_ know; /* Is the inscription know ? */
- byte mana; /* Grid mana needed */
-};
-
-/* To hold Runecrafters prefered spells */
-typedef struct rune_spell rune_spell;
-struct rune_spell
-{
- char name[30]; /* name */
-
- s16b type; /* Type of the spell(GF) */
- s16b rune2; /* Modifiers */
- s16b mana; /* Mana involved */
-};
-
-/* For level gaining artifacts, artifact creation, ... */
-typedef struct flags_group flags_group;
-struct flags_group
-{
- char name[30]; /* Name */
- byte color; /* Color */
-
- byte price; /* Price to "buy" it */
-
- u32b flags1; /* Flags set 1 */
- u32b flags2; /* Flags set 2 */
- u32b flags3; /* Flags set 3 */
- u32b flags4; /* Flags set 4 */
- u32b esp; /* ESP flags set */
-};
-
-/* For powers(racial, class, mutation, artifacts, ... */
-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 */
-
- byte level; /* Min level */
- byte cost; /* Mana/Life cost */
- byte stat; /* Stat used */
- byte diff; /* Difficulty */
-};
-
-/* Hooks */
-typedef bool_ (*hook_type)(char *fmt);
-
-/*
- * Structure for the "quests"
- */
-typedef struct quest_type quest_type;
-
-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 */
-
- s16b status; /* Is the quest taken, completed, finished? */
-
- s16b level; /* Dungeon level */
-
- 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[4]; /* Various datas used by the quests */
-
- bool_ (*gen_desc)(FILE *fff); /* Function for generating description. */
-};
-typedef struct random_quest random_quest;
-struct random_quest
-{
- byte type; /* Type/number of monsters to kill(0 = no quest) */
- s16b r_idx; /* Monsters to crush */
- bool_ done; /* Done ? */
-};
-
-/* Monster powers for player uses */
-typedef struct monster_power monster_power;
-struct monster_power
-{
- u32b power; /* Power RF?_xxx */
- cptr name; /* Name of it */
- int mana; /* Mana needed */
- bool_ great; /* Need the use of great spells */
-};
-
-/* Tval descs */
-typedef struct tval_desc tval_desc;
-struct tval_desc
-{
- int tval; /* tval */
- cptr desc; /* desc */
-};
-
-/*
- * Between exit
- */
-typedef struct between_exit between_exit;
-struct between_exit
-{
- s16b corresp; /* Corresponding between gate */
- bool_ dungeon; /* Do we exit in a dungeon or in the wild ? */
-
- s16b wild_x, wild_y; /* Wilderness spot to land onto */
- s16b px, py; /* Location of the map */
-
- s16b d_idx; /* Dungeon to land onto */
- s16b level;
-};
-
-/*
- * A structure to hold "rolled" information
- */
-typedef struct birther birther;
-struct birther
-{
- s16b sex;
- s16b race;
- s16b rmod;
- s16b pclass;
- s16b spec;
-
- byte quests;
-
- byte god;
- s32b grace;
- s32b god_favor;
-
- s16b age;
- s16b wt;
- s16b ht;
- s16b sc;
-
- s32b au;
-
- s16b stat[6];
- s16b luck;
-
- s16b chaos_patron;
-
- u32b weapon;
-
- char history[4][60];
-
- bool_ quick_ok;
-};
-
-typedef struct hooks_chain hooks_chain;
-struct hooks_chain
-{
- hook_type hook;
- char name[40];
- char script[40];
- byte type;
- hooks_chain *next;
-};
-
-typedef union hook_return hook_return;
-union hook_return
-{
- s32b num;
- cptr str;
- object_type *o_ptr;
- monster_type *m_ptr;
-};
-
-/*
- * Forward declare
- */
-typedef struct hist_type hist_type;
-
-/*
- * Player background information
- */
-struct hist_type
-{
- s32b info; /* Textual History -- uses rp_text */
-
- byte roll; /* Frequency of this entry */
- s16b chart; /* Chart index */
- s16b next; /* Next chart index */
- byte bonus; /* Social Class Bonus + 50 */
-};
-
-/*
- * Item sets
- */
-typedef struct set_type set_type;
-struct set_type
-{
- u32b name; /* Name */
- u32b desc; /* Desc */
-
- byte num; /* Number of artifacts used */
- byte num_use; /* Number actually wore */
- struct /* the various items */
- {
- bool_ present; /* Is it actually wore ? */
- s16b a_idx; /* What artifact ? */
- s16b pval[6]; /* Pval for each combination */
- u32b flags1[6]; /* Flags */
- u32b flags2[6]; /* Flags */
- u32b flags3[6]; /* Flags */
- u32b flags4[6]; /* Flags */
- u32b flags5[6]; /* Flags */
- u32b esp[6]; /* Flags */
- } arts[6];
-};
-
-/* A structure for CLI commands. */
-typedef struct cli_comm cli_comm;
-struct cli_comm
-{
- cptr comm; /* Extended name of the command. */
- cptr descrip; /* Description of the command. */
- s16b key; /* Key to convert command to. */
-};
-
-/*
- * Skills !
- */
-typedef struct skill_type skill_type;
-struct skill_type
-{
- u32b name; /* Name */
- u32b desc; /* Description */
- u32b action_desc; /* Action Description */
-
- s16b action_mkey; /* Action do to */
-
- s32b i_value; /* Actual value */
- s32b i_mod; /* Modifier(1 skill point = modifier skill) */
-
- s32b value; /* Actual value */
- s32b mod; /* Modifier(1 skill point = modifier skill) */
- s16b rate; /* Modifier decreasing rate */
-
- u32b uses; /* Number of times used */
-
- s16b action[MAX_SKILLS]; /* List of actions against other skills */
-
- s16b father; /* Father in the skill tree */
- bool_ dev; /* Is the branch developped ? */
- s16b order; /* Order in the tree */
- bool_ hidden; /* Innactive */
-
- byte random_gain_chance; /* random gain chance, still needs the flag */
-
- u32b flags1; /* Skill flags */
-};
-
-
-/*
- * 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) */
- 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) */
-};
-
-typedef struct school_type school_type;
-struct school_type
-{
- cptr name; /* Name */
- s16b skill; /* Skill used for that school */
-};
-
-/*
- * Desc for GF_FOO
- */
-typedef struct gf_name_type gf_name_type;
-struct gf_name_type
-{
- int gf;
- cptr name;
-};
-
-/*
- * Timers
- */
-typedef struct timer_type timer_type;
-struct timer_type
-{
- timer_type *next; /* The next timer in the list */
-
- bool_ enabled; /* Is it currently counting? */
-
- 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) */
-};
-
-/*
- * 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
- */
-typedef struct ability_type ability_type;
-struct ability_type
-{
- u32b name; /* Name */
- u32b desc; /* Description */
- u32b action_desc; /* Action Description */
-
- s16b action_mkey; /* Action do to */
-
- s16b cost; /* Skill points cost */
-
- bool_ acquired; /* Do the player actualylg ot it ? */
-
- /* Prereqs */
- s16b skills[10]; /* List of prereq skills(10 max) */
- s16b skill_levels[10]; /* List of prereq skills(10 max) */
- s16b stat[6]; /* List of prereq stats */
- s16b need_abilities[10]; /* List of prereq abilities(10 max) */
- s16b forbid_abilities[10]; /* List of forbidden abilities(10 max) */
-};
diff --git a/src/util.c b/src/util.cc
index 93e38e4a..7d795828 100644
--- a/src/util.c
+++ b/src/util.cc
@@ -2,137 +2,60 @@
/* Purpose: Angband utilities -BEN- */
-
-#include "angband.h"
-
-
-
-
-#ifndef HAS_MEMSET
-
-/*
-* For those systems that don't have "memset()"
-*
-* Set the value of each of 'n' bytes starting at 's' to 'c', return 's'
-* If 'n' is negative, you will erase a whole lot of memory.
-*/
-char *memset(char *s, int c, huge n)
-{
- char *t;
- for (t = s; len--; ) *t++ = c;
- return (s);
-}
-
-#endif
-
-
-
-#ifndef HAS_STRICMP
-
-/*
-* For those systems that don't have "stricmp()"
-*
-* Compare the two strings "a" and "b" ala "strcmp()" ignoring case.
-*/
-int stricmp(cptr a, cptr b)
-{
- cptr s1, s2;
- char z1, z2;
-
- /* Scan the strings */
- for (s1 = a, s2 = b; TRUE; s1++, s2++)
- {
- z1 = FORCEUPPER(*s1);
- z2 = FORCEUPPER(*s2);
- if (z1 < z2) return ( -1);
- if (z1 > z2) return (1);
- if (!z1) return (0);
- }
-}
-
-#endif
-
-
-#ifdef SET_UID
-
-# ifndef HAS_USLEEP
-
-/*
-* For those systems that don't have "usleep()" but need it.
-*
-* Fake "usleep()" function grabbed from the inl netrek server -cba
-*/
-int usleep(huge usecs)
-{
- struct timeval Timer;
-
- int nfds = 0;
-
-#ifdef FD_SET
- fd_set *no_fds = NULL;
-#else
-int *no_fds = NULL;
-#endif
-
-
- /* Was: int readfds, writefds, exceptfds; */
- /* Was: readfds = writefds = exceptfds = 0; */
-
-
- /* Paranoia -- No excessive sleeping */
- if (usecs > 4000000L) core("Illegal usleep() call");
-
-
- /* Wait for it */
- Timer.tv_sec = (usecs / 1000000L);
- Timer.tv_usec = (usecs % 1000000L);
-
- /* Wait for it */
- if (select(nfds, no_fds, no_fds, no_fds, &Timer) < 0)
- {
- /* Hack -- ignore interrupts */
- if (errno != EINTR) return -1;
- }
-
- /* Success */
- return 0;
-}
-
-# endif
-
-
-/*
-* Hack -- External functions
-*/
-extern struct passwd *getpwuid();
-extern struct passwd *getpwnam();
-
+#include "util.hpp"
+#include "util.h"
+
+#include "cli_comm.hpp"
+#include "cmd3.hpp"
+#include "cmd4.hpp"
+#include "game.hpp"
+#include "init1.hpp"
+#include "messages.hpp"
+#include "monster_ego.hpp"
+#include "monster_race.hpp"
+#include "object_kind.hpp"
+#include "options.hpp"
+#include "player_race.hpp"
+#include "player_race_mod.hpp"
+#include "player_type.hpp"
+#include "tables.h"
+#include "tables.hpp"
+#include "timer_type.hpp"
+#include "variable.h"
+#include "variable.hpp"
+#include "xtra1.hpp"
+
+#include <boost/algorithm/string/predicate.hpp>
+#include <chrono>
+#include <sstream>
+#include <thread>
+
+using boost::algorithm::iequals;
+using std::this_thread::sleep_for;
+using std::chrono::milliseconds;
/*
* Find a default user name from the system.
*/
-void user_name(char *buf, int id)
+std::string user_name()
{
#ifdef SET_UID
+ /* Get the user id (?) */
+ int player_uid = getuid();
+
struct passwd *pw;
/* Look up the user name */
- if ((pw = getpwuid(id)))
+ if ((pw = getpwuid(player_uid)))
{
- (void)strcpy(buf, pw->pw_name);
- buf[16] = '\0';
-
- return;
+ return pw->pw_name;
}
#endif /* SET_UID */
- /* Oops. Hack -- default to "PLAYER" */
- strcpy(buf, "PLAYER");
+ /* Default to "PLAYER" if we don't have platform support */
+ return "PLAYER";
}
-#endif /* SET_UID */
-
-
/*
@@ -148,8 +71,6 @@ void user_name(char *buf, int id)
* to assume that all filenames are "Unix" filenames, and explicitly "extract"
* such filenames if needed (by "path_parse()", or perhaps "path_canon()").
*
-* Note that "path_temp" should probably return a "canonical" filename.
-*
* Note that "my_fopen()" and "my_open()" and "my_make()" and "my_kill()"
* and "my_move()" and "my_copy()" should all take "canonical" filenames.
*
@@ -204,7 +125,7 @@ errr path_parse(char *buf, int max, cptr file)
if (!u) return (1);
- (void)strcpy(buf, u);
+ strcpy(buf, u);
#else
/* Look up password data for user */
pw = getpwuid(getuid());
@@ -213,11 +134,11 @@ errr path_parse(char *buf, int max, cptr file)
if (!pw) return (1);
/* Make use of the info */
- (void)strcpy(buf, pw->pw_dir);
+ strcpy(buf, pw->pw_dir);
#endif
/* Append the rest of the filename, if any */
- if (s) (void)strcat(buf, s);
+ if (s) strcat(buf, s);
/* Success */
return (0);
@@ -247,42 +168,6 @@ errr path_parse(char *buf, int max, cptr file)
/*
-* Hack -- acquire a "temporary" file name if possible
-*
-* This filename is always in "system-specific" form.
-*/
-errr path_temp(char *buf, int max)
-{
-#ifdef WINDOWS
- static u32b tmp_counter;
- static char valid_characters[] =
- "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
- char rand_ext[4];
-
- rand_ext[0] = valid_characters[rand_int(sizeof (valid_characters))];
- rand_ext[1] = valid_characters[rand_int(sizeof (valid_characters))];
- rand_ext[2] = valid_characters[rand_int(sizeof (valid_characters))];
- rand_ext[3] = '\0';
- strnfmt(buf, max, "%s/t_%ud.%s", ANGBAND_DIR_XTRA, tmp_counter, rand_ext);
- tmp_counter++;
-#else
- cptr s;
-
- /* Temp file */
- s = tmpnam(NULL);
-
- /* Oops */
- if (!s) return ( -1);
-
- /* Format to length */
- strnfmt(buf, max, "%s", s);
-#endif
- /* Success */
- return (0);
-}
-
-
-/*
* Create a new path by appending a file (or directory) to a path
*
* This requires no special processing on simple machines, except
@@ -335,7 +220,6 @@ errr path_build(char *buf, int max, cptr path, cptr file)
*/
FILE *my_fopen(cptr file, cptr mode)
{
-#ifndef MACH_O_CARBON
char buf[1024];
@@ -345,24 +229,6 @@ FILE *my_fopen(cptr file, cptr mode)
/* Attempt to fopen the file anyway */
return (fopen(buf, mode));
-#else /* MACH_O_CARBON */
-
-char buf[1024];
-FILE *s;
-
-/* Hack -- Try to parse the path */
-if (path_parse(buf, 1024, file)) return (NULL);
-
-/* Attempt to fopen the file anyway */
-s = fopen(buf, mode);
-
-/* Set creator and type if the file is successfully opened */
-if (s) fsetfileinfo(buf, _fcreator, _ftype);
-
-/* Done */
-return (s);
-
-#endif /* MACH_O_CARBON */
}
@@ -460,49 +326,6 @@ errr my_fgets(FILE *fff, char *buf, huge n)
/*
-* Hack -- replacement for "fputs()"
-*
-* Dump a string, plus a newline, to a file
-*
-* XXX XXX XXX Process internal weirdness?
-*/
-errr my_fputs(FILE *fff, cptr buf, huge n)
-{
- /* XXX XXX */
- n = n ? n : 0;
-
- /* Dump, ignore errors */
- (void)fprintf(fff, "%s\n", buf);
-
- /* Success */
- return (0);
-}
-
-
-/*
-* 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
-*/
-#ifdef MACINTOSH
-# define open(N, F, M) \
-((M), open((char*)(N), F))
-# define write(F, B, S) \
-write(F, (char*)(B), S)
-#endif /* MACINTOSH */
-
-
-/*
* Several systems have no "O_BINARY" flag
*/
#ifndef O_BINARY
@@ -521,7 +344,7 @@ errr fd_kill(cptr file)
if (path_parse(buf, 1024, file)) return ( -1);
/* Remove */
- (void)remove(buf);
+ remove(buf);
/* XXX XXX XXX */
return (0);
@@ -543,7 +366,7 @@ errr fd_move(cptr file, cptr what)
if (path_parse(aux, 1024, what)) return ( -1);
/* Rename */
- (void)rename(buf, aux);
+ rename(buf, aux);
/* XXX XXX XXX */
return (0);
@@ -551,39 +374,12 @@ errr fd_move(cptr file, cptr what)
/*
-* Hack -- attempt to copy a file
-*/
-errr fd_copy(cptr file, cptr what)
-{
- char buf[1024];
- char aux[1024];
-
- /* Hack -- Try to parse the path */
- if (path_parse(buf, 1024, file)) return ( -1);
-
- /* Hack -- Try to parse the path */
- if (path_parse(aux, 1024, what)) return ( -1);
-
- /* Copy XXX XXX XXX */
- /* (void)rename(buf, aux); */
-
- /* XXX XXX XXX */
- return (1);
-}
-
-
-/*
* Hack -- attempt to open a file descriptor (create file)
*
* This function should fail if the file already exists
*
* 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)
{
@@ -592,42 +388,10 @@ 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
-
-{
-int fdes;
-
-/* Create the file, fail if exists, write-only, binary */
-fdes = open(buf, O_CREAT | O_EXCL | O_WRONLY | O_BINARY, mode);
-
-/* Set creator and type if the file is successfully opened */
-if (fdes >= 0) fsetfileinfo(buf, _fcreator, _ftype);
-
-/* Return the descriptor */
-return (fdes);
-}
-
-#else /* MACH_O_CARBON */
/* Create the file, fail if exists, write-only, binary */
return (open(buf, O_CREAT | O_EXCL | O_WRONLY | O_BINARY, mode));
-#endif /* MACH_O_CARBON */
-
-#endif /* BEN_HACK */
}
@@ -644,91 +408,10 @@ int fd_open(cptr file, int flags)
/* Hack -- Try to parse the path */
if (path_parse(buf, 1024, file)) return ( -1);
-#ifdef MACH_O_CARBON
-
- {
- int fdes;
-
- /* Attempt to open the file */
- fdes = open(buf, flags | O_BINARY, 0);
-
- /* Set creator and type if the file is successfully opened */
- if (fdes >= 0) fsetfileinfo(buf, _fcreator, _ftype);
-
- /* Return the descriptor */
- return (fdes);
- }
-
-#else /* MACH_O_CARBON */
/* Attempt to open the file */
return (open(buf, flags | O_BINARY, 0));
-#endif /* MACH_O_CARBON */
-}
-
-
-/*
-* Hack -- attempt to lock a file descriptor
-*
-* Legal lock types -- F_UNLCK, F_RDLCK, F_WRLCK
-*/
-errr fd_lock(int fd, int what)
-{
- /* XXX XXX */
- what = what ? what : 0;
-
- /* Verify the fd */
- if (fd < 0) return ( -1);
-
-#ifdef SET_UID
-
-# ifdef USG
-
-# if defined(F_ULOCK) && defined(F_LOCK)
-
- /* Un-Lock */
- if (what == F_UNLCK)
- {
- /* Unlock it, Ignore errors */
- lockf(fd, F_ULOCK, 0);
- }
-
- /* Lock */
- else
- {
- /* Lock the score file */
- if (lockf(fd, F_LOCK, 0) != 0) return (1);
- }
-
-# endif
-
-# else
-
-# if defined(LOCK_UN) && defined(LOCK_EX)
-
- /* Un-Lock */
- if (what == F_UNLCK)
- {
- /* Unlock it, Ignore errors */
- (void)flock(fd, LOCK_UN);
- }
-
- /* Lock */
- else
- {
- /* Lock the score file */
- if (flock(fd, LOCK_EX) != 0) return (1);
- }
-
-# endif
-
-# endif
-
-#endif
-
- /* Success */
- return (0);
}
@@ -831,7 +514,7 @@ errr fd_close(int fd)
if (fd < 0) return ( -1);
/* Close */
- (void)close(fd);
+ close(fd);
/* XXX XXX XXX */
return (0);
@@ -932,40 +615,6 @@ static int dehex(char c)
}
-static int my_stricmp(cptr a, cptr b)
-{
- cptr s1, s2;
- char z1, z2;
-
- /* Scan the strings */
- for (s1 = a, s2 = b; TRUE; s1++, s2++)
- {
- z1 = FORCEUPPER(*s1);
- z2 = FORCEUPPER(*s2);
- if (z1 < z2) return ( -1);
- if (z1 > z2) return (1);
- if (!z1) return (0);
- }
-}
-
-static int my_strnicmp(cptr a, cptr b, int n)
-{
- cptr s1, s2;
- char z1, z2;
-
- /* Scan the strings */
- for (s1 = a, s2 = b; n > 0; s1++, s2++, n--)
- {
- z1 = FORCEUPPER(*s1);
- z2 = FORCEUPPER(*s2);
- if (z1 < z2) return ( -1);
- if (z1 > z2) return (1);
- if (!z1) return (0);
- }
- return 0;
-}
-
-
static void trigger_text_to_ascii(char **bufptr, cptr *strptr)
{
char *s = *bufptr;
@@ -989,8 +638,7 @@ static void trigger_text_to_ascii(char **bufptr, cptr *strptr)
for (i = 0; macro_modifier_chr[i]; i++)
{
len = strlen(macro_modifier_name[i]);
-
- if (!my_strnicmp(str, macro_modifier_name[i], len))
+ if (iequals(str, macro_modifier_name[i]))
break;
}
if (!macro_modifier_chr[i]) break;
@@ -1002,7 +650,7 @@ static void trigger_text_to_ascii(char **bufptr, cptr *strptr)
for (i = 0; i < max_macrotrigger; i++)
{
len = strlen(macro_trigger_name[i]);
- if (!my_strnicmp(str, macro_trigger_name[i], len) && ']' == str[len])
+ if (iequals(str, macro_trigger_name[i]) && ']' == str[len])
{
/* a trigger name found */
break;
@@ -1234,8 +882,8 @@ bool_ trigger_ascii_to_text(char **bufptr, cptr *strptr)
for (i = 0; i < max_macrotrigger; i++)
{
- if (!my_stricmp(key_code, macro_trigger_keycode[0][i])
- || !my_stricmp(key_code, macro_trigger_keycode[1][i]))
+ if (iequals(key_code, macro_trigger_keycode[0][i])
+ || iequals(key_code, macro_trigger_keycode[1][i]))
break;
}
if (i == max_macrotrigger)
@@ -1512,7 +1160,7 @@ errr macro_add(cptr pat, cptr act)
if (n >= 0)
{
/* Free the old macro action */
- string_free(macro__act[n]);
+ free(macro__act[n]);
}
/* Create a new macro */
@@ -1522,11 +1170,11 @@ errr macro_add(cptr pat, cptr act)
n = macro__num++;
/* Save the pattern */
- macro__pat[n] = string_make(pat);
+ macro__pat[n] = strdup(pat);
}
/* Save the action */
- macro__act[n] = string_make(act);
+ macro__act[n] = strdup(act);
/* Efficiency */
macro__use[(byte)(pat[0])] = TRUE;
@@ -1538,22 +1186,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
*/
static bool_ flush_later = FALSE;
@@ -1581,7 +1213,7 @@ static bool_ parse_under = FALSE;
* This is not only more efficient, but also necessary to make sure
* that various "inkey()" codes are not "lost" along the way.
*/
-void flush(void)
+void flush()
{
/* Do it later */
flush_later = TRUE;
@@ -1589,34 +1221,36 @@ void flush(void)
/*
+ * Flush input if the 'flush_failure' option is set.
+ */
+void flush_on_failure()
+{
+ if (options->flush_failure)
+ {
+ flush();
+ }
+}
+
+
+/*
* Flush the screen, make a noise
*/
-void bell(void)
+void bell()
{
/* Mega-Hack -- Flush the output */
Term_fresh();
/* Make a bell noise (if allowed) */
- if (ring_bell) Term_xtra(TERM_XTRA_NOISE, 0);
+ if (options->ring_bell)
+ {
+ Term_bell();
+ }
/* Flush the input (later!) */
flush();
}
-/*
-* Hack -- Make a (relevant?) sound
-*/
-void sound(int val)
-{
- /* No sound */
- if (!use_sound) return;
-
- /* Make a sound (if allowed) */
- Term_xtra(TERM_XTRA_SOUND, val);
-}
-
-
/*
* Helper function called only from "inkey()"
@@ -1635,7 +1269,7 @@ void sound(int val)
* macro trigger, 500 milliseconds must pass before the key sequence is
* known not to be that macro trigger. XXX XXX XXX
*/
-static char inkey_aux(void)
+static char inkey_aux()
{
int k = 0, n, p = 0, w = 0;
@@ -1647,7 +1281,7 @@ static char inkey_aux(void)
/* Wait for a keypress */
- (void)(Term_inkey(&ch, TRUE, TRUE));
+ (Term_inkey(&ch, TRUE, TRUE));
/* End "macro action" */
@@ -1705,7 +1339,7 @@ static char inkey_aux(void)
if (w >= 100) break;
/* Delay */
- Term_xtra(TERM_XTRA_DELAY, w);
+ sleep_for(milliseconds(w));
}
}
@@ -1724,7 +1358,7 @@ static char inkey_aux(void)
}
/* Wait for (and remove) a pending key */
- (void)Term_inkey(&ch, TRUE, TRUE);
+ Term_inkey(&ch, TRUE, TRUE);
/* Return the key */
return (ch);
@@ -1781,6 +1415,8 @@ static char inkey_aux(void)
*/
static cptr inkey_next = NULL;
+bool_ inkey_flag = FALSE;
+
/*
* Get a keypress from the user.
@@ -1791,11 +1427,6 @@ static cptr inkey_next = NULL;
* before this function returns. Thus they function just like normal
* parameters, except that most calls to this function can ignore them.
*
-* 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".
-*
* If "inkey_scan" is TRUE, then we will immediately return "zero" if no
* keypress is available, instead of waiting for a keypress.
*
@@ -1840,11 +1471,8 @@ static cptr inkey_next = NULL;
* "signal_count" variable, and of the "character_saved" variable.
*
* Hack -- Note the use of "inkey_next" to allow "keymaps" to be processed.
-*
-* Mega-Hack -- Note the use of "inkey_hack" to allow the "Borg" to steal
-* control of the keyboard from the user.
*/
-char inkey(void)
+static char inkey_real(bool_ inkey_scan)
{
int v;
@@ -1857,13 +1485,13 @@ char inkey(void)
term *old = Term;
/* Hack -- Use the "inkey_next" pointer */
- if (inkey_next && *inkey_next && !inkey_xtra)
+ if (inkey_next && *inkey_next)
{
/* Get next character, and advance */
ch = *inkey_next++;
/* Cancel the various "global parameters" */
- inkey_base = inkey_xtra = inkey_flag = inkey_scan = FALSE;
+ inkey_base = inkey_flag = inkey_scan = FALSE;
/* Accept result */
macro_recorder_add(ch);
@@ -1874,28 +1502,14 @@ char inkey(void)
inkey_next = NULL;
- /* Hack -- handle delayed "flush()" */
- if (inkey_xtra)
- {
- /* End "macro action" */
- parse_macro = FALSE;
-
- /* End "macro trigger" */
- parse_under = FALSE;
-
- /* Forget old keypresses */
- Term_flush();
- }
-
-
/* Access cursor state */
- (void)Term_get_cursor(&v);
+ Term_get_cursor(&v);
/* Show the cursor if waiting, except sometimes in "command" mode */
- if (!inkey_scan && (!inkey_flag || hilite_player || character_icky))
+ if (!inkey_scan && (!inkey_flag || options->hilite_player || character_icky))
{
/* Show the cursor */
- (void)Term_set_cursor(1);
+ Term_set_cursor(1);
}
@@ -1926,12 +1540,6 @@ char inkey(void)
/* Hack -- activate main screen */
Term_activate(angband_term[0]);
- /* Mega-Hack -- reset saved flag */
- character_saved = FALSE;
-
- /* Mega-Hack -- reset signal counter */
- signal_count = 0;
-
/* Only once */
done = TRUE;
}
@@ -1976,7 +1584,7 @@ char inkey(void)
if (w >= 100) break;
/* Delay */
- Term_xtra(TERM_XTRA_DELAY, w);
+ sleep_for(milliseconds(w));
}
}
@@ -1990,18 +1598,13 @@ char inkey(void)
/* Handle "control-right-bracket" */
- if ((ch == 29) || ((!rogue_like_commands) && (ch == KTRL('D'))))
+ if ((ch == 29) || ((!options->rogue_like_commands) && (ch == KTRL('D'))))
{
/* Strip this key */
ch = 0;
- if (!do_movies)
- /* Do an html dump */
- do_cmd_html_dump();
- else
- /* Do a text box in the cmovie */
- do_cmovie_insert();
-
+ /* Do an html dump */
+ do_cmd_html_dump();
/* Continue */
continue;
@@ -2058,7 +1661,7 @@ char inkey(void)
/* Cancel the various "global parameters" */
- inkey_base = inkey_xtra = inkey_flag = inkey_scan = FALSE;
+ inkey_base = inkey_flag = FALSE;
/* Return the keypress */
@@ -2066,393 +1669,14 @@ 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);
+char inkey() {
+ return inkey_real(FALSE);
}
-
-/*
-* 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);
+char inkey_scan() {
+ return inkey_real(TRUE);
}
-
-
-
-/*
-* 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
*/
@@ -2467,7 +1691,7 @@ static void msg_flush(int x)
while (1)
{
int cmd = inkey();
- if (quick_messages) break;
+ if (options->quick_messages) break;
if ((cmd == ESCAPE) || (cmd == ' ')) break;
if ((cmd == '\n') || (cmd == '\r')) break;
bell();
@@ -2534,22 +1758,23 @@ void display_message(int x, int y, int split, byte color, cptr t)
*/
void cmsg_print(byte color, cptr msg)
{
- static int p = 0;
+ auto &messages = game->messages;
- int n;
+ static int p = 0;
char *t;
char buf[1024];
- int lim = Term->wid - 8;
-
+ int wid;
+ Term_get_size(&wid, nullptr);
+ int lim = wid - 8;
/* Hack -- Reset */
if (!msg_flag) p = 0;
/* Message Length */
- n = (msg ? strlen(msg) : 0);
+ int n = (msg ? strlen(msg) : 0);
/* Hack -- flush when requested or needed */
if (p && (!msg || ((p + n) > lim)))
@@ -2573,10 +1798,13 @@ void cmsg_print(byte color, cptr msg)
/* Memorize the message */
- if (character_generated) message_add(MESSAGE_MSG, msg, color);
+ if (character_generated)
+ {
+ messages.add(msg, color);
+ }
/* Handle "auto_more" */
- if (auto_more)
+ if (options->auto_more)
{
/* Window stuff */
p_ptr->window |= (PW_MESSAGE);
@@ -2642,11 +1870,11 @@ void cmsg_print(byte color, cptr msg)
/* Display the tail of the message */
display_message(p, 0, n, color, t);
- /* Memorize the tail */
- /* if (character_generated) message_add(t); */
-
/* Window stuff */
- p_ptr->window |= (PW_MESSAGE);
+ if (p_ptr)
+ {
+ p_ptr->window |= (PW_MESSAGE);
+ }
/* Remember the message */
msg_flag = TRUE;
@@ -2655,7 +1883,12 @@ void cmsg_print(byte color, cptr msg)
p += n + 1;
/* Optional refresh */
- if (fresh_message) Term_fresh();
+ if (options->fresh_message) Term_fresh();
+}
+
+void cmsg_print(byte color, std::string const &msg)
+{
+ cmsg_print(color, msg.c_str());
}
/* Hack -- for compatibility and easy sake */
@@ -2676,7 +1909,7 @@ static int screen_depth = 0;
*
* This function must match exactly one call to "screen_load()".
*/
-void screen_save(void)
+void screen_save()
{
/* Hack -- Flush messages */
msg_print(NULL);
@@ -2694,7 +1927,7 @@ void screen_save(void)
*
* This function must match exactly one call to "screen_save()".
*/
-void screen_load(void)
+void screen_load()
{
/* Hack -- Flush messages */
msg_print(NULL);
@@ -2720,7 +1953,7 @@ void msg_format(cptr fmt, ...)
va_start(vp, fmt);
/* Format the args, save the length */
- (void)vstrnfmt(buf, 1024, fmt, vp);
+ vstrnfmt(buf, 1024, fmt, vp);
/* End the Varargs Stuff */
va_end(vp);
@@ -2739,7 +1972,7 @@ void cmsg_format(byte color, cptr fmt, ...)
va_start(vp, fmt);
/* Format the args, save the length */
- (void)vstrnfmt(buf, 1024, fmt, vp);
+ vstrnfmt(buf, 1024, fmt, vp);
/* End the Varargs Stuff */
va_end(vp);
@@ -2748,29 +1981,25 @@ void cmsg_format(byte color, cptr fmt, ...)
cmsg_print(color, buf);
}
-
-
-/*
-* Display a string on the screen using an attribute.
-*
-* At the given location, using the given attribute, if allowed,
-* add the given string. Do not clear the line.
-*/
void c_put_str(byte attr, cptr str, int row, int col)
{
- /* Position cursor, Dump the attr/text */
Term_putstr(col, row, -1, attr, str);
}
-/*
-* As above, but in "white"
-*/
+void c_put_str(byte attr, std::string const &str, int row, int col)
+{
+ Term_putstr(col, row, -1, attr, str.c_str());
+}
+
void put_str(cptr str, int row, int col)
{
- /* Spawn */
Term_putstr(col, row, -1, TERM_WHITE, str);
}
+void put_str(std::string const &str, int row, int col)
+{
+ Term_putstr(col, row, -1, TERM_WHITE, str.c_str());
+}
/*
@@ -2786,16 +2015,20 @@ void c_prt(byte attr, cptr str, int row, int col)
Term_addstr( -1, attr, str);
}
-/*
-* As above, but in "white"
-*/
+void c_prt(byte attr, std::string const &s, int row, int col)
+{
+ c_prt(attr, s.c_str(), row, col);
+}
+
void prt(cptr str, int row, int col)
{
- /* Spawn */
c_prt(TERM_WHITE, str, row, col);
}
-
+void prt(std::string const &s, int row, int col)
+{
+ prt(s.c_str(), row, col);
+}
/*
* Print some (colored) text to the screen at the current cursor position,
@@ -2823,16 +2056,13 @@ void text_out_to_screen(byte a, cptr str)
/* Obtain the size */
- (void)Term_get_size(&wid, &h);
+ Term_get_size(&wid, &h);
/* Obtain the cursor */
- (void)Term_locate(&x, &y);
+ 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++)
@@ -2919,8 +2149,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.
@@ -2931,13 +2160,13 @@ 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;
/* Unused parameter */
- (void)a;
+ a;
/* Process the string */
while (*s)
@@ -3063,9 +2292,11 @@ void text_out_c(byte a, cptr str)
void clear_from(int row)
{
int y;
+ int hgt;
+ Term_get_size(nullptr, &hgt);
/* Erase requested rows */
- for (y = row; y < Term->hgt; y++)
+ for (y = row; y < hgt; y++)
{
/* Erase part of the screen */
Term_erase(0, y, 255);
@@ -3123,6 +2354,23 @@ static int complete_command(char *buf, int clen, int mlen)
}
+bool askfor_aux(std::string *buf, std::size_t max_len)
+{
+ // Buffer
+ char cstr[1024];
+ // Sanity
+ assert(max_len < sizeof(cstr));
+ // Copy into temporary buffer
+ cstr[buf->size()] = '\0';
+ buf->copy(cstr, std::string::npos);
+ // Delegate
+ bool result = askfor_aux(cstr, max_len);
+ // Copy back
+ (*buf) = cstr;
+ // Done
+ return result;
+}
+
/*
* Get some input at the cursor location.
* Assume the buffer is initialized to a default string.
@@ -3134,7 +2382,8 @@ static int complete_command(char *buf, int clen, int mlen)
* ESCAPE clears the buffer and the window and returns FALSE.
* RETURN accepts the current buffer contents and returns TRUE.
*/
-bool_ askfor_aux_complete = FALSE;
+static bool_ askfor_aux_complete = FALSE;
+
bool_ askfor_aux(char *buf, int len)
{
int y, x;
@@ -3162,7 +2411,7 @@ bool_ askfor_aux(char *buf, int len)
/* Paranoia -- Clip the default entry */
- buf[len] = '\0';
+ buf[len - 1] = '\0';
/* Display the default answer */
@@ -3250,6 +2499,13 @@ bool_ askfor_aux(char *buf, int len)
return (TRUE);
}
+bool_ askfor_aux_with_completion(char *buf, int len)
+{
+ askfor_aux_complete = TRUE;
+ bool_ res = askfor_aux(buf, len);
+ askfor_aux_complete = FALSE;
+ return res;
+}
/*
* Get a string from the user
@@ -3308,7 +2564,7 @@ bool_ get_check(cptr prompt)
while (TRUE)
{
i = inkey();
- if (quick_messages) break;
+ if (options->quick_messages) break;
if (i == ESCAPE) break;
if (strchr("YyNn", i)) break;
bell();
@@ -3462,7 +2718,6 @@ static char request_command_buffer[256];
* request_command(). This MUST have at least twice as many characters as
* there are building actions in the actions[] array in store_info_type.
*/
-#define MAX_IGNORE_KEYMAPS 12
char request_command_ignore_keymaps[MAX_IGNORE_KEYMAPS];
/*
@@ -3659,7 +2914,7 @@ void request_command(int shopping)
if (cmd == '\\')
{
/* Get a real command */
- (void)get_com("Command: ", &cmd_char);
+ get_com("Command: ", &cmd_char);
cmd = cmd_char;
@@ -3717,7 +2972,7 @@ void request_command(int shopping)
}
/* Hack -- Auto-repeat certain commands */
- if (always_repeat && (command_arg <= 0))
+ if (options->always_repeat && (command_arg <= 0))
{
/* Hack -- auto repeat certain commands */
if (strchr("TBDoc+", command_cmd))
@@ -3730,18 +2985,19 @@ void request_command(int shopping)
/* Hack -- Scan equipment */
for (i = INVEN_WIELD; i < INVEN_TOTAL; i++)
{
- cptr s;
-
object_type *o_ptr = &p_ptr->inventory[i];
/* Skip non-objects */
if (!o_ptr->k_idx) continue;
/* No inscription */
- if (!o_ptr->note) continue;
+ if (o_ptr->inscription.empty())
+ {
+ continue;
+ }
/* Obtain the inscription */
- s = quark_str(o_ptr->note);
+ auto s = o_ptr->inscription.c_str();
/* Find a '^' */
s = strchr(s, '^');
@@ -3886,7 +3142,7 @@ bool_ repeat_pull(int *what)
return (TRUE);
}
-void repeat_check(void)
+void repeat_check()
{
int what;
@@ -3930,7 +3186,7 @@ void repeat_check(void)
*
* Allow numbers of any size and save the last keypress.
*/
-u32b get_number(u32b def, u32b max, int y, int x, char *cmd)
+static u32b get_number(u32b def, u32b max, int y, int x, char *cmd)
{
u32b res = def;
@@ -4027,7 +3283,10 @@ void get_count(int number, int max)
command_arg = number;
/* Hack -- Optional flush */
- if (flush_command) flush();
+ if (options->flush_command)
+ {
+ flush();
+ }
/* Clear top line */
prt("", 0, 0);
@@ -4068,36 +3327,35 @@ void strlower(char *buf)
* must exactly match (look out for commas and the like!), or else 0 is
* returned. Case doesn't matter. -GSN-
*/
-
int test_monster_name(cptr name)
{
- int i;
+ auto const &r_info = game->edit_data.r_info;
- /* Scan the monsters */
- for (i = 1; i < max_r_idx; i++)
+ for (std::size_t i = 0; i < r_info.size(); i++)
{
- monster_race *r_ptr = &r_info[i];
- cptr mon_name = r_name + r_ptr->name;
-
- /* If name matches, give us the number */
- if (stricmp(name, mon_name) == 0) return (i);
+ auto r_ptr = &r_info[i];
+ if (r_ptr->name && iequals(name, r_ptr->name))
+ {
+ return (i);
+ }
}
return (0);
}
-int test_mego_name(cptr name)
+
+int test_mego_name(cptr needle)
{
- int i;
+ const auto &re_info = game->edit_data.re_info;
/* Scan the monsters */
- for (i = 1; i < max_re_idx; i++)
+ for (std::size_t i = 0; i < re_info.size(); i++)
{
- monster_ego *re_ptr = &re_info[i];
- cptr mon_name = re_name + re_ptr->name;
-
- /* If name matches, give us the number */
- if (stricmp(name, mon_name) == 0) return (i);
+ auto name = re_info[i].name;
+ if (name && iequals(name, needle))
+ {
+ return i;
+ }
}
- return (0);
+ return 0;
}
/*
@@ -4106,20 +3364,20 @@ int test_mego_name(cptr name)
* returned. Case doesn't matter. -DG-
*/
-int test_item_name(cptr name)
+int test_item_name(cptr needle)
{
- int i;
+ auto const &k_info = game->edit_data.k_info;
- /* Scan the items */
- for (i = 1; i < max_k_idx; i++)
+ for (std::size_t i = 0; i < k_info.size(); i++)
{
- object_kind *k_ptr = &k_info[i];
- cptr obj_name = k_name + k_ptr->name;
-
- /* If name matches, give us the number */
- if (stricmp(name, obj_name) == 0) return (i);
+ auto const &name = k_info[i].name;
+ if (name && iequals(needle, name))
+ {
+ return i;
+ }
}
- return (0);
+
+ return 0;
}
/*
@@ -4144,87 +3402,63 @@ s32b bst(s32b what, s32b t)
}
}
-cptr get_month_name(int day, bool_ full, bool_ compact)
+std::string get_day(s32b day_no)
{
- int i = 8;
- static char buf[40];
-
- /* Find the period name */
- while ((i > 0) && (day < month_day[i]))
+ // Convert the number
+ std::string day(std::to_string(day_no));
+ // Suffix
+ if ((day_no / 10) == 1)
{
- i--;
+ return day + "th";
}
-
- switch (i)
+ else if ((day_no % 10) == 1)
{
- /* Yestare/Mettare */
- case 0:
- case 8:
- {
- char buf2[20];
-
- sprintf(buf2, "%s", get_day(day + 1));
- if (full) sprintf(buf, "%s (%s day)", month_name[i], buf2);
- else sprintf(buf, "%s", month_name[i]);
- break;
- }
- /* 'Normal' months + Enderi */
- default:
- {
- char buf2[20];
- char buf3[20];
-
- sprintf(buf2, "%s", get_day(day + 1 - month_day[i]));
- sprintf(buf3, "%s", get_day(day + 1));
-
- if (full) sprintf(buf, "%s day of %s (%s day)", buf2, month_name[i], buf3);
- else if (compact) sprintf(buf, "%s day of %s", buf2, month_name[i]);
- else sprintf(buf, "%s %s", buf2, month_name[i]);
- break;
- }
+ return day + "st";
+ }
+ else if ((day_no % 10) == 2)
+ {
+ return day + "nd";
+ }
+ else if ((day_no % 10) == 3)
+ {
+ return day + "rd";
+ }
+ else
+ {
+ return day + "th";
}
-
- return (buf);
-}
-
-cptr get_day(int day)
-{
- static char buf[20];
- cptr p = "th";
-
- if ((day / 10) == 1) ;
- else if ((day % 10) == 1) p = "st";
- else if ((day % 10) == 2) p = "nd";
- else if ((day % 10) == 3) p = "rd";
-
- sprintf(buf, "%d%s", day, p);
- return (buf);
}
-cptr get_player_race_name(int pr, int ps)
+std::string get_player_race_name(int pr, int ps)
{
- static char buf[50];
+ auto const &race_info = game->edit_data.race_info;
+ auto const &race_mod_info = game->edit_data.race_mod_info;
if (ps)
{
- if (race_mod_info[ps].place) sprintf(buf, "%s %s", race_info[pr].title + rp_name, race_mod_info[ps].title + rmp_name);
- else sprintf(buf, "%s %s", race_mod_info[ps].title + rmp_name, race_info[pr].title + rp_name);
+ if (race_mod_info[ps].place)
+ {
+ return std::string(race_info[pr].title) + " " + race_mod_info[ps].title;
+ }
+ else
+ {
+ return std::string(race_mod_info[ps].title) + " " + race_info[pr].title;
+ }
}
else
{
- sprintf(buf, "%s", race_info[pr].title + rp_name);
+ return std::string(race_info[pr].title);
}
-
- return (buf);
}
/*
* Ask to select an item in a list
*/
-int ask_menu(cptr ask, char **items, int max)
+int ask_menu(cptr ask, const std::vector<std::string> &items)
{
int ret = -1, i, start = 0;
char c;
+ int size = static_cast<int>(items.size()); // Convert to int to avoid warnings
/* Enter "icky" mode */
character_icky = TRUE;
@@ -4238,9 +3472,9 @@ int ask_menu(cptr ask, char **items, int max)
Term_load();
Term_save();
prt(ask, 0, 0);
- for (i = start; (i < max) && (i < start + 20); i++)
+ for (i = start; (i < size) && (i < start + 20); i++)
{
- prt(format("%c) %s", I2A(i - start), items[i]), i - start + 1, 0);
+ prt(format("%c) %s", I2A(i - start), items[i].c_str()), i - start + 1, 0);
}
/* Wait for user input */
@@ -4252,7 +3486,7 @@ int ask_menu(cptr ask, char **items, int max)
/* Scroll */
else if (c == '+')
{
- if (start + 20 < max)
+ if (start + 20 < size)
start += 20;
continue;
}
@@ -4269,7 +3503,7 @@ int ask_menu(cptr ask, char **items, int max)
else
{
c = tolower(c);
- if (A2I(c) + start >= max)
+ if (A2I(c) + start >= size)
{
bell();
continue;
@@ -4302,7 +3536,6 @@ bool_ prefix(cptr s, cptr t)
/* Paranoia */
if (!s || !t)
{
- if (alert_failure) message_add(MESSAGE_MSG, "prefix() called with null argument!", TERM_RED);
return FALSE;
}
@@ -4318,19 +3551,6 @@ bool_ prefix(cptr s, cptr t)
}
/*
- * 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
*/
void draw_box(int y, int x, int h, int w)
@@ -4361,114 +3581,77 @@ void draw_box(int y, int x, int h, int w)
/*
* Displays a scrollable boxed list with a selected item
*/
-void display_list(int y, int x, int h, int w, cptr title, cptr *list, int max, int begin, int sel, byte sel_color)
+void display_list(int y, int x, int h, int w, cptr title, std::vector<std::string> const &list, std::size_t begin, std::size_t sel, byte sel_color)
{
- int i;
-
draw_box(y, x, h, w);
c_put_str(TERM_L_BLUE, title, y, x + ((w - strlen(title)) / 2));
- for (i = 0; i < h - 1; i++)
+ for (int i = 0; i < h - 1; i++)
{
byte color = TERM_WHITE;
- if (i + begin >= max) break;
+ if (i + begin >= list.size())
+ {
+ break;
+ }
if (i + begin == sel) color = sel_color;
- c_put_str(color, list[i + begin], y + 1 + i, x + 1);
+ c_put_str(color, list[i + begin].c_str(), y + 1 + i, x + 1);
}
}
-/*
- * Creates an input box
- */
-bool_ input_box(cptr text, int y, int x, char *buf, int max)
+bool input_box_auto(std::string const &prompt, std::string *buf, std::size_t max)
{
- int smax = strlen(text);
+ int wid, hgt;
+ Term_get_size(&wid, &hgt);
+
+ auto const y = hgt / 2;
+ auto const x = wid / 2;
- if (max > smax) smax = max;
- smax++;
+ auto const smax = std::max(prompt.size(), max) + 1;
draw_box(y - 1, x - (smax / 2), 3, smax);
- c_put_str(TERM_WHITE, text, y, x - (strlen(text) / 2));
+ c_put_str(TERM_WHITE, prompt.c_str(), y, x - (prompt.size() / 2));
Term_gotoxy(x - (smax / 2) + 1, y + 1);
return askfor_aux(buf, max);
}
-/*
- * Creates a msg bbox and ask a question
- */
-char msg_box(cptr text, int y, int x)
+std::string input_box_auto(std::string const &title, std::size_t max)
{
- if (x == -1)
- {
- int wid = 0, hgt = 0;
- Term_get_size(&wid, &hgt);
- x = wid / 2;
- y = hgt / 2;
- }
-
- draw_box(y - 1, x - ((strlen(text) + 1) / 2), 2, strlen(text) + 1);
- c_put_str(TERM_WHITE, text, y, x - ((strlen(text) + 1) / 2) + 1);
- return inkey();
+ std::string buf;
+ input_box_auto(title, &buf, max);
+ return buf;
}
-/* Rescale a value */
-s32b rescale(s32b x, s32b max, s32b new_max)
+char msg_box_auto(std::string const &text)
{
- return (x * new_max) / max;
-}
+ int wid, hgt;
+ Term_get_size(&wid, &hgt);
-/* Nicer wrapper around TERM_XTRA_SCANSUBDIR */
-void scansubdir(cptr dir)
-{
- strnfmt(scansubdir_dir, 1024, "%s", dir);
- Term_xtra(TERM_XTRA_SCANSUBDIR, 0);
+ auto const y = hgt / 2;
+ auto const x = wid / 2;
+
+ draw_box(y - 1, x - ((text.size() + 1) / 2), 2, text.size() + 1);
+ c_put_str(TERM_WHITE, text.c_str(), y, x - ((text.size() + 1) / 2) + 1);
+ return inkey();
}
/*
* Timers
*/
-timer_type *new_timer(cptr callback, s32b delay)
+timer_type *new_timer(void (*callback)(), s32b delay)
{
- timer_type *t_ptr;
-
- MAKE(t_ptr, timer_type);
- t_ptr->next = gl_timers;
- gl_timers = t_ptr;
-
- t_ptr->callback = string_make(callback);
- t_ptr->delay = delay;
- t_ptr->countdown = delay;
- t_ptr->enabled = FALSE;
+ auto &timers = game->timers;
+ timer_type *t_ptr = new timer_type(callback, delay);
+ timers.push_back(t_ptr);
return t_ptr;
}
-void del_timer(timer_type *t_ptr)
-{
- timer_type *i, *old;
-
- old = NULL;
- for (i = gl_timers; (i != NULL) && (i != t_ptr); old = i, i = i->next)
- ;
- if (i)
- {
- if (old == NULL)
- gl_timers = t_ptr->next;
- else
- old->next = t_ptr->next;
- string_free(t_ptr->callback);
- FREE(t_ptr, timer_type);
- }
- else
- cmsg_print(TERM_VIOLET, "Unknown timer!");
-}
-
int get_keymap_mode()
{
- if (rogue_like_commands)
+ if (options->rogue_like_commands)
{
return KEYMAP_MODE_ROGUE;
}
@@ -4477,3 +3660,28 @@ int get_keymap_mode()
return KEYMAP_MODE_ORIG;
}
}
+
+/**
+ * Determines if a map location is fully inside the outer walls
+ */
+bool in_bounds(int y, int x)
+{
+ return (y > 0) && (x > 0) && (y < cur_hgt-1) && (x < cur_wid-1);
+}
+
+/**
+ * Determines if a map location is on or inside the outer walls
+ */
+bool in_bounds2(int y, int x)
+{
+ return (y >= 0) && (x >= 0) && (y < cur_hgt) && (x < cur_wid);
+}
+
+/**
+ * Determines if a map location is currently "on screen" -RAK-
+ * Note that "panel_contains(Y,X)" always implies "in_bounds2(Y,X)".
+ */
+bool panel_contains(int y, int x)
+{
+ return (y >= panel_row_min) && (y <= panel_row_max) && (x >= panel_col_min) && (x <= panel_col_max);
+}
diff --git a/src/util.h b/src/util.h
new file mode 100644
index 00000000..7be705a0
--- /dev/null
+++ b/src/util.h
@@ -0,0 +1,19 @@
+#pragma once
+
+#include "h-basic.h"
+
+// C linkage required for these functions since main-* code uses them.
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+errr path_build(char *buf, int max, cptr path, cptr file);
+void bell();
+errr macro_add(cptr pat, cptr act);
+sint macro_find_exact(cptr pat);
+char inkey();
+void prt(cptr str, int row, int col);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/src/util.hpp b/src/util.hpp
new file mode 100644
index 00000000..1f5c3aed
--- /dev/null
+++ b/src/util.hpp
@@ -0,0 +1,86 @@
+#pragma once
+
+#include "h-basic.h"
+#include "timer_type_fwd.hpp"
+
+#include <vector>
+#include <string>
+
+#define MAX_IGNORE_KEYMAPS 12
+
+bool input_box(std::string const &text, int y, int x, std::string *buf, std::size_t max);
+std::string input_box_auto(std::string const &title, std::size_t max);
+bool input_box_auto(std::string const &prompt, std::string *buf, std::size_t max);
+void draw_box(int y, int x, int h, int w);
+void display_list(int y, int x, int h, int w, cptr title, std::vector<std::string> const &list, std::size_t begin, std::size_t sel, byte sel_color);
+std::string get_player_race_name(int pr, int ps);
+std::string get_day(s32b day);
+s32b bst(s32b what, s32b t);
+FILE *my_fopen(cptr file, cptr mode);
+errr my_fgets(FILE *fff, char *buf, huge n);
+errr my_fclose(FILE *fff);
+errr fd_kill(cptr file);
+errr fd_move(cptr file, cptr what);
+int fd_make(cptr file, int mode);
+int fd_open(cptr file, int flags);
+errr fd_seek(int fd, huge n);
+errr fd_read(int fd, char *buf, huge n);
+errr fd_write(int fd, cptr buf, huge n);
+errr fd_close(int fd);
+void flush();
+void flush_on_failure();
+void move_cursor(int row, int col);
+void text_to_ascii(char *buf, cptr str);
+void ascii_to_text(char *buf, cptr str);
+char inkey_scan();
+void display_message(int x, int y, int split, byte color, cptr t);
+void cmsg_print(byte color, cptr msg);
+void cmsg_print(byte color, std::string const &msg);
+void msg_print(cptr msg);
+void cmsg_format(byte color, cptr fmt, ...);
+void msg_format(cptr fmt, ...);
+void screen_save();
+void screen_load();
+void c_put_str(byte attr, cptr str, int row, int col);
+void c_put_str(byte attr, std::string const &str, int row, int col);
+void put_str(cptr str, int row, int col);
+void put_str(std::string const &s, int row, int col);
+void c_prt(byte attr, cptr str, int row, int col);
+void c_prt(byte attr, std::string const &s, int row, int col);
+void prt(std::string const &s, int row, int col);
+void text_out_to_screen(byte a, cptr str);
+void text_out_to_file(byte a, cptr str);
+void text_out(cptr str);
+void text_out_c(byte a, cptr str);
+void clear_from(int row);
+int ask_menu(cptr ask, const std::vector<std::string> &items);
+bool askfor_aux(std::string *buf, std::size_t max_len);
+bool_ askfor_aux(char *buf, int len);
+bool_ askfor_aux_with_completion(char *buf, int len);
+bool_ get_string(cptr prompt, char *buf, int len);
+bool_ get_check(cptr prompt);
+bool_ get_com(cptr prompt, char *command);
+s32b get_quantity(cptr prompt, s32b max);
+extern char request_command_ignore_keymaps[MAX_IGNORE_KEYMAPS];
+extern bool_ request_command_inven_mode;
+void request_command(int shopping);
+bool_ is_a_vowel(int ch);
+int get_keymap_dir(char ch);
+byte count_bits(u32b array);
+void strlower(char *buf);
+int test_monster_name(cptr name);
+int test_mego_name(cptr name);
+int test_item_name(cptr name);
+char msg_box_auto(std::string const &title);
+timer_type *new_timer(void (*callback)(), s32b delay);
+int get_keymap_mode();
+void repeat_push(int what);
+bool_ repeat_pull(int *what);
+void repeat_check();
+void get_count(int number, int max);
+bool in_bounds(int y, int x);
+bool in_bounds2(int y, int x);
+bool panel_contains(int y, int x);
+errr path_parse(char *buf, int max, cptr file);
+void pause_line(int row);
+std::string user_name();
diff --git a/src/util.pkg b/src/util.pkg
deleted file mode 100644
index 39f70b40..00000000
--- a/src/util.pkg
+++ /dev/null
@@ -1,2683 +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_INIT
- * @brief Game initialised.
- * @note (see file dungeon.c)
- */
-#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
-
-/** @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_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_BONUS
- * @brief Calculate player "state" bonuses.
- * @note (see xtra1.c)
- */
-#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)
- */
-#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_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)
- */
-#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_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.
- * @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_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)
- */
-#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_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.
- * @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_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_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)
- */
-#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_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.
- * @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 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
- */
-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
- * @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);
-
-/* 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]
- * @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);
-
-/** @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
- * @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);
-
-/*
- * 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;
-};
-
-/** @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
- */
-/** @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);
-
-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);
diff --git a/src/variable.c b/src/variable.c
deleted file mode 100644
index 0eb0fadf..00000000
--- a/src/variable.c
+++ /dev/null
@@ -1,1604 +0,0 @@
-/* File: variable.c */
-
-/* Purpose: Angband variables */
-
-/*
- * 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"
-
-
-/*
- * 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;
-char *macro_modifier_name[MAX_MACRO_MOD];
-char *macro_trigger_name[MAX_MACRO_TRIG];
-char *macro_trigger_keycode[2][MAX_MACRO_TRIG];
-
-/*
- * Executable version
- */
-byte version_major;
-byte version_minor;
-byte version_patch;
-byte version_extra = VERSION_EXTRA;
-
-/*
- * Savefile version
- */
-byte sf_major; /* Savefile's "version_major" */
-byte sf_minor; /* Savefile's "version_minor" */
-byte sf_patch; /* Savefile's "version_patch" */
-byte sf_extra; /* Savefile's "version_extra" */
-u32b vernum;
-
-/*
- * Savefile information
- */
-u32b sf_xtra; /* Operating system info */
-u32b sf_when; /* Time when savefile created */
-u16b sf_lives; /* Number of past "lives" with this file */
-u16b sf_saves; /* Number of "saves" during this life */
-
-/*
- * Run-time arguments
- */
-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 */
-bool_ arg_force_original; /* Command arg -- Request original keyset */
-bool_ arg_force_roguelike; /* Command arg -- Request roguelike keyset */
-bool_ arg_bigtile = FALSE; /* Command arg -- Request big tile mode */
-
-/*
- * Various things
- */
-
-bool_ character_generated; /* The character exists */
-bool_ character_dungeon; /* The character has a dungeon */
-bool_ character_loaded; /* The character was loaded from a savefile */
-bool_ character_saved; /* The character was just saved to a savefile */
-
-bool_ character_icky; /* The game is in an icky full screen mode */
-bool_ character_xtra; /* The game is in an icky startup mode */
-
-u32b seed_flavor; /* Hack -- consistent object colors */
-
-s16b command_cmd; /* Current "Angband Command" */
-
-s16b command_arg; /* Gives argument of current command */
-s16b command_rep; /* Gives repetition of current command */
-s16b command_dir; /* Gives direction of current command */
-
-s16b command_wrk; /* See "cmd1.c" */
-
-s16b command_new; /* Command chaining from inven/equip view */
-
-s32b energy_use; /* Energy use this turn */
-
-bool_ create_up_stair; /* Auto-create "up stairs" */
-bool_ create_down_stair; /* Auto-create "down stairs" */
-
-bool_ create_up_shaft; /* Auto-create "up shaft" */
-bool_ create_down_shaft; /* Auto-create "down shaft" */
-
-bool_ msg_flag; /* Used in msg_print() for "buffering" */
-
-bool_ alive; /* True if game is running */
-
-bool_ death; /* True if player has died */
-
-s16b running; /* Current counter for running, if any */
-s16b resting; /* Current counter for resting, if any */
-
-s16b cur_hgt; /* Current dungeon height */
-s16b cur_wid; /* Current dungeon width */
-s16b dun_level; /* Current dungeon level */
-s16b old_dun_level; /* Old dungeon level */
-s16b num_repro; /* Current reproducer count */
-s16b object_level; /* Current object creation level */
-s16b monster_level; /* Current monster creation level */
-
-s32b turn; /* Current game turn */
-s32b old_turn; /* Turn when level began (feelings) */
-
-bool_ wizard; /* Is the player currently in Wizard mode? */
-
-bool_ use_sound; /* The "sound" mode is enabled */
-bool_ use_graphics; /* The "graphics" mode is enabled */
-bool_ use_bigtile = FALSE;
-byte graphics_mode; /* Current graphics mode */
-
-u16b total_winner; /* Semi-Hack -- Game has been won */
-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 */
-bool_ inkey_flag; /* See the "inkey()" function */
-
-s16b coin_type; /* Hack -- force coin type */
-
-bool_ opening_chest; /* Hack -- prevent chest generation */
-
-bool_ shimmer_monsters; /* Hack -- optimize multi-hued monsters */
-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;
-
-s16b inven_cnt; /* Number of items in inventory */
-s16b equip_cnt; /* Number of items in equipment */
-
-s16b o_max = 1; /* Number of allocated objects */
-s16b o_cnt = 0; /* Number of live objects */
-
-s16b m_max = 1; /* Number of allocated monsters */
-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;
-s32b total_friend_levels = 0;
-
-int leaving_quest = 0;
-
-
-
-/*
- * Hack - the destination file for text_out_to_file.
- */
-FILE *text_out_file = NULL;
-
-
-/*
- * Hack -- function hook to output (colored) text to the
- * screen or to a file.
- */
-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().
- */
-int text_out_indent = 0;
-
-
-/*
- * The "highscore" file descriptor, if available.
- */
-int highscore_fd = -1;
-
-
-/*
- * Software options (set via the '=' command). See "tables.c"
- */
-
-
-/* Option Set 1 -- User Interface */
-
-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 */
-bool_ prompt_pickup_heavy; /* Don't pick up the corpses */
-bool_ always_repeat; /* Repeat obvious commands */
-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_ 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 */
-
-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 */
-
-bool_ find_ignore_stairs; /* Run past stairs */
-bool_ find_ignore_doors; /* Run through open doors */
-bool_ find_cut; /* Run past known corners */
-bool_ find_examine; /* Run into potential corners */
-
-bool_ disturb_move; /* Disturb whenever any monster moves */
-bool_ disturb_near; /* Disturb whenever viewable monster moves */
-bool_ disturb_panel; /* Disturb whenever map panel changes */
-bool_ disturb_detect; /* Disturb whenever leaving trap-detected area */
-bool_ disturb_state; /* Disturn whenever player state changes */
-bool_ disturb_minor; /* Disturb whenever boring things happen */
-bool_ disturb_other; /* Disturb whenever various things happen */
-
-bool_ alert_hitpoint; /* Alert user to critical hitpoints */
-bool_ alert_failure; /* Alert user to various failures */
-bool_ last_words; /* Get last words upon dying */
-bool_ speak_unique; /* Speaking uniques + shopkeepers */
-bool_ small_levels; /* Allow unusually small dungeon levels */
-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 */
-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 */
-bool_ stack_allow_wands; /* Allow wands/staffs/rods to stack */
-
-bool_ expand_look; /* Expand the power of the look command */
-bool_ expand_list; /* Expand the power of the list commands */
-
-bool_ view_perma_grids; /* Map remembers all perma-lit grids */
-bool_ view_torch_grids; /* Map remembers all torch-lit grids */
-
-bool_ monster_lite; /* Allow some monsters to carry light */
-
-bool_ dungeon_align; /* Generate dungeons with aligned rooms */
-bool_ dungeon_stair; /* Generate dungeons with connected stairs */
-
-bool_ flow_by_sound; /* Monsters track new player location */
-
-bool_ track_follow; /* Monsters follow the player */
-bool_ track_target; /* Monsters target the player */
-
-bool_ smart_learn; /* Monsters learn from their mistakes */
-bool_ smart_cheat; /* Monsters exploit player weaknesses */
-
-
-/* Option Set 4 -- Efficiency */
-
-bool_ view_reduce_lite; /* Reduce lite-radius when running */
-bool_ view_reduce_view; /* Reduce view-radius in town */
-
-bool_ avoid_abort; /* Avoid checking for user abort */
-bool_ avoid_shimmer; /* Avoid processing extra shimmering */
-bool_ avoid_other; /* Avoid processing special colors */
-
-bool_ flush_failure; /* Flush input on any failure */
-bool_ flush_disturb; /* Flush input on disturbance */
-bool_ flush_command; /* Flush input before every command */
-
-bool_ fresh_before; /* Flush output before normal commands */
-bool_ fresh_after; /* Flush output after normal commands */
-bool_ fresh_message; /* Flush output after all messages */
-
-bool_ hilite_player; /* Hilite the player with the cursor */
-
-bool_ view_yellow_lite; /* Use special colors for torch-lit grids */
-bool_ view_bright_lite; /* Use special colors for 'viewable' grids */
-
-bool_ view_granite_lite; /* Use special colors for wall grids (slow) */
-bool_ view_special_lite; /* Use special colors for floor grids (slow) */
-
-/* Option set 5 -- Testing */
-
-bool_ testing_stack; /* Test the stacking code */
-
-bool_ testing_carry; /* Test the carrying code */
-
-
-/* Cheating options */
-
-bool_ cheat_peek; /* Peek into object creation */
-bool_ cheat_hear; /* Peek into monster creation */
-bool_ cheat_room; /* Peek into dungeon creation */
-bool_ cheat_xtra; /* Peek into something else */
-bool_ cheat_know; /* Know complete monster info */
-bool_ cheat_live; /* Allow player to avoid death */
-
-
-/* Special options */
-
-byte hitpoint_warn; /* Hitpoint warning (0 to 9) */
-
-byte delay_factor; /* Delay factor (0 to 9) */
-
-bool_ autosave_l; /* Autosave before entering new levels */
-bool_ autosave_t; /* Timed autosave */
-s16b autosave_freq; /* Autosave frequency */
-
-
-/*
- * Dungeon variables
- */
-
-s16b feeling; /* Most recent feeling */
-s16b rating; /* Level's current rating */
-
-bool_ good_item_flag; /* True if "Artifact" on this level */
-
-bool_ closing_flag; /* Dungeon is closing */
-
-/*
- * Dungeon size info
- */
-
-s16b max_panel_rows, max_panel_cols;
-s16b panel_row_min, panel_row_max;
-s16b panel_col_min, panel_col_max;
-s16b panel_col_prt, panel_row_prt;
-
-/*
- * Dungeon graphics info
- * Why the first two are byte and the rest s16b???
- */
-byte feat_wall_outer = FEAT_WALL_OUTER; /* Outer wall of rooms */
-byte feat_wall_inner = FEAT_WALL_INNER; /* Inner wall of rooms */
-s16b floor_type[100]; /* Dungeon floor */
-s16b fill_type[100]; /* Dungeon filler */
-
-/*
- * Targetting variables
- */
-s16b target_who;
-s16b target_col;
-s16b target_row;
-
-/*
- * Health bar variable -DRS-
- */
-s16b health_who;
-
-/*
- * Monster race to track
- */
-s16b monster_race_idx;
-s16b monster_ego_idx;
-
-/*
- * Object to track
- */
-object_type *tracked_object;
-
-
-
-/*
- * User info
- */
-int player_uid;
-
-/*
- * Current player's character name
- */
-char player_name[32];
-
-/*
- * Stripped version of "player_name"
- */
-char player_base[32];
-
-/*
- * What killed the player
- */
-char died_from[80];
-
-/*
- * Hack -- Textual "history" for the Player
- */
-char history[4][60];
-
-/*
- * Buffer to hold the current savefile name
- */
-char savefile[1024];
-
-
-/*
- * Array of grids lit by player lite (see "cave.c")
- */
-s16b lite_n;
-s16b lite_y[LITE_MAX];
-s16b lite_x[LITE_MAX];
-
-/*
- * Array of grids viewable to the player (see "cave.c")
- */
-s16b view_n;
-byte view_y[VIEW_MAX];
-byte view_x[VIEW_MAX];
-
-/*
- * Array of grids for use by various functions (see "cave.c")
- */
-s16b temp_n;
-byte temp_y[TEMP_MAX];
-byte temp_x[TEMP_MAX];
-
-
-/*
- * Number of active macros.
- */
-s16b macro__num;
-
-/*
- * Array of macro patterns [MACRO_MAX]
- */
-cptr *macro__pat;
-
-/*
- * Array of macro actions [MACRO_MAX]
- */
-cptr *macro__act;
-
-/*
- * Array of macro types [MACRO_MAX]
- */
-bool_ *macro__cmd;
-
-/*
- * Current macro action [1024]
- */
-char *macro__buf;
-
-
-/*
- * The number of quarks
- */
-s16b quark__num;
-
-/*
- * The pointers to the quarks [QUARK_MAX]
- */
-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
- */
-u32b option_flag[8];
-u32b option_mask[8];
-
-
-/*
- * The array of window options
- */
-u32b window_flag[8];
-u32b window_mask[8];
-
-
-/*
- * The array of window pointers
- */
-term *angband_term[ANGBAND_TERM_MAX];
-
-
-/*
- * Standard window names
- */
-char angband_term_name[ANGBAND_TERM_MAX][80] =
-{
- "ToME",
- "Mirror",
- "Recall",
- "Choice",
- "Term-4",
- "Term-5",
- "Term-6",
- "Term-7"
-};
-
-
-/*
- * Global table of color definitions
- */
-byte angband_color_table[256][4] =
-{
- {0x00, 0x00, 0x00, 0x00}, /* TERM_DARK */
- {0x00, 0xFF, 0xFF, 0xFF}, /* TERM_WHITE */
- {0x00, 0x80, 0x80, 0x80}, /* TERM_SLATE */
- {0x00, 0xFF, 0x80, 0x00}, /* TERM_ORANGE */
- {0x00, 0xC0, 0x00, 0x00}, /* TERM_RED */
- {0x00, 0x00, 0x80, 0x40}, /* TERM_GREEN */
- {0x00, 0x00, 0x00, 0xFF}, /* TERM_BLUE */
- {0x00, 0x80, 0x40, 0x00}, /* TERM_UMBER */
- {0x00, 0x40, 0x40, 0x40}, /* TERM_L_DARK */
- {0x00, 0xC0, 0xC0, 0xC0}, /* TERM_L_WHITE */
- {0x00, 0xFF, 0x00, 0xFF}, /* TERM_VIOLET */
- {0x00, 0xFF, 0xFF, 0x00}, /* TERM_YELLOW */
- {0x00, 0xFF, 0x00, 0x00}, /* TERM_L_RED */
- {0x00, 0x00, 0xFF, 0x00}, /* TERM_L_GREEN */
- {0x00, 0x00, 0xFF, 0xFF}, /* TERM_L_BLUE */
- {0x00, 0xC0, 0x80, 0x40} /* TERM_L_UMBER */
-};
-
-
-/*
- * Standard sound names
- */
-char angband_sound_name[SOUND_MAX][16] =
-{
- "",
- "hit",
- "miss",
- "flee",
- "drop",
- "kill",
- "level",
- "death",
- "study",
- "teleport",
- "shoot",
- "quaff",
- "zap",
- "walk",
- "tpother",
- "hitwall",
- "eat",
- "store1",
- "store2",
- "store3",
- "store4",
- "dig",
- "opendoor",
- "shutdoor",
- "tplevel",
- "scroll",
- "buy",
- "sell",
- "warn",
- "rocket",
- "n_kill",
- "u_kill",
- "quest",
- "heal",
- "x_heal",
- "bite",
- "claw",
- "m_spell",
- "summon",
- "breath",
- "ball",
- "m_heal",
- "atkspell",
- "evil",
- "touch",
- "sting",
- "crush",
- "slime",
- "wail",
- "winner",
- "fire",
- "acid",
- "elec",
- "cold",
- "illegal",
- "fail",
- "wakeup",
- "invuln",
- "fall",
- "pain",
- "destitem",
- "moan",
- "show",
- "unused",
- "explode",
-};
-
-
-/*
- * The array of "cave grids" [MAX_WID][MAX_HGT].
- * Not completely allocated, that would be inefficient
- * Not completely hardcoded, that would overflow memory
- */
-cave_type *cave[MAX_HGT];
-
-/*
- * The array of dungeon items [max_o_idx]
- */
-object_type *o_list;
-
-/*
- * The array of dungeon monsters [max_m_idx]
- */
-monster_type *m_list;
-
-/*
- * The array of to keep monsters [max_m_idx]
- */
-monster_type *km_list;
-
-
-/*
- * Maximum number of towns
- */
-u16b max_towns;
-u16b max_real_towns;
-
-/*
- * The towns [max_towns]
- */
-town_type *town_info;
-
-/*
- * The size of "alloc_kind_table" (at most max_k_idx * 4)
- */
-s16b alloc_kind_size;
-
-/*
- * The entries in the "kind allocator table"
- */
-alloc_entry *alloc_kind_table;
-
-/*
- * The flag to tell if alloc_kind_table contains valid entries
- * for normal (i.e. kind_is_legal) object allocation
- */
-bool_ alloc_kind_table_valid = FALSE;
-
-
-/*
- * The size of "alloc_race_table" (at most max_r_idx)
- */
-s16b alloc_race_size;
-
-/*
- * The entries in the "race allocator table"
- */
-alloc_entry *alloc_race_table;
-
-
-/*
- * Specify attr/char pairs for visual special effects
- * Be sure to use "index & 0x7F" to avoid illegal access
- */
-byte misc_to_attr[256];
-char misc_to_char[256];
-
-
-/*
- * Specify attr/char pairs for inventory items (by tval)
- * Be sure to use "index & 0x7F" to avoid illegal access
- */
-byte tval_to_attr[128];
-char tval_to_char[128];
-
-
-/*
- * Keymaps for each "mode" associated with each keypress.
- */
-cptr keymap_act[KEYMAP_MODES][256];
-
-
-
-/*** Player information ***/
-
-/*
- * Static player info record
- */
-player_type p_body;
-
-/*
- * Pointer to the player info
- */
-player_type *p_ptr = &p_body;
-
-/*
- * Pointer to the player tables
- * (sex, race, race mod, class, magic)
- */
-player_sex *sp_ptr;
-player_race *rp_ptr;
-player_race_mod *rmp_ptr;
-player_class *cp_ptr;
-player_spec *spp_ptr;
-
-
-/*
- * More spell info
- */
-u32b alchemist_known_egos[32];
-u32b alchemist_known_artifacts[6];
-u32b alchemist_gained;
-
-
-/*
- * Calculated base hp values for player at each level,
- * store them so that drain life + restore life does not
- * affect hit points. Also prevents shameless use of backup
- * savefiles for hitpoint acquirement.
- */
-s16b player_hp[PY_MAX_LEVEL];
-
-/*
- * The alchemy recipe arrays
- */
-header *al_head;
-alchemist_recipe *alchemist_recipes;
-char *al_name;
-artifact_select_flag *a_select_flags;
-
-/*
- * The vault generation arrays
- */
-header *v_head;
-vault_type *v_info;
-char *v_name;
-char *v_text;
-
-/*
- * The terrain feature arrays
- */
-header *f_head;
-feature_type *f_info;
-char *f_name;
-char *f_text;
-
-/*
- * The object kind arrays
- */
-header *k_head;
-object_kind *k_info;
-char *k_name;
-char *k_text;
-
-/*
- * The artifact arrays
- */
-header *a_head;
-artifact_type *a_info;
-char *a_name;
-char *a_text;
-
-/*
- * The item set arrays
- */
-header *set_head;
-set_type *set_info;
-char *set_name;
-char *set_text;
-
-/*
- * The ego-item arrays
- */
-header *e_head;
-ego_item_type *e_info;
-char *e_name;
-char *e_text;
-
-/*
- * The randart arrays
- */
-header *ra_head;
-randart_part_type *ra_info;
-randart_gen_type ra_gen[30];
-
-/* jk */
-/* the trap-arrays */
-header *t_head;
-trap_type *t_info;
-char *t_name;
-char *t_text;
-
-/*
- * The monster race arrays
- */
-header *r_head;
-monster_race *r_info;
-char *r_name;
-char *r_text;
-
-/*
- * The monster ego race arrays
- */
-header *re_head;
-monster_ego *re_info;
-char *re_name;
-
-/*
- * The dungeon types arrays
- */
-header *d_head;
-dungeon_info_type *d_info;
-char *d_name;
-char *d_text;
-
-/*
- * Player abilities arrays
- */
-header *ab_head;
-ability_type *ab_info;
-char *ab_name;
-char *ab_text;
-
-/*
- * Player skills arrays
- */
-header *s_head;
-skill_type *s_info;
-char *s_name;
-char *s_text;
-
-/*
- * Player race arrays
- */
-header *rp_head;
-player_race *race_info;
-char *rp_name;
-char *rp_text;
-
-/*
- * Player mod race arrays
- */
-header *rmp_head;
-player_race_mod *race_mod_info;
-char *rmp_name;
-char *rmp_text;
-
-/*
- * Player class arrays
- */
-header *c_head;
-player_class *class_info;
-char *c_name;
-char *c_text;
-meta_class_type *meta_class_info;
-
-/*
- * The wilderness features arrays
- */
-header *wf_head;
-wilderness_type_info *wf_info;
-char *wf_name;
-char *wf_text;
-int wildc2i[256];
-
-/*
- * The store/building types arrays
- */
-header *st_head;
-store_info_type *st_info;
-char *st_name;
-/* char *st_text; */
-
-/*
- * The building actions types arrays
- */
-header *ba_head;
-store_action_type *ba_info;
-char *ba_name;
-/* char *ba_text; */
-
-/*
- * The owner types arrays
- */
-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"
- * This variable is used to choose an appropriate "pref-xxx" file
- */
-cptr ANGBAND_SYS = "xxx";
-
-/*
- * Hack -- The special Angband "Keyboard Suffix"
- * This variable is used to choose an appropriate macro-trigger definition
- */
-#ifdef JP
-cptr ANGBAND_KEYBOARD = "JAPAN";
-#else
-cptr ANGBAND_KEYBOARD = "0";
-#endif
-
-/*
- * Hack -- The special Angband "Graphics Suffix"
- * This variable is used to choose an appropriate "graf-xxx" file
- */
-cptr ANGBAND_GRAF = "old";
-
-/*
- * Path name: The main "lib" directory
- * This variable is not actually used anywhere in the code
- */
-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
- */
-cptr ANGBAND_DIR_CORE;
-
-/*
- * Textual dungeon level definition files
- * These files are portable between platforms
- */
-cptr ANGBAND_DIR_DNGN;
-
-/*
- * Binary image files for the "*_info" arrays (binary)
- * These files are not portable between platforms
- */
-cptr ANGBAND_DIR_DATA;
-
-/*
- * Textual template files for the "*_info" arrays (ascii)
- * These files are portable between platforms
- */
-cptr ANGBAND_DIR_EDIT;
-
-/*
- * Various extra files (ascii)
- * These files may be portable between platforms
- */
-cptr ANGBAND_DIR_FILE;
-
-/*
- * Help files (normal) for the online help (ascii)
- * These files are portable between platforms
- */
-cptr ANGBAND_DIR_HELP;
-
-/*
- * Help files (spoilers) for the online help (ascii)
- * These files are portable between platforms
- */
-cptr ANGBAND_DIR_INFO;
-
-/*
- * Modules, those subdirectories are half-mirrors of lib/
- */
-cptr ANGBAND_DIR_MODULES;
-
-/*
- * Patches, contains one subdir per patch with a patch.lua file
- * in it and a patch_init() function in it
- */
-cptr ANGBAND_DIR_PATCH;
-
-/*
- * Textual template files for the plot files (ascii)
- * These files are portable between platforms
- */
-cptr ANGBAND_DIR_NOTE;
-
-/*
- * Savefiles for current characters (binary)
- * These files are portable between platforms
- */
-cptr ANGBAND_DIR_SAVE;
-
-/*
- * Scripts.
- * These files are portable between platforms
- */
-cptr ANGBAND_DIR_SCPT;
-
-/*
- * Default "preference" files (ascii)
- * These files are rarely portable between platforms
- */
-cptr ANGBAND_DIR_PREF;
-
-/*
- * User "preference" files (ascii)
- * These files are rarely portable between platforms
- */
-cptr ANGBAND_DIR_USER;
-
-/*
- * Various extra files (binary)
- * These files are rarely portable between platforms
- */
-cptr ANGBAND_DIR_XTRA;
-
-/*
- * Cmovie files of entire games (ascii)
- * Apart from possible newline things, likely portable btw platforms
- */
-
-cptr ANGBAND_DIR_CMOV;
-
-/*
- * Some variables values are created on the fly XXX XXX
- */
-
-char pref_tmp_value[8];
-
-
-
-/*
- * Total Hack -- allow all items to be listed (even empty ones)
- * This is only used by "do_cmd_inven_e()" and is cleared there.
- */
-bool_ item_tester_full;
-
-
-/*
- * Here is a "pseudo-hook" used during calls to "get_item()" and
- * "show_inven()" and "show_equip()", and the choice window routines.
- */
-byte item_tester_tval;
-
-
-/*
- * Here is a "hook" used during calls to "get_item()" and
- * "show_inven()" and "show_equip()", and the choice window routines.
- */
-bool_ (*item_tester_hook)(object_type*);
-
-
-
-/*
- * Current "comp" function for ang_sort()
- */
-bool_ (*ang_sort_comp)(vptr u, vptr v, int a, int b);
-
-
-/*
- * Current "swap" function for ang_sort()
- */
-void (*ang_sort_swap)(vptr u, vptr v, int a, int b);
-
-
-
-/*
- * Hack -- function hooks to restrict "get_mon_num_prep()" function
- */
-bool_ (*get_mon_num_hook)(int r_idx);
-bool_ (*get_mon_num2_hook)(int r_idx);
-
-
-/*
- * Hack -- function hook to restrict "get_obj_num_prep()" function
- */
-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;
-
-
-/*
- * Maximum size of the wilderness map
- */
-u16b max_wild_x;
-u16b max_wild_y;
-
-/*
- * Wilderness map
- */
-wilderness_map **wild_map;
-
-
-/*
- * Maximum number of skills in s_info.txt
- */
-u16b old_max_s_idx = 0;
-u16b max_s_idx;
-
-/*
- * Maximum number of abilities in ab_info.txt
- */
-u16b max_ab_idx;
-
-/*
- * Maximum number of monsters in r_info.txt
- */
-u16b max_r_idx;
-
-/*
- * Maximum number of ego monsters in re_info.txt
- */
-u16b max_re_idx;
-
-/*
- * Maximum number of items in k_info.txt
- */
-u16b max_k_idx;
-
-/*
- * Maximum number of vaults in v_info.txt
- */
-u16b max_v_idx;
-
-/*
- * Maximum number of terrain features in f_info.txt
- */
-u16b max_f_idx;
-
-/*
- * Maximum number of alchemist recipies in al_info.txt
- */
-u16b max_al_idx;
-
-/*
- * Maximum number of artifacts in a_info.txt
- */
-u16b max_a_idx;
-
-/*
- * Maximum number of ego-items in e_info.txt
- */
-u16b max_e_idx;
-
-/*
- * Maximum number of randarts in ra_info.txt
- */
-u16b max_ra_idx;
-
-/*
- * Maximum number of dungeon types in d_info.txt
- */
-u16b max_d_idx;
-
-/*
- * Maximum number of stores types in st_info.txt
- */
-u16b max_st_idx;
-
-/*
- * Item sets
- */
-s16b max_set_idx = 1;
-
-/*
- * Maximum number of players info in p_info.txt
- */
-u16b max_rp_idx;
-u16b max_rmp_idx;
-u16b max_c_idx;
-u16b max_mc_idx;
-
-/*
- * Maximum number of actions types in ba_info.txt
- */
-u16b max_ba_idx;
-
-/*
- * Maximum number of owner types in ow_info.txt
- */
-u16b max_ow_idx;
-
-/*
- * Maximum number of objects in the level
- */
-u16b max_o_idx;
-
-/*
- * Maximum number of monsters in the level
- */
-u16b max_m_idx;
-
-/*
- * Maximum number of traps in tr_info.txt
- */
-u16b max_t_idx;
-
-/*
- * Maximum number of wilderness features in wf_info.txt
- */
-u16b max_wf_idx;
-
-/*
- * Flags for initialization
- */
-int init_flags;
-
-/* True if on an ambush */
-bool_ ambush_flag;
-
-/* True if on fated level */
-bool_ fate_flag;
-
-/* No breeders */
-s16b no_breeds;
-
-/* Carried monsters can't take the damage if this is them which attack the player */
-bool_ carried_monster_hit = FALSE;
-
-/*
- * Random artifacts.
- */
-random_artifact random_artifacts[MAX_RANDARTS];
-/* These three used to be constants but now are set by modules */
-s32b RANDART_WEAPON;
-s32b RANDART_ARMOR;
-s32b RANDART_JEWEL;
-
-/*
- * Current bounties. An array of tuples of two, with the first being the
- * r_idx of the monster, and the second the monster's worth.
- */
-s16b bounties[MAX_BOUNTIES][2];
-
-/*
- * Spell description
- */
-bool_ info_spell = FALSE;
-char spell_txt[50];
-
-/*
- * Random spells.
- */
-random_spell random_spells[MAX_SPELLS];
-s16b spell_num;
-
-/*
- * Runecrafter's selfmade spells.
- */
-rune_spell rune_spells[MAX_RUNES];
-s16b rune_num;
-
-/*
- * Fate.
- */
-fate fates[MAX_FATES];
-
-/*
- * Which dungeon ?
- * 0 = Wilderness
- * 1 = Mirkwood
- * 2 = Mordor
- * 3 = Angband
- * 4 = Barrow Downs
- * 5 = Mount Doom
- * 6 = Nether Realm
- * etc. (see d_info.txt)
- */
-byte dungeon_type;
-s16b *max_dlv;
-
-/*
- * Number of total bounties the player had had.
- */
-u32b total_bounties;
-
-/* The Doppleganger index in m_list */
-s16b doppleganger;
-
-/* To allow wilderness encounters */
-bool_ generate_encounter;
-
-/* Permanent dungeons ? */
-bool_ permanent_levels;
-
-/* Autoroler */
-bool_ autoroll;
-
-/* Point based */
-bool_ point_based;
-
-/* Maximize, preserve, special levels, ironman_rooms */
-bool_ maximize, preserve, special_lvls, ironman_rooms;
-
-/* In inventory option window, just erase the letters,
- * rather that displaying the list without the invalid
- * selections */
-bool_ inventory_no_move;
-
-/* Notes patch */
-bool_ take_notes, auto_notes;
-
-/*
- * Such an ugly hack ...
- */
-bool_ *m_allow_special;
-bool_ *k_allow_special;
-bool_ *a_allow_special;
-
-/*
- * Gives a random object to newly created characters
- */
-bool_ rand_birth;
-
-/*
- * Fast autoroller
- */
-bool_ fast_autoroller;
-
-/*
- * Which monsters are allowed ?
- */
-bool_ joke_monsters;
-
-/*
- * How will mana staf & weapons of life act
- */
-bool_ munchkin_multipliers = TRUE;
-
-/*
- * Center view
- */
-bool_ center_player = FALSE;
-
-/*
- * Plots
- */
-s16b plots[MAX_PLOTS];
-
-/*
- * Random quest
- */
-random_quest random_quests[MAX_RANDOM_QUEST];
-
-/*
- * Show exp left
- */
-bool_ exp_need;
-
-/*
- * Auto load old colors;
- */
-bool_ autoload_old_colors;
-
-/*
- * Fated ?
- */
-bool_ fate_option;
-
-/*
- * Special levels
- */
-bool_ *special_lvl[MAX_DUNGEON_DEPTH];
-bool_ generate_special_feeling = FALSE;
-
-/*
- * Auto more
- */
-bool_ auto_more;
-
-/*
- * Dungeon flags
- */
-u32b dungeon_flags1;
-u32b dungeon_flags2;
-
-/*
- * The last character displayed
- */
-birther previous_char;
-
-/*
- * Race histories
- */
-hist_type *bg;
-int max_bg_idx;
-
-/*
- * Powers
- */
-s16b power_max = POWER_MAX_INIT;
-power_type *powers_type;
-
-/*
- * Variable savefile stuff
- */
-s32b extra_savefile_parts = 0;
-
-/*
- * Quests
- */
-s16b max_q_idx = MAX_Q_IDX_INIT;
-quest_type *quest;
-
-/*
- * Display the player as a special symbol when in bad health ?
- */
-bool_ player_char_health;
-
-
-/*
- * The spell list of schools
- */
-s16b max_spells;
-spell_type *school_spells;
-s16b max_schools;
-school_type *schools;
-
-/*
- * Lasting spell effects
- */
-int project_time = 0;
-s32b project_time_effect = 0;
-effect_type effects[MAX_EFFECTS];
-
-/*
- * General skills set
- */
-char gen_skill_basem[MAX_SKILLS];
-u32b gen_skill_base[MAX_SKILLS];
-char gen_skill_modm[MAX_SKILLS];
-s16b gen_skill_mod[MAX_SKILLS];
-
-/*
- * Display stats as linear
- */
-bool_ linear_stats;
-
-/*
- * Table of "cli" macros.
- */
-cli_comm *cli_info;
-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;
-
-/*
- * Max corruptions
- */
-s16b max_corruptions = 0;
-
-/*
- * Ingame contextual help
- */
-bool_ option_ingame_help = TRUE;
-
-/*
- * Automatizer enabled status
- */
-bool_ automatizer_enabled = FALSE;
-
-/*
- * Location of the last teleportation thath affected the level
- */
-s16b last_teleportation_y = -1;
-s16b last_teleportation_x = -1;
-
-/*
- * The current game module
- */
-cptr game_module;
-s32b VERSION_MAJOR;
-s32b VERSION_MINOR;
-s32b VERSION_PATCH;
-
-/*
- * Some module info
- */
-s32b max_plev = 50;
-s32b DUNGEON_DEATH = 28;
-
-/*
- * Gods
- */
-deity_type *deity_info;
-s32b max_gods = MAX_GODS_INIT;
-
-/*
- * Timers
- */
-timer_type *gl_timers = NULL;
-
-/**
- * Get the version string.
- */
-const char *get_version_string()
-{
- static char version_str[80];
- static bool_ initialized = 0;
- if (!initialized) {
- sprintf(version_str, "%s %ld.%ld.%ld%s",
- game_module,
- (long int) VERSION_MAJOR,
- (long int) VERSION_MINOR,
- (long int) VERSION_PATCH, IS_CVS);
- initialized = TRUE;
- }
- return version_str;
-}
diff --git a/src/variable.cc b/src/variable.cc
new file mode 100644
index 00000000..ae40676f
--- /dev/null
+++ b/src/variable.cc
@@ -0,0 +1,649 @@
+/*
+ * 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 "variable.hpp"
+#include "variable.h"
+
+#include "cli_comm_fwd.hpp"
+#include "player_type.hpp"
+#include "skill_modifiers.hpp"
+#include "util.hpp"
+
+
+int max_macrotrigger = 0;
+char *macro_template = NULL;
+char *macro_modifier_chr;
+char *macro_modifier_name[MAX_MACRO_MOD];
+char *macro_trigger_name[MAX_MACRO_TRIG];
+char *macro_trigger_keycode[2][MAX_MACRO_TRIG];
+
+/*
+ * Run-time aruments
+ */
+bool_ arg_wizard; /* Command arg -- Request wizard mode */
+bool_ arg_force_original; /* Command arg -- Request original keyset */
+bool_ arg_force_roguelike; /* Command arg -- Request roguelike keyset */
+
+/*
+ * Various things
+ */
+
+bool_ character_generated; /* The character exists */
+bool_ character_dungeon; /* The character has a dungeon */
+bool_ character_loaded; /* The character was loaded from a savefile */
+
+bool_ character_icky; /* The game is in an icky full screen mode */
+bool_ character_xtra; /* The game is in an icky startup mode */
+
+seed_t &seed_flavor()
+{
+ static seed_t *instance = new seed_t(seed_t::system());
+ return *instance;
+}
+
+s16b command_cmd; /* Current "Angband Command" */
+
+s16b command_arg; /* Gives argument of current command */
+s16b command_rep; /* Gives repetition of current command */
+s16b command_dir; /* Gives direction of current command */
+
+s16b command_wrk; /* See "cmd1.c" */
+
+s16b command_new; /* Command chaining from inven/equip view */
+
+s32b energy_use; /* Energy use this turn */
+
+bool_ create_up_stair; /* Auto-create "up stairs" */
+bool_ create_down_stair; /* Auto-create "down stairs" */
+
+bool_ create_up_shaft; /* Auto-create "up shaft" */
+bool_ create_down_shaft; /* Auto-create "down shaft" */
+
+bool_ msg_flag; /* Used in msg_print() for "buffering" */
+
+bool_ alive; /* True if game is running */
+
+bool_ death; /* True if player has died */
+
+s16b running; /* Current counter for running, if any */
+s16b resting; /* Current counter for resting, if any */
+
+s16b cur_hgt; /* Current dungeon height */
+s16b cur_wid; /* Current dungeon width */
+s16b dun_level; /* Current dungeon level */
+s16b old_dun_level; /* Old dungeon level */
+s16b num_repro; /* Current reproducer count */
+s16b object_level; /* Current object creation level */
+s16b monster_level; /* Current monster creation level */
+
+s32b turn; /* Current game turn */
+s32b old_turn; /* Turn when level began (feelings) */
+
+bool_ wizard; /* Is the player currently in Wizard mode? */
+
+u16b total_winner; /* Semi-Hack -- Game has been won */
+u16b has_won; /* Semi-Hack -- Game has been won */
+
+u16b noscore; /* Track various "cheating" conditions */
+
+bool_ inkey_base; /* See the "inkey()" function */
+
+s16b coin_type; /* Hack -- force coin type */
+
+bool_ opening_chest; /* Hack -- prevent chest generation */
+
+bool_ shimmer_monsters; /* Hack -- optimize multi-hued monsters */
+bool_ shimmer_objects; /* Hack -- optimize multi-hued objects */
+
+bool_ repair_monsters; /* Hack -- optimize detect monsters */
+
+bool_ hack_mind;
+int artifact_bias;
+bool_ is_autosave = FALSE;
+
+s16b inven_cnt; /* Number of items in inventory */
+s16b equip_cnt; /* Number of items in equipment */
+
+s16b o_max = 1; /* Number of allocated objects */
+s16b o_cnt = 0; /* Number of live objects */
+
+s16b m_max = 1; /* Number of allocated monsters */
+s16b m_cnt = 0; /* Number of live monsters */
+
+s16b hack_m_idx = 0; /* Hack -- see "process_monsters()" */
+char summon_kin_type; /* Hack, by Julian Lighton: summon 'relatives' */
+
+int total_friends = 0;
+s32b total_friend_levels = 0;
+
+int leaving_quest = 0;
+
+
+
+/*
+ * Hack - the destination file for text_out_to_file.
+ */
+FILE *text_out_file = NULL;
+
+
+/*
+ * Hack -- function hook to output (colored) text to the
+ * screen or to a file.
+ */
+void (*text_out_hook)(byte a, cptr str) = text_out_to_screen;
+
+
+/*
+ * Hack -- Indentation for the text when using text_out().
+ */
+int text_out_indent = 0;
+
+
+/*
+ * Options
+ */
+struct options *options = nullptr;
+
+/*
+ * Dungeon variables
+ */
+
+s16b feeling; /* Most recent feeling */
+s16b rating; /* Level's current rating */
+
+bool_ good_item_flag; /* True if "Artifact" on this level */
+
+/*
+ * Dungeon size info
+ */
+
+s16b max_panel_rows, max_panel_cols;
+s16b panel_row_min, panel_row_max;
+s16b panel_col_min, panel_col_max;
+s16b panel_col_prt, panel_row_prt;
+
+/*
+ * Dungeon graphics info
+ * Why the first two are byte and the rest s16b???
+ */
+byte feat_wall_outer = FEAT_WALL_OUTER; /* Outer wall of rooms */
+byte feat_wall_inner = FEAT_WALL_INNER; /* Inner wall of rooms */
+s16b floor_type[100]; /* Dungeon floor */
+s16b fill_type[100]; /* Dungeon filler */
+
+/*
+ * Targetting variables
+ */
+s16b target_who;
+s16b target_col;
+s16b target_row;
+
+/*
+ * Health bar variable -DRS-
+ */
+s16b health_who;
+
+/*
+ * Monster race to track
+ */
+s16b monster_race_idx;
+s16b monster_ego_idx;
+
+/*
+ * Object to track
+ */
+object_type *tracked_object;
+
+
+
+/*
+ * Buffer to hold the current savefile name
+ */
+char savefile[1024];
+
+
+/*
+ * Array of grids lit by player lite (see "cave.c")
+ */
+s16b lite_n;
+s16b lite_y[LITE_MAX];
+s16b lite_x[LITE_MAX];
+
+/*
+ * Array of grids viewable to the player (see "cave.c")
+ */
+s16b view_n;
+byte view_y[VIEW_MAX];
+byte view_x[VIEW_MAX];
+
+/*
+ * Array of grids for use by various functions (see "cave.c")
+ */
+s16b temp_n;
+byte temp_y[TEMP_MAX];
+byte temp_x[TEMP_MAX];
+
+
+/*
+ * Number of active macros.
+ */
+s16b macro__num;
+
+/*
+ * Array of macro patterns [MACRO_MAX]
+ */
+char **macro__pat;
+
+/*
+ * Array of macro actions [MACRO_MAX]
+ */
+char **macro__act;
+
+/*
+ * Array of macro types [MACRO_MAX]
+ */
+bool_ *macro__cmd;
+
+/*
+ * Current macro action [1024]
+ */
+char *macro__buf;
+
+
+/*
+ * The array of window options
+ */
+u32b window_flag[ANGBAND_TERM_MAX];
+u32b window_mask[ANGBAND_TERM_MAX];
+
+
+/*
+ * The array of window pointers
+ */
+term *angband_term[ANGBAND_TERM_MAX];
+
+
+/*
+ * Standard window names
+ */
+char angband_term_name[ANGBAND_TERM_MAX][80] =
+{
+ "ToME",
+ "Mirror",
+ "Recall",
+ "Choice",
+ "Term-4",
+ "Term-5",
+ "Term-6",
+ "Term-7"
+};
+
+
+/*
+ * Global table of color definitions
+ */
+byte angband_color_table[256][4] =
+{
+ {0x00, 0x00, 0x00, 0x00}, /* TERM_DARK */
+ {0x00, 0xFF, 0xFF, 0xFF}, /* TERM_WHITE */
+ {0x00, 0x80, 0x80, 0x80}, /* TERM_SLATE */
+ {0x00, 0xFF, 0x80, 0x00}, /* TERM_ORANGE */
+ {0x00, 0xC0, 0x00, 0x00}, /* TERM_RED */
+ {0x00, 0x00, 0x80, 0x40}, /* TERM_GREEN */
+ {0x00, 0x00, 0x00, 0xFF}, /* TERM_BLUE */
+ {0x00, 0x80, 0x40, 0x00}, /* TERM_UMBER */
+ {0x00, 0x40, 0x40, 0x40}, /* TERM_L_DARK */
+ {0x00, 0xC0, 0xC0, 0xC0}, /* TERM_L_WHITE */
+ {0x00, 0xFF, 0x00, 0xFF}, /* TERM_VIOLET */
+ {0x00, 0xFF, 0xFF, 0x00}, /* TERM_YELLOW */
+ {0x00, 0xFF, 0x00, 0x00}, /* TERM_L_RED */
+ {0x00, 0x00, 0xFF, 0x00}, /* TERM_L_GREEN */
+ {0x00, 0x00, 0xFF, 0xFF}, /* TERM_L_BLUE */
+ {0x00, 0xC0, 0x80, 0x40} /* TERM_L_UMBER */
+};
+
+
+/*
+ * The array of "cave grids" [MAX_WID][MAX_HGT].
+ */
+cave_type **cave = nullptr;
+
+/*
+ * The array of dungeon items [max_o_idx]
+ */
+object_type *o_list;
+
+/*
+ * The array of dungeon monsters [max_m_idx]
+ */
+monster_type *m_list;
+
+/*
+ * The array of to keep monsters [max_m_idx]
+ */
+monster_type *km_list;
+
+
+/*
+ * Maximum number of towns
+ */
+u16b max_towns;
+u16b max_real_towns;
+
+/*
+ * The towns [max_towns]
+ */
+town_type *town_info;
+
+/*
+ * Specify attr/char pairs for visual special effects
+ * Be sure to use "index & 0x7F" to avoid illegal access
+ */
+byte misc_to_attr[256];
+char misc_to_char[256];
+
+
+/*
+ * Specify attr/char pairs for inventory items (by tval)
+ * Be sure to use "index & 0x7F" to avoid illegal access
+ */
+byte tval_to_attr[128];
+char tval_to_char[128];
+
+
+/*
+ * Keymaps for each "mode" associated with each keypress.
+ */
+char *keymap_act[KEYMAP_MODES][256];
+
+
+
+/*** Player information ***/
+
+/*
+ * Pointer to the player info
+ */
+player_type *p_ptr = nullptr;
+
+/*
+ * Pointer to the player tables
+ * (sex, race, race mod, class, magic)
+ */
+player_race const *rp_ptr;
+player_race_mod const *rmp_ptr;
+player_class const *cp_ptr;
+player_spec const *spp_ptr;
+
+/*
+ * The wilderness features arrays
+ */
+int wildc2i[256];
+
+/*
+ * Default texts for feature information.
+ */
+cptr DEFAULT_FEAT_TEXT = "a wall blocking your way";
+cptr DEFAULT_FEAT_TUNNEL = "You cannot tunnel through that.";
+cptr DEFAULT_FEAT_BLOCK = DEFAULT_FEAT_TEXT;
+
+/*
+ * Hack -- The special Angband "System Suffix"
+ * This variable is used to choose an appropriate "pref-xxx" file
+ */
+cptr ANGBAND_SYS = "xxx";
+
+/*
+ * Path name: The main "lib" directory
+ * This variable is not actually used anywhere in the code
+ */
+char *ANGBAND_DIR;
+
+/*
+ * Core lua system
+ * These files are portable between platforms
+ */
+char *ANGBAND_DIR_CORE;
+
+/*
+ * Textual dungeon level definition files
+ * These files are portable between platforms
+ */
+char *ANGBAND_DIR_DNGN;
+
+/*
+ * Binary image files for the "*_info" arrays (binary)
+ * These files are not portable between platforms
+ */
+char *ANGBAND_DIR_DATA;
+
+/*
+ * Textual template files for the "*_info" arrays (ascii)
+ * These files are portable between platforms
+ */
+char *ANGBAND_DIR_EDIT;
+
+/*
+ * Various extra files (ascii)
+ * These files may be portable between platforms
+ */
+char *ANGBAND_DIR_FILE;
+
+/*
+ * Help files (normal) for the online help (ascii)
+ * These files are portable between platforms
+ */
+char *ANGBAND_DIR_HELP;
+
+/*
+ * Help files (spoilers) for the online help (ascii)
+ * These files are portable between platforms
+ */
+char *ANGBAND_DIR_INFO;
+
+/*
+ * Modules, those subdirectories are half-mirrors of lib/
+ */
+char *ANGBAND_DIR_MODULES;
+
+/*
+ * Textual template files for the plot files (ascii)
+ * These files are portable between platforms
+ */
+char *ANGBAND_DIR_NOTE;
+
+/*
+ * Savefiles for current characters (binary)
+ * These files are portable between platforms
+ */
+char *ANGBAND_DIR_SAVE;
+
+/*
+ * Default "preference" files (ascii)
+ * These files are rarely portable between platforms
+ */
+char *ANGBAND_DIR_PREF;
+
+/*
+ * User "preference" files (ascii)
+ * These files are rarely portable between platforms
+ */
+char *ANGBAND_DIR_USER;
+
+/*
+ * Various extra files (binary)
+ * These files are rarely portable between platforms
+ */
+char *ANGBAND_DIR_XTRA;
+
+
+
+/*
+ * Hack -- function hooks to restrict "get_mon_num_prep()" function
+ */
+bool_ (*get_mon_num_hook)(int r_idx);
+bool_ (*get_mon_num2_hook)(int r_idx);
+
+
+/*
+ * Hack -- function hook to restrict "get_obj_num_prep()" function
+ */
+bool_ (*get_obj_num_hook)(int k_idx);
+
+/*
+ * Devices
+ */
+s32b get_level_max_stick = -1;
+s32b get_level_use_stick = -1;
+
+/*
+ * Maximum number of objects in the level
+ */
+u16b max_o_idx;
+
+/*
+ * Maximum number of monsters in the level
+ */
+u16b max_m_idx;
+
+/*
+ * Flags for initialization
+ */
+int init_flags;
+
+/* True if on an ambush */
+bool_ ambush_flag;
+
+/* True if on fated level */
+bool_ fate_flag;
+
+/* No breeders */
+s16b no_breeds;
+
+/* Carried monsters can't take the damage if this is them which attack the player */
+bool_ carried_monster_hit = FALSE;
+
+/*
+ * Random artifacts.
+ */
+s32b RANDART_WEAPON;
+s32b RANDART_ARMOR;
+s32b RANDART_JEWEL;
+
+/*
+ * Fate.
+ */
+fate fates[MAX_FATES];
+
+/*
+ * Which dungeon ?
+ * 0 = Wilderness
+ * 1 = Mirkwood
+ * 2 = Mordor
+ * 3 = Angband
+ * 4 = Barrow Downs
+ * 5 = Mount Doom
+ * 6 = Nether Realm
+ * etc. (see d_info.txt)
+ */
+byte dungeon_type;
+s16b *max_dlv;
+
+/* The Doppleganger index in m_list */
+s16b doppleganger;
+
+/* To allow wilderness encounters */
+bool_ generate_encounter = FALSE;
+
+/*
+ * Such an ugly hack ...
+ */
+bool_ *m_allow_special;
+bool_ *k_allow_special;
+bool_ *a_allow_special;
+
+/*
+ * Plots
+ */
+s16b plots[MAX_PLOTS];
+
+/*
+ * Random quest
+ */
+random_quest random_quests[MAX_RANDOM_QUEST];
+
+/*
+ * Dungeon flags
+ */
+DECLARE_FLAG_ZERO_IMPL(dungeon_flag_set, dungeon_flags);
+
+/*
+ * The spell list of schools
+ */
+s16b schools_count = 0;
+school_type schools[SCHOOLS_MAX];
+
+/*
+ * Lasting spell effects
+ */
+int project_time = 0;
+s32b project_time_effect = 0;
+effect_type effects[MAX_EFFECTS];
+
+/*
+ * Table of "cli" macros.
+ */
+cli_comm *cli_info;
+int cli_total = 0;
+
+/*
+ * Automatizer enabled status
+ */
+bool_ automatizer_enabled = FALSE;
+bool_ automatizer_create = FALSE;
+
+/*
+ * Location of the last teleportation thath affected the level
+ */
+s16b last_teleportation_y = -1;
+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;
+
+/*
+ * Some module info
+ */
+s32b DUNGEON_BASE = 4;
+s32b DUNGEON_DEATH = 28;
+s32b DUNGEON_ASTRAL = 8;
+s32b DUNGEON_ASTRAL_WILD_X = 45;
+s32b DUNGEON_ASTRAL_WILD_Y = 19;
+
+/**
+ * Get the version string.
+ */
+const char *get_version_string()
+{
+ static char version_str[80];
+ static bool_ initialized = 0;
+ if (!initialized) {
+ sprintf(version_str, "%s %ld.%ld.%ld%s",
+ game_module,
+ (long int) VERSION_MAJOR,
+ (long int) VERSION_MINOR,
+ (long int) VERSION_PATCH, IS_CVS);
+ initialized = TRUE;
+ }
+ return version_str;
+}
diff --git a/src/variable.h b/src/variable.h
new file mode 100644
index 00000000..6d6e5775
--- /dev/null
+++ b/src/variable.h
@@ -0,0 +1,31 @@
+#pragma once
+
+#include "angband.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern cptr ANGBAND_SYS;
+extern char *ANGBAND_DIR_SAVE;
+extern char *ANGBAND_DIR_DATA;
+extern char *ANGBAND_DIR_EDIT;
+extern char *ANGBAND_DIR_FILE;
+extern char *ANGBAND_DIR_HELP;
+extern char *ANGBAND_DIR_INFO;
+extern char *ANGBAND_DIR_NOTE;
+extern char *ANGBAND_DIR_PREF;
+extern char *ANGBAND_DIR_USER;
+extern char *ANGBAND_DIR_XTRA;
+extern term *angband_term[ANGBAND_TERM_MAX];
+extern char angband_term_name[ANGBAND_TERM_MAX][80];
+extern byte angband_color_table[256][4];
+extern bool_ character_generated;
+extern bool_ character_icky;
+extern bool_ inkey_flag;
+extern bool_ msg_flag;
+extern char savefile[1024];
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/src/variable.hpp b/src/variable.hpp
new file mode 100644
index 00000000..73d63be7
--- /dev/null
+++ b/src/variable.hpp
@@ -0,0 +1,195 @@
+#pragma once
+
+#include "angband.h"
+#include "alloc_entry_fwd.hpp"
+#include "birther.hpp"
+#include "cave_type_fwd.hpp"
+#include "deity_type.hpp"
+#include "dungeon_flag_set.hpp"
+#include "effect_type.hpp"
+#include "fate.hpp"
+#include "monster_type_fwd.hpp"
+#include "object_type_fwd.hpp"
+#include "options.hpp"
+#include "player_class_fwd.hpp"
+#include "player_defs.hpp"
+#include "player_race_fwd.hpp"
+#include "player_race_mod_fwd.hpp"
+#include "player_spec_fwd.hpp"
+#include "player_type_fwd.hpp"
+#include "random_quest.hpp"
+#include "school_type.hpp"
+#include "skill_modifiers_fwd.hpp"
+#include "skills_defs.hpp"
+#include "timer_type_fwd.hpp"
+#include "town_type_fwd.hpp"
+#include "seed.hpp"
+
+extern int max_macrotrigger;
+extern char *macro_template;
+extern char *macro_modifier_chr;
+extern char *macro_modifier_name[MAX_MACRO_MOD];
+extern char *macro_trigger_name[MAX_MACRO_TRIG];
+extern char *macro_trigger_keycode[2][MAX_MACRO_TRIG];
+extern bool_ character_dungeon;
+extern bool_ character_loaded;
+extern bool_ character_xtra;
+seed_t &seed_flavor();
+extern s16b command_cmd;
+extern s16b command_arg;
+extern s16b command_rep;
+extern s16b command_dir;
+extern s16b command_wrk;
+extern s16b command_new;
+extern s32b energy_use;
+extern bool_ create_up_stair;
+extern bool_ create_down_stair;
+extern bool_ create_up_shaft;
+extern bool_ create_down_shaft;
+extern bool_ alive;
+extern bool_ death;
+extern s16b running;
+extern s16b resting;
+extern s16b cur_hgt;
+extern s16b cur_wid;
+extern s16b dun_level;
+extern s16b old_dun_level;
+extern s16b num_repro;
+extern s16b object_level;
+extern s16b monster_level;
+extern s32b turn;
+extern s32b old_turn;
+extern bool_ wizard;
+extern u16b total_winner;
+extern u16b has_won;
+extern u16b noscore;
+extern bool_ inkey_base;
+extern s16b coin_type;
+extern bool_ opening_chest;
+extern bool_ shimmer_monsters;
+extern bool_ shimmer_objects;
+extern bool_ repair_monsters;
+extern s16b inven_cnt;
+extern s16b equip_cnt;
+extern s16b o_max;
+extern s16b o_cnt;
+extern s16b m_max;
+extern s16b m_cnt;
+extern s16b hack_m_idx;
+extern int total_friends;
+extern s32b total_friend_levels;
+extern int leaving_quest;
+extern char summon_kin_type;
+extern bool_ hack_mind;
+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_indent;
+extern s16b feeling;
+extern s16b rating;
+extern bool_ good_item_flag;
+extern s16b max_panel_rows, max_panel_cols;
+extern s16b panel_row_min, panel_row_max;
+extern s16b panel_col_min, panel_col_max;
+extern s16b panel_col_prt, panel_row_prt;
+extern byte feat_wall_outer;
+extern byte feat_wall_inner;
+extern s16b floor_type[100];
+extern s16b fill_type[100];
+extern s16b target_who;
+extern s16b target_col;
+extern s16b target_row;
+extern s16b health_who;
+extern s16b monster_race_idx;
+extern s16b monster_ego_idx;
+extern object_type *tracked_object;
+extern s16b lite_n;
+extern s16b lite_y[LITE_MAX];
+extern s16b lite_x[LITE_MAX];
+extern s16b view_n;
+extern byte view_y[VIEW_MAX];
+extern byte view_x[VIEW_MAX];
+extern s16b temp_n;
+extern byte temp_y[TEMP_MAX];
+extern byte temp_x[TEMP_MAX];
+extern s16b macro__num;
+extern char **macro__pat;
+extern char **macro__act;
+extern bool_ *macro__cmd;
+extern char *macro__buf;
+extern u32b window_flag[ANGBAND_TERM_MAX];
+extern u32b window_mask[ANGBAND_TERM_MAX];
+extern cave_type **cave;
+extern object_type *o_list;
+extern monster_type *m_list;
+extern monster_type *km_list;
+extern u16b max_real_towns;
+extern u16b max_towns;
+extern town_type *town_info;
+extern byte misc_to_attr[256];
+extern char misc_to_char[256];
+extern byte tval_to_attr[128];
+extern char tval_to_char[128];
+extern char *keymap_act[KEYMAP_MODES][256];
+extern player_type *p_ptr;
+extern player_race const *rp_ptr;
+extern player_race_mod const *rmp_ptr;
+extern player_class const *cp_ptr;
+extern player_spec const *spp_ptr;
+extern int wildc2i[256];
+extern cptr DEFAULT_FEAT_TEXT;
+extern cptr DEFAULT_FEAT_TUNNEL;
+extern cptr DEFAULT_FEAT_BLOCK;
+extern char *ANGBAND_DIR;
+extern char *ANGBAND_DIR_MODULES;
+extern char *ANGBAND_DIR_CORE;
+extern char *ANGBAND_DIR_DNGN;
+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 u16b max_o_idx;
+extern u16b max_m_idx;
+extern int init_flags;
+extern bool_ ambush_flag;
+extern bool_ fate_flag;
+extern s16b no_breeds;
+extern bool_ carried_monster_hit;
+extern s32b RANDART_WEAPON;
+extern s32b RANDART_ARMOR;
+extern s32b RANDART_JEWEL;
+extern fate fates[MAX_FATES];
+extern byte dungeon_type;
+extern s16b *max_dlv;
+extern s16b doppleganger;
+extern bool_ generate_encounter;
+extern bool_ *m_allow_special;
+extern bool_ *k_allow_special;
+extern bool_ *a_allow_special;
+extern s16b plots[MAX_PLOTS];
+extern random_quest random_quests[MAX_RANDOM_QUEST];
+DECLARE_FLAG_ZERO_INTF(dungeon_flag_set, dungeon_flags);
+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];
+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 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[MAX_GODS];
+const char *get_version_string();
+extern bool_ arg_wizard;
+extern bool_ arg_force_original;
+extern bool_ arg_force_roguelike;
+extern struct options *options;
diff --git a/src/vault_type.hpp b/src/vault_type.hpp
new file mode 100644
index 00000000..9d407d8f
--- /dev/null
+++ b/src/vault_type.hpp
@@ -0,0 +1,25 @@
+#pragma once
+
+#include "h-basic.h"
+#include <string>
+
+/**
+ * Vault descriptors.
+ */
+struct vault_type
+{
+ std::string data; /* Vault data */
+
+ byte typ = 0; /* Vault type */
+
+ byte rat = 0; /* Vault rating */
+
+ byte hgt = 0; /* Vault height */
+ byte wid = 0; /* Vault width */
+
+ s16b lvl = 0; /* level of special (if any) */
+ byte dun_type = 0; /* Dungeon type where the level will show up */
+
+ s16b mon[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* special monster */
+ int item[3] = { 0, 0, 0 }; /* number of item (usually artifact) */
+};
diff --git a/src/wild.c b/src/wild.cc
index 7a9d1c51..3d86c0b7 100644
--- a/src/wild.c
+++ b/src/wild.cc
@@ -1,7 +1,3 @@
-/* File: generate.c */
-
-/* Purpose: Wilderness & Town related things */
-
/*
* Copyright (c) 2001 James E. Wilson, Robert A. Koeneke, DarkGod
*
@@ -10,8 +6,33 @@
* included in all such copies.
*/
-#include "angband.h"
-
+#include "wild.hpp"
+
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "feature_flag.hpp"
+#include "feature_type.hpp"
+#include "game.hpp"
+#include "hook_wild_gen_in.hpp"
+#include "hooks.hpp"
+#include "init1.hpp"
+#include "monster2.hpp"
+#include "monster_race.hpp"
+#include "monster_type.hpp"
+#include "options.hpp"
+#include "player_type.hpp"
+#include "store_info_type.hpp"
+#include "store_flag.hpp"
+#include "tables.hpp"
+#include "town_type.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+#include "wilderness_map.hpp"
+#include "wilderness_type_info.hpp"
+#include "z-rand.hpp"
+
+#include <algorithm>
+#include <memory>
/*
@@ -49,7 +70,7 @@ static void perturb_point_mid(int x1, int x2, int x3, int x4,
if (avg > depth_max) avg = depth_max;
/* Set the new value. */
- cave[ymid][xmid].feat = (byte)avg;
+ cave[ymid][xmid].feat = static_cast<byte>(avg);
}
@@ -73,7 +94,7 @@ static void perturb_point_end(int x1, int x2, int x3,
if (avg > depth_max) avg = depth_max;
/* Set the new value. */
- cave[ymid][xmid].feat = (byte)avg;
+ cave[ymid][xmid].feat = static_cast<byte>(avg);
}
@@ -133,15 +154,21 @@ static void plasma_recursive(int x1, int y1, int x2, int y2,
*
* Return the number of floor grids
*/
-int generate_area(int y, int x, bool_ border, bool_ corner, bool_ refresh)
+static int generate_area(int y, int x, bool_ border, bool_ corner)
{
+ auto const &wilderness = game->wilderness;
+ auto const &wf_info = game->edit_data.wf_info;
+
int road, entrance;
int x1, y1;
int hack_floor = 0;
/* Number of the town (if any) */
- p_ptr->town_num = wf_info[wild_map[y][x].feat].entrance;
- if (!p_ptr->town_num) p_ptr->town_num = wild_map[y][x].entrance;
+ p_ptr->town_num = wf_info[wilderness(x, y).feat].entrance;
+ if (!p_ptr->town_num)
+ {
+ p_ptr->town_num = wilderness(x, y).entrance;
+ }
{
int roughness = 1; /* The roughness of the level. */
@@ -153,35 +180,30 @@ int generate_area(int y, int x, bool_ border, bool_ corner, bool_ refresh)
if (!p_ptr->oldpy) p_ptr->oldpy = MAX_HGT / 2;
/* Initialize the terrain array */
- ym = ((y - 1) < 0) ? 0 : (y - 1);
- xm = ((x - 1) < 0) ? 0 : (x - 1);
- yp = ((y + 1) >= max_wild_y) ? (max_wild_y - 1) : (y + 1);
- xp = ((x + 1) >= max_wild_x) ? (max_wild_x - 1) : (x + 1);
- terrain[0][0] = wild_map[ym][xm].feat;
- terrain[0][1] = wild_map[ym][x].feat;
- terrain[0][2] = wild_map[ym][xp].feat;
- terrain[1][0] = wild_map[y][xm].feat;
- terrain[1][1] = wild_map[y][x].feat;
- terrain[1][2] = wild_map[y][xp].feat;
- terrain[2][0] = wild_map[yp][xm].feat;
- terrain[2][1] = wild_map[yp][x].feat;
- terrain[2][2] = wild_map[yp][xp].feat;
-
- /* Hack -- Use the "simple" RNG */
- Rand_quick = TRUE;
+ ym = std::max<int>(y - 1, 0);
+ xm = std::max<int>(x - 1, 0);
+ yp = std::min<int>(y + 1, static_cast<int>(wilderness.height()) - 1);
+ xp = std::min<int>(x + 1, static_cast<int>(wilderness.width()) - 1);
+
+ terrain[0][0] = wilderness(xm, ym).feat;
+ terrain[0][1] = wilderness(x , ym).feat;
+ terrain[0][2] = wilderness(xp, ym).feat;
+ terrain[1][0] = wilderness(xm, y ).feat;
+ terrain[1][1] = wilderness(x , y ).feat;
+ terrain[1][2] = wilderness(xp, y ).feat;
+ terrain[2][0] = wilderness(xm, yp).feat;
+ terrain[2][1] = wilderness(x , yp).feat;
+ terrain[2][2] = wilderness(xp, yp).feat;
/* Hack -- Induce consistant town layout */
- Rand_value = wild_map[y][x].seed;
+ set_quick_rng(wilderness(x, y).seed);
- if (!corner)
+ /* Create level background */
+ for (y1 = 0; y1 < MAX_HGT; y1++)
{
- /* Create level background */
- for (y1 = 0; y1 < MAX_HGT; y1++)
+ for (x1 = 0; x1 < MAX_WID; x1++)
{
- for (x1 = 0; x1 < MAX_WID; x1++)
- {
- cave_set_feat(y1, x1, MAX_WILD_TERRAIN / 2);
- }
+ cave_set_feat(y1, x1, MAX_WILD_TERRAIN / 2);
}
}
@@ -190,10 +212,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)
{
@@ -201,9 +223,6 @@ int generate_area(int y, int x, bool_ border, bool_ corner, bool_ refresh)
plasma_recursive(1, 1, MAX_WID - 2, MAX_HGT - 2, MAX_WILD_TERRAIN - 1, roughness);
}
- /* Use the complex RNG */
- Rand_quick = FALSE;
-
for (y1 = 1; y1 < MAX_HGT - 1; y1++)
{
for (x1 = 1; x1 < MAX_WID - 1; x1++)
@@ -213,6 +232,8 @@ int generate_area(int y, int x, bool_ border, bool_ corner, bool_ refresh)
}
}
+ /* Change back to "complex" RNG */
+ set_complex_rng();
}
/* Should we create a town ? */
@@ -238,7 +259,7 @@ int generate_area(int y, int x, bool_ border, bool_ corner, bool_ refresh)
* Place roads in the wilderness
* ToDo: make the road a bit more interresting
*/
- road = wf_info[wild_map[y][x].feat].road;
+ road = wf_info[wilderness(x, y).feat].road;
if (road & ROAD_NORTH)
{
@@ -281,14 +302,11 @@ int generate_area(int y, int x, bool_ border, bool_ corner, bool_ refresh)
}
}
- /* Hack -- Use the "simple" RNG */
- Rand_quick = TRUE;
-
/* Hack -- Induce consistant town layout */
- Rand_value = wild_map[y][x].seed;
+ set_quick_rng(wilderness(x, y).seed);
- entrance = wf_info[wild_map[y][x].feat].entrance;
- if (!entrance) entrance = wild_map[y][x].entrance;
+ entrance = wf_info[wilderness(x, y).feat].entrance;
+ if (!entrance) entrance = wilderness(x, y).entrance;
/* Create the dungeon if requested on the map */
if (entrance >= 1000)
@@ -304,7 +322,7 @@ int generate_area(int y, int x, bool_ border, bool_ corner, bool_ refresh)
}
/* Use the complex RNG */
- Rand_quick = FALSE;
+ set_complex_rng();
/* MEGA HACK -- set at least one floor grid */
for (y1 = 1; y1 < cur_hgt - 1; y1++)
@@ -323,11 +341,10 @@ int generate_area(int y, int x, bool_ border, bool_ corner, bool_ refresh)
hack_floor = 1;
}
- /* Set the monster generation level to the wilderness level */
- monster_level = wf_info[wild_map[y][x].feat].level;
-
- /* Set the object generation level to the wilderness level */
- object_level = wf_info[wild_map[y][x].feat].level;
+ /* Set the monster/object generation level to the wilderness level */
+ auto const &wf = wf_info[wilderness(x, y).feat];
+ monster_level = wf.level;
+ object_level = wf.level;
return hack_floor;
}
@@ -335,14 +352,32 @@ int generate_area(int y, int x, bool_ border, bool_ corner, bool_ refresh)
/*
* Border of the wilderness area
*/
-static border_type border;
+namespace {
+
+ struct border_type
+ {
+ byte north[MAX_WID];
+ byte south[MAX_WID];
+ byte east[MAX_HGT];
+ byte west[MAX_HGT];
+ byte north_west;
+ byte north_east;
+ byte south_west;
+ byte south_east;
+ };
+
+ border_type border;
+
+}
/*
* Build the wilderness area outside of the town.
* -KMW-
*/
-void wilderness_gen(int refresh)
+void wilderness_gen()
{
+ auto const &f_info = game->edit_data.f_info;
+
int i, y, x, hack_floor;
bool_ daytime;
int xstart = 0;
@@ -362,7 +397,7 @@ void wilderness_gen(int refresh)
get_mon_num_prep();
/* North border */
- generate_area(y - 1, x, TRUE, FALSE, refresh);
+ generate_area(y - 1, x, TRUE, FALSE);
for (i = 1; i < MAX_WID - 1; i++)
{
@@ -370,7 +405,7 @@ void wilderness_gen(int refresh)
}
/* South border */
- generate_area(y + 1, x, TRUE, FALSE, refresh);
+ generate_area(y + 1, x, TRUE, FALSE);
for (i = 1; i < MAX_WID - 1; i++)
{
@@ -378,7 +413,7 @@ void wilderness_gen(int refresh)
}
/* West border */
- generate_area(y, x - 1, TRUE, FALSE, refresh);
+ generate_area(y, x - 1, TRUE, FALSE);
for (i = 1; i < MAX_HGT - 1; i++)
{
@@ -386,7 +421,7 @@ void wilderness_gen(int refresh)
}
/* East border */
- generate_area(y, x + 1, TRUE, FALSE, refresh);
+ generate_area(y, x + 1, TRUE, FALSE);
for (i = 1; i < MAX_HGT - 1; i++)
{
@@ -394,24 +429,24 @@ void wilderness_gen(int refresh)
}
/* North west corner */
- generate_area(y - 1, x - 1, FALSE, TRUE, refresh);
+ generate_area(y - 1, x - 1, FALSE, TRUE);
border.north_west = cave[MAX_HGT - 2][MAX_WID - 2].feat;
/* North east corner */
- generate_area(y - 1, x + 1, FALSE, TRUE, refresh);
+ generate_area(y - 1, x + 1, FALSE, TRUE);
border.north_east = cave[MAX_HGT - 2][1].feat;
/* South west corner */
- generate_area(y + 1, x - 1, FALSE, TRUE, refresh);
+ generate_area(y + 1, x - 1, FALSE, TRUE);
border.south_west = cave[1][MAX_WID - 2].feat;
/* South east corner */
- generate_area(y + 1, x + 1, FALSE, TRUE, refresh);
+ generate_area(y + 1, x + 1, FALSE, TRUE);
border.south_east = cave[1][1].feat;
/* Create terrain of the current area */
- hack_floor = generate_area(y, x, FALSE, FALSE, refresh);
+ hack_floor = generate_area(y, x, FALSE, FALSE);
/* Special boundary walls -- North */
@@ -484,15 +519,18 @@ void wilderness_gen(int refresh)
if (daytime)
{
/* Assume lit */
- c_ptr->info |= (CAVE_GLOW);
+ c_ptr->info |= CAVE_GLOW;
/* Hack -- Memorize lit grids if allowed */
- if (view_perma_grids) c_ptr->info |= (CAVE_MARK);
+ if (options->view_perma_grids)
+ {
+ c_ptr->info |= CAVE_MARK;
+ }
}
else
{
/* Darken "boring" features */
- if (!(f_info[c_ptr->feat].flags1 & FF1_REMEMBER))
+ if (!(f_info[c_ptr->feat].flags & FF_REMEMBER))
{
/* Forget the grid */
c_ptr->info &= ~(CAVE_GLOW | CAVE_MARK);
@@ -503,7 +541,6 @@ void wilderness_gen(int refresh)
player_place(p_ptr->oldpy, p_ptr->oldpx);
- if (!refresh)
{
int lim = (generate_encounter == TRUE) ? 60 : MIN_M_ALLOC_TN;
@@ -517,7 +554,7 @@ void wilderness_gen(int refresh)
for (i = 0; i < lim; i++)
{
/* Make a resident */
- (void)alloc_monster((generate_encounter == TRUE) ? 0 : 3, (generate_encounter == TRUE) ? FALSE : TRUE);
+ alloc_monster((generate_encounter == TRUE) ? 0 : 3, (generate_encounter == TRUE) ? FALSE : TRUE);
}
if (generate_encounter) ambush_flag = TRUE;
@@ -525,13 +562,16 @@ 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);
+ struct hook_wild_gen_in in = { FALSE };
+ process_hooks_new(HOOK_WILD_GEN, &in, NULL);
}
/*
@@ -540,14 +580,16 @@ void wilderness_gen(int refresh)
*/
void wilderness_gen_small()
{
- int i, j, entrance;
+ auto const &wilderness = game->wilderness;
+ auto const &wf_info = game->edit_data.wf_info;
+
int xstart = 0;
int ystart = 0;
/* To prevent stupid things */
- for (i = 0; i < MAX_WID; i++)
+ for (int i = 0; i < MAX_WID; i++)
{
- for (j = 0; j < MAX_HGT; j++)
+ for (int j = 0; j < MAX_HGT; j++)
{
cave_set_feat(j, i, FEAT_EKKAIA);
}
@@ -557,31 +599,35 @@ void wilderness_gen_small()
process_dungeon_file("w_info.txt", &ystart, &xstart, cur_hgt, cur_wid, TRUE, FALSE);
/* Fill the map */
- for (i = 0; i < max_wild_x; i++)
+ for (std::size_t x = 0; x < wilderness.width(); x++)
{
- for (j = 0; j < max_wild_y; j++)
+ for (std::size_t y = 0; y < wilderness.height(); y++)
{
- entrance = wf_info[wild_map[j][i].feat].entrance;
- if (!entrance) entrance = wild_map[j][i].entrance;
+ auto const &wm = wilderness(x, y);
+
+ int entrance = wf_info[wm.feat].entrance;
+ if (!entrance) entrance = wm.entrance;
- if (wild_map[j][i].entrance)
+ if (wm.entrance)
{
- cave_set_feat(j, i, FEAT_MORE);
+ cave_set_feat(y, x, FEAT_MORE);
}
else
{
- cave_set_feat(j, i, wf_info[wild_map[j][i].feat].feat);
+ cave_set_feat(y, x, wf_info[wm.feat].feat);
}
- if ((cave[j][i].feat == FEAT_MORE) && (entrance >= 1000))
+ auto &cv = cave[y][x];
+
+ if ((cv.feat == FEAT_MORE) && (entrance >= 1000))
{
- cave[j][i].special = entrance - 1000;
+ cv.special = entrance - 1000;
}
/* Show it if we know it */
- if (wild_map[j][i].known)
+ if (wm.known)
{
- cave[j][i].info |= (CAVE_GLOW | CAVE_MARK);
+ cv.info |= (CAVE_GLOW | CAVE_MARK);
}
}
}
@@ -591,38 +637,45 @@ 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 (int 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);
+ struct hook_wild_gen_in in = { TRUE };
+ process_hooks_new(HOOK_WILD_GEN, &in, NULL);
}
/* Show a small radius of wilderness around the player */
void reveal_wilderness_around_player(int y, int x, int h, int w)
{
- int i, j;
+ auto &wilderness = game->wilderness;
/* Circle or square ? */
if (h == 0)
{
- for (i = x - w; i < x + w; i++)
+ for (int i = x - w; i < x + w; i++)
{
- for (j = y - w; j < y + w; j++)
+ for (int j = y - w; j < y + w; j++)
{
/* Bound checking */
if (!in_bounds(j, i)) continue;
/* Severe bound checking */
- if ((i < 0) || (i >= max_wild_x) || (j < 0) || (j >= max_wild_y)) continue;
+ if ((i < 0) || (static_cast<size_t>(i) >= wilderness.width()) ||
+ (j < 0) || (static_cast<size_t>(j) >= wilderness.height()))
+ {
+ continue;
+ }
/* We want a radius, not a "squarus" :) */
if (distance(y, x, j, i) >= w) continue;
/* New we know here */
- wild_map[j][i].known = TRUE;
+ wilderness(i, j).known = TRUE;
/* Only if we are in overview */
if (p_ptr->wild_mode)
@@ -637,15 +690,15 @@ void reveal_wilderness_around_player(int y, int x, int h, int w)
}
else
{
- for (i = x; i < x + w; i++)
+ for (int i = x; i < x + w; i++)
{
- for (j = y; j < y + h; j++)
+ for (int j = y; j < y + h; j++)
{
/* Bound checking */
if (!in_bounds(j, i)) continue;
/* New we know here */
- wild_map[j][i].known = TRUE;
+ wilderness(i, j).known = TRUE;
/* Only if we are in overview */
if (p_ptr->wild_mode)
@@ -841,38 +894,58 @@ static void build_store_hidden(int n, int yy, int xx)
}
/* Return a list of stores */
-static int get_shops(int *rooms)
+static std::vector<std::size_t> get_shops()
{
- int i, n, num = 0;
+ auto const &st_info = game->edit_data.st_info;
- for (n = 0; n < max_st_idx; n++)
- {
- rooms[n] = 0;
- }
+ std::vector<std::size_t> rooms;
- for (n = 0; n < max_st_idx; n++)
+ for (std::size_t n = 0; n < st_info.size(); n++)
{
int chance = 50;
- if (st_info[n].flags1 & SF1_COMMON) chance += 30;
- if (st_info[n].flags1 & SF1_RARE) chance -= 20;
- if (st_info[n].flags1 & SF1_VERY_RARE) chance -= 30;
+ if (st_info[n].flags & STF_COMMON)
+ {
+ chance += 30;
+ }
+
+ if (st_info[n].flags & STF_RARE)
+ {
+ chance -= 20;
+ }
- if (!magik(chance)) continue;
+ if (st_info[n].flags & STF_VERY_RARE)
+ {
+ chance -= 30;
+ }
- for (i = 0; i < num; ++i)
+ if (!magik(chance))
+ {
+ continue;
+ }
+
+ for (std::size_t i = 0; i < rooms.size(); ++i)
+ {
if (rooms[i] == n)
+ {
continue;
+ }
+ }
- if (st_info[n].flags1 & SF1_RANDOM) rooms[num++] = n;
+ if (st_info[n].flags & STF_RANDOM)
+ {
+ rooms.push_back(n);
+ }
}
- return num;
+ return rooms;
}
/* Generate town borders */
static void set_border(int y, int x)
{
+ auto const &f_info = game->edit_data.f_info;
+
cave_type *c_ptr;
/* Paranoia */
@@ -880,7 +953,7 @@ static void set_border(int y, int x)
/* Was a floor */
if (cave_floor_bold(y, x) ||
- (f_info[cave[y][x].feat].flags1 & FF1_DOOR))
+ (f_info[cave[y][x].feat].flags & FF_DOOR))
{
cave_set_feat(y, x, FEAT_DOOR_HEAD);
}
@@ -902,7 +975,7 @@ static void set_border(int y, int x)
}
-static void town_borders(int t_idx, int qy, int qx)
+static void town_borders(int qy, int qx)
{
int y, x;
@@ -933,10 +1006,11 @@ static void town_borders(int t_idx, int qy, int qx)
static bool_ create_townpeople_hook(int r_idx)
{
- monster_race *r_ptr = &r_info[r_idx];
+ auto const &r_info = game->edit_data.r_info;
- if (r_ptr->d_char == 't') return TRUE;
- else return FALSE;
+ auto r_ptr = &r_info[r_idx];
+
+ return (r_ptr->d_char == 't');
}
@@ -947,13 +1021,11 @@ static bool_ create_townpeople_hook(int r_idx)
* layout, including the size and shape of the buildings, the
* locations of the doorways, and the location of the stairs.
*/
-static void town_gen_hack(int t_idx, int qy, int qx)
+static void town_gen_hack(int qy, int qx)
{
- int y, x, floor, num = 0;
+ int y, x, floor;
bool_ (*old_get_mon_num_hook)(int r_idx);
- int *rooms;
-
/* Do we use dungeon floor or normal one */
if (magik(TOWN_NORMAL_FLOOR)) floor = FEAT_FLOOR;
else floor = 0;
@@ -970,8 +1042,7 @@ static void town_gen_hack(int t_idx, int qy, int qx)
}
/* Prepare an Array of "remaining stores", and count them */
- C_MAKE(rooms, max_st_idx, int);
- num = get_shops(rooms);
+ auto rooms = get_shops();
/* Place two rows of stores */
for (y = 0; y < 2; y++)
@@ -979,17 +1050,20 @@ static void town_gen_hack(int t_idx, int qy, int qx)
/* Place four stores per row */
for (x = 0; x < 4; x++)
{
- if(--num > -1)
+ if (!rooms.empty())
{
+ /* Extract store */
+ auto room = rooms.back();
+ rooms.pop_back();
+
/* Build that store at the proper location */
- build_store(qy, qx, rooms[num], y, x);
+ build_store(qy, qx, room, y, x);
}
}
}
- C_FREE(rooms, max_st_idx, int);
/* Generates the town's borders */
- if (magik(TOWN_NORMAL_FLOOR)) town_borders(t_idx, qy, qx);
+ if (magik(TOWN_NORMAL_FLOOR)) town_borders(qy, qx);
/* Some inhabitants(leveled .. hehe :) */
@@ -1025,7 +1099,7 @@ static void town_gen_hack(int t_idx, int qy, int qx)
monster_type *m_ptr = &m_list[m_idx];
if (m_ptr->level < (dun_level / 2))
{
- m_ptr->exp = MONSTER_EXP(m_ptr->level + (dun_level / 2) + randint(dun_level / 2));
+ m_ptr->exp = monster_exp(m_ptr->level + (dun_level / 2) + randint(dun_level / 2));
monster_check_experience(m_idx, TRUE);
}
}
@@ -1038,13 +1112,11 @@ static void town_gen_hack(int t_idx, int qy, int qx)
get_mon_num_prep();
}
-static void town_gen_circle(int t_idx, int qy, int qx)
+static void town_gen_circle(int qy, int qx)
{
- int y, x, cy, cx, rad, floor, num = 0;
+ int y, x, cy, cx, rad, floor;
bool_ (*old_get_mon_num_hook)(int r_idx);
- int *rooms;
-
/* Do we use dungeon floor or normal one */
if (magik(TOWN_NORMAL_FLOOR)) floor = FEAT_FLOOR;
else floor = 0;
@@ -1105,9 +1177,8 @@ static void town_gen_circle(int t_idx, int qy, int qx)
}
}
- /* Prepare an Array of "remaining stores", and count them */
- C_MAKE(rooms, max_st_idx, int);
- num = get_shops(rooms);
+ /* Get "remaining stores" */
+ auto rooms = get_shops();
/* Place two rows of stores */
for (y = 0; y < 2; y++)
@@ -1115,14 +1186,17 @@ static void town_gen_circle(int t_idx, int qy, int qx)
/* Place four stores per row */
for (x = 0; x < 4; x++)
{
- if(--num > -1)
+ if (!rooms.empty())
{
+ /* Extract store */
+ auto room = rooms.back();
+ rooms.pop_back();
+
/* Build that store at the proper location */
- build_store_circle(qy, qx, rooms[num], y, x);
+ build_store_circle(qy, qx, room, y, x);
}
}
}
- C_FREE(rooms, max_st_idx, int);
/* Some inhabitants(leveled .. hehe :) */
@@ -1156,7 +1230,7 @@ static void town_gen_circle(int t_idx, int qy, int qx)
monster_type *m_ptr = &m_list[m_idx];
if (m_ptr->level < (dun_level / 2))
{
- m_ptr->exp = MONSTER_EXP(m_ptr->level + (dun_level / 2) + randint(dun_level / 2));
+ m_ptr->exp = monster_exp(m_ptr->level + (dun_level / 2) + randint(dun_level / 2));
monster_check_experience(m_idx, TRUE);
}
}
@@ -1170,38 +1244,42 @@ static void town_gen_circle(int t_idx, int qy, int qx)
}
-static void town_gen_hidden(int t_idx, int qy, int qx)
+static void town_gen_hidden()
{
- int y, x, n, num = 0, i;
-
- int *rooms;
-
- /* Prepare an Array of "remaining stores", and count them */
- C_MAKE(rooms, max_st_idx, int);
- num = get_shops(rooms);
+ /* Get "remaining stores" */
+ auto rooms = get_shops();
/* Get a number of stores to place */
- n = rand_int(num / 2) + (num / 2);
+ std::size_t n = rand_int(rooms.size() / 2) + (rooms.size() / 2);
/* Place k stores */
- for (i = 0; i < n; i++)
+ for (std::size_t i = 0; i < n; i++)
{
/* Find a good spot */
+ int x;
+ int y;
while (TRUE)
{
y = rand_range(1, cur_hgt - 2);
x = rand_range(1, cur_wid - 2);
- if (cave_empty_bold(y, x)) break;
+ if (cave_empty_bold(y, x))
+ {
+ break;
+ }
}
- if(--num > -1)
+ /* Any stores left? */
+ if (!rooms.empty())
{
+ /* Extract store */
+ auto room = rooms.back();
+ rooms.pop_back();
+
/* Build that store at the proper location */
- build_store_hidden(rooms[num], y, x);
+ build_store_hidden(room, y, x);
}
}
- C_FREE(rooms, max_st_idx, int);
}
@@ -1224,22 +1302,20 @@ static void town_gen_hidden(int t_idx, int qy, int qx)
*/
void town_gen(int t_idx)
{
- int qy, qx;
-
/* Level too small to contain a town */
if (cur_hgt < SCREEN_HGT) return;
if (cur_wid < SCREEN_WID) return;
- /* Center fo the level */
- qy = (cur_hgt - SCREEN_HGT) / 2;
- qx = (cur_wid - SCREEN_WID) / 2;
+ /* Center of the level */
+ int qy = (cur_hgt - SCREEN_HGT) / 2;
+ int qx = (cur_wid - SCREEN_WID) / 2;
/* Build stuff */
switch (rand_int(3))
{
case 0:
{
- town_gen_hack(t_idx, qy, qx);
+ town_gen_hack(qy, qx);
if (wizard)
{
msg_format("Town level(normal) (%d, seed %d)",
@@ -1250,7 +1326,7 @@ void town_gen(int t_idx)
case 1:
{
- town_gen_circle(t_idx, qy, qx);
+ town_gen_circle(qy, qx);
if (wizard)
{
msg_format("Town level(circle)(%d, seed %d)",
@@ -1261,7 +1337,7 @@ void town_gen(int t_idx)
case 2:
{
- town_gen_hidden(t_idx, qy, qx);
+ town_gen_hidden();
if (wizard)
{
msg_format("Town level(hidden)(%d, seed %d)",
diff --git a/src/wild.hpp b/src/wild.hpp
new file mode 100644
index 00000000..d6a40e8d
--- /dev/null
+++ b/src/wild.hpp
@@ -0,0 +1,6 @@
+#pragma once
+
+void wilderness_gen();
+void wilderness_gen_small();
+void reveal_wilderness_around_player(int y, int x, int h, int w);
+void town_gen(int t_idx);
diff --git a/src/wilderness_map.hpp b/src/wilderness_map.hpp
new file mode 100644
index 00000000..3db36101
--- /dev/null
+++ b/src/wilderness_map.hpp
@@ -0,0 +1,15 @@
+#pragma once
+
+#include "h-basic.h"
+#include "seed.hpp"
+
+/**
+ * A structure describing a wilderness map
+ */
+struct wilderness_map
+{
+ int feat = 0; /* Wilderness feature */
+ seed_t seed = seed_t::system(); /* Seed for the RNG when building tile */
+ u16b entrance = 0; /* Entrance for dungeons */
+ bool_ known = FALSE; /* Is it seen by the player ? */
+};
diff --git a/src/wilderness_map_fwd.hpp b/src/wilderness_map_fwd.hpp
new file mode 100644
index 00000000..806efb1b
--- /dev/null
+++ b/src/wilderness_map_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct wilderness_map;
diff --git a/src/wilderness_type_info.hpp b/src/wilderness_type_info.hpp
new file mode 100644
index 00000000..fa834e09
--- /dev/null
+++ b/src/wilderness_type_info.hpp
@@ -0,0 +1,24 @@
+#pragma once
+
+#include "h-basic.h"
+#include "terrain.hpp"
+
+/**
+ * A structure describing a wilderness area
+ * with a terrain, a town or a dungeon entrance
+ */
+struct wilderness_type_info
+{
+ const char *name = nullptr; /* Name */
+ const char *text = nullptr; /* Text */
+
+ u16b entrance = 0; /* Which town is there(<1000 i's a town, >=1000 it a dungeon) */
+ s32b wild_x = 0; /* Map coordinates (backed out while parsing map) */
+ s32b wild_y = 0;
+ byte road = 0; /* Flags of road */
+ int level = 0; /* Difficulty level */
+ byte feat = 0; /* The feature of f_info.txt that is used to allow passing, ... and to get a char/color/graph */
+ byte terrain_idx = 0; /* Terrain index(defined in defines.h) */
+
+ byte terrain[MAX_WILD_TERRAIN] = { 0 }; /* Feature types for the plasma generator */
+};
diff --git a/src/wizard1.c b/src/wizard1.c
deleted file mode 100644
index 7daef324..00000000
--- a/src/wizard1.c
+++ /dev/null
@@ -1,2756 +0,0 @@
-/* File: wizard1.c */
-
-/* Purpose: Spoiler generation -BEN- */
-
-#include "angband.h"
-
-
-/*
- * The spoiler file being created
- */
-static FILE *fff = NULL;
-
-
-/*
- * Write out `n' of the character `c' to the spoiler file
- */
-static void spoiler_out_n_chars(int n, char c)
-{
- while (--n >= 0) fputc(c, fff);
-}
-
-
-/*
- * Write out `n' blank lines to the spoiler file
- */
-static void spoiler_blanklines(int n)
-{
- spoiler_out_n_chars(n, '\n');
-}
-
-
-/*
- * Write a line to the spoiler file and then "underline" it with hyphens
- */
-static void spoiler_underline(cptr str)
-{
- fprintf(fff, "%s\n", str);
- spoiler_out_n_chars(strlen(str), '-');
- fprintf(fff, "\n");
-}
-
-
-/*
- * Buffer text to the given file. (-SHAWN-)
- * This is basically c_roff() from mon-desc.c with a few changes.
- */
-static void spoil_out(cptr str)
-{
- cptr r;
-
- /* Line buffer */
- static char roff_buf[256];
-
- /* Current pointer into line roff_buf */
- static char *roff_p = roff_buf;
-
- /* Last space saved into roff_buf */
- static char *roff_s = NULL;
-
- /* Special handling for "new sequence" */
- if (!str)
- {
- if (roff_p != roff_buf) roff_p--;
- while (*roff_p == ' ' && roff_p != roff_buf) roff_p--;
- if (roff_p == roff_buf) fprintf(fff, "\n");
- else
- {
- *(roff_p + 1) = '\0';
- fprintf(fff, "%s\n\n", roff_buf);
- }
- roff_p = roff_buf;
- roff_s = NULL;
- roff_buf[0] = '\0';
- return;
- }
-
- /* Scan the given string, character at a time */
- for (; *str; str++)
- {
- char ch = *str;
- int wrap = (ch == '\n');
-
- if (!isprint(ch)) ch = ' ';
- if (roff_p >= roff_buf + 75) wrap = 1;
- if ((ch == ' ') && (roff_p + 2 >= roff_buf + 75)) wrap = 1;
-
- /* Handle line-wrap */
- if (wrap)
- {
- *roff_p = '\0';
- r = roff_p;
- if (roff_s && (ch != ' '))
- {
- *roff_s = '\0';
- r = roff_s + 1;
- }
- fprintf(fff, "%s\n", roff_buf);
- roff_s = NULL;
- roff_p = roff_buf;
- while (*r) *roff_p++ = *r++;
- }
-
- /* Save the char */
- if ((roff_p > roff_buf) || (ch != ' '))
- {
- if (ch == ' ') roff_s = roff_p;
- *roff_p++ = ch;
- }
- }
-}
-
-
-/*
- * Extract a textual representation of an attribute
- */
-static cptr attr_to_text(byte a)
-{
- switch (a)
- {
- case TERM_DARK:
- return ("xxx");
- case TERM_WHITE:
- return ("White");
- case TERM_SLATE:
- return ("Slate");
- case TERM_ORANGE:
- return ("Orange");
- case TERM_RED:
- return ("Red");
- case TERM_GREEN:
- return ("Green");
- case TERM_BLUE:
- return ("Blue");
- case TERM_UMBER:
- return ("Umber");
- case TERM_L_DARK:
- return ("L.Dark");
- case TERM_L_WHITE:
- return ("L.Slate");
- case TERM_VIOLET:
- return ("Violet");
- case TERM_YELLOW:
- return ("Yellow");
- case TERM_L_RED:
- return ("L.Red");
- case TERM_L_GREEN:
- return ("L.Green");
- case TERM_L_BLUE:
- return ("L.Blue");
- case TERM_L_UMBER:
- return ("L.Umber");
- }
-
- /* Oops */
- return ("Icky");
-}
-
-
-
-/*
- * A tval grouper
- */
-typedef struct
-{
- byte tval;
- cptr name;
-}
-grouper;
-
-
-
-/*
- * Item Spoilers by: benh@phial.com (Ben Harrison)
- */
-
-
-/*
- * The basic items categorized by type
- */
-static grouper group_item[] =
-{
- { TV_SWORD, "Melee Weapons" },
- { TV_POLEARM, NULL },
- { TV_HAFTED, NULL },
- { TV_AXE, NULL },
- { TV_MSTAFF, NULL },
-
- { TV_BOW, "Bows and Slings" },
-
- { TV_SHOT, "Ammo" },
- { TV_ARROW, NULL },
- { TV_BOLT, NULL },
-
- { TV_BOOMERANG, "Boomerangs" },
-
- { TV_INSTRUMENT, "Instruments" },
-
- { TV_SOFT_ARMOR, "Armour (Body)" },
- { TV_HARD_ARMOR, NULL },
- { TV_DRAG_ARMOR, NULL },
-
- { TV_SHIELD, "Armour (Misc)" },
- { TV_HELM, NULL },
- { TV_CROWN, NULL },
- { TV_GLOVES, NULL },
- { TV_BOOTS, NULL },
-
- { TV_CLOAK, "Cloaks" },
- { TV_AMULET, "Amulets" },
- { TV_RING, "Rings" },
-
- { TV_SCROLL, "Scrolls" },
- { TV_POTION, "Potions" },
- { TV_POTION2, NULL },
-
- { TV_FOOD, "Food" },
-
- { TV_ROD_MAIN, "Rods" },
- { TV_ROD, "Rod Tips" },
- { TV_WAND, "Wands" },
- { TV_STAFF, "Staves" },
-
- { TV_BOOK, "Books (Magic, Gods, Music)" },
- { TV_DAEMON_BOOK, "Demonic Equipment" },
-
- { TV_RUNE1, "Runes" },
- { TV_RUNE2, NULL },
-
- { TV_BATERIE, "Essences" },
-
- { TV_PARCHMENT, "Parchments" },
-
- { TV_DIGGING, "Tools" },
- { TV_TOOL, NULL },
-
- { TV_TRAPKIT, "Trapping Kits" },
-
- { TV_CHEST, "Chests" },
-
- { TV_SPIKE, "Various" },
- { TV_LITE, NULL },
- { TV_FLASK, NULL },
- { TV_BOTTLE, NULL },
- { TV_JUNK, NULL },
-
- { TV_SKELETON, "Corpses and Eggs" },
- { TV_CORPSE, NULL },
- { TV_EGG, NULL },
-
- { 0, "" }
-};
-
-
-/*
- * Describe the kind
- */
-static void kind_info(char *buf, char *dam, char *wgt, int *lev, s32b *val, int k)
-{
- object_type forge;
- object_type *q_ptr;
-
- object_kind *k_ptr;
-
-
- /* Get local object */
- q_ptr = &forge;
-
- /* Prepare a fake item */
- object_prep(q_ptr, k);
-
- /* Obtain the "kind" info */
- k_ptr = &k_info[q_ptr->k_idx];
-
- /* It is known */
- q_ptr->ident |= (IDENT_KNOWN);
-
- /* Cancel bonuses */
- q_ptr->to_a = 0;
- q_ptr->to_h = 0;
- q_ptr->to_d = 0;
-
- if ((k_ptr->tval == TV_WAND) || (k_ptr->tval == TV_STAFF))
- {
- hack_apply_magic_power = -99;
- apply_magic(q_ptr, 0, FALSE, FALSE, FALSE);
- }
-
- /* Level */
- (*lev) = k_ptr->level;
-
- /* Value */
- (*val) = object_value(q_ptr);
-
-
- /* Hack */
- if (!buf || !dam || !wgt) return;
-
-
- /* Description (too brief) */
- object_desc_store(buf, q_ptr, FALSE, 0);
-
-
- /* Misc info */
- strcpy(dam, "");
-
- /* Damage */
- switch (q_ptr->tval)
- {
- /* Bows */
- case TV_BOW:
- {
- break;
- }
-
- /* Ammo */
- case TV_SHOT:
- case TV_BOLT:
- case TV_ARROW:
-
- /* Boomerangs */
- case TV_BOOMERANG:
-
- /* Weapons */
- case TV_HAFTED:
- case TV_POLEARM:
- case TV_SWORD:
- case TV_AXE:
- case TV_MSTAFF:
-
- /* Tools */
- case TV_DIGGING:
- {
- sprintf(dam, "%dd%d", q_ptr->dd, q_ptr->ds);
- break;
- }
-
- /* Armour */
- case TV_BOOTS:
- case TV_GLOVES:
- case TV_CLOAK:
- case TV_CROWN:
- case TV_HELM:
- case TV_SHIELD:
- case TV_SOFT_ARMOR:
- case TV_HARD_ARMOR:
- case TV_DRAG_ARMOR:
- {
- sprintf(dam, "%d", q_ptr->ac);
- break;
- }
- }
-
-
- /* Weight */
- sprintf(wgt, "%3ld.%ld", (long int) (q_ptr->weight / 10), (long int) (q_ptr->weight % 10));
-}
-
-
-/*
- * Create a spoiler file for items
- */
-static void spoil_obj_desc(cptr fname)
-{
- int i, k, s, t, n = 0;
-
- u16b who[200];
-
- char buf[1024];
-
- char wgt[80];
- char dam[80];
-
-
- /* Build the filename */
- path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname);
-
- /* File type is "TEXT" */
- FILE_TYPE(FILE_TYPE_TEXT);
-
- /* Open the file */
- fff = my_fopen(buf, "w");
-
- /* Oops */
- if (!fff)
- {
- msg_print("Cannot create spoiler file.");
- return;
- }
-
-
- /* Header */
- sprintf(buf, "Basic Items Spoilers for %s", get_version_string());
- spoiler_underline(buf);
- spoiler_blanklines(2);
-
- /* More Header */
- fprintf(fff, "%-45s %8s%7s%5s%9s\n",
- "Description", "Dam/AC", "Wgt", "Lev", "Cost");
- fprintf(fff, "%-45s %8s%7s%5s%9s\n",
- "----------------------------------------",
- "------", "---", "---", "----");
-
- /* List the groups */
- for (i = 0; TRUE; i++)
- {
- /* Write out the group title */
- if (group_item[i].name)
- {
- /* Hack -- bubble-sort by cost and then level */
- for (s = 0; s < n - 1; s++)
- {
- for (t = 0; t < n - 1; t++)
- {
- int i1 = t;
- int i2 = t + 1;
-
- int e1;
- int e2;
-
- s32b t1;
- s32b t2;
-
- kind_info(NULL, NULL, NULL, &e1, &t1, who[i1]);
- kind_info(NULL, NULL, NULL, &e2, &t2, who[i2]);
-
- if ((t1 > t2) || ((t1 == t2) && (e1 > e2)))
- {
- int tmp = who[i1];
- who[i1] = who[i2];
- who[i2] = tmp;
- }
- }
- }
-
- /* Spoil each item */
- for (s = 0; s < n; s++)
- {
- int e;
- s32b v;
-
- /* Describe the kind */
- kind_info(buf, dam, wgt, &e, &v, who[s]);
-
- /* Dump it */
- fprintf(fff, " %-45s%8s%7s%5d%9ld\n",
- buf, dam, wgt, e, (long)(v));
- }
-
- /* Start a new set */
- n = 0;
-
- /* Notice the end */
- if (!group_item[i].tval) break;
-
- /* Start a new set */
- fprintf(fff, "\n\n%s\n\n", group_item[i].name);
- }
-
- /* Acquire legal item types */
- for (k = 1; k < max_k_idx; k++)
- {
- object_kind *k_ptr = &k_info[k];
-
- /* Skip wrong tval's */
- if (k_ptr->tval != group_item[i].tval) continue;
-
- /* Hack -- Skip artifacts */
- if (k_ptr->flags3 & (TR3_INSTA_ART | TR3_NORM_ART)) continue;
-
- /* Hack -- Skip Ring of Powers */
- if (k == 785) continue;
-
- /* Save the index */
- who[n++] = k;
- }
- }
-
-
- /* Check for errors */
- if (ferror(fff) || my_fclose(fff))
- {
- msg_print("Cannot close spoiler file.");
- return;
- }
-
- /* Message */
- msg_print("Successfully created a spoiler file.");
-}
-
-
-
-/*
- * Artifact Spoilers by: randy@PICARD.tamu.edu (Randy Hutson)
- */
-
-
-/*
- * Returns a "+" string if a number is non-negative and an empty
- * string if negative
- */
-#define POSITIZE(v) (((v) >= 0) ? "+" : "")
-
-/*
- * These are used to format the artifact spoiler file. INDENT1 is used
- * to indent all but the first line of an artifact spoiler. INDENT2 is
- * used when a line "wraps". (Bladeturner's resistances cause this.)
- */
-#define INDENT1 " "
-#define INDENT2 " "
-
-/*
- * MAX_LINE_LEN specifies when a line should wrap.
- */
-#define MAX_LINE_LEN 75
-
-/*
- * Given an array, determine how many elements are in the array
- */
-#define N_ELEMENTS(a) (sizeof (a) / sizeof ((a)[0]))
-
-/*
- * The artifacts categorized by type
- */
-static grouper group_artifact[] =
-{
- { TV_SWORD, "Edged Weapons" },
- { TV_POLEARM, "Polearms" },
- { TV_HAFTED, "Hafted Weapons" },
- { TV_AXE, "Axes" },
-
- { TV_MSTAFF, "Mage Staffs" },
-
- { TV_BOW, "Bows" },
-
- { TV_SHOT, "Ammo" },
- { TV_ARROW, NULL },
- { TV_BOLT, NULL },
-
- { TV_BOOMERANG, "Boomerangs" },
-
- { TV_INSTRUMENT, "Instruments" },
-
- { TV_SOFT_ARMOR, "Body Armor" },
- { TV_HARD_ARMOR, NULL },
- { TV_DRAG_ARMOR, NULL },
-
- { TV_CLOAK, "Cloaks" },
- { TV_SHIELD, "Shields" },
- { TV_HELM, "Helms/Crowns" },
- { TV_CROWN, NULL },
- { TV_GLOVES, "Gloves" },
- { TV_BOOTS, "Boots" },
-
- { TV_DAEMON_BOOK, "Demonic Equipment" },
-
- { TV_LITE, "Light Sources" },
- { TV_AMULET, "Amulets" },
- { TV_RING, "Rings" },
-
- { TV_TOOL, "Tools" },
- { TV_DIGGING, NULL },
- { TV_TRAPKIT, "Trapping Kits" },
-
- { 0, NULL }
-};
-
-
-
-/*
- * Pair together a constant flag with a textual description.
- *
- * Used by both "init.c" and "wiz-spo.c".
- *
- * Note that it sometimes more efficient to actually make an array
- * of textual names, where entry 'N' is assumed to be paired with
- * the flag whose value is "1L << N", but that requires hard-coding.
- */
-
-typedef struct flag_desc flag_desc;
-
-struct flag_desc
-{
- const u32b flag;
- const char *const desc;
-};
-
-
-
-/*
- * These are used for "+3 to STR, DEX", etc. These are separate from
- * the other pval affected traits to simplify the case where an object
- * affects all stats. In this case, "All stats" is used instead of
- * listing each stat individually.
- */
-
-static flag_desc stat_flags_desc[] =
-{
- { TR1_STR, "STR" },
- { TR1_INT, "INT" },
- { TR1_WIS, "WIS" },
- { TR1_DEX, "DEX" },
- { TR1_CON, "CON" },
- { TR1_CHR, "CHR" }
-};
-
-/*
- * Besides stats, these are the other player traits
- * which may be affected by an object's pval
- */
-
-static flag_desc pval_flags1_desc[] =
-{
- { TR1_STEALTH, "Stealth" },
- { TR1_SEARCH, "Searching" },
- { TR1_INFRA, "Infravision" },
- { TR1_TUNNEL, "Tunnelling" },
- { TR1_BLOWS, "Attacks" },
- { TR1_SPEED, "Speed" }
-};
-
-/*
- * Slaying preferences for weapons
- */
-
-static flag_desc slay_flags_desc[] =
-{
- { TR1_SLAY_ANIMAL, "Animal" },
- { TR1_SLAY_EVIL, "Evil" },
- { TR1_SLAY_UNDEAD, "Undead" },
- { TR1_SLAY_DEMON, "Demon" },
- { TR1_SLAY_ORC, "Orc" },
- { TR1_SLAY_TROLL, "Troll" },
- { TR1_SLAY_GIANT, "Giant" },
- { TR1_SLAY_DRAGON, "Dragon" },
- { TR1_KILL_DRAGON, "Xdragon" }
-};
-
-/*
- * Elemental brands for weapons
- *
- * Clearly, TR1_IMPACT is a bit out of place here. To simplify
- * coding, it has been included here along with the elemental
- * brands. It does seem to fit in with the brands and slaying
- * more than the miscellaneous section.
- */
-static flag_desc brand_flags_desc[] =
-{
- { TR1_BRAND_ACID, "Acid Brand" },
- { TR1_BRAND_ELEC, "Lightning Brand" },
- { TR1_BRAND_FIRE, "Flame Tongue" },
- { TR1_BRAND_COLD, "Frost Brand" },
- { TR1_BRAND_POIS, "Poisoned" },
-
- { TR1_CHAOTIC, "Mark of Chaos" },
- { TR1_VAMPIRIC, "Vampiric" },
- { TR1_IMPACT, "Earthquake impact on hit" },
- { TR1_VORPAL, "Very sharp" },
-};
-
-
-/*
- * The 15 resistables
- */
-static const flag_desc resist_flags_desc[] =
-{
- { TR2_RES_ACID, "Acid" },
- { TR2_RES_ELEC, "Lightning" },
- { TR2_RES_FIRE, "Fire" },
- { TR2_RES_COLD, "Cold" },
- { TR2_RES_POIS, "Poison" },
- { TR2_RES_FEAR, "Fear"},
- { TR2_RES_LITE, "Light" },
- { TR2_RES_DARK, "Dark" },
- { TR2_RES_BLIND, "Blindness" },
- { TR2_RES_CONF, "Confusion" },
- { TR2_RES_SOUND, "Sound" },
- { TR2_RES_SHARDS, "Shards" },
- { TR2_RES_NETHER, "Nether" },
- { TR2_RES_NEXUS, "Nexus" },
- { TR2_RES_CHAOS, "Chaos" },
- { TR2_RES_DISEN, "Disenchantment" },
-};
-
-/*
- * Elemental immunities (along with poison)
- */
-
-static const flag_desc immune_flags_desc[] =
-{
- { TR2_IM_ACID, "Acid" },
- { TR2_IM_ELEC, "Lightning" },
- { TR2_IM_FIRE, "Fire" },
- { TR2_IM_COLD, "Cold" },
-};
-
-/*
- * Sustain stats - these are given their "own" line in the
- * spoiler file, mainly for simplicity
- */
-static const flag_desc sustain_flags_desc[] =
-{
- { TR2_SUST_STR, "STR" },
- { TR2_SUST_INT, "INT" },
- { TR2_SUST_WIS, "WIS" },
- { TR2_SUST_DEX, "DEX" },
- { TR2_SUST_CON, "CON" },
- { TR2_SUST_CHR, "CHR" },
-};
-
-/*
- * Miscellaneous magic given by an object's "flags2" field
- */
-
-static const flag_desc misc_flags2_desc[] =
-{
- { TR2_REFLECT, "Reflection" },
- { TR2_FREE_ACT, "Free Action" },
- { TR2_HOLD_LIFE, "Hold Life" },
-};
-
-/*
- * Miscellaneous magic given by an object's "flags3" field
- *
- * Note that cursed artifacts and objects with permanent light
- * are handled "directly" -- see analyze_misc_magic()
- */
-
-static const flag_desc misc_flags3_desc[] =
-{
- { TR3_SH_FIRE, "Fiery Aura" },
- { TR3_SH_ELEC, "Electric Aura" },
- { TR3_NO_TELE, "Prevent Teleportation" },
- { TR3_NO_MAGIC, "Anti-Magic" },
- { TR3_WRAITH, "Wraith Form" },
- { TR3_FEATHER, "Levitation" },
- { TR3_SEE_INVIS, "See Invisible" },
- { TR3_SLOW_DIGEST, "Slow Digestion" },
- { TR3_REGEN, "Regeneration" },
- { TR3_XTRA_SHOTS, "+1 Extra Shot" }, /* always +1? */
- { TR3_DRAIN_EXP, "Drains Experience" },
- { TR3_AGGRAVATE, "Aggravates" },
- { TR3_BLESSED, "Blessed Blade" },
-};
-
-
-/*
- * A special type used just for dealing with pvals
- */
-typedef struct
-{
- /*
- * This will contain a string such as "+2", "-10", etc.
- */
- char pval_desc[12];
-
- /*
- * A list of various player traits affected by an object's pval such
- * as stats, speed, stealth, etc. "Extra attacks" is NOT included in
- * this list since it will probably be desirable to format its
- * description differently.
- *
- * Note that room need only be reserved for the number of stats - 1
- * since the description "All stats" is used if an object affects all
- * all stats. Also, room must be reserved for a sentinel NULL pointer.
- *
- * This will be a list such as ["STR", "DEX", "Stealth", NULL] etc.
- *
- * This list includes extra attacks, for simplicity.
- */
- cptr pval_affects[N_ELEMENTS(stat_flags_desc) - 1 +
- N_ELEMENTS(pval_flags1_desc) + 1];
-
-}
-pval_info_type;
-
-
-/*
- * An "object analysis structure"
- *
- * It will be filled with descriptive strings detailing an object's
- * various magical powers. The "ignore X" traits are not noted since
- * all artifacts ignore "normal" destruction.
- */
-
-typedef struct
-{
- /* "The Longsword Dragonsmiter (6d4) (+20, +25)" */
- char description[160];
-
- /* Description of what is affected by an object's pval */
- pval_info_type pval_info;
-
- /* A list of an object's slaying preferences */
- cptr slays[N_ELEMENTS(slay_flags_desc) + 1];
-
- /* A list if an object's elemental brands */
- cptr brands[N_ELEMENTS(brand_flags_desc) + 1];
-
- /* A list of immunities granted by an object */
- cptr immunities[N_ELEMENTS(immune_flags_desc) + 1];
-
- /* A list of resistances granted by an object */
- cptr resistances[N_ELEMENTS(resist_flags_desc) + 1];
-
- /* A list of stats sustained by an object */
- cptr sustains[N_ELEMENTS(sustain_flags_desc) - 1 + 1];
-
- /* A list of various magical qualities an object may have */
- cptr misc_magic[N_ELEMENTS(misc_flags2_desc) + N_ELEMENTS(misc_flags3_desc)
- + 1 /* Permanent Light */
- + 1 /* type of curse */
- + 1]; /* sentinel NULL */
-
- /* A string describing an artifact's activation */
- cptr activation;
-
- /* "Level 20, Rarity 30, 3.0 lbs, 20000 Gold" */
- char misc_desc[80];
-}
-obj_desc_list;
-
-
-
-
-
-
-/*
- * This function does most of the actual "analysis". Given a set of bit flags
- * (which will be from one of the flags fields from the object in question),
- * a "flag description structure", a "description list", and the number of
- * elements in the "flag description structure", this function sets the
- * "description list" members to the appropriate descriptions contained in
- * the "flag description structure".
- *
- * The possibly updated description pointer is returned.
- */
-static cptr *spoiler_flag_aux(const u32b art_flags, const flag_desc *flag_ptr,
- cptr *desc_ptr, const int n_elmnts)
-{
- int i;
-
- for (i = 0; i < n_elmnts; ++i)
- {
- if (art_flags & flag_ptr[i].flag)
- {
- *desc_ptr++ = flag_ptr[i].desc;
- }
- }
-
- return desc_ptr;
-}
-
-
-/*
- * Acquire a "basic" description "The Cloak of Death [1,+10]"
- */
-static void analyze_general (object_type *o_ptr, char *desc_ptr)
-{
- /* Get a "useful" description of the object */
- object_desc_store(desc_ptr, o_ptr, TRUE, 1);
-}
-
-
-/*
- * List "player traits" altered by an artifact's pval. These include stats,
- * speed, infravision, tunnelling, stealth, searching, and extra attacks.
- */
-static void analyze_pval (object_type *o_ptr, pval_info_type *p_ptr)
-{
- const u32b all_stats = (TR1_STR | TR1_INT | TR1_WIS |
- TR1_DEX | TR1_CON | TR1_CHR);
-
- u32b f1, f2, f3, f4, f5, esp;
-
- cptr *affects_list;
-
- /* If pval == 0, there is nothing to do. */
- if (!o_ptr->pval)
- {
- /* An "empty" pval description indicates that pval == 0 */
- p_ptr->pval_desc[0] = '\0';
- return;
- }
-
- /* Extract the flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
-
- affects_list = p_ptr->pval_affects;
-
- /* Create the "+N" string */
- sprintf(p_ptr->pval_desc, "%s%ld", POSITIZE(o_ptr->pval), (long int) o_ptr->pval);
-
- /* First, check to see if the pval affects all stats */
- if ((f1 & all_stats) == all_stats)
- {
- *affects_list++ = "All stats";
- }
-
- /* Are any stats affected? */
- else if (f1 & all_stats)
- {
- affects_list = spoiler_flag_aux(f1, stat_flags_desc,
- affects_list,
- N_ELEMENTS(stat_flags_desc));
- }
-
- /* And now the "rest" */
- affects_list = spoiler_flag_aux(f1, pval_flags1_desc,
- affects_list,
- N_ELEMENTS(pval_flags1_desc));
-
- /* Terminate the description list */
- *affects_list = NULL;
-}
-
-
-/* Note the slaying specialties of a weapon */
-static void analyze_slay (object_type *o_ptr, cptr *slay_list)
-{
- u32b f1, f2, f3, f4, f5, esp;
-
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
-
- slay_list = spoiler_flag_aux(f1, slay_flags_desc, slay_list,
- N_ELEMENTS(slay_flags_desc));
-
- /* Terminate the description list */
- *slay_list = NULL;
-}
-
-/* Note an object's elemental brands */
-static void analyze_brand (object_type *o_ptr, cptr *brand_list)
-{
- u32b f1, f2, f3, f4, f5, esp;
-
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
-
- brand_list = spoiler_flag_aux(f1, brand_flags_desc, brand_list,
- N_ELEMENTS(brand_flags_desc));
-
- /* Terminate the description list */
- *brand_list = NULL;
-}
-
-
-/* Note the resistances granted by an object */
-static void analyze_resist (object_type *o_ptr, cptr *resist_list)
-{
- u32b f1, f2, f3, f4, f5, esp;
-
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
-
- resist_list = spoiler_flag_aux(f2, resist_flags_desc,
- resist_list, N_ELEMENTS(resist_flags_desc));
-
- /* Terminate the description list */
- *resist_list = NULL;
-}
-
-
-/* Note the immunities granted by an object */
-static void analyze_immune (object_type *o_ptr, cptr *immune_list)
-{
- u32b f1, f2, f3, f4, f5, esp;
-
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
-
- immune_list = spoiler_flag_aux(f2, immune_flags_desc,
- immune_list, N_ELEMENTS(immune_flags_desc));
-
- /* Terminate the description list */
- *immune_list = NULL;
-}
-
-/* Note which stats an object sustains */
-
-static void analyze_sustains (object_type *o_ptr, cptr *sustain_list)
-{
- const u32b all_sustains = (TR2_SUST_STR | TR2_SUST_INT | TR2_SUST_WIS |
- TR2_SUST_DEX | TR2_SUST_CON | TR2_SUST_CHR);
-
- u32b f1, f2, f3, f4, f5, esp;
-
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
-
- /* Simplify things if an item sustains all stats */
- if ((f2 & all_sustains) == all_sustains)
- {
- *sustain_list++ = "All stats";
- }
-
- /* Should we bother? */
- else if ((f2 & all_sustains))
- {
- sustain_list = spoiler_flag_aux(f2, sustain_flags_desc,
- sustain_list,
- N_ELEMENTS(sustain_flags_desc));
- }
-
- /* Terminate the description list */
- *sustain_list = NULL;
-}
-
-
-/*
- * Note miscellaneous powers bestowed by an artifact such as see invisible,
- * free action, permanent light, etc.
- */
-static void analyze_misc_magic (object_type *o_ptr, cptr *misc_list)
-{
- u32b f1, f2, f3, f4, f5, esp;
- int radius = 0;
-
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
-
- misc_list = spoiler_flag_aux(f2, misc_flags2_desc, misc_list,
- N_ELEMENTS(misc_flags2_desc));
-
- misc_list = spoiler_flag_aux(f3, misc_flags3_desc, misc_list,
- N_ELEMENTS(misc_flags3_desc));
-
- /*
- * Glowing artifacts -- small radius light.
- */
-
- if (f3 & TR3_LITE1) radius++;
- if (f4 & TR4_LITE2) radius += 2;
- if (f4 & TR4_LITE3) radius += 3;
-
- if (f4 & TR4_FUEL_LITE)
- {
- *misc_list++ = format("It provides light (radius %d) forever.", radius);
- }
- else
- {
- *misc_list++ = format("It provides light (radius %d) when fueled.", radius);
- }
-
- /*
- * Handle cursed objects here to avoid redundancies such as noting
- * that a permanently cursed object is heavily cursed as well as
- * being "lightly cursed".
- */
-
- if (cursed_p(o_ptr))
- {
- if (f3 & (TR3_TY_CURSE))
- {
- *misc_list++ = "Ancient Curse";
- }
- if (f3 & (TR3_PERMA_CURSE))
- {
- *misc_list++ = "Permanently Cursed";
- }
- else if (f3 & (TR3_HEAVY_CURSE))
- {
- *misc_list++ = "Heavily Cursed";
- }
- else
- {
- *misc_list++ = "Cursed";
- }
- }
-
- /* Terminate the description list */
- *misc_list = NULL;
-}
-
-
-
-
-/*
- * Determine the minimum depth an artifact can appear, its rarity, its weight,
- * and its value in gold pieces
- */
-static void analyze_misc (object_type *o_ptr, char *misc_desc)
-{
- artifact_type *a_ptr = &a_info[o_ptr->name1];
-
- sprintf(misc_desc, "Level %u, Rarity %u, %d.%d lbs, %ld Gold",
- a_ptr->level, a_ptr->rarity,
- a_ptr->weight / 10, a_ptr->weight % 10, (long int) a_ptr->cost);
-}
-
-
-/*
- * Fill in an object description structure for a given object
- */
-static void object_analyze(object_type *o_ptr, obj_desc_list *desc_ptr)
-{
- analyze_general(o_ptr, desc_ptr->description);
-
- analyze_pval(o_ptr, &desc_ptr->pval_info);
-
- analyze_brand(o_ptr, desc_ptr->brands);
-
- analyze_slay(o_ptr, desc_ptr->slays);
-
- analyze_immune(o_ptr, desc_ptr->immunities);
-
- analyze_resist(o_ptr, desc_ptr->resistances);
-
- analyze_sustains(o_ptr, desc_ptr->sustains);
-
- analyze_misc_magic(o_ptr, desc_ptr->misc_magic);
-
- analyze_misc(o_ptr, desc_ptr->misc_desc);
-
- desc_ptr->activation = item_activation(o_ptr, 0);
-}
-
-
-static void print_header(void)
-{
- char buf[80];
-
- sprintf(buf, "Artifact Spoilers for %s", get_version_string());
- spoiler_underline(buf);
-}
-
-/*
- * This is somewhat ugly.
- *
- * Given a header ("Resist", e.g.), a list ("Fire", "Cold", Acid", e.g.),
- * and a separator character (',', e.g.), write the list to the spoiler file
- * in a "nice" format, such as:
- *
- * Resist Fire, Cold, Acid
- *
- * That was a simple example, but when the list is long, a line wrap
- * should occur, and this should induce a new level of indention if
- * a list is being spread across lines. So for example, Bladeturner's
- * list of resistances should look something like this
- *
- * Resist Acid, Lightning, Fire, Cold, Poison, Light, Dark, Blindness,
- * Confusion, Sound, Shards, Nether, Nexus, Chaos, Disenchantment
- *
- * However, the code distinguishes between a single list of many items vs.
- * many lists. (The separator is used to make this determination.) A single
- * list of many items will not cause line wrapping (since there is no
- * apparent reason to do so). So the lists of Ulmo's miscellaneous traits
- * might look like this:
- *
- * Free Action; Hold Life; See Invisible; Slow Digestion; Regeneration
- * Blessed Blade
- *
- * So comparing the two, "Regeneration" has no trailing separator and
- * "Blessed Blade" was not indented. (Also, Ulmo's lists have no headers,
- * but that's not relevant to line wrapping and indention.)
- */
-
-/* ITEM_SEP separates items within a list */
-#define ITEM_SEP ','
-
-
-/* LIST_SEP separates lists */
-#define LIST_SEP ';'
-
-
-/* Create a spoiler file entry for an artifact */
-
-static void spoiler_print_art(obj_desc_list *art_ptr, int name1, int set, object_type *o_ptr)
-{
- /* Don't indent the first line */
- fprintf(fff, "%s\n ", art_ptr->description);
- text_out_indent = 4;
- object_out_desc(o_ptr, fff, FALSE, TRUE);
- text_out_indent = 0;
-
- /* End with the miscellaneous facts */
- fprintf(fff, "%s%s\n\n", INDENT1, art_ptr->misc_desc);
-}
-
-
-/*
- * Hack -- Create a "forged" artifact
- */
-static bool_ make_fake_artifact(object_type *o_ptr, int name1)
-{
- int i;
- int cur;
-
- artifact_type *a_ptr = &a_info[name1];
-
-
- /* Ignore "empty" artifacts */
- if (!a_ptr->name) return FALSE;
-
- /* Acquire the "kind" index */
- i = lookup_kind(a_ptr->tval, a_ptr->sval);
-
- /* Oops */
- if (!i) return (FALSE);
-
- /* Create the artifact */
- object_prep(o_ptr, i);
-
- /* Save the name */
- o_ptr->name1 = name1;
-
- /* Keep the One Ring untouched by apply_magic */
- if (name1 != ART_POWER)
- {
- cur = a_ptr->cur_num;
- apply_magic(o_ptr, -1, TRUE, TRUE, TRUE);
- a_ptr->cur_num = cur;
- }
- else
- {
- o_ptr->pval = a_ptr->pval;
- }
-
- /* Success */
- return (TRUE);
-}
-
-
-/*
- * Create a spoiler file for artifacts
- */
-static void spoil_artifact(cptr fname)
-{
- int i, j;
-
- object_type forge;
- object_type *q_ptr;
-
- obj_desc_list artifact;
-
- char buf[1024];
-
-
- /* Build the filename */
- path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname);
-
- /* File type is "TEXT" */
- FILE_TYPE(FILE_TYPE_TEXT);
-
- /* Open the file */
- fff = my_fopen(buf, "w");
-
- /* Oops */
- if (!fff)
- {
- msg_print("Cannot create spoiler file.");
- return;
- }
-
- /* Dump the header */
- print_header();
-
- /* List the artifacts by tval */
- for (i = 0; group_artifact[i].tval; i++)
- {
- /* Write out the group title */
- if (group_artifact[i].name)
- {
- spoiler_blanklines(2);
- spoiler_underline(group_artifact[i].name);
- spoiler_blanklines(1);
- }
-
- /* Now search through all of the artifacts */
- for (j = 1; j < max_a_idx; ++j)
- {
- artifact_type *a_ptr = &a_info[j];
-
- /* We only want objects in the current group */
- if (a_ptr->tval != group_artifact[i].tval) continue;
-
- /* Get local object */
- q_ptr = &forge;
-
- /* Wipe the object */
- object_wipe(q_ptr);
-
- /* Attempt to "forge" the artifact */
- if (!make_fake_artifact(q_ptr, j)) continue;
-
- /* Aware and Known */
- object_known(q_ptr);
-
- /* Mark the item as fully known */
- q_ptr->ident |= (IDENT_MENTAL);
-
- /* Analyze the artifact */
- object_analyze(q_ptr, &artifact);
-
- /* Write out the artifact description to the spoiler file */
- spoiler_print_art(&artifact, j, a_ptr->set, q_ptr);
- }
- }
-
- /* Check for errors */
- if (ferror(fff) || my_fclose(fff))
- {
- msg_print("Cannot close spoiler file.");
- return;
- }
-
- /* Message */
- msg_print("Successfully created a spoiler file.");
-}
-
-
-
-
-
-/*
- * Create a spoiler file for monsters -BEN-
- */
-static void spoil_mon_desc(cptr fname)
-{
- int i, n = 0;
-
- s16b *who;
-
- char buf[1024];
-
- char nam[80];
- char lev[80];
- char rar[80];
- char spd[80];
- char ac[80];
- char hp[80];
- char exp[80];
-
- /* Build the filename */
- path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname);
-
- /* File type is "TEXT" */
- FILE_TYPE(FILE_TYPE_TEXT);
-
- /* Open the file */
- fff = my_fopen(buf, "w");
-
- /* Oops */
- if (!fff)
- {
- msg_print("Cannot create spoiler file.");
- return;
- }
-
- /* Allocate the "who" array */
- C_MAKE(who, max_r_idx, s16b);
-
- /* Dump the header */
- sprintf(buf, "Monster Spoilers for %s", get_version_string());
- spoiler_underline(buf);
- spoiler_blanklines(2);
-
- /* Dump the header */
- fprintf(fff, "%-40.40s%4s%4s%6s%8s%4s %11.11s\n",
- "Name", "Lev", "Rar", "Spd", "Hp", "Ac", "Visual Info");
- fprintf(fff, "%-40.40s%4s%4s%6s%8s%4s %11.11s\n",
- "----", "---", "---", "---", "--", "--", "-----------");
-
-
- /* Scan the monsters */
- for (i = 1; i < max_r_idx; i++)
- {
- monster_race *r_ptr = &r_info[i];
-
- /* Use that monster */
- if (r_ptr->name) who[n++] = i;
- }
-
-
- /* Scan again */
- for (i = 0; i < n; i++)
- {
- monster_race *r_ptr = &r_info[who[i]];
-
- cptr name = (r_name + r_ptr->name);
-
- /* Get the "name" */
- if (r_ptr->flags1 & (RF1_UNIQUE))
- {
- sprintf(nam, "[U] %s", name);
- }
- else
- {
- sprintf(nam, "The %s", name);
- }
-
-
- /* Level */
- sprintf(lev, "%d", r_ptr->level);
-
- /* Rarity */
- sprintf(rar, "%d", r_ptr->rarity);
-
- /* Speed */
- if (r_ptr->speed >= 110)
- {
- sprintf(spd, "+%d", (r_ptr->speed - 110));
- }
- else
- {
- sprintf(spd, "-%d", (110 - r_ptr->speed));
- }
-
- /* Armor Class */
- sprintf(ac, "%d", r_ptr->ac);
-
- /* Hitpoints */
- if ((r_ptr->flags1 & (RF1_FORCE_MAXHP)) || (r_ptr->hside == 1))
- {
- sprintf(hp, "%d", r_ptr->hdice * r_ptr->hside);
- }
- else
- {
- sprintf(hp, "%dd%d", r_ptr->hdice, r_ptr->hside);
- }
-
-
- /* Experience */
- sprintf(exp, "%ld", (long)(r_ptr->mexp));
-
- /* Hack -- use visual instead */
- sprintf(exp, "%s '%c'", attr_to_text(r_ptr->d_attr), r_ptr->d_char);
-
- /* Dump the info */
- fprintf(fff, "%-40.40s%4s%4s%6s%8s%4s %11.11s\n",
- nam, lev, rar, spd, hp, ac, exp);
- }
-
- /* End it */
- fprintf(fff, "\n");
-
- /* Free the "who" array */
- C_KILL(who, max_r_idx, s16b);
-
- /* Check for errors */
- if (ferror(fff) || my_fclose(fff))
- {
- msg_print("Cannot close spoiler file.");
- return;
- }
-
- /* Worked */
- msg_print("Successfully created a spoiler file.");
-}
-
-
-
-
-/*
- * Monster spoilers by: smchorse@ringer.cs.utsa.edu (Shawn McHorse)
- *
- * Primarily based on code already in mon-desc.c, mostly by -BEN-
- */
-
-/*
- * Pronoun arrays
- */
-static cptr wd_che[3] = { "It", "He", "She" };
-static cptr wd_lhe[3] = { "it", "he", "she" };
-
-
-
-/*
- * Create a spoiler file for monsters (-SHAWN-)
- */
-static void spoil_mon_info(cptr fname)
-{
- char buf[1024];
- int msex, vn, i, j, k, n;
- bool_ breath, magic, sin;
- cptr p, q;
- cptr vp[64];
- u32b flags1, flags2, flags3, flags4, flags5, flags6, flags9;
-
-
- /* Build the filename */
- path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname);
-
- /* File type is "TEXT" */
- FILE_TYPE(FILE_TYPE_TEXT);
-
- /* Open the file */
- fff = my_fopen(buf, "w");
-
- /* Oops */
- if (!fff)
- {
- msg_print("Cannot create spoiler file.");
- return;
- }
-
-
- /* Dump the header */
- sprintf(buf, "Monster Spoilers for %s", get_version_string());
- spoiler_underline(buf);
- spoiler_blanklines(2);
-
- /*
- * List all monsters in order.
- */
- for (n = 1; n < max_r_idx; n++)
- {
- monster_race *r_ptr = &r_info[n];
-
- /* Extract the flags */
- flags1 = r_ptr->flags1;
- flags2 = r_ptr->flags2;
- flags3 = r_ptr->flags3;
- flags4 = r_ptr->flags4;
- flags5 = r_ptr->flags5;
- flags6 = r_ptr->flags6;
- flags9 = r_ptr->flags9;
- breath = FALSE;
- magic = FALSE;
-
- /* Extract a gender (if applicable) */
- if (flags1 & (RF1_FEMALE)) msex = 2;
- else if (flags1 & (RF1_MALE)) msex = 1;
- else msex = 0;
-
-
- /* Prefix */
- if (flags1 & (RF1_UNIQUE))
- {
- spoil_out("[U] ");
- }
- else
- {
- spoil_out("The ");
- }
-
- /* Name */
- sprintf(buf, "%s (", (r_name + r_ptr->name)); /* ---)--- */
- spoil_out(buf);
-
- /* Color */
- spoil_out(attr_to_text(r_ptr->d_attr));
-
- /* Symbol --(-- */
- sprintf(buf, " '%c')\n", r_ptr->d_char);
- spoil_out(buf);
-
-
- /* Indent */
- sprintf(buf, "=== ");
- spoil_out(buf);
-
- /* Number */
- sprintf(buf, "Num:%d ", n);
- spoil_out(buf);
-
- /* Level */
- sprintf(buf, "Lev:%d ", r_ptr->level);
- spoil_out(buf);
-
- /* Rarity */
- sprintf(buf, "Rar:%d ", r_ptr->rarity);
- spoil_out(buf);
-
- /* Speed */
- if (r_ptr->speed >= 110)
- {
- sprintf(buf, "Spd:+%d ", (r_ptr->speed - 110));
- }
- else
- {
- sprintf(buf, "Spd:-%d ", (110 - r_ptr->speed));
- }
- spoil_out(buf);
-
- /* Hitpoints */
- if ((flags1 & (RF1_FORCE_MAXHP)) || (r_ptr->hside == 1))
- {
- sprintf(buf, "Hp:%d ", r_ptr->hdice * r_ptr->hside);
- }
- else
- {
- sprintf(buf, "Hp:%dd%d ", r_ptr->hdice, r_ptr->hside);
- }
- spoil_out(buf);
-
- /* Armor Class */
- sprintf(buf, "Ac:%d ", r_ptr->ac);
- spoil_out(buf);
-
- /* Experience */
- sprintf(buf, "Exp:%ld\n", (long)(r_ptr->mexp));
- spoil_out(buf);
-
-
- /* Describe */
- spoil_out(r_text + r_ptr->text);
- spoil_out(" ");
-
-
- spoil_out("This");
-
- if (flags2 & (RF2_ELDRITCH_HORROR)) spoil_out (" sanity-blasting");
- if (flags3 & (RF3_ANIMAL)) spoil_out(" natural");
- if (flags3 & (RF3_EVIL)) spoil_out(" evil");
- if (flags3 & (RF3_GOOD)) spoil_out(" good");
- if (flags3 & (RF3_UNDEAD)) spoil_out(" undead");
-
- if (flags3 & (RF3_DRAGON)) spoil_out(" dragon");
- else if (flags3 & (RF3_DEMON)) spoil_out(" demon");
- else if (flags3 & (RF3_GIANT)) spoil_out(" giant");
- else if (flags3 & (RF3_TROLL)) spoil_out(" troll");
- else if (flags3 & (RF3_ORC)) spoil_out(" orc");
- else if (flags3 & (RF3_THUNDERLORD)) spoil_out (" Thunderlord");
- else spoil_out(" creature");
-
- spoil_out(" moves");
-
- if ((flags1 & (RF1_RAND_50)) && (flags1 & (RF1_RAND_25)))
- {
- spoil_out(" extremely erratically");
- }
- else if (flags1 & (RF1_RAND_50))
- {
- spoil_out(" somewhat erratically");
- }
- else if (flags1 & (RF1_RAND_25))
- {
- spoil_out(" a bit erratically");
- }
- else
- {
- spoil_out(" normally");
- }
-
- if (flags1 & (RF1_NEVER_MOVE))
- {
- spoil_out(", but does not deign to chase intruders");
- }
-
- spoil_out(". ");
-
- if (!r_ptr->level || (flags1 & (RF1_FORCE_DEPTH)))
- {
- sprintf(buf, "%s is never found out of depth. ", wd_che[msex]);
- spoil_out(buf);
- }
-
- if (flags1 & (RF1_FORCE_SLEEP))
- {
- sprintf(buf, "%s is always created sluggish. ", wd_che[msex]);
- spoil_out(buf);
- }
-
- if (flags2 & (RF2_AURA_FIRE))
- {
- sprintf(buf, "%s is surrounded by flames. ", wd_che[msex]);
- spoil_out(buf);
- }
-
- if (flags2 & (RF2_AURA_ELEC))
- {
- sprintf(buf, "%s is surrounded by electricity. ", wd_che[msex]);
- spoil_out(buf);
- }
-
- if (flags2 & (RF2_REFLECTING))
- {
- sprintf(buf, "%s reflects bolt spells. ", wd_che[msex]);
- spoil_out(buf);
- }
-
- if (flags1 & (RF1_ESCORT))
- {
- sprintf(buf, "%s usually appears with ", wd_che[msex]);
- spoil_out(buf);
- if (flags1 & (RF1_ESCORTS)) spoil_out("escorts. ");
- else spoil_out("an escort. ");
- }
-
- if ((flags1 & (RF1_FRIEND)) || (flags1 & (RF1_FRIENDS)))
- {
- sprintf(buf, "%s usually appears in groups. ", wd_che[msex]);
- spoil_out(buf);
- }
-
- /* Collect innate attacks */
- vn = 0;
- if (flags4 & (RF4_SHRIEK)) vp[vn++] = "shriek for help";
- if (flags4 & (RF4_ROCKET)) vp[vn++] = "shoot a rocket";
- if (flags4 & (RF4_ARROW_1)) vp[vn++] = "fire arrows";
- if (flags4 & (RF4_ARROW_2)) vp[vn++] = "fire arrows";
- if (flags4 & (RF4_ARROW_3)) vp[vn++] = "fire missiles";
- if (flags4 & (RF4_ARROW_4)) vp[vn++] = "fire missiles";
-
- if (vn)
- {
- spoil_out(wd_che[msex]);
- for (i = 0; i < vn; i++)
- {
- if (!i) spoil_out(" may ");
- else if (i < vn - 1) spoil_out(", ");
- else spoil_out(" or ");
- spoil_out(vp[i]);
- }
- spoil_out(". ");
- }
-
- /* Collect breaths */
- vn = 0;
- if (flags4 & (RF4_BR_ACID)) vp[vn++] = "acid";
- if (flags4 & (RF4_BR_ELEC)) vp[vn++] = "lightning";
- if (flags4 & (RF4_BR_FIRE)) vp[vn++] = "fire";
- if (flags4 & (RF4_BR_COLD)) vp[vn++] = "frost";
- if (flags4 & (RF4_BR_POIS)) vp[vn++] = "poison";
- if (flags4 & (RF4_BR_NETH)) vp[vn++] = "nether";
- if (flags4 & (RF4_BR_LITE)) vp[vn++] = "light";
- if (flags4 & (RF4_BR_DARK)) vp[vn++] = "darkness";
- if (flags4 & (RF4_BR_CONF)) vp[vn++] = "confusion";
- if (flags4 & (RF4_BR_SOUN)) vp[vn++] = "sound";
- if (flags4 & (RF4_BR_CHAO)) vp[vn++] = "chaos";
- if (flags4 & (RF4_BR_DISE)) vp[vn++] = "disenchantment";
- if (flags4 & (RF4_BR_NEXU)) vp[vn++] = "nexus";
- if (flags4 & (RF4_BR_TIME)) vp[vn++] = "time";
- if (flags4 & (RF4_BR_INER)) vp[vn++] = "inertia";
- if (flags4 & (RF4_BR_GRAV)) vp[vn++] = "gravity";
- if (flags4 & (RF4_BR_SHAR)) vp[vn++] = "shards";
- if (flags4 & (RF4_BR_PLAS)) vp[vn++] = "plasma";
- if (flags4 & (RF4_BR_WALL)) vp[vn++] = "force";
- if (flags4 & (RF4_BR_MANA)) vp[vn++] = "mana";
- if (flags4 & (RF4_BR_NUKE)) vp[vn++] = "toxic waste";
- if (flags4 & (RF4_BR_DISI)) vp[vn++] = "disintegration";
-
- if (vn)
- {
- breath = TRUE;
- spoil_out(wd_che[msex]);
- for (i = 0; i < vn; i++)
- {
- if (!i) spoil_out(" may breathe ");
- else if (i < vn - 1) spoil_out(", ");
- else spoil_out(" or ");
- spoil_out(vp[i]);
- }
- if (flags2 & (RF2_POWERFUL)) spoil_out(" powerfully");
- }
-
- /* Collect spells */
- vn = 0;
- if (flags5 & (RF5_BA_ACID)) vp[vn++] = "produce acid balls";
- if (flags5 & (RF5_BA_ELEC)) vp[vn++] = "produce lightning balls";
- if (flags5 & (RF5_BA_FIRE)) vp[vn++] = "produce fire balls";
- if (flags5 & (RF5_BA_COLD)) vp[vn++] = "produce frost balls";
- if (flags5 & (RF5_BA_POIS)) vp[vn++] = "produce poison balls";
- if (flags5 & (RF5_BA_NETH)) vp[vn++] = "produce nether balls";
- if (flags5 & (RF5_BA_WATE)) vp[vn++] = "produce water balls";
- if (flags4 & (RF4_BA_NUKE)) vp[vn++] = "produce balls of radiation";
- if (flags5 & (RF5_BA_MANA)) vp[vn++] = "produce mana storms";
- if (flags5 & (RF5_BA_DARK)) vp[vn++] = "produce darkness storms";
- if (flags4 & (RF4_BA_CHAO)) vp[vn++] = "invoke raw Chaos";
- if (flags6 & (RF6_HAND_DOOM)) vp[vn++] = "invoke the Hand of Doom";
- if (flags5 & (RF5_DRAIN_MANA)) vp[vn++] = "drain mana";
- if (flags5 & (RF5_MIND_BLAST)) vp[vn++] = "cause mind blasting";
- if (flags5 & (RF5_BRAIN_SMASH)) vp[vn++] = "cause brain smashing";
- if (flags5 & (RF5_CAUSE_1)) vp[vn++] = "cause light wounds and cursing";
- if (flags5 & (RF5_CAUSE_2)) vp[vn++] = "cause serious wounds and cursing";
- if (flags5 & (RF5_CAUSE_3)) vp[vn++] = "cause critical wounds and cursing";
- if (flags5 & (RF5_CAUSE_4)) vp[vn++] = "cause mortal wounds";
- if (flags5 & (RF5_BO_ACID)) vp[vn++] = "produce acid bolts";
- if (flags5 & (RF5_BO_ELEC)) vp[vn++] = "produce lightning bolts";
- if (flags5 & (RF5_BO_FIRE)) vp[vn++] = "produce fire bolts";
- if (flags5 & (RF5_BO_COLD)) vp[vn++] = "produce frost bolts";
- if (flags5 & (RF5_BO_POIS)) vp[vn++] = "produce poison bolts";
- if (flags5 & (RF5_BO_NETH)) vp[vn++] = "produce nether bolts";
- if (flags5 & (RF5_BO_WATE)) vp[vn++] = "produce water bolts";
- if (flags5 & (RF5_BO_MANA)) vp[vn++] = "produce mana bolts";
- if (flags5 & (RF5_BO_PLAS)) vp[vn++] = "produce plasma bolts";
- if (flags5 & (RF5_BO_ICEE)) vp[vn++] = "produce ice bolts";
- if (flags5 & (RF5_MISSILE)) vp[vn++] = "produce magic missiles";
- if (flags5 & (RF5_SCARE)) vp[vn++] = "terrify";
- if (flags5 & (RF5_BLIND)) vp[vn++] = "blind";
- if (flags5 & (RF5_CONF)) vp[vn++] = "confuse";
- if (flags5 & (RF5_SLOW)) vp[vn++] = "slow";
- if (flags5 & (RF5_HOLD)) vp[vn++] = "paralyse";
- if (flags6 & (RF6_HASTE)) vp[vn++] = "haste-self";
- if (flags6 & (RF6_HEAL)) vp[vn++] = "heal-self";
- if (flags6 & (RF6_BLINK)) vp[vn++] = "blink-self";
- if (flags6 & (RF6_TPORT)) vp[vn++] = "teleport-self";
- if (flags6 & (RF6_S_BUG)) vp[vn++] = "summon software bugs";
- if (flags6 & (RF6_S_RNG)) vp[vn++] = "summon RNGs";
- if (flags6 & (RF6_TELE_TO)) vp[vn++] = "teleport to";
- if (flags6 & (RF6_TELE_AWAY)) vp[vn++] = "teleport away";
- if (flags6 & (RF6_TELE_LEVEL)) vp[vn++] = "teleport level";
- if (flags6 & (RF6_DARKNESS)) vp[vn++] = "create darkness";
- if (flags6 & (RF6_TRAPS)) vp[vn++] = "create traps";
- if (flags6 & (RF6_FORGET)) vp[vn++] = "cause amnesia";
- if (flags6 & (RF6_RAISE_DEAD)) vp[vn++] = "raise dead";
- if (flags6 & (RF6_S_THUNDERLORD)) vp[vn++] = "summon a thunderlord";
- if (flags6 & (RF6_S_MONSTER)) vp[vn++] = "summon a monster";
- if (flags6 & (RF6_S_MONSTERS)) vp[vn++] = "summon monsters";
- if (flags6 & (RF6_S_KIN)) vp[vn++] = "summon aid";
- if (flags6 & (RF6_S_ANT)) vp[vn++] = "summon ants";
- if (flags6 & (RF6_S_SPIDER)) vp[vn++] = "summon spiders";
- if (flags6 & (RF6_S_HOUND)) vp[vn++] = "summon hounds";
- if (flags6 & (RF6_S_HYDRA)) vp[vn++] = "summon hydras";
- if (flags6 & (RF6_S_ANGEL)) vp[vn++] = "summon an angel";
- if (flags6 & (RF6_S_DEMON)) vp[vn++] = "summon a demon";
- if (flags6 & (RF6_S_UNDEAD)) vp[vn++] = "summon an undead";
- if (flags6 & (RF6_S_DRAGON)) vp[vn++] = "summon a dragon";
- if (flags4 & (RF4_S_ANIMAL)) vp[vn++] = "summon animal";
- if (flags6 & (RF6_S_ANIMALS)) vp[vn++] = "summon animals";
- if (flags6 & (RF6_S_HI_UNDEAD)) vp[vn++] = "summon greater undead";
- if (flags6 & (RF6_S_HI_DRAGON)) vp[vn++] = "summon ancient dragons";
- if (flags6 & (RF6_S_HI_DEMON)) vp[vn++] = "summon greater demons";
- if (flags6 & (RF6_S_WRAITH)) vp[vn++] = "summon Ringwraith";
- if (flags6 & (RF6_S_UNIQUE)) vp[vn++] = "summon unique monsters";
-
- if (vn)
- {
- magic = TRUE;
- if (breath)
- {
- spoil_out(", and is also");
- }
- else
- {
- spoil_out(wd_che[msex]);
- spoil_out(" is");
- }
-
- spoil_out(" magical, casting spells");
- if (flags2 & (RF2_SMART)) spoil_out(" intelligently");
-
- for (i = 0; i < vn; i++)
- {
- if (!i) spoil_out(" which ");
- else if (i < vn - 1) spoil_out(", ");
- else spoil_out(" or ");
- spoil_out(vp[i]);
- }
- }
-
- if (breath || magic)
- {
- int times = r_ptr->freq_inate + r_ptr->freq_spell;
- sprintf(buf, "; 1 time in %d. ",
- 200 / ((times) ? times : 1));
- spoil_out(buf);
- }
-
- /* Collect special abilities. */
- vn = 0;
- if (flags2 & (RF2_OPEN_DOOR)) vp[vn++] = "open doors";
- if (flags2 & (RF2_BASH_DOOR)) vp[vn++] = "bash down doors";
- if (flags2 & (RF2_PASS_WALL)) vp[vn++] = "pass through walls";
- if (flags2 & (RF2_KILL_WALL)) vp[vn++] = "bore through walls";
- if (flags2 & (RF2_MOVE_BODY)) vp[vn++] = "push past weaker monsters";
- if (flags2 & (RF2_KILL_BODY)) vp[vn++] = "destroy weaker monsters";
- if (flags2 & (RF2_TAKE_ITEM)) vp[vn++] = "pick up objects";
- if (flags2 & (RF2_KILL_ITEM)) vp[vn++] = "destroy objects";
- if (flags9 & (RF9_HAS_LITE)) vp[vn++] = "illuminate the dungeon";
-
- if (vn)
- {
- spoil_out(wd_che[msex]);
- for (i = 0; i < vn; i++)
- {
- if (!i) spoil_out(" can ");
- else if (i < vn - 1) spoil_out(", ");
- else spoil_out(" and ");
- spoil_out(vp[i]);
- }
- spoil_out(". ");
- }
-
- if (flags2 & (RF2_INVISIBLE))
- {
- spoil_out(wd_che[msex]);
- spoil_out(" is invisible. ");
- }
- if (flags2 & (RF2_COLD_BLOOD))
- {
- spoil_out(wd_che[msex]);
- spoil_out(" is cold blooded. ");
- }
- if (flags2 & (RF2_EMPTY_MIND))
- {
- spoil_out(wd_che[msex]);
- spoil_out(" is not detected by telepathy. ");
- }
- if (flags2 & (RF2_WEIRD_MIND))
- {
- spoil_out(wd_che[msex]);
- spoil_out(" is rarely detected by telepathy. ");
- }
- if (flags4 & (RF4_MULTIPLY))
- {
- spoil_out(wd_che[msex]);
- spoil_out(" breeds explosively. ");
- }
- if (flags2 & (RF2_REGENERATE))
- {
- spoil_out(wd_che[msex]);
- spoil_out(" regenerates quickly. ");
- }
-
- /* Collect susceptibilities */
- vn = 0;
- if (flags3 & (RF3_HURT_ROCK)) vp[vn++] = "rock remover";
- if (flags3 & (RF3_HURT_LITE)) vp[vn++] = "bright light";
- if (flags3 & (RF3_SUSCEP_FIRE)) vp[vn++] = "fire";
- if (flags3 & (RF3_SUSCEP_COLD)) vp[vn++] = "cold";
-
- if (vn)
- {
- spoil_out(wd_che[msex]);
- for (i = 0; i < vn; i++)
- {
- if (!i) spoil_out(" is hurt by ");
- else if (i < vn - 1) spoil_out(", ");
- else spoil_out(" and ");
- spoil_out(vp[i]);
- }
- spoil_out(". ");
- }
-
- /* Collect immunities */
- vn = 0;
- if (flags3 & (RF3_IM_ACID)) vp[vn++] = "acid";
- if (flags3 & (RF3_IM_ELEC)) vp[vn++] = "lightning";
- if (flags3 & (RF3_IM_FIRE)) vp[vn++] = "fire";
- if (flags3 & (RF3_IM_COLD)) vp[vn++] = "cold";
- if (flags3 & (RF3_IM_POIS)) vp[vn++] = "poison";
-
- if (vn)
- {
- spoil_out(wd_che[msex]);
- for (i = 0; i < vn; i++)
- {
- if (!i) spoil_out(" resists ");
- else if (i < vn - 1) spoil_out(", ");
- else spoil_out(" and ");
- spoil_out(vp[i]);
- }
- spoil_out(". ");
- }
-
- /* Collect resistances */
- vn = 0;
- if (flags3 & (RF3_RES_NETH)) vp[vn++] = "nether";
- if (flags3 & (RF3_RES_WATE)) vp[vn++] = "water";
- if (flags3 & (RF3_RES_PLAS)) vp[vn++] = "plasma";
- if (flags3 & (RF3_RES_NEXU)) vp[vn++] = "nexus";
- if (flags3 & (RF3_RES_DISE)) vp[vn++] = "disenchantment";
- if (flags3 & (RF3_RES_TELE)) vp[vn++] = "teleportation";
-
- if (vn)
- {
- spoil_out(wd_che[msex]);
- for (i = 0; i < vn; i++)
- {
- if (!i) spoil_out(" resists ");
- else if (i < vn - 1) spoil_out(", ");
- else spoil_out(" and ");
- spoil_out(vp[i]);
- }
- spoil_out(". ");
- }
-
- /* Collect non-effects */
- vn = 0;
- if (flags3 & (RF3_NO_STUN)) vp[vn++] = "stunned";
- if (flags3 & (RF3_NO_FEAR)) vp[vn++] = "frightened";
- if (flags3 & (RF3_NO_CONF)) vp[vn++] = "confused";
- if (flags3 & (RF3_NO_SLEEP)) vp[vn++] = "slept";
-
- if (vn)
- {
- spoil_out(wd_che[msex]);
- for (i = 0; i < vn; i++)
- {
- if (!i) spoil_out(" cannot be ");
- else if (i < vn - 1) spoil_out(", ");
- else spoil_out(" or ");
- spoil_out(vp[i]);
- }
- spoil_out(". ");
- }
-
- spoil_out(wd_che[msex]);
- if (r_ptr->sleep > 200) spoil_out(" prefers to ignore");
- else if (r_ptr->sleep > 95) spoil_out(" pays very little attention to");
- else if (r_ptr->sleep > 75) spoil_out(" pays little attention to");
- else if (r_ptr->sleep > 45) spoil_out(" tends to overlook");
- else if (r_ptr->sleep > 25) spoil_out(" takes quite a while to see");
- else if (r_ptr->sleep > 10) spoil_out(" takes a while to see");
- else if (r_ptr->sleep > 5) spoil_out(" is fairly observant of");
- else if (r_ptr->sleep > 3) spoil_out(" is observant of");
- else if (r_ptr->sleep > 1) spoil_out(" is very observant of");
- else if (r_ptr->sleep > 0) spoil_out(" is vigilant for");
- else spoil_out(" is ever vigilant for");
-
- sprintf(buf, " intruders, which %s may notice from %d feet. ",
- wd_lhe[msex], 10 * r_ptr->aaf);
- spoil_out(buf);
-
- i = 0;
- if (flags1 & (RF1_DROP_60)) i += 1;
- if (flags1 & (RF1_DROP_90)) i += 2;
- if (flags1 & (RF1_DROP_1D2)) i += 2;
- if (flags1 & (RF1_DROP_2D2)) i += 4;
- if (flags1 & (RF1_DROP_3D2)) i += 6;
- if (flags1 & (RF1_DROP_4D2)) i += 8;
-
- /* Drops gold and/or items */
- if (i)
- {
- sin = FALSE;
- spoil_out(wd_che[msex]);
- spoil_out(" will carry");
-
- if (i == 1)
- {
- spoil_out(" a");
- sin = TRUE;
- }
- else if (i == 2)
- {
- spoil_out(" one or two");
- }
- else
- {
- sprintf(buf, " up to %u", i);
- spoil_out(buf);
- }
-
- if (flags1 & (RF1_DROP_GREAT))
- {
- if (sin) spoil_out("n");
- spoil_out(" exceptional object");
- }
- else if (flags1 & (RF1_DROP_GOOD))
- {
- spoil_out(" good object");
- }
- else if (flags1 & (RF1_DROP_USEFUL))
- {
- spoil_out(" useful object");
- }
- else if (flags1 & (RF1_ONLY_ITEM))
- {
- spoil_out(" object");
- }
- else if (flags1 & (RF1_ONLY_GOLD))
- {
- spoil_out(" treasure");
- }
- else
- {
- if (sin) spoil_out("n");
- spoil_out(" object");
- if (i > 1) spoil_out("s");
- spoil_out(" or treasure");
- }
- if (i > 1) spoil_out("s");
-
- if (flags1 & (RF1_DROP_CHOSEN))
- {
- spoil_out(", in addition to chosen objects");
- }
-
- spoil_out(". ");
- }
-
- /* Count the actual attacks */
- for (i = 0, j = 0; j < 4; j++)
- {
- if (r_ptr->blow[j].method) i++;
- }
-
- /* Examine the actual attacks */
- for (k = 0, j = 0; j < 4; j++)
- {
- if (!r_ptr->blow[j].method) continue;
-
- /* No method yet */
- p = "???";
-
- /* Acquire the method */
- switch (r_ptr->blow[j].method)
- {
- case RBM_HIT:
- p = "hit";
- break;
- case RBM_TOUCH:
- p = "touch";
- break;
- case RBM_PUNCH:
- p = "punch";
- break;
- case RBM_KICK:
- p = "kick";
- break;
- case RBM_CLAW:
- p = "claw";
- break;
- case RBM_BITE:
- p = "bite";
- break;
- case RBM_STING:
- p = "sting";
- break;
- case RBM_XXX1:
- break;
- case RBM_BUTT:
- p = "butt";
- break;
- case RBM_CRUSH:
- p = "crush";
- break;
- case RBM_ENGULF:
- p = "engulf";
- break;
- case RBM_CHARGE:
- p = "charge";
- break;
- case RBM_CRAWL:
- p = "crawl on you";
- break;
- case RBM_DROOL:
- p = "drool on you";
- break;
- case RBM_SPIT:
- p = "spit";
- break;
- case RBM_EXPLODE:
- p = "explode";
- break;
- case RBM_GAZE:
- p = "gaze";
- break;
- case RBM_WAIL:
- p = "wail";
- break;
- case RBM_SPORE:
- p = "release spores";
- break;
- case RBM_XXX4:
- break;
- case RBM_BEG:
- p = "beg";
- break;
- case RBM_INSULT:
- p = "insult";
- break;
- case RBM_MOAN:
- p = "moan";
- break;
- case RBM_SHOW:
- p = "sing";
- break;
- }
-
-
- /* Default effect */
- q = "???";
-
- /* Acquire the effect */
- switch (r_ptr->blow[j].effect)
- {
- case RBE_HURT:
- q = "attack";
- break;
- case RBE_POISON:
- q = "poison";
- break;
- case RBE_UN_BONUS:
- q = "disenchant";
- break;
- case RBE_UN_POWER:
- q = "drain charges";
- break;
- case RBE_EAT_GOLD:
- q = "steal gold";
- break;
- case RBE_EAT_ITEM:
- q = "steal items";
- break;
- case RBE_EAT_FOOD:
- q = "eat your food";
- break;
- case RBE_EAT_LITE:
- q = "absorb light";
- break;
- case RBE_ACID:
- q = "shoot acid";
- break;
- case RBE_ELEC:
- q = "electrocute";
- break;
- case RBE_FIRE:
- q = "burn";
- break;
- case RBE_COLD:
- q = "freeze";
- break;
- case RBE_BLIND:
- q = "blind";
- break;
- case RBE_CONFUSE:
- q = "confuse";
- break;
- case RBE_TERRIFY:
- q = "terrify";
- break;
- case RBE_PARALYZE:
- q = "paralyze";
- break;
- case RBE_LOSE_STR:
- q = "reduce strength";
- break;
- case RBE_LOSE_INT:
- q = "reduce intelligence";
- break;
- case RBE_LOSE_WIS:
- q = "reduce wisdom";
- break;
- case RBE_LOSE_DEX:
- q = "reduce dexterity";
- break;
- case RBE_LOSE_CON:
- q = "reduce constitution";
- break;
- case RBE_LOSE_CHR:
- q = "reduce charisma";
- break;
- case RBE_LOSE_ALL:
- q = "reduce all stats";
- break;
- case RBE_SHATTER:
- q = "shatter";
- break;
- case RBE_EXP_10:
- q = "lower experience (by 10d6+)";
- break;
- case RBE_EXP_20:
- q = "lower experience (by 20d6+)";
- break;
- case RBE_EXP_40:
- q = "lower experience (by 40d6+)";
- break;
- case RBE_EXP_80:
- q = "lower experience (by 80d6+)";
- break;
- case RBE_DISEASE:
- q = "disease";
- break;
- case RBE_TIME:
- q = "time";
- break;
- case RBE_SANITY:
- q = "make insane";
- break;
- case RBE_HALLU:
- q = "cause hallucinations";
- break;
- case RBE_PARASITE:
- q = "parasite";
- break;
- }
-
-
- if (!k)
- {
- spoil_out(wd_che[msex]);
- spoil_out(" can ");
- }
- else if (k < i - 1)
- {
- spoil_out(", ");
- }
- else
- {
- spoil_out(", and ");
- }
-
- /* Describe the method */
- spoil_out(p);
-
- /* Describe the effect, if any */
- if (r_ptr->blow[j].effect)
- {
- spoil_out(" to ");
- spoil_out(q);
- if (r_ptr->blow[j].d_dice && r_ptr->blow[j].d_side)
- {
- spoil_out(" with damage");
- if (r_ptr->blow[j].d_side == 1)
- sprintf(buf, " %d", r_ptr->blow[j].d_dice);
- else
- sprintf(buf, " %dd%d",
- r_ptr->blow[j].d_dice, r_ptr->blow[j].d_side);
- spoil_out(buf);
- }
- }
-
- k++;
- }
-
- if (k)
- {
- spoil_out(". ");
- }
- else if (flags1 & (RF1_NEVER_BLOW))
- {
- sprintf(buf, "%s has no physical attacks. ", wd_che[msex]);
- spoil_out(buf);
- }
-
- spoil_out(NULL);
- }
-
- /* Check for errors */
- if (ferror(fff) || my_fclose(fff))
- {
- msg_print("Cannot close spoiler file.");
- return;
- }
-
- msg_print("Successfully created a spoiler file.");
-}
-
-
-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"
- "They can be either found on the floor while exploring the dungeon, "
- "or extracted from other magical items the alchemist finds "
- "during their adventures.\n\n"
- "To create an artifact, the alchemist will have to sacrifice 10 hit points, "
- "and an amount of magic essence similar to his skill in alchemy. "
- "The alchemist then allows the artifact to gain experience, "
- "and when it has enough, "
- "uses that experience to add abilities to the artifact. "
- "The alchemist can allow the artifact to continue to gain experience, "
- "thus keeping open the option to add more abilities later. "
- "This requires a similar amount of magic essence, "
- "but does not require the sacrifice of other hit points.\n\n"
- "Note that the experience you gain is divided among the artifacts "
- "that you have as well as going to yourself, "
- "so you will gain levels more slowly when empowering artifacts. "
- "Also, the artifact only gets 60% of the experience. "
- "So killing a creature worth 20xp would gain 10 for you, "
- "and 6 for the artifact.\n\n"
- "You can also modify existing artifacts when you attain skill level 50. "
- "Also at skill level 50 you will gain the ability to make temporary artifacts, "
- "which don't require the complex empowerments that regular items require, "
- "but also vanish after awhile.\n\n"
- "You cannot give an artifact an ability "
- "unless you have *Identified* an artifact which has that ability.\n\n"
- "For every four levels gained in the alchemy skill, "
- "the alchemist learns about objects of level (skill level)/4, "
- "starting by learning about level 1 objects at skill level 0. "
- "(actually 1, but who's counting?)\n\n"
- "At skill level 5 you gain the ability to make ego items - but watch it! "
- "Your base failure rate will be 90%, "
- "and won't be 0% until you reach skill level 50. "
- "Adding gold will increase the chances of success "
- "in direct proportion to the value of the item you are trying to create. "
- "Note that this results in automatic success "
- "when the item you are trying to create "
- "happens to pick up a curse in the process.\n\n"
- "At skill level 5 you also gain knowledge of some basic ego item recipes. "
- "These are: Acidic, Shocking, Fiery, Frozen, Venomous, and Chaotic weapons, "
- "Resist Fire armour, and light sources of Fearlessness.\n\n"
- "At skill level 10 you will gain knowledge of digging ego items, "
- "if you have selected the option "
- "'always generate very unusual rooms' (ironman_rooms).\n\n"
- "At skill level 15 you can create ego wands, staves, rings, etc.\n\n"
- "At skill level 25 you gain the ability to empower artifacts "
- "and double ego items.\n\n"
- "At skill level 50 you gain the ability to create temporary artifacts, "
- "which don't require any exotic ingredients "
- "beyond a single corpse of any type.\n\n"
- "Between skill levels 25 and 50, "
- "you will steadily gain the ability to set more and more flags.\n\n"
- "To finalise an artifact, you 'P'ower it, and select the powers you want.\n"
- "Powers are divided into the following six categories:\n"
- "*****essences.txt*03[Stats, Sustains, Luck, Speed, Vision, etc.]\n"
- "*****essences.txt*04[Misc. (Auras, Light, See Invisibility, etc.)]\n"
- "*****essences.txt*05[Weapon Brands]\n"
- "*****essences.txt*06[Resistances and Immunities]\n"
- "*****essences.txt*07[ESP and Curses]\n"
- "*****essences.txt*08[Artifact Activations]\n";
-
-/*
- * Create a spoiler file for essences
- */
-static void spoil_bateries(cptr fname)
-{
- int j, i, tval, sval, group;
- object_type forge, *o_ptr;
-
- char buf[1024];
-
- tval = sval = group = -1;
-
- /* Build the filename */
- path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname);
-
- /* File type is "TEXT" */
- FILE_TYPE(FILE_TYPE_TEXT);
-
- fff = my_fopen(buf, "w");
-
- /* Oops */
- if (!fff)
- {
- msg_print("Cannot create spoiler file.");
- return;
- }
-
- /* Dump the header */
-
- fprintf(fff,
- "|||||oy\n"
- "~~~~~01|Spoilers|Essences\n"
- "~~~~~02|Alchemist|Essence Spoiler\n"
- "#####REssence Spoiler for %s\n"
- "#####R-----------------------------------\n\n",
- get_version_string());
-
-
- /*New code starts here -*/
- /*print header, including artifact header*/
- /*Cycle through artifact flags*/
- /* print desc*/
- /* cycle through all alchemist_recipies*/
- /* print matching*/
- /*Print items header.*/
- /*Cycle through alchemist_recipies*/
- /* sval or tval changed?*/
- /* skip artifacts (tval=0)*/
- /* print item desc (ego (tval=1) or item)*/
- /* print essences required*/
- /*Done!*/
-
- /*Print basic header.*/
- spoil_out(long_intro);
-
- /*Cycle through artifact flags*/
- for ( i = 0 ; a_select_flags[i].group ; i++ )
- {
- if ( a_select_flags[i].group != group )
- {
- group = a_select_flags[i].group;
- spoil_out("\n~~~~~");
- switch (group)
- {
- case 1:
- spoil_out("03\n#####GStats, Sustains, Luck, Speed, Vision, etc.\n");
- break;
- case 2:
- spoil_out("04\n#####GMisc. (Auras, Light, See Invisibility, etc.)\n");
- break;
- case 3:
- spoil_out("05\n#####GWeapon Brands\n");
- break;
- case 4:
- spoil_out("06\n#####GResistances and Immunities\n");
- break;
- case 5:
- spoil_out("07\n#####GESP and Curses\n");
- break;
- case 88:
- spoil_out("08\n#####GArtifact Activations\n");
- break;
- default:
- spoil_out(format("09\n#####GExtra Group=%d\n", group));
- }
- spoil_out("lvl xp Power\n");
-
- }
- /* print desc*/
- spoil_out(format("%-2d %8d %-24s %s\n",
- a_select_flags[i].level,
- a_select_flags[i].xp,
- al_name + a_select_flags[i].desc,
- al_name + a_select_flags[i].item_desc));
- /* cycle through all alchemist_recipies*/
- for ( j = 0 ; j < max_al_idx ; j++ )
- {
- /* print matching*/
- if (alchemist_recipes[j].tval == 0
- && alchemist_recipes[j].sval == a_select_flags[i].flag
- && alchemist_recipes[j].qty
- )
- {
- spoil_out(format(" %d essences of %s\n", alchemist_recipes[j].qty,
- k_name + k_info[lookup_kind(TV_BATERIE, alchemist_recipes[j].sval_essence)].name));
- }
- }
- }
-
- spoil_out("\n\nThe following basic item recipes also exist:\n");
- /*Cycle through alchemist_recipies*/
- for ( i = 0 ; i < max_al_idx ; i ++)
- {
- alchemist_recipe *ar_ptr = &alchemist_recipes[i];
-
- /* sval or tval changed?*/
- if (tval != ar_ptr->tval || sval != ar_ptr->sval)
- {
- char o_name[80];
- /* skip artifacts (tval=0)*/
- if (ar_ptr->tval == 0 )
- continue;
-
- tval = ar_ptr->tval;
- sval = ar_ptr->sval;
-
- /* print item desc (ego (tval=1)or item)*/
- if (ar_ptr->tval == 1)
- {
- strcpy(o_name, e_name + e_info[ar_ptr->sval].name);
- }
- else
- {
- /* Find the name of that object */
- o_ptr = &forge;
- object_wipe(o_ptr);
- object_prep(o_ptr, lookup_kind(tval, sval));
- apply_magic(o_ptr, 1, FALSE, FALSE, FALSE);
- object_aware(o_ptr);
- object_known(o_ptr);
- o_ptr->name2 = o_ptr->name2b = 0;
- /* the 0 mode means only the text, leaving off any numbers */
- object_desc(o_name, o_ptr, FALSE, 0);
- }
- spoil_out("\n");
- spoil_out(o_name);
- }
- /* print essence required*/
- spoil_out(format(" %d %s", ar_ptr->qty,
- k_name + k_info[lookup_kind(TV_BATERIE, ar_ptr->sval_essence)].name));
- }
-
- spoil_out(NULL);
-
- /* Check for errors */
- if (ferror(fff) || my_fclose(fff))
- {
- msg_print("Cannot close spoiler file.");
- return;
- }
-
- /* Message */
- msg_print("Successfully created a spoiler file.");
- return;
-}
-
-
-/*
- * Print a bookless spell list
- */
-void print_magic_powers( magic_power *powers, int max_powers, void(*power_info)(char *p, int power), int skill_num )
-{
- int i, save_skill;
-
- char buf[80];
-
- magic_power spell;
-
- /* Use a maximal skill */
- save_skill = s_info[skill_num].value;
- s_info[skill_num].value = SKILL_MAX;
-
- /* Dump the header line */
- spoiler_blanklines(2);
- sprintf(buf, "%s", s_info[skill_num].name + s_name);
- spoiler_underline(buf);
- spoiler_blanklines(1);
-
- fprintf(fff, " Name Lvl Mana Fail Info\n");
-
- /* Dump the spells */
- for (i = 0; i < max_powers; i++)
- {
- /* Access the spell */
- spell = powers[i];
-
- /* Get the additional info */
- power_info(buf, i);
-
- /* Dump the spell */
- spoil_out(format("%c) %-30s%2d %4d %3d%%%s\n",
- I2A(i), spell.name,
- spell.min_lev, spell.mana_cost, spell.fail, buf));
- spoil_out(format("%s\n", spell.desc));
- }
-
- /* Restore skill */
- s_info[skill_num].value = save_skill;
-}
-
-
-/*
- * Create a spoiler file for spells
- */
-
-static void spoil_spells(cptr fname)
-{
- char buf[1024];
-
- /* Build the filename */
- path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname);
-
- /* File type is "TEXT" */
- FILE_TYPE(FILE_TYPE_TEXT);
-
- fff = my_fopen(buf, "w");
-
- /* Oops */
- if (!fff)
- {
- msg_print("Cannot create spoiler file.");
- return;
- }
-
- /* Dump the header */
- sprintf(buf, "Spell Spoiler (Skill Level 50) for %s", get_version_string());
- spoiler_underline(buf);
-
- /* Dump the bookless magic powers in alphabetical order */
-
- /* Mimicry */
- print_magic_powers(mimic_powers, MAX_MIMIC_POWERS, mimic_info, SKILL_MIMICRY);
-
- /* Mindcraft */
- print_magic_powers(mindcraft_powers, MAX_MINDCRAFT_POWERS, mindcraft_info, SKILL_MINDCRAFT);
-
- /* Necromancy */
- print_magic_powers(necro_powers, MAX_NECRO_POWERS, necro_info, SKILL_NECROMANCY);
-
- /* Symbiosis */
- print_magic_powers(symbiotic_powers, MAX_SYMBIOTIC_POWERS, symbiotic_info, SKILL_SYMBIOTIC);
-
- /* Check for errors */
- if (ferror(fff) || my_fclose(fff))
- {
- msg_print("Cannot close spoiler file.");
- return;
- }
-
- /* Message */
- msg_print("Successfully created a spoiler file.");
-}
-
-
-
-/*
- * Forward declare
- */
-extern void do_cmd_spoilers(void);
-
-/*
- * Create Spoiler files -BEN-
- */
-void do_cmd_spoilers(void)
-{
- int i;
-
-
- /* Enter "icky" mode */
- character_icky = TRUE;
-
- /* Save the screen */
- Term_save();
-
- /* Interact */
- while (1)
- {
- /* Clear screen */
- Term_clear();
-
- /* Info */
- prt("Create a spoiler file.", 2, 0);
-
- /* Prompt for a file */
- prt("(1) Brief Object Info (obj-desc.spo)", 5, 5);
- prt("(2) Full Artifact Info (artifact.spo)", 6, 5);
- prt("(3) Brief Monster Info (mon-desc.spo)", 7, 5);
- prt("(4) Full Monster Info (mon-info.spo)", 8, 5);
- prt("(5) Full Essences Info (ess-info.spo)", 9, 5);
- prt("(6) Spell Info (spell.spo)", 10, 5);
-
- /* Prompt */
- prt("Command: ", 12, 0);
-
- /* Get a choice */
- i = inkey();
-
- /* Escape */
- if (i == ESCAPE)
- {
- break;
- }
-
- /* Option (1) */
- else if (i == '1')
- {
- spoil_obj_desc("obj-desc.spo");
- }
-
- /* Option (2) */
- else if (i == '2')
- {
- spoil_artifact("artifact.spo");
- }
-
- /* Option (3) */
- else if (i == '3')
- {
- spoil_mon_desc("mon-desc.spo");
- }
-
- /* Option (4) */
- else if (i == '4')
- {
- spoil_mon_info("mon-info.spo");
- }
-
- /* Option (5) */
- else if (i == '5')
- {
- spoil_bateries("ess-info.spo");
- }
-
- /* Option (6) */
- else if (i == '6')
- {
- spoil_spells("spell.spo");
- }
-
- /* Oops */
- else
- {
- bell();
- }
-
- /* Flush messages */
- msg_print(NULL);
- }
-
-
- /* Restore the screen */
- Term_load();
-
- /* Leave "icky" mode */
- character_icky = FALSE;
-}
diff --git a/src/wizard2.c b/src/wizard2.cc
index a19b72e0..890c6fbe 100644
--- a/src/wizard2.c
+++ b/src/wizard2.cc
@@ -1,7 +1,3 @@
-/* File: wizard2.c */
-
-/* Purpose: Wizard commands */
-
/*
* Copyright (c) 1989 James E. Wilson, Robert A. Koeneke
*
@@ -10,15 +6,46 @@
* included in all such copies.
*/
-#include "angband.h"
-
-void do_cmd_wizard_body(s16b);
-extern void status_main(void);
+#include "wizard2.hpp"
+
+#include "artifact_type.hpp"
+#include "birth.hpp"
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "cmd4.hpp"
+#include "corrupt.hpp"
+#include "dungeon_info_type.hpp"
+#include "files.hpp"
+#include "game.hpp"
+#include "hooks.hpp"
+#include "monster2.hpp"
+#include "monster_race.hpp"
+#include "monster_type.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_flag.hpp"
+#include "object_flag_meta.hpp"
+#include "object_kind.hpp"
+#include "player_type.hpp"
+#include "randart.hpp"
+#include "spells1.hpp"
+#include "spells2.hpp"
+#include "stats.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "util.h"
+#include "variable.h"
+#include "variable.hpp"
+#include "wilderness_map.hpp"
+#include "wilderness_type_info.hpp"
+#include "xtra1.hpp"
+#include "xtra2.hpp"
+#include "z-rand.hpp"
/*
* Adds a lvl to a monster
*/
-void wiz_inc_monster_level(int level)
+static void wiz_inc_monster_level(int level)
{
monster_type *m_ptr;
int ii, jj;
@@ -29,12 +56,12 @@ void wiz_inc_monster_level(int level)
{
m_ptr = &m_list[cave[jj][ii].m_idx];
- m_ptr->exp = MONSTER_EXP(m_ptr->level + level);
+ m_ptr->exp = monster_exp(m_ptr->level + level);
monster_check_experience(cave[jj][ii].m_idx, FALSE);
}
}
-void wiz_align_monster(int status)
+static void wiz_align_monster(int status)
{
monster_type *m_ptr;
int ii, jj;
@@ -52,9 +79,9 @@ void wiz_align_monster(int status)
/*
* Teleport directly to a town
*/
-void teleport_player_town(int town)
+static void teleport_player_town(int town)
{
- int x = 0, y = 0;
+ auto const &wf_info = game->edit_data.wf_info;
autosave_checkpoint();
@@ -62,58 +89,48 @@ void teleport_player_town(int town)
dun_level = 0;
p_ptr->town_num = town;
- for (x = 0; x < max_wild_x; x++)
- for (y = 0; y < max_wild_y; y++)
- if (p_ptr->town_num == wf_info[wild_map[y][x].feat].entrance) goto finteletown;
-finteletown:
- p_ptr->wilderness_y = y;
- p_ptr->wilderness_x = x;
+ auto const &wilderness = game->wilderness;
+ for (std::size_t y = 0; y < wilderness.height(); y++)
+ {
+ for (std::size_t x = 0; x < wilderness.width(); x++)
+ {
+ if (p_ptr->town_num == wf_info[wilderness(x, y).feat].entrance)
+ {
+ p_ptr->wilderness_y = y;
+ p_ptr->wilderness_x = x;
- p_ptr->inside_arena = 0;
- leaving_quest = p_ptr->inside_quest;
- p_ptr->inside_quest = 0;
+ leaving_quest = p_ptr->inside_quest;
+ p_ptr->inside_quest = 0;
- /* Leaving */
- p_ptr->leaving = TRUE;
+ /* Leaving */
+ p_ptr->leaving = TRUE;
+
+ // Done
+ return;
+ }
+ }
+ }
}
/*
* Hack -- Rerate Hitpoints
*/
-void do_cmd_rerate(void)
+void do_cmd_rerate()
{
- int min_value, max_value, i, percent;
-
- min_value = (PY_MAX_LEVEL * 3 * (p_ptr->hitdie - 1)) / 8;
- min_value += PY_MAX_LEVEL;
-
- max_value = (PY_MAX_LEVEL * 5 * (p_ptr->hitdie - 1)) / 8;
- max_value += PY_MAX_LEVEL;
-
- player_hp[0] = p_ptr->hitdie;
+ auto &player_hp = game->player_hp;
- /* Rerate */
- while (1)
- {
- /* Collect values */
- for (i = 1; i < PY_MAX_LEVEL; i++)
- {
- player_hp[i] = randint(p_ptr->hitdie);
- player_hp[i] += player_hp[i - 1];
- }
-
- /* Legal values */
- if ((player_hp[PY_MAX_LEVEL - 1] >= min_value) &&
- (player_hp[PY_MAX_LEVEL - 1] <= max_value)) break;
- }
+ // Force HP re-roll
+ roll_player_hp();
- percent = (int)(((long)player_hp[PY_MAX_LEVEL - 1] * 200L) /
+ // Calculate life rating
+ int percent = static_cast<int>(
+ (static_cast<long>(player_hp[PY_MAX_LEVEL - 1]) * 200L) /
(p_ptr->hitdie + ((PY_MAX_LEVEL - 1) * p_ptr->hitdie)));
/* Update and redraw hitpoints */
p_ptr->update |= (PU_HP);
- p_ptr->redraw |= (PR_HP);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
@@ -132,20 +149,24 @@ void do_cmd_rerate(void)
*/
static void wiz_create_named_art()
{
+ auto const &a_info = game->edit_data.a_info;
+
object_type forge;
object_type *q_ptr;
int i, a_idx;
- cptr p = "Number of the artifact :";
+ cptr p = "Number of the artifact: ";
char out_val[80] = "";
- artifact_type *a_ptr;
if (!get_string(p, out_val, 4)) return;
a_idx = atoi(out_val);
/* Return if out-of-bounds */
- if ((a_idx <= 0) || (a_idx >= max_a_idx)) return;
+ if ((a_idx <= 0) || (a_idx >= static_cast<int>(a_info.size())))
+ {
+ return;
+ }
- a_ptr = &a_info[a_idx];
+ auto a_ptr = &a_info[a_idx];
/* Get local object */
q_ptr = &forge;
@@ -170,6 +191,9 @@ static void wiz_create_named_art()
apply_magic(q_ptr, -1, TRUE, TRUE, TRUE);
+ /* Apply any random resistances/powers */
+ random_artifact_resistance(q_ptr);
+
/* Identify it fully */
object_aware(q_ptr);
object_known(q_ptr);
@@ -184,45 +208,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 */
static void do_cmd_summon_horde()
{
@@ -235,42 +220,14 @@ static void do_cmd_summon_horde()
if (cave_naked_bold(wy, wx)) break;
}
- (void)alloc_horde(wy, wx);
-}
-
-#endif /* MONSTER_HORDES */
-
-
-/*
- * Output a long int in binary format.
- */
-static void prt_binary(u32b flags, int row, int col)
-{
- int i;
- u32b bitmask;
-
- /* Scan the flags */
- for (i = bitmask = 1; i <= 32; i++, bitmask *= 2)
- {
- /* Dump set bits */
- if (flags & bitmask)
- {
- Term_putch(col++, row, TERM_BLUE, '*');
- }
-
- /* Dump unset bits */
- else
- {
- Term_putch(col++, row, TERM_WHITE, '-');
- }
- }
+ alloc_horde(wy, wx);
}
/*
* Hack -- Teleport to the target
*/
-static void do_cmd_wiz_bamf(void)
+static void do_cmd_wiz_bamf()
{
/* Must have a target */
if (!target_who) return;
@@ -283,7 +240,7 @@ static void do_cmd_wiz_bamf(void)
/*
* Aux function for "do_cmd_wiz_change()". -RAK-
*/
-static void do_cmd_wiz_change_aux(void)
+static void do_cmd_wiz_change_aux()
{
int i;
int tmp_int;
@@ -351,6 +308,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);
@@ -369,7 +343,7 @@ static void do_cmd_wiz_change_aux(void)
/*
* Change various "permanent" player variables.
*/
-static void do_cmd_wiz_change(void)
+static void do_cmd_wiz_change()
{
/* Interact */
do_cmd_wiz_change_aux();
@@ -442,12 +416,13 @@ static void do_cmd_wiz_change(void)
*/
static void wiz_display_item(object_type *o_ptr)
{
+ auto const &k_info = game->edit_data.k_info;
+
int i, j = 13;
- u32b f1, f2, f3, f4, f5, esp;
char buf[256];
/* Extract the flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ auto const flags = object_flags(o_ptr);
/* Clear the screen */
for (i = 1; i <= 23; i++) prt("", i, j - 2);
@@ -474,106 +449,44 @@ static void wiz_display_item(object_type *o_ptr)
prt(format("ident = %04x timeout = %-d",
o_ptr->ident, o_ptr->timeout), 8, j);
- prt("+------------FLAGS1------------+", 10, j);
- prt("AFFECT........SLAY........BRAND.", 11, j);
- prt(" cvae xsqpaefc", 12, j);
- prt("siwdcc ssidsahanvudotgddhuoclio", 13, j);
- prt("tnieoh trnipttmiinmrrnrrraiierl", 14, j);
- prt("rtsxna..lcfgdkcpmldncltggpksdced", 15, j);
- prt_binary(f1, 16, j);
-
- prt("+------------FLAGS2------------+", 17, j);
- prt("SUST....IMMUN.RESIST............", 18, j);
- prt(" aefcprpsaefcpfldbc sn ", 19, j);
- prt("siwdcc cliooeatcliooeialoshtncd", 20, j);
- prt("tnieoh ierlifraierliatrnnnrhehi", 21, j);
- prt("rtsxna..dcedslatdcedsrekdfddrxss", 22, j);
- prt_binary(f2, 23, j);
-
- prt("+------------FLAGS3------------+", 10, j + 32);
- prt("fe ehsi st iiiiadta hp", 11, j + 32);
- prt("il n taihnf ee ggggcregb vr", 12, j + 32);
- prt("re nowysdose eld nnnntalrl ym", 13, j + 32);
- prt("ec omrcyewta ieirmsrrrriieaeccc", 14, j + 32);
- prt("aa taauktmatlnpgeihaefcvnpvsuuu", 15, j + 32);
- prt("uu egirnyoahivaeggoclioaeoasrrr", 16, j + 32);
- prt("rr litsopdretitsehtierltxrtesss", 17, j + 32);
- prt("aa echewestreshtntsdcedeptedeee", 18, j + 32);
- prt_binary(f3, 19, j + 32);
+ /* Print all the flags which are set */
+ prt("Flags:", 10, j);
+
+ int const row0 = 11;
+ int row = row0;
+ int col = 0;
+ for (auto const &object_flag_meta: object_flags_meta())
+ {
+ // Is the flag set?
+ if (object_flag_meta->flag_set & flags)
+ {
+ // Advance to next row/column
+ row += 1;
+ if (row >= 23) {
+ row = row0 + 1;
+ col += 1;
+ }
+ // Display
+ prt(object_flag_meta->name, row, j + 1 + 20 * col);
+ }
+ }
}
-/*
- * A list of tvals and their textual names
- */
-tval_desc2 tvals[] =
-{
- { TV_SWORD, "Sword" },
- { TV_POLEARM, "Polearm" },
- { TV_HAFTED, "Hafted Weapon" },
- { TV_AXE, "Axe" },
- { TV_BOW, "Bow" },
- { TV_BOOMERANG, "Boomerang" },
- { TV_ARROW, "Arrows" },
- { TV_BOLT, "Bolts" },
- { TV_SHOT, "Shots" },
- { TV_SHIELD, "Shield" },
- { TV_CROWN, "Crown" },
- { TV_HELM, "Helm" },
- { TV_GLOVES, "Gloves" },
- { TV_BOOTS, "Boots" },
- { TV_CLOAK, "Cloak" },
- { TV_DRAG_ARMOR, "Dragon Scale Mail" },
- { TV_HARD_ARMOR, "Hard Armor" },
- { TV_SOFT_ARMOR, "Soft Armor" },
- { TV_RING, "Ring" },
- { TV_AMULET, "Amulet" },
- { TV_LITE, "Lite" },
- { TV_POTION, "Potion" },
- { TV_POTION2, "Potion" },
- { TV_SCROLL, "Scroll" },
- { TV_WAND, "Wand" },
- { TV_STAFF, "Staff" },
- { TV_ROD_MAIN, "Rod" },
- { TV_ROD, "Rod Tip" },
- { TV_BOOK, "Schools Spellbook", },
- { TV_SYMBIOTIC_BOOK, "Symbiotic Spellbook", },
- { TV_DRUID_BOOK, "Elemental Stone" },
- { TV_MUSIC_BOOK, "Music Book" },
- { TV_DAEMON_BOOK, "Daemon Book" },
- { TV_SPIKE, "Spikes" },
- { TV_DIGGING, "Digger" },
- { TV_CHEST, "Chest" },
- { TV_FOOD, "Food" },
- { TV_FLASK, "Flask" },
- { TV_MSTAFF, "Mage Staff" },
- { TV_BATERIE, "Essence" },
- { TV_PARCHMENT, "Parchment" },
- { TV_INSTRUMENT, "Musical Instrument" },
- { TV_RUNE1, "Rune 1" },
- { TV_RUNE2, "Rune 2" },
- { TV_JUNK, "Junk" },
- { TV_TRAPKIT, "Trapping Kit" },
- { 0, NULL }
-};
-
/*
* Strip an "object name" into a buffer
*/
-static void strip_name(char *buf, int k_idx)
+static void strip_name(char *buf, const object_kind *k_ptr)
{
- char *t;
-
- object_kind *k_ptr = &k_info[k_idx];
-
- cptr str = (k_name + k_ptr->name);
+ cptr str = k_ptr->name;
/* Skip past leading characters */
while ((*str == ' ') || (*str == '&')) str++;
/* Copy useful chars */
+ char *t;
for (t = buf; *str; str++)
{
if (*str != '~') *t++ = *str;
@@ -621,16 +534,16 @@ static void wci_string(cptr string, int num)
*
* List up to 50 choices in three columns
*/
-static int wiz_create_itemtype(void)
+static int wiz_create_itemtype()
{
- int i, num, max_num;
+ auto const &k_info = game->edit_data.k_info;
+
+ int num, max_num;
int tval;
cptr tval_desc2;
char ch;
- int choice[60];
-
char buf[160];
@@ -669,29 +582,32 @@ static int wiz_create_itemtype(void)
Term_clear();
/* We have to search the whole itemlist. */
- for (num = 0, i = 1; (num < 60) && (i < max_k_idx); i++)
+ std::vector<std::size_t> choice;
+ choice.reserve(60);
+ std::size_t i;
+ for (i = 1; (choice.size() < 60) && (i < k_info.size()); i++)
{
- object_kind *k_ptr = &k_info[i];
+ auto k_ptr = &k_info[i];
/* Analyze matching items */
if (k_ptr->tval == tval)
{
/* Hack -- Skip instant artifacts */
- if (k_ptr->flags3 & (TR3_INSTA_ART)) continue;
+ if (k_ptr->flags & TR_INSTA_ART) continue;
- /* Acquire the "name" of object "i" */
- strip_name(buf, i);
+ /* Acquire the "name" of object */
+ strip_name(buf, k_ptr);
/* Print it */
- wci_string(buf, num);
+ wci_string(buf, choice.size());
/* Remember the object index */
- choice[num++] = i;
+ choice.push_back(i);
}
}
/* Me need to know the maximal possible remembered object_index */
- max_num = num;
+ max_num = choice.size();
/* Choose! */
if (!get_com(format("What Kind of %s? ", tval_desc2), &ch)) return (0);
@@ -717,10 +633,9 @@ static void wiz_tweak_item(object_type *o_ptr)
{
cptr p;
char tmp_val[80];
- u32b f1, f2, f3, f4, f5, esp;
/* Extract the flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ auto const flags = object_flags(o_ptr);
p = "Enter new 'pval' setting: ";
@@ -782,7 +697,7 @@ static void wiz_tweak_item(object_type *o_ptr)
if (!get_string(p, tmp_val, 9)) return;
wiz_display_item(o_ptr);
o_ptr->exp = atoi(tmp_val);
- if (f4 & TR4_LEVELS) check_experience_obj(o_ptr);
+ if (flags & TR_LEVELS) check_experience_obj(o_ptr);
p = "Enter new 'timeout' setting: ";
sprintf(tmp_val, "%d", o_ptr->timeout);
@@ -806,7 +721,7 @@ static void wiz_reroll_item(object_type *o_ptr)
/* Hack -- leave artifacts alone */
- if (artifact_p(o_ptr) || o_ptr->art_name) return;
+ if (artifact_p(o_ptr)) return;
/* Get local object */
@@ -840,8 +755,7 @@ static void wiz_reroll_item(object_type *o_ptr)
else if (ch == 'b' || ch == 'B')
{
object_prep(q_ptr, o_ptr->k_idx);
- hack_apply_magic_power = -2;
- apply_magic(q_ptr, dun_level, FALSE, FALSE, FALSE);
+ apply_magic(q_ptr, dun_level, FALSE, FALSE, FALSE, boost::make_optional(-2));
}
/* Apply normal magic, but first clear object */
@@ -910,26 +824,21 @@ static void wiz_reroll_item(object_type *o_ptr)
*/
static void wiz_statistics(object_type *o_ptr)
{
+ auto &a_info = game->edit_data.a_info;
+ auto &random_artifacts = game->random_artifacts;
+
long i, matches, better, worse, other;
char ch;
- char *quality;
+ const char *quality;
bool_ good, great;
object_type forge;
object_type *q_ptr;
- obj_theme theme;
-
cptr q = "Rolls: %ld, Matches: %ld, Better: %ld, Worse: %ld, Other: %ld";
- /* We can have everything */
- theme.treasure = OBJ_GENE_TREASURE;
- theme.combat = OBJ_GENE_COMBAT;
- theme.magic = OBJ_GENE_MAGIC;
- theme.tools = OBJ_GENE_TOOL;
-
/* XXX XXX XXX Mega-Hack -- allow multiple artifacts */
if (artifact_p(o_ptr))
{
@@ -994,11 +903,8 @@ static void wiz_statistics(object_type *o_ptr)
/* Output every few rolls */
if ((i < 100) || (i % 100 == 0))
{
- /* Do not wait */
- inkey_scan = TRUE;
-
/* Allow interupt */
- if (inkey())
+ if (inkey_scan())
{
/* Flush */
flush();
@@ -1020,7 +926,7 @@ static void wiz_statistics(object_type *o_ptr)
object_wipe(q_ptr);
/* Create an object */
- make_object(q_ptr, good, great, theme);
+ make_object(q_ptr, good, great, obj_theme::defaults());
/* XXX XXX XXX Mega-Hack -- allow multiple artifacts */
@@ -1131,32 +1037,24 @@ static void wiz_quantity_item(object_type *o_ptr)
* - Change properties (via wiz_tweak_item)
* - Change the number of items (via wiz_quantity_item)
*/
-static void do_cmd_wiz_play(void)
+static void do_cmd_wiz_play()
{
- int item;
-
- object_type forge;
- object_type *q_ptr;
-
- object_type *o_ptr;
-
- char ch;
-
- bool_ changed;
-
- cptr q, s;
-
/* Get an item */
- q = "Play with which object? ";
- s = "You have nothing to play with.";
- if (!get_item(&item, q, s, (USE_EQUIP | USE_INVEN | USE_FLOOR))) return;
+ int item;
+ if (!get_item(&item,
+ "Play with which object? ",
+ "You have nothing to play with.",
+ (USE_EQUIP | USE_INVEN | USE_FLOOR)))
+ {
+ return;
+ }
/* Get the item */
- o_ptr = get_object(item);
+ object_type *o_ptr = get_object(item);
/* The item was not changed */
- changed = FALSE;
+ bool_ changed = FALSE;
/* Icky */
@@ -1167,7 +1065,8 @@ static void do_cmd_wiz_play(void)
/* Get local object */
- q_ptr = &forge;
+ object_type forge;
+ object_type *q_ptr = &forge;
/* Copy object */
object_copy(q_ptr, o_ptr);
@@ -1176,6 +1075,8 @@ static void do_cmd_wiz_play(void)
/* The main loop */
while (TRUE)
{
+ char ch;
+
/* Display the item */
wiz_display_item(q_ptr);
@@ -1267,7 +1168,7 @@ static void do_cmd_wiz_play(void)
* Hack -- this routine always makes a "dungeon object", and applies
* magic to it, and attempts to decline cursed items.
*/
-static void wiz_create_item(void)
+static void wiz_create_item()
{
object_type forge;
object_type *q_ptr;
@@ -1313,25 +1214,28 @@ static void wiz_create_item(void)
/*
* As above, but takes the k_idx as a parameter instead of using menus.
*/
-static void wiz_create_item_2(void)
+static void wiz_create_item_2()
{
- object_type forge;
- object_type *q_ptr;
- int a_idx;
+ auto const &k_info = game->edit_data.k_info;
+
cptr p = "Number of the object :";
char out_val[80] = "";
if (!get_string(p, out_val, 4)) return;
- a_idx = atoi(out_val);
+ int k_idx = atoi(out_val);
/* Return if failed or out-of-bounds */
- if ((a_idx <= 0) || (a_idx >= max_k_idx)) return;
+ if ((k_idx <= 0) || (k_idx >= static_cast<int>(k_info.size())))
+ {
+ return;
+ }
/* Get local object */
- q_ptr = &forge;
+ object_type forge;
+ auto q_ptr = &forge;
/* Create the item */
- object_prep(q_ptr, a_idx);
+ object_prep(q_ptr, k_idx);
/* Apply magic (no messages, no artifacts) */
apply_magic(q_ptr, dun_level, FALSE, FALSE, FALSE);
@@ -1347,23 +1251,23 @@ static void wiz_create_item_2(void)
/*
* Cure everything instantly
*/
-void do_cmd_wiz_cure_all(void)
+void do_cmd_wiz_cure_all()
{
object_type *o_ptr;
/* Remove curses */
- (void)remove_all_curse();
+ remove_all_curse();
/* Restore stats */
- (void)res_stat(A_STR, TRUE);
- (void)res_stat(A_INT, TRUE);
- (void)res_stat(A_WIS, TRUE);
- (void)res_stat(A_CON, TRUE);
- (void)res_stat(A_DEX, TRUE);
- (void)res_stat(A_CHR, TRUE);
+ res_stat(A_STR, TRUE);
+ res_stat(A_INT, TRUE);
+ res_stat(A_WIS, TRUE);
+ res_stat(A_CON, TRUE);
+ res_stat(A_DEX, TRUE);
+ res_stat(A_CHR, TRUE);
/* Restore the level */
- (void)restore_level();
+ restore_level();
/* Heal the player */
p_ptr->chp = p_ptr->mhp;
@@ -1386,19 +1290,19 @@ void do_cmd_wiz_cure_all(void)
p_ptr->csp_frac = 0;
/* Cure stuff */
- (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);
- (void)set_slow(0);
+ set_blind(0);
+ set_confused(0);
+ set_poisoned(0);
+ set_afraid(0);
+ set_paralyzed(0);
+ set_image(0);
+ set_stun(0);
+ set_cut(0);
+ set_slow(0);
p_ptr->black_breath = FALSE;
/* No longer hungry */
- (void)set_food(PY_FOOD_MAX - 1);
+ set_food(PY_FOOD_MAX - 1);
/* Redraw everything */
do_cmd_redraw();
@@ -1408,8 +1312,10 @@ void do_cmd_wiz_cure_all(void)
/*
* Go to any level
*/
-static void do_cmd_wiz_jump(void)
+static void do_cmd_wiz_jump()
{
+ auto const &d_info = game->edit_data.d_info;
+
/* Ask for level */
if (command_arg <= 0)
{
@@ -1445,7 +1351,6 @@ static void do_cmd_wiz_jump(void)
/* Change level */
dun_level = command_arg;
- p_ptr->inside_arena = 0;
leaving_quest = p_ptr->inside_quest;
p_ptr->inside_quest = 0;
@@ -1458,23 +1363,21 @@ static void do_cmd_wiz_jump(void)
/*
* Become aware of a lot of objects
*/
-static void do_cmd_wiz_learn(void)
+static void do_cmd_wiz_learn()
{
- int i;
-
- object_type forge;
- object_type *q_ptr;
+ auto const &k_info = game->edit_data.k_info;
/* Scan every object */
- for (i = 1; i < max_k_idx; i++)
+ for (std::size_t i = 0; i < k_info.size(); i++)
{
- object_kind *k_ptr = &k_info[i];
+ auto k_ptr = &k_info[i];
/* Induce awareness */
if (k_ptr->level <= command_arg)
{
/* Get local object */
- q_ptr = &forge;
+ object_type forge;
+ auto q_ptr = &forge;
/* Prepare object */
object_prep(q_ptr, i);
@@ -1495,7 +1398,7 @@ static void do_cmd_wiz_summon(int num)
for (i = 0; i < num; i++)
{
- (void)summon_specific(p_ptr->py, p_ptr->px, dun_level, 0);
+ summon_specific(p_ptr->py, p_ptr->px, dun_level, 0);
}
}
@@ -1505,15 +1408,17 @@ static void do_cmd_wiz_summon(int num)
*
* XXX XXX XXX This function is rather dangerous
*/
-static void do_cmd_wiz_named(int r_idx, bool_ slp)
+static void do_cmd_wiz_named(std::size_t r_idx, bool_ slp)
{
+ auto const &r_info = game->edit_data.r_info;
+
int i, x, y;
/* Paranoia */
/* if (!r_idx) return; */
/* Prevent illegal monsters */
- if (r_idx >= max_r_idx) return;
+ if (r_idx >= r_info.size()) return;
/* Try 10 times */
for (i = 0; i < 10; i++)
@@ -1528,8 +1433,14 @@ static void do_cmd_wiz_named(int r_idx, bool_ slp)
/* Place it (allow groups) */
m_allow_special[r_idx] = TRUE;
- if (place_monster_aux(y, x, r_idx, slp, TRUE, MSTATUS_ENEMY)) break;
+ int m_idx = place_monster_aux(y, x, r_idx, slp, TRUE, MSTATUS_ENEMY);
m_allow_special[r_idx] = FALSE;
+
+ // If summoning succeeded, we stop.
+ if (m_idx)
+ {
+ break;
+ }
}
}
@@ -1539,18 +1450,19 @@ static void do_cmd_wiz_named(int r_idx, bool_ slp)
*
* XXX XXX XXX This function is rather dangerous
*/
-void do_cmd_wiz_named_friendly(int r_idx, bool_ slp)
+void do_cmd_wiz_named_friendly(std::size_t r_idx, bool_ slp)
{
+ auto const &r_info = game->edit_data.r_info;
+
int i, x, y;
/* Paranoia */
/* if (!r_idx) return; */
/* Prevent illegal monsters */
- if (r_idx >= max_r_idx) return;
+ if (r_idx >= r_info.size()) return;
/* Try 10 times */
- m_allow_special[r_idx] = TRUE;
for (i = 0; i < 10; i++)
{
int d = 1;
@@ -1562,9 +1474,16 @@ void do_cmd_wiz_named_friendly(int r_idx, bool_ slp)
if (!cave_empty_bold(y, x)) continue;
/* Place it (allow groups) */
- if (place_monster_aux(y, x, r_idx, slp, TRUE, MSTATUS_PET)) break;
+ m_allow_special[r_idx] = TRUE;
+ int m_idx = place_monster_aux(y, x, r_idx, slp, TRUE, MSTATUS_PET);
+ m_allow_special[r_idx] = FALSE;
+
+ // Stop if we succeeded
+ if (m_idx)
+ {
+ break;
+ }
}
- m_allow_special[r_idx] = FALSE;
}
@@ -1572,7 +1491,7 @@ void do_cmd_wiz_named_friendly(int r_idx, bool_ slp)
/*
* Hack -- Delete all nearby monsters
*/
-static void do_cmd_wiz_zap(void)
+static void do_cmd_wiz_zap()
{
int i;
@@ -1590,10 +1509,12 @@ static void do_cmd_wiz_zap(void)
}
-extern void do_cmd_wiz_body(s16b bidx)
+static void do_cmd_wiz_body(s16b bidx)
/* Might create problems with equipment slots. For safety,
be nude when calling this function */
{
+ auto const &r_info = game->edit_data.r_info;
+
p_ptr->body_monster = bidx;
p_ptr->disembodied = FALSE;
p_ptr->chp = maxroll( (&r_info[bidx])->hdice, (&r_info[bidx])->hside);
@@ -1602,25 +1523,13 @@ 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()
{
+ auto const &d_info = game->edit_data.d_info;
+
int x, y;
char cmd;
@@ -1639,15 +1548,6 @@ void do_cmd_debug(void)
break;
- /* Hack -- Generate Spoilers */
- case '"':
- do_cmd_spoilers();
- break;
-
- case 'A':
- status_main();
- break;
-
/* Hack -- Help */
case '?':
do_cmd_help();
@@ -1690,11 +1590,11 @@ void do_cmd_debug(void)
/* Change of Dungeon type */
case 'D':
- if ((command_arg >= 0) && (command_arg < max_d_idx))
+ if ((command_arg >= 0) && (std::size_t(command_arg) < d_info.size()))
{
dungeon_type = command_arg;
dun_level = d_info[dungeon_type].mindepth;
- msg_format("You go into %s", d_text + d_info[dungeon_type].text);
+ msg_format("You go into %s", d_info[dungeon_type].text.c_str());
/* Leaving */
p_ptr->leaving = TRUE;
@@ -1726,14 +1626,12 @@ 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':
- (void)ident_spell();
+ ident_spell();
break;
/* Go up or down in the dungeon */
@@ -1741,11 +1639,6 @@ void do_cmd_debug(void)
do_cmd_wiz_jump();
break;
- /* Self-Knowledge */
- case 'k':
- self_knowledge(NULL);
- break;
-
/* Learn about objects */
case 'l':
do_cmd_wiz_learn();
@@ -1758,17 +1651,7 @@ void do_cmd_debug(void)
/* corruption */
case 'M':
- (void) gain_random_corruption(command_arg);
- 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);
+ gain_random_corruption();
break;
/* Summon _friendly_ named monster */
@@ -1795,11 +1678,11 @@ 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;
- if (quest[command_arg].type == HOOK_TYPE_C) quest[command_arg].init(command_arg);
+ quest[command_arg].init();
break;
}
break;
@@ -1828,7 +1711,7 @@ void do_cmd_debug(void)
/* Display the hitpoints */
p_ptr->update |= (PU_HP);
- p_ptr->redraw |= (PR_HP);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
@@ -1892,17 +1775,12 @@ 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;
p_ptr->mimic_form = command_arg;
/* Redraw title */
- p_ptr->redraw |= (PR_TITLE);
+ p_ptr->redraw |= (PR_FRAME);
/* Recalculate bonuses */
p_ptr->update |= (PU_BONUS);
break;
@@ -1919,7 +1797,6 @@ void do_cmd_debug(void)
/* Change the feature of the map */
case 'F':
- msg_format("Trap: %d", cave[p_ptr->py][p_ptr->px].t_idx);
msg_format("Old feature: %d", cave[p_ptr->py][p_ptr->px].feat);
msg_format("Special: %d", cave[p_ptr->py][p_ptr->px].special);
cave_set_feat(p_ptr->py, p_ptr->px, command_arg);
@@ -1937,14 +1814,9 @@ 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))
- msg_print("That is not a valid debug command.");
+ msg_print("That is not a valid debug command.");
break;
}
}
diff --git a/src/wizard2.hpp b/src/wizard2.hpp
new file mode 100644
index 00000000..9bad7f92
--- /dev/null
+++ b/src/wizard2.hpp
@@ -0,0 +1,10 @@
+#pragma once
+
+#include "h-basic.h"
+
+#include <cstddef>
+
+void do_cmd_rerate();
+void do_cmd_wiz_cure_all();
+void do_cmd_wiz_named_friendly(std::size_t r_idx, bool_ slp);
+void do_cmd_debug();
diff --git a/src/xtra1.c b/src/xtra1.cc
index 933bc265..ae797aa8 100644
--- a/src/xtra1.c
+++ b/src/xtra1.cc
@@ -1,7 +1,3 @@
-/* File: misc.c */
-
-/* Purpose: misc code */
-
/*
* Copyright (c) 1989 James E. Wilson, Robert A. Koeneke
*
@@ -10,15 +6,65 @@
* included in all such copies.
*/
-#include "angband.h"
-
+#include "xtra1.hpp"
+
+#include "artifact_type.hpp"
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "corrupt.hpp"
+#include "cmd7.hpp"
+#include "dungeon_flag.hpp"
+#include "dungeon_info_type.hpp"
+#include "files.hpp"
+#include "game.hpp"
+#include "gods.hpp"
+#include "hook_calculate_hp_in.hpp"
+#include "hook_calculate_hp_out.hpp"
+#include "hooks.hpp"
+#include "levels.hpp"
+#include "messages.hpp"
+#include "mimic.hpp"
+#include "monster1.hpp"
+#include "monster2.hpp"
+#include "monster_race.hpp"
+#include "monster_race_flag.hpp"
+#include "monster_type.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_flag.hpp"
+#include "object_flag_meta.hpp"
+#include "object_kind.hpp"
+#include "options.hpp"
+#include "player_class.hpp"
+#include "player_race.hpp"
+#include "player_race_flag.hpp"
+#include "player_race_mod.hpp"
+#include "player_type.hpp"
+#include "skill_flag.hpp"
+#include "skill_type.hpp"
+#include "skills.hpp"
+#include "spells3.hpp"
+#include "spells6.hpp"
+#include "stats.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "util.h"
+#include "variable.h"
+#include "variable.hpp"
+#include "wilderness_map.hpp"
+#include "wilderness_type_info.hpp"
+#include "xtra2.hpp"
+#include "z-rand.hpp"
+
+#include <cassert>
+#include <fmt/format.h>
/*
* Converts stat num into a six-char (right justified) string
*/
void cnv_stat(int val, char *out_val)
{
- if (!linear_stats)
+ if (!options->linear_stats)
{
/* Above 18 */
if (val > 18)
@@ -116,6 +162,12 @@ s16b modify_stat_value(int value, int amount)
}
}
+ /* Clip to permissible range */
+ if (value < 3)
+ {
+ value = 3;
+ }
+
/* Return new value */
return (value);
}
@@ -137,7 +189,7 @@ static void prt_field(cptr info, int row, int col)
/*
* Prints players max/cur piety
*/
-static void prt_piety(void)
+static void prt_piety()
{
char tmp[32];
@@ -156,7 +208,7 @@ static void prt_piety(void)
/*
* Prints the player's current sanity.
*/
-static void prt_sane(void)
+static void prt_sane()
{
char tmp[32];
byte color;
@@ -179,7 +231,7 @@ static void prt_sane(void)
{
color = TERM_L_GREEN;
}
- else if (perc > (10 * hitpoint_warn))
+ else if (perc > (10 * options->hitpoint_warn))
{
color = TERM_YELLOW;
}
@@ -242,14 +294,14 @@ static void prt_stat(int stat)
/*
* Prints "title", including "wizard" or "winner" as needed.
*/
-static void prt_title(void)
+static void prt_title()
{
cptr p = "";
/* 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 */
@@ -273,7 +325,7 @@ static void prt_title(void)
/* Normal */
else
{
- p = cp_ptr->titles[(p_ptr->lev - 1) / 5] + c_text;
+ p = cp_ptr->titles[(p_ptr->lev - 1) / 5];
}
@@ -284,7 +336,7 @@ static void prt_title(void)
/*
* Prints level
*/
-static void prt_level(void)
+static void prt_level()
{
char tmp[32];
@@ -306,24 +358,17 @@ static void prt_level(void)
/*
* Display the experience
*/
-static void prt_exp(void)
+static void prt_exp()
{
char out_val[32];
- if (!exp_need)
+ if (p_ptr->lev >= PY_MAX_LEVEL)
{
- (void)sprintf(out_val, "%8ld", (long)p_ptr->exp);
+ sprintf(out_val, "********");
}
else
{
- if ((p_ptr->lev >= PY_MAX_LEVEL) || (p_ptr->lev >= max_plev))
- {
- (void)sprintf(out_val, "********");
- }
- else
- {
- (void)sprintf(out_val, "%8ld", (long)(player_exp[p_ptr->lev - 1] * p_ptr->expfact / 100L) - p_ptr->exp);
- }
+ sprintf(out_val, "%8ld", (long)(player_exp[p_ptr->lev - 1] * p_ptr->expfact / 100L) - p_ptr->exp);
}
if (p_ptr->exp >= p_ptr->max_exp)
@@ -342,7 +387,7 @@ static void prt_exp(void)
/*
* Prints current gold
*/
-static void prt_gold(void)
+static void prt_gold()
{
char tmp[32];
@@ -356,7 +401,7 @@ static void prt_gold(void)
/*
* Prints current AC
*/
-static void prt_ac(void)
+static void prt_ac()
{
char tmp[32];
@@ -369,13 +414,16 @@ static void prt_ac(void)
/*
* Prints Cur/Max hit points
*/
-static void prt_hp(void)
+static void prt_hp()
{
char tmp[32];
byte color;
- if (player_char_health) lite_spot(p_ptr->py, p_ptr->px);
+ if (options->player_char_health)
+ {
+ lite_spot(p_ptr->py, p_ptr->px);
+ }
if (p_ptr->necro_extra & CLASS_UNDEAD)
{
@@ -387,7 +435,7 @@ static void prt_hp(void)
{
color = TERM_L_BLUE;
}
- else if (p_ptr->chp > (p_ptr->mhp * hitpoint_warn) / 10)
+ else if (p_ptr->chp > (p_ptr->mhp * options->hitpoint_warn) / 10)
{
color = TERM_VIOLET;
}
@@ -407,7 +455,7 @@ static void prt_hp(void)
{
color = TERM_L_GREEN;
}
- else if (p_ptr->chp > (p_ptr->mhp * hitpoint_warn) / 10)
+ else if (p_ptr->chp > (p_ptr->mhp * options->hitpoint_warn) / 10)
{
color = TERM_YELLOW;
}
@@ -422,7 +470,7 @@ static void prt_hp(void)
/*
* Prints Cur/Max monster hit points
*/
-static void prt_mh(void)
+static void prt_mh()
{
char tmp[32];
@@ -446,7 +494,7 @@ static void prt_mh(void)
{
color = TERM_L_GREEN;
}
- else if (o_ptr->pval2 > (o_ptr->pval3 * hitpoint_warn) / 10)
+ else if (o_ptr->pval2 > (o_ptr->pval3 * options->hitpoint_warn) / 10)
{
color = TERM_YELLOW;
}
@@ -461,7 +509,7 @@ static void prt_mh(void)
/*
* Prints players max/cur spell points
*/
-static void prt_sp(void)
+static void prt_sp()
{
char tmp[32];
byte color;
@@ -474,7 +522,7 @@ static void prt_sp(void)
{
color = TERM_L_GREEN;
}
- else if (p_ptr->csp > (p_ptr->msp * hitpoint_warn) / 10)
+ else if (p_ptr->csp > (p_ptr->msp * options->hitpoint_warn) / 10)
{
color = TERM_YELLOW;
}
@@ -489,24 +537,23 @@ static void prt_sp(void)
/*
* Prints depth in stat area
*/
-static void prt_depth(void)
+static void prt_depth(int row, int col)
{
+ auto const &d_info = game->edit_data.d_info;
+ auto const &wf_info = game->edit_data.wf_info;
+
char depths[32];
- dungeon_info_type *d_ptr = &d_info[dungeon_type];
+ auto d_ptr = &d_info[dungeon_type];
if (p_ptr->wild_mode)
{
strcpy(depths, " ");
}
- else if (p_ptr->inside_arena)
- {
- strcpy(depths, "Arena");
- }
else if (get_dungeon_name(depths))
{
/* Empty */
}
- else if (dungeon_flags2 & DF2_SPECIAL)
+ else if (dungeon_flags & DF_SPECIAL)
{
strcpy(depths, "Special");
}
@@ -516,35 +563,22 @@ static void prt_depth(void)
}
else if (!dun_level)
{
- if (wf_info[wild_map[p_ptr->wilderness_y][p_ptr->wilderness_x].feat].name + wf_name)
- strcpy(depths, wf_info[wild_map[p_ptr->wilderness_y][p_ptr->wilderness_x].feat].name + wf_name);
- else
- strcpy(depths, "Town/Wild");
- }
- else if (depth_in_feet)
- {
- if (dungeon_flags1 & DF1_TOWER)
+ auto const &wilderness = game->wilderness;
+ auto const &wf = wf_info[wilderness(p_ptr->wilderness_x, p_ptr->wilderness_y).feat];
+ if (wf.name)
{
- (void)strnfmt(depths, 32, "%c%c%c -%d ft",
- d_ptr->short_name[0],
- d_ptr->short_name[1],
- d_ptr->short_name[2],
- dun_level * 50);
+ strcpy(depths, wf.name);
}
else
{
- (void)strnfmt(depths, 32, "%c%c%c %d ft",
- d_ptr->short_name[0],
- d_ptr->short_name[1],
- d_ptr->short_name[2],
- dun_level * 50);
+ strcpy(depths, "Town/Wild");
}
}
else
{
- if (dungeon_flags1 & DF1_TOWER)
+ if (dungeon_flags & DF_TOWER)
{
- (void)strnfmt(depths, 32, "%c%c%c -%d",
+ strnfmt(depths, 32, "%c%c%c -%d",
d_ptr->short_name[0],
d_ptr->short_name[1],
d_ptr->short_name[2],
@@ -552,7 +586,7 @@ static void prt_depth(void)
}
else
{
- (void)strnfmt(depths, 32, "%c%c%c %d",
+ strnfmt(depths, 32, "%c%c%c %d",
d_ptr->short_name[0],
d_ptr->short_name[1],
d_ptr->short_name[2],
@@ -562,132 +596,9 @@ static void prt_depth(void)
/* Right-Adjust the "depth", and clear old values */
if (p_ptr->word_recall)
- c_prt(TERM_ORANGE, format("%13s", depths), ROW_DEPTH, COL_DEPTH);
- else
- prt(format("%13s", depths), ROW_DEPTH, COL_DEPTH);
-}
-
-
-/*
- * Prints status of hunger
- */
-static void prt_hunger(void)
-{
- /* Fainting / Starving */
- if (p_ptr->food < PY_FOOD_FAINT)
- {
- c_put_str(TERM_RED, "Weak ", ROW_HUNGRY, COL_HUNGRY);
- }
-
- /* Weak */
- else if (p_ptr->food < PY_FOOD_WEAK)
- {
- c_put_str(TERM_ORANGE, "Weak ", ROW_HUNGRY, COL_HUNGRY);
- }
-
- /* Hungry */
- else if (p_ptr->food < PY_FOOD_ALERT)
- {
- c_put_str(TERM_YELLOW, "Hungry", ROW_HUNGRY, COL_HUNGRY);
- }
-
- /* Normal */
- else if (p_ptr->food < PY_FOOD_FULL)
- {
- c_put_str(TERM_L_GREEN, " ", ROW_HUNGRY, COL_HUNGRY);
- }
-
- /* Full */
- else if (p_ptr->food < PY_FOOD_MAX)
- {
- c_put_str(TERM_L_GREEN, "Full ", ROW_HUNGRY, COL_HUNGRY);
- }
-
- /* Gorged */
- else
- {
- c_put_str(TERM_GREEN, "Gorged", ROW_HUNGRY, COL_HUNGRY);
- }
-}
-
-
-/*
- * Prints Blind status
- */
-static void prt_blind(void)
-{
- if (p_ptr->blind)
- {
- c_put_str(TERM_ORANGE, "Blind", ROW_BLIND, COL_BLIND);
- }
+ c_prt(TERM_ORANGE, format("%13s", depths), row, col);
else
- {
- put_str(" ", ROW_BLIND, COL_BLIND);
- }
-}
-
-
-/*
- * Prints Confusion status
- */
-static void prt_confused(void)
-{
- if (p_ptr->confused)
- {
- c_put_str(TERM_ORANGE, "Conf", ROW_CONFUSED, COL_CONFUSED);
- }
- else
- {
- put_str(" ", ROW_CONFUSED, COL_CONFUSED);
- }
-}
-
-
-/*
- * Prints Fear status
- */
-static void prt_afraid(void)
-{
- if (p_ptr->afraid)
- {
- c_put_str(TERM_ORANGE, "Afraid", ROW_AFRAID, COL_AFRAID);
- }
- else
- {
- put_str(" ", ROW_AFRAID, COL_AFRAID);
- }
-}
-
-
-/*
- * Prints Poisoned status
- */
-static void prt_poisoned(void)
-{
- if (p_ptr->poisoned)
- {
- c_put_str(TERM_ORANGE, "Poison", ROW_POISONED, COL_POISONED);
- }
- else
- {
- put_str(" ", ROW_POISONED, COL_POISONED);
- }
-}
-
-
-/*
- * Prints trap detection status
- */
-static void prt_dtrap(void)
-{
- if (cave[p_ptr->py][p_ptr->px].info & CAVE_DETECT)
- {
- c_put_str(TERM_L_GREEN, "DTrap", ROW_DTRAP, COL_DTRAP);
- }
- else
- {
- put_str(" ", ROW_DTRAP, COL_DTRAP);
- }
+ prt(format("%13s", depths), row, col);
}
@@ -698,7 +609,7 @@ static void prt_dtrap(void)
* This function was a major bottleneck when resting, so a lot of
* the text formatting code was optimized in place below.
*/
-static void prt_state(void)
+static void prt_state(int row, int col)
{
byte attr = TERM_WHITE;
@@ -782,20 +693,14 @@ static void prt_state(void)
{
if (command_rep > 999)
{
- (void)sprintf(text, "Rep. %3d00", command_rep / 100);
+ sprintf(text, "Rep. %3d00", command_rep / 100);
}
else
{
- (void)sprintf(text, "Repeat %3d", command_rep);
+ sprintf(text, "Repeat %3d", command_rep);
}
}
- /* Searching */
- else if (p_ptr->searching)
- {
- strcpy(text, "Searching ");
- }
-
/* Nothing interesting */
else
{
@@ -803,23 +708,20 @@ static void prt_state(void)
}
/* Display the info (or blanks) */
- c_put_str(attr, text, ROW_STATE, COL_STATE);
+ c_put_str(attr, text, row, col);
}
/*
* Prints the speed of a character. -CJS-
*/
-static void prt_speed(void)
+static void prt_speed(int row, int col)
{
int i = p_ptr->pspeed;
byte attr = TERM_WHITE;
char buf[32] = "";
- /* Hack -- Visually "undo" the Search Mode Slowdown */
- if (p_ptr->searching) i += 10;
-
/* Fast */
if (i > 110)
{
@@ -835,82 +737,184 @@ static void prt_speed(void)
}
/* Display the speed */
- c_put_str(attr, format("%-10s", buf), ROW_SPEED, COL_SPEED);
+ c_put_str(attr, format("%-10s", buf), row, col);
}
-static void prt_study(void)
+
+/*
+ * Prints status line
+ */
+static void prt_status_line()
{
+ int wid, hgt;
+ Term_get_size(&wid, &hgt);
+ int row = hgt - 1;
+
+ /* Fainting / Starving */
+ int col = 0;
+ if (p_ptr->food < PY_FOOD_FAINT)
+ {
+ c_put_str(TERM_RED, "Weak ", row, col);
+ }
+ else if (p_ptr->food < PY_FOOD_WEAK)
+ {
+ c_put_str(TERM_ORANGE, "Weak ", row, col);
+ }
+ else if (p_ptr->food < PY_FOOD_ALERT)
+ {
+ c_put_str(TERM_YELLOW, "Hungry", row, col);
+ }
+ else if (p_ptr->food < PY_FOOD_FULL)
+ {
+ c_put_str(TERM_L_GREEN, " ", row, col);
+ }
+ else if (p_ptr->food < PY_FOOD_MAX)
+ {
+ c_put_str(TERM_L_GREEN, "Full ", row, col);
+ }
+ else
+ {
+ c_put_str(TERM_GREEN, "Gorged", row, col);
+ }
+
+ /* Blind */
+ col = 7;
+ if (p_ptr->blind)
+ {
+ c_put_str(TERM_ORANGE, "Blind", row, col);
+ }
+ else
+ {
+ put_str(" ", row, col);
+ }
+
+ /* Confusion */
+ col = 13;
+ if (p_ptr->confused)
+ {
+ c_put_str(TERM_ORANGE, "Conf", row, col);
+ }
+ else
+ {
+ put_str(" ", row, col);
+ }
+
+ /* Fear */
+ col = 18;
+ if (p_ptr->afraid)
+ {
+ c_put_str(TERM_ORANGE, "Afraid", row, col);
+ }
+ else
+ {
+ put_str(" ", row, col);
+ }
+
+ /* Poison */
+ col = 25;
+ if (p_ptr->poisoned)
+ {
+ c_put_str(TERM_ORANGE, "Poison", row, col);
+ }
+ else
+ {
+ put_str(" ", row, col);
+ }
+
+ /* State */
+ col = 38;
+ prt_state(row, col);
+
+ /* Speed */
+ col = 49;
+ prt_speed(row, col);
+
+ /* "Study" */
+ col = 60;
if (p_ptr->skill_points)
{
- put_str("Skill", ROW_STUDY, COL_STUDY);
+ put_str("Skill", row, col);
}
else
{
- put_str(" ", ROW_STUDY, COL_STUDY);
+ put_str(" ", row, col);
}
+
+ /* Depth */
+ col = wid - 14;
+ prt_depth(row, col);
}
-static void prt_cut(void)
+
+static void prt_cut()
{
int c = p_ptr->cut;
+ int hgt;
+ Term_get_size(nullptr, &hgt);
+ int row = hgt - 3;
+ int col = 0;
if (c > 1000)
{
- c_put_str(TERM_L_RED, "Mortal wound", ROW_CUT, COL_CUT);
+ c_put_str(TERM_L_RED, "Mortal wound", row, col);
}
else if (c > 200)
{
- c_put_str(TERM_RED, "Deep gash ", ROW_CUT, COL_CUT);
+ c_put_str(TERM_RED, "Deep gash ", row, col);
}
else if (c > 100)
{
- c_put_str(TERM_RED, "Severe cut ", ROW_CUT, COL_CUT);
+ c_put_str(TERM_RED, "Severe cut ", row, col);
}
else if (c > 50)
{
- c_put_str(TERM_ORANGE, "Nasty cut ", ROW_CUT, COL_CUT);
+ c_put_str(TERM_ORANGE, "Nasty cut ", row, col);
}
else if (c > 25)
{
- c_put_str(TERM_ORANGE, "Bad cut ", ROW_CUT, COL_CUT);
+ c_put_str(TERM_ORANGE, "Bad cut ", row, col);
}
else if (c > 10)
{
- c_put_str(TERM_YELLOW, "Light cut ", ROW_CUT, COL_CUT);
+ c_put_str(TERM_YELLOW, "Light cut ", row, col);
}
else if (c)
{
- c_put_str(TERM_YELLOW, "Graze ", ROW_CUT, COL_CUT);
+ c_put_str(TERM_YELLOW, "Graze ", row, col);
}
else
{
- put_str(" ", ROW_CUT, COL_CUT);
+ put_str(" ", row, col);
}
}
-static void prt_stun(void)
+static void prt_stun()
{
int s = p_ptr->stun;
+ int hgt;
+ Term_get_size(nullptr, &hgt);
+ int row = hgt - 2;
+ int col = 0;
if (s > 100)
{
- c_put_str(TERM_RED, "Knocked out ", ROW_STUN, COL_STUN);
+ c_put_str(TERM_RED, "Knocked out ", row, col);
}
else if (s > 50)
{
- c_put_str(TERM_ORANGE, "Heavy stun ", ROW_STUN, COL_STUN);
+ c_put_str(TERM_ORANGE, "Heavy stun ", row, col);
}
else if (s)
{
- c_put_str(TERM_ORANGE, "Stun ", ROW_STUN, COL_STUN);
+ c_put_str(TERM_ORANGE, "Stun ", row, col);
}
else
{
- put_str(" ", ROW_STUN, COL_STUN);
+ put_str(" ", row, col);
}
}
@@ -930,37 +934,39 @@ static void prt_stun(void)
* Auto-track current target monster when bored. Note that the
* health-bar stops tracking any monster that "disappears".
*/
-static void health_redraw(void)
+static void health_redraw()
{
-
-#ifdef DRS_SHOW_HEALTH_BAR
+ int hgt;
+ Term_get_size(nullptr, &hgt);
+ int col = 0;
+ int row = hgt - 4;
/* Not tracking */
if (!health_who)
{
/* Erase the health bar */
- Term_erase(COL_INFO, ROW_INFO, 12);
+ Term_erase(col, row, 12);
}
/* Tracking an unseen monster */
else if (!m_list[health_who].ml)
{
/* Indicate that the monster health is "unknown" */
- Term_putstr(COL_INFO, ROW_INFO, 12, TERM_WHITE, "[----------]");
+ Term_putstr(col, row, 12, TERM_WHITE, "[----------]");
}
/* Tracking a hallucinatory monster */
else if (p_ptr->image)
{
/* Indicate that the monster health is "unknown" */
- Term_putstr(COL_INFO, ROW_INFO, 12, TERM_WHITE, "[----------]");
+ Term_putstr(col, row, 12, TERM_WHITE, "[----------]");
}
/* Tracking a dead monster (???) */
- else if (!m_list[health_who].hp < 0)
+ else if ((m_list[health_who].hp < 0))
{
/* Indicate that the monster health is "unknown" */
- Term_putstr(COL_INFO, ROW_INFO, 12, TERM_WHITE, "[----------]");
+ Term_putstr(col, row, 12, TERM_WHITE, "[----------]");
}
/* Tracking a visible monster */
@@ -1004,14 +1010,17 @@ static void health_redraw(void)
len = (pct < 10) ? 1 : (pct < 90) ? (pct / 10 + 1) : 10;
/* Default to "unknown" */
- Term_putstr(COL_INFO, ROW_INFO, 12, TERM_WHITE, "[----------]");
+ Term_putstr(col, row, 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 + 1, row, len, attr, "ssssssssss");
+ } else if (m_ptr->confused) {
+ Term_putstr(col + 1, row, len, attr, "cccccccccc");
+ } else {
+ Term_putstr(col + 1, row, len, attr, "**********");
+ }
}
-
-#endif
-
}
@@ -1019,13 +1028,13 @@ static void health_redraw(void)
/*
* Display basic info (mostly left of map)
*/
-static void prt_frame_basic(void)
+static void prt_frame()
{
int i;
/* Race and Class */
- prt_field(rp_ptr->title + rp_name, ROW_RACE, COL_RACE);
- prt_field(spp_ptr->title + c_name, ROW_CLASS, COL_CLASS);
+ prt_field(rp_ptr->title.c_str(), ROW_RACE, COL_RACE);
+ prt_field(spp_ptr->title, ROW_CLASS, COL_CLASS);
/* Title */
prt_title();
@@ -1058,53 +1067,28 @@ static void prt_frame_basic(void)
/* Gold */
prt_gold();
- /* Current depth */
- prt_depth();
-
- /* Special */
- health_redraw();
-}
-
-
-/*
- * Display extra info (mostly below map)
- */
-static void prt_frame_extra(void)
-{
/* Cut/Stun */
prt_cut();
prt_stun();
- /* Food */
- prt_hunger();
-
- /* Various */
- prt_blind();
- prt_confused();
- prt_afraid();
- prt_poisoned();
- prt_dtrap();
-
- /* State */
- prt_state();
-
- /* Speed */
- prt_speed();
+ /* Current depth */
+ prt_status_line();
- /* Study spells */
- prt_study();
+ /* Special */
+ health_redraw();
}
-/*
- * Hack -- display inventory in sub-windows
+/**
+ * Fix up each terminal based on whether a window flag
+ * is set.
*/
-static void fix_inven(void)
-{
- int j;
+namespace { // anonymous
- /* Scan windows */
- for (j = 0; j < 8; j++)
+template <typename F>
+static void fixup_display(u32b mask, F callback)
+{
+ for (int j = 0; j < ANGBAND_TERM_MAX; j++)
{
term *old = Term;
@@ -1112,13 +1096,13 @@ static void fix_inven(void)
if (!angband_term[j]) continue;
/* No relevant flags */
- if (!(window_flag[j] & (PW_INVEN))) continue;
+ if (!(window_flag[j] & mask)) continue;
/* Activate */
Term_activate(angband_term[j]);
- /* Display inventory */
- display_inven();
+ /* Apply fixup callback */
+ callback();
/* Fresh */
Term_fresh();
@@ -1128,70 +1112,33 @@ static void fix_inven(void)
}
}
+} // namespace anonymous
/*
- * Hack -- display equipment in sub-windows
+ * Hack -- display inventory in sub-windows
*/
-static void fix_equip(void)
+static void fix_inven()
{
- int j;
-
- /* Scan windows */
- for (j = 0; j < 8; j++)
- {
- term *old = Term;
-
- /* No window */
- if (!angband_term[j]) continue;
-
- /* No relevant flags */
- if (!(window_flag[j] & (PW_EQUIP))) continue;
-
- /* Activate */
- Term_activate(angband_term[j]);
-
- /* Display equipment */
- display_equip();
-
- /* Fresh */
- Term_fresh();
+ fixup_display(PW_INVEN, display_inven);
+}
- /* Restore */
- Term_activate(old);
- }
+/*
+ * Hack -- display equipment in sub-windows
+ */
+static void fix_equip()
+{
+ fixup_display(PW_EQUIP, display_equip);
}
/*
* Hack -- display character in sub-windows
*/
-static void fix_player(void)
+static void fix_player()
{
- int j;
-
- /* Scan windows */
- for (j = 0; j < 8; j++)
- {
- term *old = Term;
-
- /* No window */
- if (!angband_term[j]) continue;
-
- /* No relevant flags */
- if (!(window_flag[j] & (PW_PLAYER))) continue;
-
- /* Activate */
- Term_activate(angband_term[j]);
-
- /* Display player */
+ fixup_display(PW_PLAYER, [] {
display_player(0);
-
- /* Fresh */
- Term_fresh();
-
- /* Restore */
- Term_activate(old);
- }
+ });
}
@@ -1201,48 +1148,32 @@ static void fix_player(void)
*
* XXX XXX XXX Adjust for width and split messages
*/
-void fix_message(void)
+void fix_message()
{
- int j, i;
- int w, h;
- int x, y;
-
- /* Scan windows */
- for (j = 0; j < 8; j++)
- {
- term *old = Term;
-
- /* No window */
- if (!angband_term[j]) continue;
-
- /* No relevant flags */
- if (!(window_flag[j] & (PW_MESSAGE))) continue;
-
- /* Activate */
- Term_activate(angband_term[j]);
+ auto const &messages = game->messages;
+ fixup_display(PW_MESSAGE, [&messages] {
/* Get size */
+ int w, h;
Term_get_size(&w, &h);
/* Dump messages */
- for (i = 0; i < h; i++)
+ for (int i = 0; i < h; i++)
{
+ auto message = messages.at(i);
+ auto text_with_count = message.text_with_count();
+
/* Dump the message on the appropriate line */
- display_message(0, (h - 1) - i, strlen(message_str((s16b)i)), message_color((s16b)i), message_str((s16b)i));
+ display_message(0, (h - 1) - i, text_with_count.size(), message.color, text_with_count.c_str());
/* Cursor */
+ int x, y;
Term_locate(&x, &y);
/* Clear to end of line */
Term_erase(x, y, 255);
}
-
- /* Fresh */
- Term_fresh();
-
- /* Restore */
- Term_activate(old);
- }
+ });
}
@@ -1251,129 +1182,60 @@ void fix_message(void)
*
* Note that the "player" symbol does NOT appear on the map.
*/
-static void fix_overhead(void)
+static void fix_overhead()
{
- int j;
-
- int cy, cx;
-
- /* Scan windows */
- for (j = 0; j < 8; j++)
- {
- term *old = Term;
-
- /* No window */
- if (!angband_term[j]) continue;
-
- /* No relevant flags */
- if (!(window_flag[j] & (PW_OVERHEAD))) continue;
-
- /* Activate */
- Term_activate(angband_term[j]);
-
- /* Redraw map */
+ fixup_display(PW_OVERHEAD, [] {
+ int cy, cx;
display_map(&cy, &cx);
-
- /* Fresh */
- Term_fresh();
-
- /* Restore */
- Term_activate(old);
- }
+ });
}
/*
* Hack -- display monster recall in sub-windows
*/
-static void fix_monster(void)
+static void fix_monster()
{
- int j;
-
- /* Scan windows */
- for (j = 0; j < 8; j++)
- {
- term *old = Term;
-
- /* No window */
- if (!angband_term[j]) continue;
-
- /* No relevant flags */
- if (!(window_flag[j] & (PW_MONSTER))) continue;
-
- /* Activate */
- Term_activate(angband_term[j]);
-
+ fixup_display(PW_MONSTER, [] {
/* Display monster race info */
- if (monster_race_idx) display_roff(monster_race_idx, monster_ego_idx);
-
- /* Fresh */
- Term_fresh();
-
- /* Restore */
- Term_activate(old);
- }
+ if (monster_race_idx)
+ {
+ display_roff(monster_race_idx, monster_ego_idx);
+ }
+ });
}
/*
* Hack -- display object recall in sub-windows
*/
-static void fix_object(void)
+static void fix_object()
{
- int j;
-
- /* Scan windows */
- for (j = 0; j < 8; j++)
- {
- term *old = Term;
-
- /* No window */
- if (!angband_term[j]) continue;
-
- /* No relevant flags */
- if (!(window_flag[j] & (PW_OBJECT))) continue;
-
- /* Activate */
- Term_activate(angband_term[j]);
-
+ fixup_display(PW_OBJECT, [] {
/* Clear */
Term_clear();
/* Display object info */
- if (tracked_object)
- if (!object_out_desc(tracked_object, NULL, FALSE, FALSE)) text_out("You see nothing special.");
-
- /* Fresh */
- Term_fresh();
-
- /* Restore */
- Term_activate(old);
- }
+ if (tracked_object &&
+ !object_out_desc(tracked_object, NULL, FALSE, FALSE))
+ {
+ text_out("You see nothing special.");
+ }
+ });
}
/* Show the monster list in a window */
-static void fix_m_list(void)
+static void fix_m_list()
{
- int i, j;
-
- /* Scan windows */
- for (j = 0; j < 8; j++)
- {
- term *old = Term;
-
- int c = 0;
-
- /* No window */
- if (!angband_term[j]) continue;
-
- /* No relevant flags */
- if (!(window_flag[j] & (PW_M_LIST))) continue;
+ auto const &r_info = game->edit_data.r_info;
- /* Activate */
- Term_activate(angband_term[j]);
+ // Mirror of the r_info array, index by index. We use a
+ // statically allocated value to avoid frequent allocations.
+ static auto r_total_visible =
+ std::vector<u16b>(r_info.size(), 0);
+ fixup_display(PW_M_LIST, [&r_info] {
/* Clear */
Term_clear();
@@ -1381,40 +1243,31 @@ static void fix_m_list(void)
if (p_ptr->image)
{
c_prt(TERM_WHITE, "You can not see clearly", 0, 0);
-
- /* Fresh */
- Term_fresh();
-
- /* Restore */
- Term_activate(old);
-
return;
}
/* reset visible count */
- for (i = 1; i < max_r_idx; i++)
+ for (std::size_t i = 1; i < r_info.size(); i++)
{
- monster_race *r_ptr = &r_info[i];
-
- r_ptr->total_visible = 0;
+ r_total_visible[i] = 0;
}
/* Count up the number visible in each race */
- for (i = 1; i < m_max; i++)
+ int c = 0;
+ for (std::size_t i = 1; i < static_cast<u16b>(m_max); i++)
{
- monster_type *m_ptr = &m_list[i];
- monster_race *r_ptr = &r_info[m_ptr->r_idx];
+ auto const m_ptr = &m_list[i];
+ auto const r_ptr = &r_info[m_ptr->r_idx];
+ auto total_visible = &r_total_visible[m_ptr->r_idx];
/* Skip dead monsters */
if (m_ptr->hp < 0) continue;
/* Skip unseen monsters */
- if (r_ptr->flags9 & RF9_MIMIC)
+ if (r_ptr->flags & RF_MIMIC)
{
- object_type *o_ptr;
-
/* Acquire object */
- o_ptr = &o_list[m_ptr->hold_o_idx];
+ object_type *o_ptr = &o_list[m_ptr->mimic_o_idx()];
/* Memorized objects */
if (!o_ptr->marked) continue;
@@ -1425,7 +1278,7 @@ static void fix_m_list(void)
}
/* Increase for this race */
- r_ptr->total_visible++;
+ (*total_visible)++;
/* Increase total Count */
c++;
@@ -1436,34 +1289,38 @@ static void fix_m_list(void)
{
int w, h, num = 0;
- (void)Term_get_size(&w, &h);
+ Term_get_size(&w, &h);
c_prt(TERM_WHITE, format("You can see %d monster%s", c, (c > 1 ? "s:" : ":")), 0, 0);
- for (i = 1; i < max_r_idx; i++)
+ for (std::size_t i = 1; i < r_info.size(); i++)
{
- monster_race *r_ptr = &r_info[i];
+ auto const r_ptr = &r_info[i];
+ auto const total_visible = r_total_visible[i];
/* Default Colour */
byte attr = TERM_SLATE;
/* Only visible monsters */
- if (!r_ptr->total_visible) continue;
+ if (!total_visible)
+ {
+ continue;
+ }
/* Uniques */
- if (r_ptr->flags1 & RF1_UNIQUE)
+ if (r_ptr->flags & RF_UNIQUE)
{
attr = TERM_L_BLUE;
}
- /* Have we ever killed one? */
- if (r_ptr->r_tkills)
+ /* Have we killed one? */
+ if (r_ptr->r_pkills)
{
if (r_ptr->level > dun_level)
{
attr = TERM_VIOLET;
- if (r_ptr->flags1 & RF1_UNIQUE)
+ if (r_ptr->flags & RF_UNIQUE)
{
attr = TERM_RED;
}
@@ -1471,18 +1328,17 @@ static void fix_m_list(void)
}
else
{
- if (!(r_ptr->flags1 & RF1_UNIQUE)) attr = TERM_GREEN;
+ if (!(r_ptr->flags & RF_UNIQUE)) attr = TERM_GREEN;
}
-
/* Dump the monster name */
- if (r_ptr->total_visible == 1)
+ if (total_visible == 1)
{
- c_prt(attr, (r_name + r_ptr->name), (num % (h - 1)) + 1, (num / (h - 1) * 26));
+ c_prt(attr, r_ptr->name, (num % (h - 1)) + 1, (num / (h - 1) * 26));
}
else
{
- c_prt(attr, format("%s (x%d)", r_name + r_ptr->name, r_ptr->total_visible), (num % (h - 1)) + 1, (num / (h - 1)) * 26);
+ c_prt(attr, format("%s (x%d)", r_ptr->name, total_visible), (num % (h - 1)) + 1, (num / (h - 1)) * 26);
}
num++;
@@ -1494,36 +1350,50 @@ static void fix_m_list(void)
{
c_prt(TERM_WHITE, "You see no monsters.", 0, 0);
}
-
- /* Fresh */
- Term_fresh();
-
- /* Restore */
- Term_activate(old);
- }
+ });
}
/*
- * Calculate number of spells player should have, and forget,
- * or remember, spells until that number is properly reflected.
- *
- * Note that this function induces various "status" messages,
- * which must be bypasses until the character is created.
+ * Calculate powers of player given the current set of corruptions.
*/
-static void calc_spells(void)
+static void calc_powers_corruption()
{
- p_ptr->new_spells = 0;
+ /* Map of corruptions to a power */
+ int i;
+
+ /* Grant powers according to whatever corruptions the player has */
+ for (i = 0; i < CORRUPTIONS_MAX; i++)
+ {
+ if (player_has_corruption(i))
+ {
+ int p = get_corruption_power(i);
+ if (p >= 0)
+ {
+ p_ptr->powers[p] = TRUE;
+ }
+ }
+ }
}
+
/* Ugly hack */
bool_ calc_powers_silent = FALSE;
+/* Add in powers */
+static void add_powers(std::vector<s16b> const &powers)
+{
+ for (auto const &p: powers)
+ {
+ p_ptr->powers[p] = TRUE;
+ }
+}
+
/* Calc the player powers */
-static void calc_powers(void)
+static void calc_powers()
{
int i, p = 0;
- bool_ *old_powers;
+ bool_ old_powers[POWER_MAX];
/* Hack -- wait for creation */
if (!character_generated) return;
@@ -1531,17 +1401,15 @@ 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;
- /* Hooked powers */
- process_hooks(HOOK_CALC_POWERS, "()");
+ /* Calculate powers granted by corruptions */
+ calc_powers_corruption();
/* Add objects powers */
for (i = INVEN_WIELD; i < INVEN_TOTAL; i++)
@@ -1551,31 +1419,24 @@ static void calc_powers(void)
if (!o_ptr->k_idx) continue;
p = object_power(o_ptr);
- if (p != -1) p_ptr->powers[p] = TRUE;
+ if (p != -1)
+ {
+ p_ptr->powers[p] = TRUE;
+ }
}
if ((!p_ptr->tim_mimic) && (!p_ptr->body_monster))
{
- /* Add in racial and subracial powers */
- for (i = 0; i < 4; i++)
- {
- p = rp_ptr->powers[i];
- if (p != -1) p_ptr->powers[p] = TRUE;
-
- p = rmp_ptr->powers[i];
- if (p != -1) p_ptr->powers[p] = TRUE;
- }
+ add_powers(rp_ptr->ps.powers);
+ add_powers(rmp_ptr->ps.powers);
}
else if (p_ptr->mimic_form)
- call_lua("calc_mimic_power", "(d)", "", p_ptr->mimic_form);
-
- /* Add in class powers */
- for (i = 0; i < 4; i++)
{
- p = cp_ptr->powers[i];
- if (p != -1) p_ptr->powers[p] = TRUE;
+ calc_mimic_power();
}
+ add_powers(cp_ptr->ps.powers);
+
if (p_ptr->disembodied)
{
p = PWR_INCARNATE;
@@ -1583,7 +1444,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];
@@ -1599,15 +1460,13 @@ static void calc_powers(void)
}
calc_powers_silent = FALSE;
- C_FREE(old_powers, power_max, bool_);
}
/*
* Calculate the player's sanity
*/
-
-void calc_sanity(void)
+static void calc_sanity()
{
int bonus, msane;
@@ -1632,7 +1491,7 @@ void calc_sanity(void)
p_ptr->csane_frac = 0;
}
- p_ptr->redraw |= (PR_SANITY);
+ p_ptr->redraw |= (PR_FRAME);
p_ptr->window |= (PW_PLAYER);
}
}
@@ -1644,12 +1503,11 @@ void calc_sanity(void)
*
* This function induces status messages.
*/
-static void calc_mana(void)
+static void calc_mana()
{
- int msp, levels, cur_wgt, max_wgt;
- u32b f1, f2, f3, f4, f5, esp;
+ auto const &r_info = game->edit_data.r_info;
- object_type *o_ptr;
+ int msp, levels, cur_wgt, max_wgt;
levels = p_ptr->lev;
@@ -1669,7 +1527,8 @@ static void calc_mana(void)
/* Possessors mana is different */
if (p_ptr->body_monster && (!p_ptr->disembodied))
{
- monster_race *r_ptr = &r_info[p_ptr->body_monster];
+ auto r_ptr = &r_info[p_ptr->body_monster];
+
int f = 100 / (r_ptr->freq_spell ? r_ptr->freq_spell : 1);
msp = 21 - f;
@@ -1684,7 +1543,7 @@ static void calc_mana(void)
msp += msp * cp_ptr->mana / 100;
/* Apply Eru mana */
- GOD(GOD_ERU)
+ if (p_ptr->pgod == GOD_ERU)
{
s32b tmp = p_ptr->grace;
@@ -1700,16 +1559,16 @@ static void calc_mana(void)
p_ptr->cumber_glove = FALSE;
/* Get the gloves */
- o_ptr = &p_ptr->inventory[INVEN_HANDS];
+ object_type *o_ptr = &p_ptr->inventory[INVEN_HANDS];
/* Examine the gloves */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ auto const flags = object_flags(o_ptr);
/* Normal gloves hurt mage-type spells */
if (o_ptr->k_idx &&
- !(f2 & (TR2_FREE_ACT)) &&
- !((f1 & (TR1_DEX)) && (o_ptr->pval > 0)) &&
- !(f5 & TR5_SPELL_CONTAIN))
+ !(flags & TR_FREE_ACT) &&
+ !((flags & TR_DEX) && (o_ptr->pval > 0)) &&
+ !(flags & TR_SPELL_CONTAIN))
{
/* Encumbered */
p_ptr->cumber_glove = TRUE;
@@ -1720,13 +1579,9 @@ static void calc_mana(void)
}
/* Augment mana */
- if (munchkin_multipliers)
- {
- if (p_ptr->to_m) msp += msp * p_ptr->to_m / 5;
- }
- else
+ if (p_ptr->to_m)
{
- 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 */
@@ -1754,18 +1609,9 @@ static void calc_mana(void)
msp -= ((cur_wgt - max_wgt) / 10);
}
- /* When meditating your mana is increased ! */
- if (p_ptr->meditation)
- {
- msp += 50;
- p_ptr->csp += 50;
- }
-
/* Sp mods? */
- if (process_hooks_ret(HOOK_CALC_MANA, "d", "(d)", msp))
- {
- msp = process_hooks_return[0].num;
- }
+ mana_school_calc_mana(&msp);
+ meta_inertia_control_calc_mana(&msp);
/* Mana can never be negative */
if (msp < 0) msp = 0;
@@ -1785,7 +1631,7 @@ static void calc_mana(void)
}
/* Display mana later */
- p_ptr->redraw |= (PR_MANA);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
@@ -1837,15 +1683,16 @@ static void calc_mana(void)
* Calculate the players (maximal) hit points
* Adjust current hitpoints if necessary
*/
-void calc_hitpoints(void)
+void calc_hitpoints()
{
- int bonus, mhp;
+ auto const &player_hp = game->player_hp;
+ auto const &r_info = game->edit_data.r_info;
/* Un-inflate "half-hitpoint bonus per level" value */
- bonus = ((int)(adj_con_mhp[p_ptr->stat_ind[A_CON]]) - 128);
+ int const bonus = ((int)(adj_con_mhp[p_ptr->stat_ind[A_CON]]) - 128);
/* Calculate hitpoints */
- mhp = player_hp[p_ptr->lev - 1] + (bonus * p_ptr->lev / 2);
+ int mhp = player_hp[p_ptr->lev - 1] + (bonus * p_ptr->lev / 2);
/* Always have at least one hitpoint per level */
if (mhp < p_ptr->lev + 1) mhp = p_ptr->lev + 1;
@@ -1862,7 +1709,7 @@ void calc_hitpoints(void)
}
/* Factor in the melkor hp modifications */
- GOD(GOD_MELKOR)
+ if (p_ptr->pgod == GOD_MELKOR)
{
mhp -= (p_ptr->melkor_sacrifice * 10);
if (mhp < 1) mhp = 1;
@@ -1873,19 +1720,13 @@ 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)
{
- monster_race *r_ptr = &r_info[p_ptr->body_monster];
+ auto r_ptr = &r_info[p_ptr->body_monster];
u32b rhp = maxroll(r_ptr->hdice, r_ptr->hside);
/* Adjust the hp with the possession skill */
@@ -1911,9 +1752,13 @@ void calc_hitpoints(void)
}
/* Hp mods? */
- if (process_hooks_ret(HOOK_CALC_HP, "d", "(d)", mhp))
{
- mhp = process_hooks_return[0].num;
+ struct hook_calculate_hp_in in = { mhp };
+ struct hook_calculate_hp_out out = { 0 };
+ if (process_hooks_new(HOOK_CALC_HP, &in, &out))
+ {
+ mhp = out.mhp;
+ }
}
/* Never less than 1 */
@@ -1935,7 +1780,7 @@ void calc_hitpoints(void)
p_ptr->mhp = mhp;
/* Display hitpoints (later) */
- p_ptr->redraw |= (PR_HP);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
@@ -1943,6 +1788,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"
@@ -1950,11 +1807,10 @@ void calc_hitpoints(void)
* SWD: Experimental modification: multiple light sources have additive effect.
*
*/
-static void calc_torch(void)
+static void calc_torch()
{
int i;
object_type *o_ptr;
- u32b f1, f2, f3, f4, f5, esp;
/* Assume no light */
p_ptr->cur_lite = 0;
@@ -1968,14 +1824,14 @@ static void calc_torch(void)
if (!o_ptr->k_idx) continue;
/* Extract the flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ auto const flags = object_flags(o_ptr);
/* does this item glow? */
- if (((f4 & TR4_FUEL_LITE) && (o_ptr->timeout > 0)) || (!(f4 & TR4_FUEL_LITE)))
+ if (((flags & TR_FUEL_LITE) && (o_ptr->timeout > 0)) || (!(flags & TR_FUEL_LITE)))
{
- if (f3 & TR3_LITE1) p_ptr->cur_lite++;
- if (f4 & TR4_LITE2) p_ptr->cur_lite += 2;
- if (f4 & TR4_LITE3) p_ptr->cur_lite += 3;
+ if (flags & TR_LITE1) p_ptr->cur_lite++;
+ if (flags & TR_LITE2) p_ptr->cur_lite += 2;
+ if (flags & TR_LITE3) p_ptr->cur_lite += 3;
}
}
@@ -1992,8 +1848,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 */
@@ -2009,7 +1865,7 @@ static void calc_torch(void)
/* Reduce lite when running if requested */
- if (running && view_reduce_lite)
+ if (running && options->view_reduce_lite)
{
/* Reduce the lite radius if needed */
if (p_ptr->cur_lite > 1) p_ptr->cur_lite = 1;
@@ -2034,39 +1890,35 @@ static void calc_torch(void)
/*
* Computes current weight limit.
*/
-int weight_limit(void)
+int weight_limit()
{
int i;
/* Weight limit based only on strength */
i = adj_str_wgt[p_ptr->stat_ind[A_STR]] * 100;
- if (process_hooks_ret(HOOK_CALC_WEIGHT, "d", "(d)", i))
- i = process_hooks_return[0].num;
-
/* Return the result */
return (i);
}
void calc_wield_monster()
{
- object_type *o_ptr;
- monster_race *r_ptr;
+ auto const &r_info = game->edit_data.r_info;
/* Get the carried monster */
- o_ptr = &p_ptr->inventory[INVEN_CARRY];
+ auto o_ptr = &p_ptr->inventory[INVEN_CARRY];
if (o_ptr->k_idx)
{
- r_ptr = &r_info[o_ptr->pval];
+ auto r_ptr = &r_info[o_ptr->pval];
- if (r_ptr->flags2 & RF2_INVISIBLE)
+ if (r_ptr->flags & RF_INVISIBLE)
p_ptr->invis += 20;
- if (r_ptr->flags2 & RF2_REFLECTING)
+ if (r_ptr->flags & RF_REFLECTING)
p_ptr->reflect = TRUE;
- if (r_ptr->flags7 & RF7_CAN_FLY)
+ if (r_ptr->flags & RF_CAN_FLY)
p_ptr->ffall = TRUE;
- if (r_ptr->flags7 & RF7_AQUATIC)
+ if (r_ptr->flags & RF_AQUATIC)
p_ptr->water_breath = TRUE;
}
}
@@ -2079,7 +1931,9 @@ void calc_wield_monster()
*/
void calc_body()
{
- monster_race *r_ptr = &r_info[p_ptr->body_monster];
+ auto const &r_info = game->edit_data.r_info;
+
+ auto r_ptr = &r_info[p_ptr->body_monster];
int i, b_weapon, b_legs, b_arms;
byte *body_parts, bp[BODY_MAX];
@@ -2198,10 +2052,15 @@ void calc_body()
/* Should be called by every calc_bonus call */
void calc_body_bonus()
{
- monster_race *r_ptr = &r_info[p_ptr->body_monster];
+ auto const &r_info = game->edit_data.r_info;
+
+ auto r_ptr = &r_info[p_ptr->body_monster];
/* If in the player body nothing have to be done */
- if (!p_ptr->body_monster) return;
+ if (!p_ptr->body_monster)
+ {
+ return;
+ }
if (p_ptr->disembodied)
{
@@ -2212,46 +2071,38 @@ void calc_body_bonus()
p_ptr->ac += r_ptr->ac;
p_ptr->pspeed = r_ptr->speed;
- if (r_ptr->flags1 & RF1_NEVER_MOVE) p_ptr->immovable = TRUE;
- if (r_ptr->flags2 & RF2_STUPID) p_ptr->stat_add[A_INT] -= 1;
- if (r_ptr->flags2 & RF2_SMART) p_ptr->stat_add[A_INT] += 1;
- if (r_ptr->flags2 & RF2_REFLECTING) p_ptr->reflect = TRUE;
- if (r_ptr->flags2 & RF2_INVISIBLE) p_ptr->invis += 20;
- if (r_ptr->flags2 & RF2_REGENERATE) p_ptr->regenerate = TRUE;
- if (r_ptr->flags2 & RF2_AURA_FIRE) p_ptr->sh_fire = TRUE;
- if (r_ptr->flags2 & RF2_AURA_ELEC) p_ptr->sh_elec = TRUE;
- if (r_ptr->flags2 & RF2_PASS_WALL) p_ptr->wraith_form = TRUE;
- if (r_ptr->flags3 & RF3_SUSCEP_FIRE) p_ptr->sensible_fire = TRUE;
- if (r_ptr->flags3 & RF3_IM_ACID) p_ptr->resist_acid = TRUE;
- if (r_ptr->flags3 & RF3_IM_ELEC) p_ptr->resist_elec = TRUE;
- if (r_ptr->flags3 & RF3_IM_FIRE) p_ptr->resist_fire = TRUE;
- if (r_ptr->flags3 & RF3_IM_POIS) p_ptr->resist_pois = TRUE;
- if (r_ptr->flags3 & RF3_IM_COLD) p_ptr->resist_cold = TRUE;
- if (r_ptr->flags3 & RF3_RES_NETH) p_ptr->resist_neth = TRUE;
- if (r_ptr->flags3 & RF3_RES_NEXU) p_ptr->resist_nexus = TRUE;
- if (r_ptr->flags3 & RF3_RES_DISE) p_ptr->resist_disen = TRUE;
- if (r_ptr->flags3 & RF3_NO_FEAR) p_ptr->resist_fear = TRUE;
- if (r_ptr->flags3 & RF3_NO_SLEEP) p_ptr->free_act = TRUE;
- if (r_ptr->flags3 & RF3_NO_CONF) p_ptr->resist_conf = TRUE;
- if (r_ptr->flags7 & RF7_CAN_FLY) p_ptr->ffall = TRUE;
- if (r_ptr->flags7 & RF7_AQUATIC) p_ptr->water_breath = TRUE;
+ if (r_ptr->flags & RF_NEVER_MOVE) p_ptr->immovable = TRUE;
+ if (r_ptr->flags & RF_STUPID) p_ptr->stat_add[A_INT] -= 1;
+ if (r_ptr->flags & RF_SMART) p_ptr->stat_add[A_INT] += 1;
+ if (r_ptr->flags & RF_REFLECTING) p_ptr->reflect = TRUE;
+ if (r_ptr->flags & RF_INVISIBLE) p_ptr->invis += 20;
+ if (r_ptr->flags & RF_REGENERATE) p_ptr->regenerate = TRUE;
+ if (r_ptr->flags & RF_AURA_FIRE) p_ptr->sh_fire = TRUE;
+ if (r_ptr->flags & RF_AURA_ELEC) p_ptr->sh_elec = TRUE;
+ if (r_ptr->flags & RF_PASS_WALL) p_ptr->wraith_form = TRUE;
+ if (r_ptr->flags & RF_SUSCEP_FIRE) p_ptr->sensible_fire = TRUE;
+ if (r_ptr->flags & RF_IM_ACID) p_ptr->resist_acid = TRUE;
+ if (r_ptr->flags & RF_IM_ELEC) p_ptr->resist_elec = TRUE;
+ if (r_ptr->flags & RF_IM_FIRE) p_ptr->resist_fire = TRUE;
+ if (r_ptr->flags & RF_IM_POIS) p_ptr->resist_pois = TRUE;
+ if (r_ptr->flags & RF_IM_COLD) p_ptr->resist_cold = TRUE;
+ if (r_ptr->flags & RF_RES_NETH) p_ptr->resist_neth = TRUE;
+ if (r_ptr->flags & RF_RES_NEXU) p_ptr->resist_nexus = TRUE;
+ if (r_ptr->flags & RF_RES_DISE) p_ptr->resist_disen = TRUE;
+ if (r_ptr->flags & RF_NO_FEAR) p_ptr->resist_fear = TRUE;
+ if (r_ptr->flags & RF_NO_SLEEP) p_ptr->free_act = TRUE;
+ if (r_ptr->flags & RF_NO_CONF) p_ptr->resist_conf = TRUE;
+ if (r_ptr->flags & RF_CAN_FLY) p_ptr->ffall = TRUE;
+ if (r_ptr->flags & RF_AQUATIC) p_ptr->water_breath = TRUE;
}
-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 */
int num = 0;
- if (has_ability(AB_MAX_BLOW1)) num++;
- if (has_ability(AB_MAX_BLOW2)) num++;
+ if (p_ptr->has_ability(AB_MAX_BLOW1)) num++;
+ if (p_ptr->has_ability(AB_MAX_BLOW2)) num++;
return num;
}
@@ -2351,10 +2202,10 @@ int get_archery_skill()
}
/* Apply gods */
-void calc_gods()
+static void calc_gods()
{
/* Boost WIS if the player follows Eru */
- GOD(GOD_ERU)
+ if (p_ptr->pgod == GOD_ERU)
{
if (p_ptr->grace > 10000) p_ptr->stat_add[A_WIS] += 1;
if (p_ptr->grace > 20000) p_ptr->stat_add[A_WIS] += 1;
@@ -2362,7 +2213,7 @@ void calc_gods()
}
/* Boost str, con, chr and reduce int, wis if the player follows Melkor */
- GOD(GOD_MELKOR)
+ if (p_ptr->pgod == GOD_MELKOR)
{
if (p_ptr->grace > 10000) p_ptr->stat_add[A_STR] += 1;
if (p_ptr->grace > 20000) p_ptr->stat_add[A_STR] += 1;
@@ -2384,7 +2235,7 @@ void calc_gods()
if (p_ptr->grace > 20000) p_ptr->stat_add[A_WIS] -= 1;
if (p_ptr->grace > 30000) p_ptr->stat_add[A_WIS] -= 1;
- PRAY_GOD(GOD_MELKOR)
+ if (praying_to(GOD_MELKOR))
{
if (p_ptr->grace > 5000) p_ptr->invis += 30;
if (p_ptr->grace > 15000) p_ptr->immune_fire = TRUE;
@@ -2393,7 +2244,7 @@ void calc_gods()
}
/* Gifts of Manwe if the player is praying to Manwe */
- PRAY_GOD(GOD_MANWE)
+ if (praying_to(GOD_MANWE))
{
s32b add = p_ptr->grace;
@@ -2408,13 +2259,13 @@ void calc_gods()
}
/* Manwe bonus not requiring the praying status */
- GOD(GOD_MANWE)
+ if (p_ptr->pgod == GOD_MANWE)
{
if (p_ptr->grace >= 2000) p_ptr->ffall = TRUE;
}
/* Boost Str and Con if the player is following Tulkas */
- GOD(GOD_TULKAS)
+ if (p_ptr->pgod == GOD_TULKAS)
{
if (p_ptr->grace > 5000) p_ptr->stat_add[A_CON] += 1;
if (p_ptr->grace > 10000) p_ptr->stat_add[A_CON] += 1;
@@ -2424,133 +2275,279 @@ 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 */
+ if (p_ptr->pgod == GOD_AULE)
+ {
+ if (p_ptr->grace > 0)
+ {
+ int bonus;
+ /* Resist fire*/
+ 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. */
+ if (p_ptr->pgod == 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. */
+ if (p_ptr->pgod == 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 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 corruptions */
+static void calc_corruptions()
+{
+ auto &s_info = game->s_info;
+
+ if (player_has_corruption(CORRUPT_BALROG_AURA))
+ {
+ p_ptr->xtra_flags |= TR_SH_FIRE;
+ p_ptr->xtra_flags |= TR_LITE1;
+ }
+
+ if (player_has_corruption(CORRUPT_BALROG_WINGS))
+ {
+ p_ptr->xtra_flags |= TR_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_flags |= TR_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_flags |= TR_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_flags |= (TR_REGEN | TR_AGGRAVATE | ESP_TROLL);
+ }
}
/* Apply flags */
static int extra_blows;
static int extra_shots;
-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)
+void apply_flags(object_flag_set const &f, s16b pval, s16b tval, s16b to_h, s16b to_d, s16b to_a)
{
s16b antimagic_mod;
+ // Mix into computed flags
+ p_ptr->computed_flags |= f;
+
/* Affect stats */
- if (f1 & (TR1_STR)) p_ptr->stat_add[A_STR] += pval;
- if (f1 & (TR1_INT)) p_ptr->stat_add[A_INT] += pval;
- if (f1 & (TR1_WIS)) p_ptr->stat_add[A_WIS] += pval;
- if (f1 & (TR1_DEX)) p_ptr->stat_add[A_DEX] += pval;
- if (f1 & (TR1_CON)) p_ptr->stat_add[A_CON] += pval;
- if (f1 & (TR1_CHR)) p_ptr->stat_add[A_CHR] += pval;
- if (f5 & (TR5_LUCK)) p_ptr->luck_cur += pval;
+ if (f & TR_STR) p_ptr->stat_add[A_STR] += pval;
+ if (f & TR_INT) p_ptr->stat_add[A_INT] += pval;
+ if (f & TR_WIS) p_ptr->stat_add[A_WIS] += pval;
+ if (f & TR_DEX) p_ptr->stat_add[A_DEX] += pval;
+ if (f & TR_CON) p_ptr->stat_add[A_CON] += pval;
+ if (f & TR_CHR) p_ptr->stat_add[A_CHR] += pval;
+ if (f & TR_LUCK) p_ptr->luck_cur += pval;
/* Affect spell power */
- if (f1 & (TR1_SPELL)) p_ptr->to_s += pval;
+ if (f & TR_SPELL) p_ptr->to_s += pval;
/* Affect mana capacity */
- if (f1 & (TR1_MANA)) p_ptr->to_m += pval;
+ if (f & TR_MANA) p_ptr->to_m += pval;
/* Affect life capacity */
- if (f2 & (TR2_LIFE)) p_ptr->to_l += pval;
+ if (f & TR_LIFE) p_ptr->to_l += pval;
/* Affect stealth */
- if (f1 & (TR1_STEALTH)) p_ptr->skill_stl += pval;
-
- /* Affect searching ability (factor of five) */
- if (f1 & (TR1_SEARCH)) p_ptr->skill_srh += (pval * 5);
-
- /* Affect searching frequency (factor of five) */
- if (f1 & (TR1_SEARCH)) p_ptr->skill_fos += (pval * 5);
+ if (f & TR_STEALTH) p_ptr->skill_stl += pval;
/* Affect infravision */
- if (f1 & (TR1_INFRA)) p_ptr->see_infra += pval;
+ if (f & TR_INFRA) p_ptr->see_infra += pval;
/* Affect digging (factor of 20) */
- if (f1 & (TR1_TUNNEL)) p_ptr->skill_dig += (pval * 20);
+ if (f & TR_TUNNEL) p_ptr->skill_dig += (pval * 20);
/* Affect speed */
- if (f1 & (TR1_SPEED)) p_ptr->pspeed += pval;
+ if (f & TR_SPEED) p_ptr->pspeed += pval;
/* Affect blows */
- if (f1 & (TR1_BLOWS)) extra_blows += pval;
- if (f5 & (TR5_CRIT)) p_ptr->xtra_crit += pval;
+ if (f & TR_BLOWS) extra_blows += pval;
+ if (f & TR_CRIT) p_ptr->xtra_crit += pval;
/* Hack -- Sensible fire */
- if (f2 & (TR2_SENS_FIRE)) p_ptr->sensible_fire = TRUE;
+ if (f & TR_SENS_FIRE) p_ptr->sensible_fire = TRUE;
/* Hack -- cause earthquakes */
- if (f1 & (TR1_IMPACT)) p_ptr->impact = TRUE;
+ if (f & TR_IMPACT) p_ptr->impact = TRUE;
/* Affect invisibility */
- if (f2 & (TR2_INVIS)) p_ptr->invis += (pval * 10);
+ if (f & TR_INVIS) p_ptr->invis += (pval * 10);
/* Boost shots */
- if (f3 & (TR3_XTRA_SHOTS)) extra_shots++;
+ if (f & TR_XTRA_SHOTS) extra_shots++;
/* Various flags */
- if (f3 & (TR3_AGGRAVATE)) p_ptr->aggravate = TRUE;
- if (f3 & (TR3_TELEPORT)) p_ptr->teleport = TRUE;
- if (f5 & (TR5_DRAIN_MANA)) p_ptr->drain_mana++;
- if (f5 & (TR5_DRAIN_HP)) p_ptr->drain_life++;
- if (f3 & (TR3_DRAIN_EXP)) p_ptr->exp_drain = TRUE;
- if (f3 & (TR3_BLESSED)) p_ptr->bless_blade = TRUE;
- if (f3 & (TR3_XTRA_MIGHT)) p_ptr->xtra_might += pval;
- if (f3 & (TR3_SLOW_DIGEST)) p_ptr->slow_digest = TRUE;
- if (f3 & (TR3_REGEN)) p_ptr->regenerate = TRUE;
- if (esp) p_ptr->telepathy |= esp;
- if ((tval != TV_LITE) && (f3 & (TR3_LITE1))) p_ptr->lite = TRUE;
- if ((tval != TV_LITE) && (f4 & (TR4_LITE2))) p_ptr->lite = TRUE;
- if ((tval != TV_LITE) && (f4 & (TR4_LITE3))) p_ptr->lite = TRUE;
- if (f3 & (TR3_SEE_INVIS)) p_ptr->see_inv = TRUE;
- if (f2 & (TR2_FREE_ACT)) p_ptr->free_act = TRUE;
- if (f2 & (TR2_HOLD_LIFE)) p_ptr->hold_life = TRUE;
- if (f3 & (TR3_WRAITH)) p_ptr->wraith_form = TRUE;
- if (f3 & (TR3_FEATHER)) p_ptr->ffall = TRUE;
- if (f4 & (TR4_FLY)) p_ptr->fly = TRUE;
- if (f4 & (TR4_CLIMB)) p_ptr->climb = TRUE;
+ if (f & TR_AGGRAVATE) p_ptr->aggravate = TRUE;
+ if (f & TR_TELEPORT) p_ptr->teleport = TRUE;
+ if (f & TR_DRAIN_MANA) p_ptr->drain_mana++;
+ if (f & TR_DRAIN_HP) p_ptr->drain_life++;
+ if (f & TR_DRAIN_EXP) p_ptr->exp_drain = TRUE;
+ if (f & TR_BLESSED) p_ptr->bless_blade = TRUE;
+ if (f & TR_XTRA_MIGHT) p_ptr->xtra_might += pval;
+ if (f & TR_SLOW_DIGEST) p_ptr->slow_digest = TRUE;
+ if (f & TR_REGEN) p_ptr->regenerate = TRUE;
+ if ((tval != TV_LITE) && (f & TR_LITE1)) p_ptr->lite = TRUE;
+ if ((tval != TV_LITE) && (f & TR_LITE2)) p_ptr->lite = TRUE;
+ if ((tval != TV_LITE) && (f & TR_LITE3)) p_ptr->lite = TRUE;
+ if (f & TR_SEE_INVIS) p_ptr->see_inv = TRUE;
+ if (f & TR_FREE_ACT) p_ptr->free_act = TRUE;
+ if (f & TR_HOLD_LIFE) p_ptr->hold_life = TRUE;
+ if (f & TR_WRAITH) p_ptr->wraith_form = TRUE;
+ if (f & TR_FEATHER) p_ptr->ffall = TRUE;
+ if (f & TR_FLY) p_ptr->fly = TRUE;
+ if (f & TR_CLIMB) p_ptr->climb = TRUE;
/* Immunity flags */
- if (f2 & (TR2_IM_FIRE)) p_ptr->immune_fire = TRUE;
- if (f2 & (TR2_IM_ACID)) p_ptr->immune_acid = TRUE;
- if (f2 & (TR2_IM_COLD)) p_ptr->immune_cold = TRUE;
- if (f2 & (TR2_IM_ELEC)) p_ptr->immune_elec = TRUE;
+ if (f & TR_IM_FIRE) p_ptr->immune_fire = TRUE;
+ if (f & TR_IM_ACID) p_ptr->immune_acid = TRUE;
+ if (f & TR_IM_COLD) p_ptr->immune_cold = TRUE;
+ if (f & TR_IM_ELEC) p_ptr->immune_elec = TRUE;
/* Resistance flags */
- if (f2 & (TR2_RES_ACID)) p_ptr->resist_acid = TRUE;
- if (f2 & (TR2_RES_ELEC)) p_ptr->resist_elec = TRUE;
- if (f2 & (TR2_RES_FIRE)) p_ptr->resist_fire = TRUE;
- if (f2 & (TR2_RES_COLD)) p_ptr->resist_cold = TRUE;
- if (f2 & (TR2_RES_POIS)) p_ptr->resist_pois = TRUE;
- if (f2 & (TR2_RES_FEAR)) p_ptr->resist_fear = TRUE;
- if (f2 & (TR2_RES_CONF)) p_ptr->resist_conf = TRUE;
- if (f2 & (TR2_RES_SOUND)) p_ptr->resist_sound = TRUE;
- if (f2 & (TR2_RES_LITE)) p_ptr->resist_lite = TRUE;
- if (f2 & (TR2_RES_DARK)) p_ptr->resist_dark = TRUE;
- if (f2 & (TR2_RES_CHAOS)) p_ptr->resist_chaos = TRUE;
- if (f2 & (TR2_RES_DISEN)) p_ptr->resist_disen = TRUE;
- if (f2 & (TR2_RES_SHARDS)) p_ptr->resist_shard = TRUE;
- if (f2 & (TR2_RES_NEXUS)) p_ptr->resist_nexus = TRUE;
- if (f2 & (TR2_RES_BLIND)) p_ptr->resist_blind = TRUE;
- if (f2 & (TR2_RES_NETHER)) p_ptr->resist_neth = TRUE;
- if (f4 & (TR4_IM_NETHER)) p_ptr->immune_neth = TRUE;
-
- if (f2 & (TR2_REFLECT)) p_ptr->reflect = TRUE;
- if (f3 & (TR3_SH_FIRE)) p_ptr->sh_fire = TRUE;
- if (f3 & (TR3_SH_ELEC)) p_ptr->sh_elec = TRUE;
- if (f3 & (TR3_NO_MAGIC)) p_ptr->anti_magic = TRUE;
- if (f3 & (TR3_NO_TELE)) p_ptr->anti_tele = TRUE;
+ if (f & TR_RES_ACID) p_ptr->resist_acid = TRUE;
+ if (f & TR_RES_ELEC) p_ptr->resist_elec = TRUE;
+ if (f & TR_RES_FIRE) p_ptr->resist_fire = TRUE;
+ if (f & TR_RES_COLD) p_ptr->resist_cold = TRUE;
+ if (f & TR_RES_POIS) p_ptr->resist_pois = TRUE;
+ if (f & TR_RES_FEAR) p_ptr->resist_fear = TRUE;
+ if (f & TR_RES_CONF) p_ptr->resist_conf = TRUE;
+ if (f & TR_RES_SOUND) p_ptr->resist_sound = TRUE;
+ if (f & TR_RES_LITE) p_ptr->resist_lite = TRUE;
+ if (f & TR_RES_DARK) p_ptr->resist_dark = TRUE;
+ if (f & TR_RES_CHAOS) p_ptr->resist_chaos = TRUE;
+ if (f & TR_RES_DISEN) p_ptr->resist_disen = TRUE;
+ if (f & TR_RES_SHARDS) p_ptr->resist_shard = TRUE;
+ if (f & TR_RES_NEXUS) p_ptr->resist_nexus = TRUE;
+ if (f & TR_RES_BLIND) p_ptr->resist_blind = TRUE;
+ if (f & TR_RES_NETHER) p_ptr->resist_neth = TRUE;
+ if (f & TR_IM_NETHER) p_ptr->immune_neth = TRUE;
+
+ if (f & TR_REFLECT) p_ptr->reflect = TRUE;
+ if (f & TR_SH_FIRE) p_ptr->sh_fire = TRUE;
+ if (f & TR_SH_ELEC) p_ptr->sh_elec = TRUE;
+ if (f & TR_NO_MAGIC) p_ptr->anti_magic = TRUE;
+ if (f & TR_NO_TELE) p_ptr->anti_tele = TRUE;
/* Sustain flags */
- if (f2 & (TR2_SUST_STR)) p_ptr->sustain_str = TRUE;
- if (f2 & (TR2_SUST_INT)) p_ptr->sustain_int = TRUE;
- if (f2 & (TR2_SUST_WIS)) p_ptr->sustain_wis = TRUE;
- if (f2 & (TR2_SUST_DEX)) p_ptr->sustain_dex = TRUE;
- if (f2 & (TR2_SUST_CON)) p_ptr->sustain_con = TRUE;
- if (f2 & (TR2_SUST_CHR)) p_ptr->sustain_chr = TRUE;
+ if (f & TR_SUST_STR) p_ptr->sustain_str = TRUE;
+ if (f & TR_SUST_INT) p_ptr->sustain_int = TRUE;
+ if (f & TR_SUST_WIS) p_ptr->sustain_wis = TRUE;
+ if (f & TR_SUST_DEX) p_ptr->sustain_dex = TRUE;
+ if (f & TR_SUST_CON) p_ptr->sustain_con = TRUE;
+ if (f & TR_SUST_CHR) p_ptr->sustain_chr = TRUE;
- if (f4 & (TR4_PRECOGNITION)) p_ptr->precognition = TRUE;
+ if (f & TR_PRECOGNITION) p_ptr->precognition = TRUE;
antimagic_mod = to_h + to_d + to_a;
- if (f4 & (TR4_ANTIMAGIC_50))
+ if (f & TR_ANTIMAGIC_50)
{
s32b tmp;
@@ -2561,60 +2558,72 @@ void apply_flags(u32b f1, u32b f2, u32b f3, u32b f4, u32b f5, u32b esp, s16b pva
if (tmp > 0) p_ptr->antimagic_dis += tmp;
}
- if (f4 & (TR4_ANTIMAGIC_30))
+ if (f & TR_AUTO_ID)
{
- s32b tmp;
-
- tmp = 7 + get_skill_scale(SKILL_ANTIMAGIC, 33) - antimagic_mod;
- if (tmp > 0) p_ptr->antimagic += tmp;
-
- tmp = 1 + get_skill_scale(SKILL_ANTIMAGIC, 2) - antimagic_mod / 15;
- if (tmp > 0) p_ptr->antimagic_dis += tmp;
+ p_ptr->auto_id = TRUE;
}
- if (f4 & (TR4_ANTIMAGIC_20))
- {
- s32b tmp;
+ /* The new code implementing Tolkien's concept of "Black Breath"
+ * takes advantage of the existing drain_exp character flag, renamed
+ * "black_breath". This flag can also be set by a unlucky blow from
+ * an undead. -LM-
+ */
+ if (f & TR_BLACK_BREATH) p_ptr->black_breath = TRUE;
- tmp = 5 + get_skill_scale(SKILL_ANTIMAGIC, 15) - antimagic_mod;
- if (tmp > 0) p_ptr->antimagic += tmp;
+ if (f & TR_IMMOVABLE) p_ptr->immovable = TRUE;
- p_ptr->antimagic_dis += 2;
+ /* Breaths */
+ if (f & TR_WATER_BREATH)
+ {
+ p_ptr->water_breath = TRUE;
}
- if (f4 & (TR4_ANTIMAGIC_10))
+ if (f & TR_MAGIC_BREATH)
{
- s32b tmp;
-
- tmp = 1 + get_skill_scale(SKILL_ANTIMAGIC, 9) - antimagic_mod;
- if (tmp > 0) p_ptr->antimagic += tmp;
-
- p_ptr->antimagic_dis += 1;
+ p_ptr->magical_breath = TRUE;
+ p_ptr->water_breath = TRUE;
}
+}
+
- if (f4 & (TR4_AUTO_ID))
+/**
+ * Apply player level flags
+ */
+template <class LF>
+static void apply_lflags(LF const &lflags)
+{
+ for (int i = 1; i <= p_ptr->lev; i++)
{
- p_ptr->auto_id = TRUE;
+ apply_flags(lflags[i].oflags, lflags[i].pval, 0, 0, 0, 0);
}
+}
- /* The new code implementing Tolkien's concept of "Black Breath"
- * takes advantage of the existing drain_exp character flag, renamed
- * "black_breath". This flag can also be set by a unlucky blow from
- * an undead. -LM-
- */
- if (f4 & (TR4_BLACK_BREATH)) p_ptr->black_breath = TRUE;
- if (f5 & (TR5_IMMOVABLE)) p_ptr->immovable = TRUE;
+/**
+ * Are barehand fighter's hands empty?
+ */
+static bool_ monk_empty_hands()
+{
+ int i;
+ object_type *o_ptr;
- /* Breaths */
- if (f5 & (TR5_WATER_BREATH)) p_ptr->water_breath = TRUE;
- if (f5 & (TR5_MAGIC_BREATH))
+ if (p_ptr->melee_style != SKILL_HAND) return FALSE;
+
+ i = 0;
+ while (p_ptr->body_parts[i] == INVEN_WIELD)
{
- p_ptr->magical_breath = TRUE;
- p_ptr->water_breath = TRUE;
+ o_ptr = &p_ptr->inventory[INVEN_WIELD + i];
+
+ if (o_ptr->k_idx) return FALSE;
+
+ i++;
}
+
+ return TRUE;
}
+
+
/*
* Calculate the players current "state", taking into account
* not only race/class intrinsics, but also objects being worn
@@ -2638,21 +2647,28 @@ void apply_flags(u32b f1, u32b f2, u32b f3, u32b f4, u32b f5, u32b esp, s16b pva
*/
void calc_bonuses(bool_ silent)
{
+ auto const &s_descriptors = game->edit_data.s_descriptors;
+ auto const &r_info = game->edit_data.r_info;
+ auto &s_info = game->s_info;
+ auto const &a_info = game->edit_data.a_info;
+
+ static bool_ monk_notify_aux = FALSE;
int i, j, hold;
int old_speed;
- u32b old_telepathy;
int old_see_inv;
int old_dis_ac;
int old_dis_to_a;
object_type *o_ptr;
- u32b f1, f2, f3, f4, f5, esp;
+ bool_ monk_armour_aux;
+ /* Save the old computed_flags */
+ auto old_computed_flags = p_ptr->computed_flags;
+
/* Save the old speed */
old_speed = p_ptr->pspeed;
/* Save the old vision stuff */
- old_telepathy = p_ptr->telepathy;
old_see_inv = p_ptr->see_inv;
/* Save the old armor class */
@@ -2697,9 +2713,6 @@ void calc_bonuses(bool_ silent)
/* Starts with single throwing damage */
p_ptr->throw_mult = 1;
- /* Reset the "xtra" tval */
- p_ptr->tval_xtra = 0;
-
/* Reset the "ammo" tval */
p_ptr->tval_ammo = 0;
@@ -2723,7 +2736,7 @@ void calc_bonuses(bool_ silent)
p_ptr->climb = FALSE;
p_ptr->ffall = FALSE;
p_ptr->hold_life = FALSE;
- p_ptr->telepathy = 0;
+ p_ptr->computed_flags = object_flag_set();
p_ptr->lite = FALSE;
p_ptr->sustain_str = FALSE;
p_ptr->sustain_int = FALSE;
@@ -2777,10 +2790,6 @@ void calc_bonuses(bool_ silent)
/* Base infravision (purely racial) */
p_ptr->see_infra = rp_ptr->infra + rmp_ptr->infra;
-
- /* Base skill -- disarming */
- p_ptr->skill_dis = 0;
-
/* Base skill -- magic devices */
p_ptr->skill_dev = 0;
@@ -2790,12 +2799,6 @@ void calc_bonuses(bool_ silent)
/* Base skill -- stealth */
p_ptr->skill_stl = 0;
- /* Base skill -- searching ability */
- p_ptr->skill_srh = 0;
-
- /* Base skill -- searching frequency */
- p_ptr->skill_fos = 0;
-
/* Base skill -- combat (normal) */
p_ptr->skill_thn = 0;
@@ -2810,18 +2813,15 @@ void calc_bonuses(bool_ silent)
p_ptr->skill_dig = 0;
/* Xtra player flags */
- p_ptr->xtra_f1 = 0;
- p_ptr->xtra_f2 = 0;
- p_ptr->xtra_f3 = 0;
- p_ptr->xtra_f4 = 0;
- p_ptr->xtra_f5 = 0;
- p_ptr->xtra_esp = 0;
+ p_ptr->xtra_flags = object_flag_set();
/* Hide the skills that should auto hide */
- for (i = 0; i < max_s_idx; i++)
+ for (std::size_t i = 0; i < s_descriptors.size(); i++)
{
- if (s_info[i].flags1 & SKF1_AUTO_HIDE)
- s_info[i].hidden = TRUE;
+ if (s_descriptors[i].flags & SKF_AUTO_HIDE)
+ {
+ s_info[i].hidden = true;
+ }
}
/* Base Luck */
@@ -2837,16 +2837,17 @@ 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();
+
+ /* Take care of corruptions */
+ calc_corruptions();
/* The powers gived by the wielded monster */
calc_wield_monster();
- for (i = 1; i <= p_ptr->lev; i++)
- {
- apply_flags(cp_ptr->oflags1[i], cp_ptr->oflags2[i], cp_ptr->oflags3[i], cp_ptr->oflags4[i], cp_ptr->oflags5[i], cp_ptr->oesp[i], cp_ptr->opval[i], 0, 0, 0, 0);
- }
+ /* Apply all the level-dependent class flags */
+ apply_lflags(cp_ptr->lflags);
if (p_ptr->melee_style == SKILL_HAND)
{
@@ -2874,7 +2875,10 @@ void calc_bonuses(bool_ silent)
if (get_skill(SKILL_DAEMON) > 20) p_ptr->resist_conf = TRUE;
if (get_skill(SKILL_DAEMON) > 30) p_ptr->resist_fear = TRUE;
- if ( get_skill(SKILL_MINDCRAFT) >= 40 ) p_ptr->telepathy = ESP_ALL;
+ if ( get_skill(SKILL_MINDCRAFT) >= 40 )
+ {
+ p_ptr->computed_flags |= ESP_ALL;
+ }
if (p_ptr->astral)
{
@@ -2884,30 +2888,23 @@ void calc_bonuses(bool_ silent)
/***** Races ****/
if ((!p_ptr->mimic_form) && (!p_ptr->body_monster))
{
- int i;
-
- for (i = 1; i <= p_ptr->lev; i++)
- {
- apply_flags(rp_ptr->oflags1[i], rp_ptr->oflags2[i], rp_ptr->oflags3[i], rp_ptr->oflags4[i], rp_ptr->oflags5[i], rp_ptr->oesp[i], rp_ptr->opval[i], 0, 0, 0, 0);
- apply_flags(rmp_ptr->oflags1[i], rmp_ptr->oflags2[i], rmp_ptr->oflags3[i], rmp_ptr->oflags4[i], rmp_ptr->oflags5[i], rmp_ptr->oesp[i], rmp_ptr->opval[i], 0, 0, 0, 0);
- }
+ /* Apply level-dependent flags from race/sub-race */
+ apply_lflags(rp_ptr->lflags);
+ apply_lflags(rmp_ptr->lflags);
- if (PRACE_FLAG(PR1_HURT_LITE))
+ /* Is the player's race hurt by light? */
+ if (race_flags_p(PR_HURT_LITE))
p_ptr->sensible_lite = TRUE;
}
/* The extra flags */
- apply_flags(p_ptr->xtra_f1, p_ptr->xtra_f2, p_ptr->xtra_f3, p_ptr->xtra_f4, p_ptr->xtra_f5, p_ptr->xtra_esp, 0, 0, 0, 0, 0);
+ apply_flags(p_ptr->xtra_flags, 0, 0, 0, 0, 0);
- /* Hack -- apply racial/class stat maxes */
- if (p_ptr->maximize)
+ /* Apply the racial modifiers */
+ for (i = 0; i < 6; i++)
{
- /* Apply the racial modifiers */
- for (i = 0; i < 6; i++)
- {
- /* Modify the stats for "race" */
- p_ptr->stat_add[i] += (rp_ptr->r_adj[i] + rmp_ptr->r_adj[i] + cp_ptr->c_adj[i]);
- }
+ /* Modify the stats for "race" */
+ p_ptr->stat_add[i] += (rp_ptr->ps.adj[i] + rmp_ptr->ps.adj[i] + cp_ptr->ps.adj[i]);
}
@@ -2921,7 +2918,7 @@ void calc_bonuses(bool_ silent)
/* Extract the item flags */
object_flags_no_set = TRUE;
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ auto flags = object_flags(o_ptr);
object_flags_no_set = FALSE;
/* MEGA ugly hack -- set spacetime distortion resistance */
@@ -2933,10 +2930,10 @@ void calc_bonuses(bool_ silent)
/* Hack - don't give the Black Breath when merely inspecting a weapon */
if (silent)
{
- f4 &= ~TR4_BLACK_BREATH;
+ flags &= ~TR_BLACK_BREATH;
}
- apply_flags(f1, f2, f3, f4, f5, esp, o_ptr->pval, o_ptr->tval, o_ptr->to_h, o_ptr->to_d, o_ptr->to_a);
+ apply_flags(flags, o_ptr->pval, o_ptr->tval, o_ptr->to_h, o_ptr->to_d, o_ptr->to_a);
if (o_ptr->name1)
{
@@ -3014,7 +3011,7 @@ void calc_bonuses(bool_ silent)
/* Hack -- aura of fire also provides light */
if (p_ptr->sh_fire) p_ptr->lite = TRUE;
- if (PRACE_FLAG(PR1_AC_LEVEL))
+ if (race_flags_p(PR_AC_LEVEL))
{
p_ptr->to_a += 20 + (p_ptr->lev / 5);
p_ptr->dis_to_a += 20 + (p_ptr->lev / 5);
@@ -3039,7 +3036,7 @@ void calc_bonuses(bool_ silent)
p_ptr->stat_top[i] = top;
/* Redisplay the stats later */
- p_ptr->redraw |= (PR_STATS);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
@@ -3055,7 +3052,7 @@ void calc_bonuses(bool_ silent)
p_ptr->stat_use[i] = use;
/* Redisplay the stats later */
- p_ptr->redraw |= (PR_STATS);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
@@ -3101,7 +3098,7 @@ void calc_bonuses(bool_ silent)
}
/* Provide the damage we get from sacrifice */
- GOD(GOD_MELKOR)
+ if (p_ptr->pgod == GOD_MELKOR)
{
int x = wisdom_scale(4);
if (x < 1) x = 1;
@@ -3119,12 +3116,9 @@ void calc_bonuses(bool_ silent)
p_ptr->to_a += tactic_info[(byte)p_ptr->tactic].to_ac;
p_ptr->skill_stl += tactic_info[(byte)p_ptr->tactic].to_stealth;
- p_ptr->skill_dis += tactic_info[(byte)p_ptr->tactic].to_disarm;
p_ptr->skill_sav += tactic_info[(byte)p_ptr->tactic].to_saving;
p_ptr->pspeed += move_info[(byte)p_ptr->movement].to_speed;
- p_ptr->skill_srh += move_info[(byte)p_ptr->movement].to_search;
- p_ptr->skill_fos += move_info[(byte)p_ptr->movement].to_percep;
p_ptr->skill_stl += move_info[(byte)p_ptr->movement].to_stealth;
/* Apply temporary "stun" */
@@ -3151,6 +3145,12 @@ void calc_bonuses(bool_ silent)
p_ptr->dis_to_a += 100;
}
+ /* Temporary precognition */
+ if (p_ptr->tim_precognition > 0)
+ {
+ apply_flags(TR_PRECOGNITION, 0, 0, 0, 0, 0);
+ }
+
/* Breath */
if (p_ptr->tim_water_breath)
{
@@ -3241,27 +3241,12 @@ void calc_bonuses(bool_ silent)
p_ptr->dis_to_h += 15;
}
- /* Temporary "Meditation" */
- if (p_ptr->meditation)
- {
- p_ptr->to_d -= 25;
- p_ptr->dis_to_d -= 25;
- p_ptr->to_h -= 25;
- p_ptr->dis_to_h -= 25;
- }
-
/* Temporary "Reflection" */
if (p_ptr->tim_reflect)
{
p_ptr->reflect = TRUE;
}
- /* Temporary "Time Resistance" */
- if (p_ptr->tim_res_time)
- {
- p_ptr->resist_continuum = TRUE;
- }
-
/* Temporary "Levitation" and "Flying" */
if (p_ptr->tim_ffall)
{
@@ -3272,19 +3257,6 @@ void calc_bonuses(bool_ silent)
p_ptr->fly = TRUE;
}
- /* Temporary "Fire Aura" */
- if (p_ptr->tim_fire_aura)
- {
- p_ptr->sh_fire = TRUE;
- }
-
- /* Oppose Light & Dark */
- if (p_ptr->oppose_ld)
- {
- p_ptr->resist_lite = TRUE;
- p_ptr->resist_dark = TRUE;
- }
-
/* Oppose Chaos & Confusion */
if (p_ptr->oppose_cc)
{
@@ -3292,26 +3264,6 @@ void calc_bonuses(bool_ silent)
p_ptr->resist_conf = TRUE;
}
- /* Oppose Sound & Shards */
- if (p_ptr->oppose_ss)
- {
- p_ptr->resist_sound = TRUE;
- p_ptr->resist_shard = TRUE;
- }
-
- /* Oppose Nexus */
- if (p_ptr->oppose_nex)
- {
- p_ptr->resist_nexus = TRUE;
- }
-
- /* Mental barrier */
- if (p_ptr->tim_mental_barrier)
- {
- p_ptr->sustain_int = TRUE;
- p_ptr->sustain_wis = TRUE;
- }
-
/* Temporary "fast" */
if (p_ptr->fast)
{
@@ -3332,7 +3284,7 @@ void calc_bonuses(bool_ silent)
if (p_ptr->tim_esp)
{
- p_ptr->telepathy |= ESP_ALL;
+ p_ptr->computed_flags |= ESP_ALL;
}
/* Temporary see invisible */
@@ -3373,9 +3325,12 @@ void calc_bonuses(bool_ silent)
/* Hack -- Telepathy Change */
- if (p_ptr->telepathy != old_telepathy)
{
- p_ptr->update |= (PU_MONSTERS);
+ auto const &esp_mask = object_flags_esp();
+ if ((p_ptr->computed_flags & esp_mask) != (old_computed_flags & esp_mask))
+ {
+ p_ptr->update |= (PU_MONSTERS);
+ }
}
/* Hack -- See Invis Change */
@@ -3397,15 +3352,8 @@ void calc_bonuses(bool_ silent)
/* Bloating slows the player down (a little) */
if (p_ptr->food >= PY_FOOD_MAX) p_ptr->pspeed -= 10;
- /* Searching slows the player down */
- if (p_ptr->searching) p_ptr->pspeed -= 10;
-
- /* In order to get a "nice" mana path druids need to ahve a 0 speed */
- if ((p_ptr->druid_extra2 == CLASS_MANA_PATH) && (p_ptr->pspeed > 110))
- p_ptr->pspeed = 110;
-
/* Display the speed (if needed) */
- if (p_ptr->pspeed != old_speed) p_ptr->redraw |= (PR_SPEED);
+ if (p_ptr->pspeed != old_speed) p_ptr->redraw |= (PR_FRAME);
/* Actual Modifier Bonuses (Un-inflate stat bonuses) */
@@ -3424,7 +3372,7 @@ void calc_bonuses(bool_ silent)
if ((p_ptr->dis_ac != old_dis_ac) || (p_ptr->dis_to_a != old_dis_to_a))
{
/* Redraw */
- p_ptr->redraw |= (PR_ARMOR);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
@@ -3508,13 +3456,13 @@ void calc_bonuses(bool_ silent)
if (p_ptr->num_fire < 1) p_ptr->num_fire = 1;
}
- if (PRACE_FLAG(PR1_XTRA_MIGHT_BOW) && p_ptr->tval_ammo == TV_ARROW)
+ if (race_flags_p(PR_XTRA_MIGHT_BOW) && p_ptr->tval_ammo == TV_ARROW)
p_ptr->xtra_might += 1;
- if (PRACE_FLAG(PR1_XTRA_MIGHT_SLING) && p_ptr->tval_ammo == TV_SHOT)
+ if (race_flags_p(PR_XTRA_MIGHT_SLING) && p_ptr->tval_ammo == TV_SHOT)
p_ptr->xtra_might += 1;
- if (PRACE_FLAG(PR1_XTRA_MIGHT_XBOW) && p_ptr->tval_ammo == TV_BOLT)
+ if (race_flags_p(PR_XTRA_MIGHT_XBOW) && p_ptr->tval_ammo == TV_BOLT)
p_ptr->xtra_might += 1;
/* Examine the "current tool" */
@@ -3610,20 +3558,19 @@ void calc_bonuses(bool_ silent)
/* Monsters that only have their "natural" attacks */
else if (!r_info[p_ptr->body_monster].body_parts[BODY_WEAPON])
{
- int str_index, dex_index;
- int num = 0, wgt = 0, mul = 0;
- monster_race *r_ptr = race_info_idx(p_ptr->body_monster, 0);
-
+ int num = 0;
+ int wgt = 0;
+ int mul = 0;
analyze_blow(&num, &wgt, &mul);
/* Access the strength vs weight */
- str_index = (adj_str_blow[p_ptr->stat_ind[A_STR]] * mul / 3);
+ int str_index = (adj_str_blow[p_ptr->stat_ind[A_STR]] * mul / 3);
/* Maximal value */
if (str_index > 11) str_index = 11;
/* Index by dexterity */
- dex_index = (adj_dex_blow[p_ptr->stat_ind[A_DEX]]);
+ int dex_index = (adj_dex_blow[p_ptr->stat_ind[A_DEX]]);
/* Maximal value */
if (dex_index > 11) dex_index = 11;
@@ -3641,6 +3588,7 @@ void calc_bonuses(bool_ silent)
if (p_ptr->num_blow < 1) p_ptr->num_blow = 1;
/* Limit as defined by monster body */
+ auto r_ptr = race_info_idx(p_ptr->body_monster, 0);
for (num = 0; num < p_ptr->num_blow; num++)
if (!r_ptr->blow[num].effect)
break;
@@ -3721,10 +3669,8 @@ void calc_bonuses(bool_ silent)
/* 2handed weapon and shield = less damage */
if (p_ptr->inventory[INVEN_WIELD + i].k_idx && p_ptr->inventory[INVEN_ARM + i].k_idx)
{
- /* Extract the item flags */
- object_flags(&p_ptr->inventory[INVEN_WIELD + i], &f1, &f2, &f3, &f4, &f5, &esp);
-
- if (f4 & TR4_COULD2H)
+ auto const flags = object_flags(&p_ptr->inventory[INVEN_WIELD + i]);
+ if (flags & TR_COULD2H)
{
int tmp;
@@ -3798,22 +3744,12 @@ void calc_bonuses(bool_ silent)
/* Affect Skill -- stealth (bonus one) */
p_ptr->skill_stl += 1;
- /* Affect Skill -- disarming (DEX and INT) */
- p_ptr->skill_dis += adj_dex_dis[p_ptr->stat_ind[A_DEX]];
- p_ptr->skill_dis += adj_int_dis[p_ptr->stat_ind[A_INT]];
-
- /* Affect Skill -- magic devices (INT) */
- p_ptr->skill_dev += get_skill_scale(SKILL_DEVICE, 20);
-
/* Affect Skill -- saving throw (WIS) */
p_ptr->skill_sav += adj_wis_sav[p_ptr->stat_ind[A_WIS]];
/* Affect Skill -- digging (STR) */
p_ptr->skill_dig += adj_str_dig[p_ptr->stat_ind[A_STR]];
- /* Affect Skill -- disarming (skill) */
- p_ptr->skill_dis += (get_skill_scale(SKILL_DISARMING, 75));
-
/* Affect Skill -- magic devices (skill) */
p_ptr->skill_dev += (get_skill_scale(SKILL_DEVICE, 150));
@@ -3823,12 +3759,6 @@ void calc_bonuses(bool_ silent)
/* Affect Skill -- stealth (skill) */
p_ptr->skill_stl += (get_skill_scale(SKILL_STEALTH, 25));
- /* Affect Skill -- search ability (Sneakiness skill) */
- p_ptr->skill_srh += (get_skill_scale(SKILL_SNEAK, 35));
-
- /* Affect Skill -- search frequency (Sneakiness skill) */
- p_ptr->skill_fos += (get_skill_scale(SKILL_SNEAK, 25));
-
/* Affect Skill -- combat (Combat skill + mastery) */
p_ptr->skill_thn += (50 * (((7 * get_skill(p_ptr->melee_style)) + (3 * get_skill(SKILL_COMBAT))) / 10) / 10);
@@ -3956,9 +3886,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);
}
@@ -3966,7 +3893,7 @@ void calc_bonuses(bool_ silent)
/*
* Handle "p_ptr->notice"
*/
-void notice_stuff(void)
+void notice_stuff()
{
/* Notice stuff */
if (!p_ptr->notice) return;
@@ -3991,7 +3918,7 @@ void notice_stuff(void)
/*
* Handle "p_ptr->update"
*/
-void update_stuff(void)
+void update_stuff()
{
/* Update stuff */
if (!p_ptr->update) return;
@@ -4040,7 +3967,6 @@ void update_stuff(void)
if (p_ptr->update & (PU_SPELLS))
{
p_ptr->update &= ~(PU_SPELLS);
- calc_spells();
}
if (p_ptr->update & (PU_POWERS))
@@ -4091,7 +4017,7 @@ void update_stuff(void)
if (p_ptr->update & (PU_MON_LITE))
{
p_ptr->update &= ~(PU_MON_LITE);
- if (monster_lite) update_mon_lite();
+ update_mon_lite();
}
}
@@ -4099,7 +4025,7 @@ void update_stuff(void)
/*
* Handle "p_ptr->redraw"
*/
-void redraw_stuff(void)
+void redraw_stuff()
{
/* Redraw stuff */
if (!p_ptr->redraw) return;
@@ -4113,10 +4039,6 @@ void redraw_stuff(void)
if (character_icky) return;
- /* Should we tell lua to redisplay too ? */
- process_hooks(HOOK_REDRAW, "()");
-
-
/* Hack -- clear the screen */
if (p_ptr->redraw & (PR_WIPE))
{
@@ -4133,182 +4055,10 @@ void redraw_stuff(void)
}
- if (p_ptr->redraw & (PR_BASIC))
- {
- p_ptr->redraw &= ~(PR_BASIC);
- p_ptr->redraw &= ~(PR_MISC | PR_TITLE | PR_STATS);
- p_ptr->redraw &= ~(PR_LEV | PR_EXP | PR_GOLD);
- p_ptr->redraw &= ~(PR_ARMOR | PR_HP | PR_MANA | PR_PIETY | PR_MH);
- p_ptr->redraw &= ~(PR_DEPTH | PR_HEALTH);
- prt_frame_basic();
- }
-
- if (p_ptr->redraw & (PR_MISC))
- {
- p_ptr->redraw &= ~(PR_MISC);
- prt_field(rp_ptr->title + rp_name, ROW_RACE, COL_RACE);
- prt_field(spp_ptr->title + c_name, ROW_CLASS, COL_CLASS);
- }
-
- if (p_ptr->redraw & (PR_TITLE))
- {
- p_ptr->redraw &= ~(PR_TITLE);
- prt_title();
- }
-
- if (p_ptr->redraw & (PR_LEV))
- {
- p_ptr->redraw &= ~(PR_LEV);
- prt_level();
- }
-
- if (p_ptr->redraw & (PR_EXP))
- {
- p_ptr->redraw &= ~(PR_EXP);
- prt_exp();
- }
-
- if (p_ptr->redraw & (PR_STATS))
- {
- p_ptr->redraw &= ~(PR_STATS);
- prt_stat(A_STR);
- prt_stat(A_INT);
- prt_stat(A_WIS);
- prt_stat(A_DEX);
- prt_stat(A_CON);
- prt_stat(A_CHR);
- }
-
- if (p_ptr->redraw & (PR_ARMOR))
- {
- p_ptr->redraw &= ~(PR_ARMOR);
- prt_ac();
- }
-
- if (p_ptr->redraw & (PR_HP))
+ if (p_ptr->redraw & (PR_FRAME))
{
- p_ptr->redraw &= ~(PR_HP);
- prt_hp();
- }
-
- if (p_ptr->redraw & (PR_MANA))
- {
- p_ptr->redraw &= ~(PR_MANA);
- prt_sp();
- }
-
- if (p_ptr->redraw & (PR_PIETY))
- {
- p_ptr->redraw &= ~(PR_PIETY);
- prt_piety();
- }
-
- if (p_ptr->redraw & (PR_MH))
- {
- p_ptr->redraw &= ~(PR_MH);
- prt_mh();
- }
-
- if (p_ptr->redraw & (PR_GOLD))
- {
- p_ptr->redraw &= ~(PR_GOLD);
- prt_gold();
- }
-
- if (p_ptr->redraw & (PR_DEPTH))
- {
- p_ptr->redraw &= ~(PR_DEPTH);
- prt_depth();
- }
-
- if (p_ptr->redraw & (PR_HEALTH))
- {
- p_ptr->redraw &= ~(PR_HEALTH);
- health_redraw();
- }
-
-
- if (p_ptr->redraw & (PR_EXTRA))
- {
- p_ptr->redraw &= ~(PR_EXTRA);
- p_ptr->redraw &= ~(PR_CUT | PR_STUN);
- p_ptr->redraw &= ~(PR_HUNGER);
- p_ptr->redraw &= ~(PR_BLIND | PR_CONFUSED);
- p_ptr->redraw &= ~(PR_AFRAID | PR_POISONED);
- p_ptr->redraw &= ~(PR_STATE | PR_SPEED | PR_STUDY | PR_SANITY);
- prt_frame_extra();
- }
-
- if (p_ptr->redraw & (PR_CUT))
- {
- p_ptr->redraw &= ~(PR_CUT);
- prt_cut();
- }
-
- if (p_ptr->redraw & (PR_STUN))
- {
- p_ptr->redraw &= ~(PR_STUN);
- prt_stun();
- }
-
- if (p_ptr->redraw & (PR_HUNGER))
- {
- p_ptr->redraw &= ~(PR_HUNGER);
- prt_hunger();
- }
-
- if (p_ptr->redraw & (PR_BLIND))
- {
- p_ptr->redraw &= ~(PR_BLIND);
- prt_blind();
- }
-
- if (p_ptr->redraw & (PR_CONFUSED))
- {
- p_ptr->redraw &= ~(PR_CONFUSED);
- prt_confused();
- }
-
- if (p_ptr->redraw & (PR_AFRAID))
- {
- p_ptr->redraw &= ~(PR_AFRAID);
- prt_afraid();
- }
-
- if (p_ptr->redraw & (PR_POISONED))
- {
- p_ptr->redraw &= ~(PR_POISONED);
- prt_poisoned();
- }
-
- if (p_ptr->redraw & (PR_DTRAP))
- {
- p_ptr->redraw &= ~(PR_DTRAP);
- prt_dtrap();
- }
-
- if (p_ptr->redraw & (PR_STATE))
- {
- p_ptr->redraw &= ~(PR_STATE);
- prt_state();
- }
-
- if (p_ptr->redraw & (PR_SPEED))
- {
- p_ptr->redraw &= ~(PR_SPEED);
- prt_speed();
- }
-
- if (p_ptr->redraw & (PR_STUDY))
- {
- p_ptr->redraw &= ~(PR_STUDY);
- prt_study();
- }
-
- if (p_ptr->redraw & (PR_SANITY))
- {
- p_ptr->redraw &= ~(PR_SANITY);
- prt_sane();
+ p_ptr->redraw &= ~(PR_FRAME);
+ prt_frame();
}
}
@@ -4316,7 +4066,7 @@ void redraw_stuff(void)
/*
* Handle "p_ptr->window"
*/
-void window_stuff(void)
+void window_stuff()
{
int j;
@@ -4327,7 +4077,7 @@ void window_stuff(void)
if (!p_ptr->window) return;
/* Scan windows */
- for (j = 0; j < 8; j++)
+ for (j = 0; j < ANGBAND_TERM_MAX; j++)
{
/* Save usable flags */
if (angband_term[j]) mask |= window_flag[j];
@@ -4401,7 +4151,7 @@ void window_stuff(void)
/*
* Handle "p_ptr->update" and "p_ptr->redraw" and "p_ptr->window"
*/
-void handle_stuff(void)
+void handle_stuff()
{
/* Update stuff */
if (p_ptr->update) update_stuff();
@@ -4414,27 +4164,7 @@ void handle_stuff(void)
}
-bool_ monk_empty_hands(void)
-{
- int i;
- object_type *o_ptr;
-
- if (p_ptr->melee_style != SKILL_HAND) return FALSE;
-
- i = 0;
- while (p_ptr->body_parts[i] == INVEN_WIELD)
- {
- o_ptr = &p_ptr->inventory[INVEN_WIELD + i];
-
- if (o_ptr->k_idx) return FALSE;
-
- i++;
- }
-
- return TRUE;
-}
-
-bool_ monk_heavy_armor(void)
+bool_ monk_heavy_armor()
{
u16b monk_arm_wgt = 0;
@@ -4453,15 +4183,17 @@ bool_ monk_heavy_armor(void)
static int get_artifact_idx(int level)
{
+ auto const &a_info = game->edit_data.a_info;
+
int count = 0, i;
while (count < 1000)
{
- artifact_type *a_ptr;
count++;
- i = randint(max_a_idx - 1);
- a_ptr = &a_info[i];
+ i = rand_int(a_info.size());
+
+ auto a_ptr = &a_info[i];
if (!a_ptr->tval) continue;
/* It is found/lost */
@@ -4471,7 +4203,7 @@ static int get_artifact_idx(int level)
if (a_ptr->level > level) continue;
/* Avoid granting SPECIAL_GENE artifacts */
- if (a_ptr->flags4 & TR4_SPECIAL_GENE) continue;
+ if (a_ptr->flags & TR_SPECIAL_GENE) continue;
return i;
}
@@ -4484,6 +4216,9 @@ static int get_artifact_idx(int level)
/* Chose a fate */
void gain_fate(byte fate)
{
+ auto const &k_info = game->edit_data.k_info;
+ auto &alloc = game->alloc;
+
int i;
int level;
@@ -4554,7 +4289,6 @@ void gain_fate(byte fate)
{
while (TRUE)
{
- object_kind *k_ptr;
obj_theme theme;
/* No themes */
@@ -4573,11 +4307,11 @@ void gain_fate(byte fate)
fates[i].o_idx = get_obj_num(max_dlv[dungeon_type] + randint(10));
/* Invalidate the cached allocation table */
- alloc_kind_table_valid = FALSE;
+ alloc.kind_table_valid = false;
- k_ptr = &k_info[fates[i].o_idx];
+ auto k_ptr = &k_info[fates[i].o_idx];
- if (!(k_ptr->flags3 & TR3_INSTA_ART) && !(k_ptr->flags3 & TR3_NORM_ART)) break;
+ if (!(k_ptr->flags & TR_INSTA_ART) && !(k_ptr->flags & TR_NORM_ART)) break;
}
level = rand_range(max_dlv[dungeon_type] - 20, max_dlv[dungeon_type] + 20);
fates[i].level = (level < 1) ? 1 : (level > 98) ? 98 : level;
@@ -4627,18 +4361,21 @@ void gain_fate(byte fate)
}
}
-void fate_desc(char *desc, int fate)
+std::string fate_desc(int fate)
{
- char buf[120];
+ auto const &a_info = game->edit_data.a_info;
+
+ fmt::MemoryWriter w;
if (fates[fate].serious)
{
- strcpy(desc, "You are fated to ");
+ w.write("You are fated to ");
}
else
{
- strcpy(desc, "You may ");
+ w.write("You may ");
}
+
switch (fates[fate].fate)
{
case FATE_FIND_O:
@@ -4650,15 +4387,14 @@ void fate_desc(char *desc, int fate)
object_prep(o_ptr, fates[fate].o_idx);
object_desc_store(o_name, o_ptr, 1, 0);
- sprintf(buf, "find %s on level %d.", o_name, fates[fate].level);
- strcat(desc, buf);
+ w.write("find {} on level {}.", o_name, fates[fate].level);
break;
}
case FATE_FIND_A:
{
object_type *q_ptr, forge;
char o_name[80];
- artifact_type *a_ptr = &a_info[fates[fate].a_idx];
+ auto a_ptr = &a_info[fates[fate].a_idx];
int I_kind;
/* Failed artefact allocation XXX XXX XXX */
@@ -4696,61 +4432,62 @@ void fate_desc(char *desc, int fate)
q_ptr->weight = a_ptr->weight;
/* Hack -- acquire "cursed" flag */
- if (a_ptr->flags3 & (TR3_CURSED)) q_ptr->ident |= (IDENT_CURSED);
+ if (a_ptr->flags & (TR_CURSED)) q_ptr->ident |= (IDENT_CURSED);
random_artifact_resistance(q_ptr);
object_desc_store(o_name, q_ptr, 1, 0);
}
- sprintf(buf, "find %s on level %d.", o_name, fates[fate].level);
- strcat(desc, buf);
+ w.write("find {} on level {}.", o_name, fates[fate].level);
break;
}
case FATE_FIND_R:
{
char m_name[80];
-
monster_race_desc(m_name, fates[fate].r_idx, 0);
- sprintf(buf, "meet %s on level %d.", m_name, fates[fate].level);
- strcat(desc, buf);
+
+ w.write("meet {} on level {}.", m_name, fates[fate].level);
break;
}
case FATE_DIE:
{
- sprintf(buf, "die on level %d.", fates[fate].level);
- strcat(desc, buf);
+ w.write("die on level {}.", fates[fate].level);
break;
}
case FATE_NO_DIE_MORTAL:
{
- strcat(desc, "never to die by the hand of a mortal being.");
+ w.write("never to die by the hand of a mortal being.");
break;
}
}
+
+ return w.str();
}
-void dump_fates(FILE *outfile)
+std::string dump_fates()
{
- int i;
- char buf[120];
bool_ pending = FALSE;
- if (!outfile) return;
+ fmt::MemoryWriter w;
- for (i = 0; i < MAX_FATES; i++)
+ for (int i = 0; i < MAX_FATES; i++)
{
if ((fates[i].fate) && (fates[i].know))
{
- fate_desc(buf, i);
- fprintf(outfile, "%s\n", buf);
+ w.write("{}\n", fate_desc(i));
}
- if ((fates[i].fate) && !(fates[i].know)) pending = TRUE;
+
+ // Pending gets set if there's at least one fate we don't know
+ pending |= ((fates[i].fate) && !(fates[i].know));
}
+
if (pending)
{
- fprintf(outfile, "You do not know all of your fate.\n");
+ w.write("You do not know all of your fate.\n");
}
+
+ return w.str();
}
/*
@@ -4770,3 +4507,8 @@ int luck(int min, int max)
return (luck + min);
}
+
+bool race_flags_p(player_race_flag_set const &flags_mask)
+{
+ return bool((rp_ptr->flags | rmp_ptr->flags | cp_ptr->flags | spp_ptr->flags) & flags_mask);
+}
diff --git a/src/xtra1.hpp b/src/xtra1.hpp
new file mode 100644
index 00000000..4fde1619
--- /dev/null
+++ b/src/xtra1.hpp
@@ -0,0 +1,27 @@
+#pragma once
+
+#include "h-basic.h"
+#include "object_flag_set.hpp"
+#include "player_race_flag_set.hpp"
+
+#include <string>
+
+void fix_message();
+void apply_flags(object_flag_set const &f, s16b pval, s16b tval, s16b to_h, s16b to_d, s16b to_a);
+int luck(int min, int max);
+int weight_limit();
+extern bool_ calc_powers_silent;
+void cnv_stat(int i, char *out_val);
+s16b modify_stat_value(int value, int amount);
+void calc_hitpoints();
+void notice_stuff();
+void update_stuff();
+void redraw_stuff();
+void window_stuff();
+void handle_stuff();
+bool_ monk_heavy_armor();
+void calc_bonuses(bool_ silent);
+void gain_fate(byte fate);
+std::string fate_desc(int fate);
+std::string dump_fates();
+bool race_flags_p(player_race_flag_set const &flags_mask);
diff --git a/src/xtra2.c b/src/xtra2.cc
index 70978e47..d8b87f51 100644
--- a/src/xtra2.c
+++ b/src/xtra2.cc
@@ -1,8 +1,3 @@
-/* File: xtra2.c */
-/* File: xtra2.c */
-
-/* Purpose: effects of various "objects", targetting and panel handling */
-
/*
* Copyright (c) 1989 James E. Wilson, Robert A. Koeneke
*
@@ -11,45 +6,71 @@
* included in all such copies.
*/
-#include "angband.h"
-
-/*
- * Invoke The Rush
- */
-bool_ set_rush(int v)
-{
- int j;
-
- /* Invoke The Bust */
- if (!v)
- {
- p_ptr->rush = 0;
-
- j = 50 - randint(p_ptr->lev);
- set_paralyzed(j);
- set_slow(j + 50 - randint(p_ptr->lev));
- return TRUE;
- }
-
- /* When is The Bust going to happen? */
- p_ptr->rush = v;
-
- /* The bonuses of The Rush */
- set_hero(p_ptr->hero + v);
- set_tim_deadly(p_ptr->tim_deadly + v);
- set_strike(p_ptr->strike + v);
- if (magik(p_ptr->lev / 2))
- {
- set_light_speed(p_ptr->lightspeed + v);
- }
- else
- {
- set_fast(p_ptr->fast + v, 10);
- }
- if (magik(p_ptr->lev / 2)) set_tim_esp(p_ptr->tim_esp + v);
- return TRUE;
-}
-
+#include "xtra2.hpp"
+
+#include "artifact_type.hpp"
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "corrupt.hpp"
+#include "dungeon_info_type.hpp"
+#include "ego_item_type.hpp"
+#include "feature_flag.hpp"
+#include "feature_type.hpp"
+#include "files.hpp"
+#include "game.hpp"
+#include "gods.hpp"
+#include "hook_player_level_in.hpp"
+#include "hook_monster_death_in.hpp"
+#include "hooks.hpp"
+#include "melee2.hpp"
+#include "mimic.hpp"
+#include "monster1.hpp"
+#include "monster2.hpp"
+#include "monster3.hpp"
+#include "monster_ego.hpp"
+#include "monster_race.hpp"
+#include "monster_race_flag.hpp"
+#include "monster_type.hpp"
+#include "notes.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_flag.hpp"
+#include "object_kind.hpp"
+#include "options.hpp"
+#include "player_class.hpp"
+#include "player_race.hpp"
+#include "player_race_flag.hpp"
+#include "player_race_mod.hpp"
+#include "player_type.hpp"
+#include "point.hpp"
+#include "randart.hpp"
+#include "skill_type.hpp"
+#include "skills.hpp"
+#include "spells1.hpp"
+#include "spells2.hpp"
+#include "stats.hpp"
+#include "store_info_type.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "util.h"
+#include "variable.h"
+#include "variable.hpp"
+#include "wilderness_map.hpp"
+#include "wilderness_type_info.hpp"
+#include "wizard2.hpp"
+#include "xtra1.hpp"
+#include "z-rand.hpp"
+
+#include <boost/algorithm/string/predicate.hpp>
+#include <cassert>
+#include <fmt/format.h>
+#include <type_traits>
+
+
+
+using boost::algorithm::iequals;
+
+static void corrupt_corrupted();
/*
* Set "p_ptr->parasite" and "p_ptr->parasite_r_idx"
@@ -114,7 +135,7 @@ bool_ set_parasite(int v, int r)
if (!notice) return (FALSE);
/* Disturb */
- if (disturb_state) disturb(0, 0);
+ disturb_on_state();
/* Recalculate bonuses */
p_ptr->update |= (PU_BONUS);
@@ -167,8 +188,7 @@ static bool_ set_simple_field(
return (FALSE);
/* Disturb */
- if (disturb_state)
- disturb(0, 0);
+ disturb_on_state();
/* Recalculate bonuses */
p_ptr->update |= (PU_BONUS);
@@ -240,6 +260,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
*/
@@ -350,26 +381,6 @@ bool_ set_tim_fly(int v)
}
/*
- * Set "p_ptr->meditation"
- */
-bool_ set_meditation(int v)
-{
- bool_ notice = set_simple_field(
- &p_ptr->meditation, v,
- TERM_WHITE, "You start meditating on yourself...",
- TERM_WHITE, "You stop your self meditation.");
-
- /* Recalculate bonuses */
- if (notice)
- {
- p_ptr->update |= (PU_MANA);
- }
-
- /* Result */
- return notice;
-}
-
-/*
* Set "p_ptr->tim_reflect"
*/
bool_ set_tim_reflect(int v)
@@ -381,28 +392,6 @@ bool_ set_tim_reflect(int v)
}
/*
- * Set "p_ptr->tim_res_time"
- */
-bool_ set_tim_res_time(int v)
-{
- return set_simple_field(
- &p_ptr->tim_res_time, v,
- TERM_WHITE, "You are now protected against space-time distortions.",
- TERM_WHITE, "You are no longer protected against space-time distortions.");
-}
-
-/*
- * Set "p_ptr->tim_fire_aura"
- */
-bool_ set_tim_fire_aura(int v)
-{
- return set_simple_field(
- &p_ptr->tim_fire_aura, v,
- TERM_WHITE, "You are enveloped in flames.",
- TERM_WHITE, "You are no longer enveloped in flames.");
-}
-
-/*
* Set "p_ptr->strike"
*/
bool_ set_strike(int v)
@@ -414,17 +403,6 @@ bool_ set_strike(int v)
}
/*
- * Set "p_ptr->oppose_ld"
- */
-bool_ set_oppose_ld(int v)
-{
- return set_simple_field(
- &p_ptr->oppose_ld, v,
- TERM_WHITE, "You feel protected against light's fluctuation.",
- TERM_WHITE, "You are no longer protected against light's fluctuation.");
-}
-
-/*
* Set "p_ptr->oppose_cc"
*/
bool_ set_oppose_cc(int v)
@@ -436,33 +414,13 @@ bool_ set_oppose_cc(int v)
}
/*
- * Set "p_ptr->oppose_ss"
- */
-bool_ set_oppose_ss(int v)
-{
- return set_simple_field(
- &p_ptr->oppose_ss, v,
- TERM_WHITE, "You feel protected against the ravages of sound and shards.",
- TERM_WHITE, "You are no longer protected against the ravages of sound and shards.");
-}
-
-/*
- * Set "p_ptr->oppose_nex"
- */
-bool_ set_oppose_nex(int v)
-{
- return set_simple_field(
- &p_ptr->oppose_nex, v,
- TERM_WHITE, "You feel protected against the strange forces of nexus.",
- TERM_WHITE, "You are no longer protected against the strange forces of nexus.");
-}
-
-/*
* Set "p_ptr->tim_mimic", and "p_ptr->mimic_form",
* notice observable changes
*/
bool_ set_mimic(int v, int p, int level)
{
+ auto &s_info = game->s_info;
+
bool_ notice = FALSE;
/* Hack -- Force good values */
@@ -489,7 +447,7 @@ bool_ set_mimic(int v, int p, int level)
notice = TRUE;
if (p == resolve_mimic_name("Bear"))
{
- s_info[SKILL_BEAR].hidden = TRUE;
+ s_info[SKILL_BEAR].hidden = true;
select_default_melee();
}
p = 0;
@@ -504,10 +462,10 @@ bool_ set_mimic(int v, int p, int level)
if (!notice) return (FALSE);
/* Disturb */
- if (disturb_state) disturb(0, 0);
+ disturb_on_state();
/* Redraw title */
- p_ptr->redraw |= (PR_TITLE);
+ p_ptr->redraw |= (PR_FRAME);
/* Recalculate bonuses */
p_ptr->update |= (PU_BODY | PU_BONUS | PU_SANITY);
@@ -540,7 +498,7 @@ bool_ set_blind(int v)
p_ptr->redraw |= (PR_MAP);
/* Redraw the "blind" */
- p_ptr->redraw |= (PR_BLIND);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_OVERHEAD);
@@ -601,7 +559,7 @@ bool_ set_confused(int v)
if (notice)
{
/* Redraw the "confused" */
- p_ptr->redraw |= (PR_CONFUSED);
+ p_ptr->redraw |= (PR_FRAME);
/* Handle stuff */
handle_stuff();
@@ -625,7 +583,7 @@ bool_ set_poisoned(int v)
if (notice)
{
/* Redraw the "poisoned" */
- p_ptr->redraw |= (PR_POISONED);
+ p_ptr->redraw |= (PR_FRAME);
/* Handle stuff */
handle_stuff();
@@ -649,7 +607,7 @@ bool_ set_afraid(int v)
if (notice)
{
/* Redraw the "afraid" */
- p_ptr->redraw |= (PR_AFRAID);
+ p_ptr->redraw |= (PR_FRAME);
/* Handle stuff */
handle_stuff();
@@ -661,11 +619,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.");
@@ -673,7 +634,7 @@ bool_ set_paralyzed(int v)
if (notice)
{
/* Redraw the state */
- p_ptr->redraw |= (PR_STATE);
+ p_ptr->redraw |= (PR_FRAME);
/* Handle stuff */
handle_stuff();
@@ -683,6 +644,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
@@ -772,7 +759,7 @@ bool_ set_fast(int v, int p)
if (!notice) return (FALSE);
/* Disturb */
- if (disturb_state) disturb(0, 0);
+ disturb_on_state();
/* Recalculate bonuses */
p_ptr->update |= (PU_BONUS);
@@ -900,26 +887,6 @@ bool_ set_holy(int v)
}
/*
- * Set "p_ptr->walk_water", notice observable changes
- */
-bool_ set_walk_water(int v)
-{
- bool_ notice = set_simple_field(
- &p_ptr->walk_water, v,
- TERM_WHITE, "You feel strangely buoyant!",
- TERM_WHITE, "You feel much less buoyant.");
-
- if (notice)
- {
- /* Handle stuff */
- handle_stuff();
- }
-
- /* Result */
- return notice;
-}
-
-/*
* Set "p_ptr->shero", notice observable changes
*/
bool_ set_shero(int v)
@@ -970,45 +937,6 @@ bool_ set_protevil(int v)
}
/*
- * Set "p_ptr->protgood", notice observable changes
- */
-bool_ set_protgood(int v)
-{
- bool_ notice = set_simple_field(
- &p_ptr->protgood, v,
- TERM_WHITE, "You feel safe from good!",
- TERM_WHITE, "You no longer feel safe from good.");
-
- if (notice)
- {
- /* Handle stuff */
- handle_stuff();
- }
-
- /* Result */
- return notice;
-}
-
-/*
- * Set "p_ptr->protundead", notice observable changes
- */
-bool_ set_protundead(int v)
-{
- bool_ notice = set_simple_field(
- &p_ptr->protundead, v,
- TERM_WHITE, "You feel safe from undead!",
- TERM_WHITE, "You no longer feel safe from undead.");
-
- if (notice) {
- /* Handle stuff */
- handle_stuff();
- }
-
- /* Result */
- return notice;
-}
-
-/*
* Set "p_ptr->set_shadow", notice observable changes
*/
bool_ set_shadow(int v)
@@ -1134,7 +1062,7 @@ bool_ set_tim_thunder(int v, int p1, int p2)
if (!notice) return (FALSE);
/* Disturb */
- if (disturb_state) disturb(0, 0);
+ disturb_on_state();
/* Recalculate bonuses */
p_ptr->update |= (PU_BONUS);
@@ -1198,26 +1126,6 @@ bool_ set_tim_infra(int v)
/*
- * Set "p_ptr->tim_mental_barrier", notice observable changes
- */
-bool_ set_mental_barrier(int v)
-{
- bool_ notice = set_simple_field(
- &p_ptr->tim_mental_barrier, v,
- TERM_WHITE, "Your mind grows stronger!",
- TERM_WHITE, "Your mind is no longer especially strong.");
-
- if (notice)
- {
- /* Handle stuff */
- handle_stuff();
- }
-
- /* Result */
- return notice;
-}
-
-/*
* Set "p_ptr->oppose_acid", notice observable changes
*/
bool_ set_oppose_acid(int v)
@@ -1361,7 +1269,7 @@ bool_ set_tim_regen(int v, int p)
if (!notice) return (FALSE);
/* Disturb */
- if (disturb_state) disturb(0, 0);
+ disturb_on_state();
/* Handle stuff */
handle_stuff();
@@ -1385,7 +1293,7 @@ bool_ set_stun(int v)
/* Hack -- Force good values */
v = (v > 10000) ? 10000 : (v < 0) ? 0 : v;
- if (PRACE_FLAG(PR1_NO_STUN)) v = 0;
+ if (race_flags_p(PR_NO_STUN)) v = 0;
/* Knocked out */
if (p_ptr->stun > 100)
@@ -1465,25 +1373,25 @@ bool_ set_stun(int v)
{
if (!p_ptr->sustain_int)
{
- (void) do_dec_stat(A_INT, STAT_DEC_NORMAL);
+ do_dec_stat(A_INT, STAT_DEC_NORMAL);
}
if (!p_ptr->sustain_wis)
{
- (void) do_dec_stat(A_WIS, STAT_DEC_NORMAL);
+ do_dec_stat(A_WIS, STAT_DEC_NORMAL);
}
}
else if (randint(2) == 1)
{
if (!p_ptr->sustain_int)
{
- (void) do_dec_stat(A_INT, STAT_DEC_NORMAL);
+ do_dec_stat(A_INT, STAT_DEC_NORMAL);
}
}
else
{
if (!p_ptr->sustain_wis)
{
- (void) do_dec_stat(A_WIS, STAT_DEC_NORMAL);
+ do_dec_stat(A_WIS, STAT_DEC_NORMAL);
}
}
}
@@ -1501,7 +1409,7 @@ bool_ set_stun(int v)
/* None */
case 0:
msg_print("You are no longer stunned.");
- if (disturb_state) disturb(0, 0);
+ disturb_on_state();
break;
}
@@ -1516,13 +1424,13 @@ bool_ set_stun(int v)
if (!notice) return (FALSE);
/* Disturb */
- if (disturb_state) disturb(0, 0);
+ disturb_on_state();
/* Recalculate bonuses */
p_ptr->update |= (PU_BONUS);
/* Redraw the "stun" */
- p_ptr->redraw |= (PR_STUN);
+ p_ptr->redraw |= (PR_FRAME);
/* Handle stuff */
handle_stuff();
@@ -1546,7 +1454,7 @@ bool_ set_cut(int v)
/* Hack -- Force good values */
v = (v > 10000) ? 10000 : (v < 0) ? 0 : v;
- if (PRACE_FLAG(PR1_NO_CUT)) v = 0;
+ if (race_flags_p(PR_NO_CUT)) v = 0;
/* Mortal wound */
if (p_ptr->cut > 1000)
@@ -1709,7 +1617,7 @@ bool_ set_cut(int v)
/* None */
case 0:
msg_print("You are no longer bleeding.");
- if (disturb_state) disturb(0, 0);
+ disturb_on_state();
break;
}
@@ -1724,13 +1632,13 @@ bool_ set_cut(int v)
if (!notice) return (FALSE);
/* Disturb */
- if (disturb_state) disturb(0, 0);
+ disturb_on_state();
/* Recalculate bonuses */
p_ptr->update |= (PU_BONUS);
/* Redraw the "cut" */
- p_ptr->redraw |= (PR_CUT);
+ p_ptr->redraw |= (PR_FRAME);
/* Handle stuff */
handle_stuff();
@@ -1938,13 +1846,13 @@ bool_ set_food(int v)
if (!notice) return (FALSE);
/* Disturb */
- if (disturb_state) disturb(0, 0);
+ disturb_on_state();
/* Recalculate bonuses */
p_ptr->update |= (PU_BONUS);
/* Redraw hunger */
- p_ptr->redraw |= (PR_HUNGER);
+ p_ptr->redraw |= (PR_FRAME);
/* Handle stuff */
handle_stuff();
@@ -1957,10 +1865,9 @@ bool_ set_food(int v)
/*
* Advance experience levels and print experience
*/
-void check_experience(void)
+void check_experience()
{
int gained = 0;
- bool_ level_reward = FALSE;
bool_ level_corruption = FALSE;
@@ -1980,7 +1887,7 @@ void check_experience(void)
if (p_ptr->exp > p_ptr->max_exp) p_ptr->max_exp = p_ptr->exp;
/* Redraw experience */
- p_ptr->redraw |= (PR_EXP);
+ p_ptr->redraw |= (PR_FRAME);
/* Handle stuff */
handle_stuff();
@@ -1999,7 +1906,7 @@ void check_experience(void)
p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS | PU_SANITY);
/* Redraw some stuff */
- p_ptr->redraw |= (PR_LEV | PR_TITLE | PR_EXP);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
@@ -2010,8 +1917,8 @@ void check_experience(void)
/* Gain levels while possible */
- while ((p_ptr->lev < PY_MAX_LEVEL) && (p_ptr->lev < max_plev) &&
- (p_ptr->exp >= (player_exp[p_ptr->lev - 1] * p_ptr->expfact / 100L)))
+ while ((p_ptr->lev < PY_MAX_LEVEL) &&
+ (p_ptr->exp >= (player_exp[p_ptr->lev - 1] * p_ptr->expfact / 100L)))
{
/* Gain a level */
p_ptr->lev++;
@@ -2022,38 +1929,28 @@ void check_experience(void)
if (p_ptr->lev > p_ptr->max_plv)
{
p_ptr->max_plv = p_ptr->lev;
- if ((PRACE_FLAG(PR1_CORRUPT)) &&
+ if ((race_flags_p(PR_CORRUPT)) &&
(randint(3) == 1))
{
level_corruption = TRUE;
}
}
- /* Sound */
- sound(SOUND_LEVEL);
-
/* Message */
cmsg_format(TERM_L_GREEN, "Welcome to level %d.", p_ptr->lev);
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;
+ p_ptr->redraw |= PR_FRAME;
}
/* 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];
@@ -2066,7 +1963,7 @@ void check_experience(void)
p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS | PU_SANITY);
/* Redraw some stuff */
- p_ptr->redraw |= (PR_LEV | PR_TITLE | PR_EXP);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
@@ -2074,12 +1971,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...");
@@ -2089,8 +1980,12 @@ 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
*/
@@ -2104,7 +1999,7 @@ void check_experience_obj(object_type *o_ptr)
/* Gain levels while possible */
while ((o_ptr->elevel < PY_MAX_LEVEL) &&
- (o_ptr->exp >= (player_exp[o_ptr->elevel - 1] * 5 / 2)))
+ (o_ptr->exp >= calc_object_need_exp(o_ptr)))
{
char buf[100];
@@ -2122,45 +2017,11 @@ void check_experience_obj(object_type *o_ptr)
/*
- * Gain experience (share it to objects if needed)
+ * Gain experience
*/
void gain_exp(s32b amount)
{
- int i, num = 1;
-
- /* Count the gaining xp objects */
- for (i = INVEN_WIELD; i < INVEN_TOTAL; i++)
- {
- object_type *o_ptr = &p_ptr->inventory[i];
- u32b f1, f2, f3, f4, f5, esp;
-
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
-
- if (!o_ptr->k_idx) continue;
-
- if (f4 & TR4_ART_EXP) num++;
- }
-
- /* Now give the xp */
- for (i = INVEN_WIELD; i < INVEN_TOTAL; i++)
- {
- object_type *o_ptr = &p_ptr->inventory[i];
- u32b f1, f2, f3, f4, f5, esp;
-
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
-
- if (!o_ptr->k_idx) continue;
-
- if (f4 & TR4_ART_EXP)
- {
- o_ptr->exp += 2 * amount / (num * 3);
-
- /* Hack -- upper limit */
- if (o_ptr->exp > PY_MAX_EXP) o_ptr->exp = PY_MAX_EXP;
- }
- }
-
- if ((p_ptr->max_exp > 0) && (PRACE_FLAG(PR1_CORRUPT)))
+ if ((p_ptr->max_exp > 0) && (race_flags_p(PR_CORRUPT)))
{
if ((randint(p_ptr->max_exp) < amount) || (randint(12000000) < amount))
{
@@ -2171,10 +2032,7 @@ void gain_exp(s32b amount)
};
/* Gain some experience */
- p_ptr->exp += amount / num;
-
- /* Hook it! */
- process_hooks(HOOK_PLAYER_EXP, "(d)", amount / num);
+ p_ptr->exp += amount;
/* Slowly recover from experience drainage */
if (p_ptr->exp < p_ptr->max_exp)
@@ -2199,9 +2057,6 @@ void lose_exp(s32b amount)
/* Lose some experience */
p_ptr->exp -= amount;
- /* Hook it! */
- process_hooks(HOOK_PLAYER_EXP, "(d)", amount);
-
/* Check Experience */
check_experience();
}
@@ -2215,9 +2070,9 @@ void lose_exp(s32b amount)
*
* XXX XXX XXX Note the use of actual "monster names"
*/
-int get_coin_type(monster_race *r_ptr)
+int get_coin_type(std::shared_ptr<monster_race const> r_ptr)
{
- cptr name = (r_name + r_ptr->name);
+ cptr name = r_ptr->name;
/* Analyze "coin" monsters */
if (r_ptr->d_char == '$')
@@ -2247,25 +2102,24 @@ int get_coin_type(monster_race *r_ptr)
*/
void place_corpse(monster_type *m_ptr)
{
- monster_race *r_ptr = race_inf(m_ptr);
+ const int x = m_ptr->fx;
+ const int y = m_ptr->fy;
- object_type *i_ptr;
+ /* Get local object */
object_type object_type_body;
+ object_type *i_ptr = &object_type_body;
- int x = m_ptr->fx;
- int y = m_ptr->fy;
-
- /* Get local object */
- i_ptr = &object_type_body;
+ /* Get the race information */
+ auto const r_ptr = m_ptr->race();
/* It has a physical form */
- if (r_ptr->flags9 & RF9_DROP_CORPSE)
+ if (r_ptr->flags & RF_DROP_CORPSE)
{
/* Wipe the object */
object_prep(i_ptr, lookup_kind(TV_CORPSE, SV_CORPSE_CORPSE));
/* Unique corpses are unique */
- if (r_ptr->flags1 & RF1_UNIQUE)
+ if (r_ptr->flags & RF_UNIQUE)
{
object_aware(i_ptr);
i_ptr->name1 = 201;
@@ -2295,13 +2149,13 @@ void place_corpse(monster_type *m_ptr)
}
/* The creature is an animated skeleton. */
- if (!(r_ptr->flags9 & RF9_DROP_CORPSE) && (r_ptr->flags9 & RF9_DROP_SKELETON))
+ if (!(r_ptr->flags & RF_DROP_CORPSE) && (r_ptr->flags & RF_DROP_SKELETON))
{
/* Wipe the object */
object_prep(i_ptr, lookup_kind(TV_CORPSE, SV_CORPSE_SKELETON));
/* Unique corpses are unique */
- if (r_ptr->flags1 & RF1_UNIQUE)
+ if (r_ptr->flags & RF_UNIQUE)
{
object_aware(i_ptr);
i_ptr->name1 = 201;
@@ -2329,6 +2183,209 @@ 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);
+ }
+ }
+
+ 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);
+ }
+ }
+
+ 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);
+ }
+ }
+}
+
+/*
* Handle the "death" of a monster.
*
* Disperse treasures centered at the monster location based on the
@@ -2344,19 +2401,13 @@ void place_corpse(monster_type *m_ptr)
*/
void monster_death(int m_idx)
{
- int i, y, x, ny, nx;
-
- int dump_item = 0;
- int dump_gold = 0;
-
- s16b this_o_idx, next_o_idx = 0;
+ auto const &d_info = game->edit_data.d_info;
+ auto const &f_info = game->edit_data.f_info;
+ auto &a_info = game->edit_data.a_info;
monster_type *m_ptr = &m_list[m_idx];
- monster_race *r_ptr = race_inf(m_ptr);
-
- bool_ visible = (m_ptr->ml || (r_ptr->flags1 & (RF1_UNIQUE)));
-
+ auto const r_ptr = m_ptr->race();
bool_ create_stairs = FALSE;
int force_coin = get_coin_type(r_ptr);
@@ -2365,11 +2416,17 @@ void monster_death(int m_idx)
object_type *q_ptr;
/* Get the location */
- y = m_ptr->fy;
- x = m_ptr->fx;
+ int y = m_ptr->fy;
+ int x = m_ptr->fx;
/* Process the appropriate hooks */
- process_hooks(HOOK_MONSTER_DEATH, "(d)", m_idx);
+ {
+ struct hook_monster_death_in in = { m_idx };
+ process_hooks_new(HOOK_MONSTER_DEATH, &in, NULL);
+ }
+
+ /* 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++;
@@ -2386,7 +2443,7 @@ void monster_death(int m_idx)
/* Display the hitpoints */
p_ptr->update |= (PU_HP);
- p_ptr->redraw |= (PR_HP);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
@@ -2397,27 +2454,17 @@ void monster_death(int m_idx)
}
}
- /* Handle the possibility of player vanquishing arena combatant -KMW- */
- if (p_ptr->inside_arena)
- {
- p_ptr->exit_bldg = TRUE;
- msg_print("Victorious! You're on your way to becoming Champion.");
- p_ptr->arena_number++;
- }
-
/* If the doppleganger die, the variable must be set accordingly */
- if (r_ptr->flags9 & RF9_DOPPLEGANGER) doppleganger = 0;
+ if (r_ptr->flags & RF_DOPPLEGANGER) doppleganger = 0;
+
+ /* Need copy of object list since we're going to mutate it */
+ auto const object_idxs(m_ptr->hold_o_idxs);
/* Drop objects being carried */
- for (this_o_idx = m_ptr->hold_o_idx; this_o_idx; this_o_idx = next_o_idx)
+ for (auto const this_o_idx: object_idxs)
{
- object_type * o_ptr;
-
/* Acquire object */
- o_ptr = &o_list[this_o_idx];
-
- /* Acquire next object */
- next_o_idx = o_ptr->next_o_idx;
+ object_type * o_ptr = &o_list[this_o_idx];
/* Paranoia */
o_ptr->held_m_idx = 0;
@@ -2431,21 +2478,18 @@ void monster_death(int m_idx)
/* Delete the object */
delete_object_idx(this_o_idx);
- if (q_ptr->tval == TV_GOLD) dump_gold++;
- else dump_item++;
-
/* Drop it */
drop_near(q_ptr, -1, y, x);
}
/* Forget objects */
- m_ptr->hold_o_idx = 0;
+ m_ptr->hold_o_idxs.clear();
/* Average dungeon and monster levels */
object_level = (dun_level + m_ptr->level) / 2;
/* Mega^2-hack -- destroying the Stormbringer gives it us! */
- if (strstr((r_name + r_ptr->name), "Stormbringer"))
+ if (strstr(r_ptr->name, "Stormbringer"))
{
/* Get local object */
q_ptr = &forge;
@@ -2455,31 +2499,41 @@ void monster_death(int m_idx)
/* Mega-Hack -- Name the sword */
- q_ptr->art_name = quark_add("'Stormbringer'");
+ q_ptr->artifact_name = "'Stormbringer'";
q_ptr->to_h = 16;
q_ptr->to_d = 16;
q_ptr->ds = 6;
q_ptr->dd = 6;
q_ptr->pval = 2;
- q_ptr->art_flags1 |= ( TR1_VAMPIRIC | TR1_STR | TR1_CON | TR1_BLOWS );
- q_ptr->art_flags2 |= ( TR2_FREE_ACT | TR2_HOLD_LIFE |
- TR2_RES_NEXUS | TR2_RES_CHAOS | TR2_RES_NETHER |
- TR2_RES_CONF ); /* No longer resist_disen */
- q_ptr->art_flags3 |= ( TR3_IGNORE_ACID | TR3_IGNORE_ELEC |
- TR3_IGNORE_FIRE | TR3_IGNORE_COLD);
- /* Just to be sure */
+ q_ptr->art_flags |=
+ TR_VAMPIRIC |
+ TR_STR |
+ TR_CON |
+ TR_BLOWS |
+ TR_FREE_ACT |
+ TR_HOLD_LIFE |
+ TR_RES_NEXUS |
+ TR_RES_CHAOS |
+ TR_RES_NETHER |
+ TR_RES_CONF |
+ TR_IGNORE_ACID |
+ TR_IGNORE_ELEC |
+ TR_IGNORE_FIRE |
+ TR_IGNORE_COLD |
+ TR_NO_TELE |
+ TR_CURSED |
+ TR_HEAVY_CURSE;
- q_ptr->art_flags3 |= TR3_NO_TELE; /* How's that for a downside? */
-
- /* For game balance... */
- q_ptr->art_flags3 |= (TR3_CURSED | TR3_HEAVY_CURSE);
q_ptr->ident |= IDENT_CURSED;
-
if (randint(2) == 1)
- q_ptr->art_flags3 |= (TR3_DRAIN_EXP);
+ {
+ q_ptr->art_flags |= TR_DRAIN_EXP;
+ }
else
- q_ptr->art_flags3 |= (TR3_AGGRAVATE);
+ {
+ q_ptr->art_flags |= TR_AGGRAVATE;
+ }
q_ptr->found = OBJ_FOUND_MONSTER;
q_ptr->found_aux1 = m_ptr->r_idx;
@@ -2495,7 +2549,7 @@ void monster_death(int m_idx)
* Mega^3-hack: killing a 'Warrior of the Dawn' is likely to
* spawn another in the fallen one's place!
*/
- else if (strstr((r_name + r_ptr->name), "the Dawn"))
+ else if (strstr(r_ptr->name, "the Dawn"))
{
if (!(randint(20) == 13))
{
@@ -2531,15 +2585,15 @@ void monster_death(int m_idx)
}
/* One more ultra-hack: An Unmaker goes out with a big bang! */
- else if (strstr((r_name + r_ptr->name), "Unmaker"))
+ else if (strstr(r_ptr->name, "Unmaker"))
{
int flg = PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL;
- (void)project(m_idx, 6, y, x, 100, GF_CHAOS, flg);
+ project(m_idx, 6, y, x, 100, GF_CHAOS, flg);
}
/* Pink horrors are replaced with 2 Blue horrors */
- else if (strstr((r_name + r_ptr->name), "ink horror"))
+ else if (strstr(r_ptr->name, "ink horror"))
{
- for (i = 0; i < 2; i++)
+ for (int i = 0; i < 2; i++)
{
int wy = p_ptr->py, wx = p_ptr->px;
int attempts = 100;
@@ -2562,9 +2616,9 @@ void monster_death(int m_idx)
}
/* Mega-Hack -- drop "winner" treasures */
- else if (r_ptr->flags1 & (RF1_DROP_CHOSEN))
+ else if (r_ptr->flags & RF_DROP_CHOSEN)
{
- if (strstr((r_name + r_ptr->name), "Morgoth, Lord of Darkness"))
+ if (strstr(r_ptr->name, "Morgoth, Lord of Darkness"))
{
/* Get local object */
q_ptr = &forge;
@@ -2602,7 +2656,7 @@ void monster_death(int m_idx)
/* Drop it in the dungeon */
drop_near(q_ptr, -1, y, x);
}
- else if (strstr((r_name + r_ptr->name), "Smeagol"))
+ else if (strstr(r_ptr->name, "Smeagol"))
{
/* Get local object */
q_ptr = &forge;
@@ -2624,7 +2678,7 @@ void monster_death(int m_idx)
/* Drop it in the dungeon */
drop_near(q_ptr, -1, y, x);
}
- else if (r_ptr->flags7 & RF7_NAZGUL)
+ else if (r_ptr->flags & RF_NAZGUL)
{
/* Get local object */
q_ptr = &forge;
@@ -2641,7 +2695,7 @@ void monster_death(int m_idx)
create_artifact(q_ptr, TRUE, FALSE);
/* Save the inscription */
- q_ptr->art_name = quark_add(format("of %s", r_name + r_ptr->name));
+ q_ptr->artifact_name = fmt::format("of {}", r_ptr->name);
q_ptr->found = OBJ_FOUND_MONSTER;
q_ptr->found_aux1 = m_ptr->r_idx;
@@ -2654,46 +2708,14 @@ void monster_death(int m_idx)
}
else
{
- byte a_idx = 0;
- int chance = 0;
- int I_kind = 0;
-
- if (strstr((r_name + r_ptr->name), "Marda, rider of the Gold Laronth"))
- {
- a_idx = ART_MARDA;
- chance = 50;
- }
- else if (strstr((r_name + r_ptr->name), "Saruman of Many Colours"))
- {
- a_idx = ART_PALANTIR;
- chance = 30;
- }
- else if (strstr((r_name + r_ptr->name), "Hagen, son of Alberich"))
- {
- a_idx = ART_NIMLOTH;
- chance = 66;
- }
- else if (strstr((r_name + r_ptr->name), "Durin's Bane"))
- {
- a_idx = ART_CALRIS;
- chance = 60;
- }
- else if (strstr((r_name + r_ptr->name), "Gothmog, the High Captain of Balrogs"))
- {
- a_idx = ART_GOTHMOG;
- chance = 50;
- }
- else if (strstr((r_name + r_ptr->name), "Eol, the Dark Elf"))
- {
- a_idx = ART_ANGUIREL;
- chance = 50;
- }
+ byte a_idx = r_ptr->artifact_idx;
+ int chance = r_ptr->artifact_chance;
if ((a_idx > 0) && ((randint(99) < chance) || (wizard)))
{
if (a_info[a_idx].cur_num == 0)
{
- artifact_type *a_ptr = &a_info[a_idx];
+ auto a_ptr = &a_info[a_idx];
/* Get local object */
q_ptr = &forge;
@@ -2702,7 +2724,7 @@ void monster_death(int m_idx)
object_wipe(q_ptr);
/* Acquire the "kind" index */
- I_kind = lookup_kind(a_ptr->tval, a_ptr->sval);
+ int I_kind = lookup_kind(a_ptr->tval, a_ptr->sval);
/* Create the artifact */
object_prep(q_ptr, I_kind);
@@ -2721,7 +2743,7 @@ void monster_death(int m_idx)
q_ptr->weight = a_ptr->weight;
/* Hack -- acquire "cursed" flag */
- if (a_ptr->flags3 & (TR3_CURSED)) q_ptr->ident |= (IDENT_CURSED);
+ if (a_ptr->flags & TR_CURSED) q_ptr->ident |= (IDENT_CURSED);
random_artifact_resistance(q_ptr);
@@ -2741,7 +2763,7 @@ void monster_death(int m_idx)
}
/* Hack - the protected monsters must be advanged */
- else if (r_ptr->flags9 & RF9_WYRM_PROTECT)
+ else if (r_ptr->flags & RF_WYRM_PROTECT)
{
int xx = x, yy = y;
int attempts = 100;
@@ -2758,7 +2780,7 @@ void monster_death(int m_idx)
}
/* Let monsters explode! */
- for (i = 0; i < 4; i++)
+ for (int i = 0; i < 4; i++)
{
if (m_ptr->blow[i].method == RBM_EXPLODE)
{
@@ -2879,32 +2901,26 @@ void monster_death(int m_idx)
if ((!force_coin) && (magik(10 + get_skill_scale(SKILL_PRESERVATION, 75))) && (!(m_ptr->mflag & MFLAG_NO_DROP)))
place_corpse(m_ptr);
- /* Take note of any dropped treasure */
- if (visible && (dump_item || dump_gold))
- {
- /* Take notes on treasure */
- lore_treasure(m_idx, dump_item, dump_gold);
- }
-
- /* Current quest */
- i = p_ptr->inside_quest;
-
/* Create a magical staircase */
if (create_stairs && (dun_level < d_info[dungeon_type].maxdepth))
{
- int i, j;
-
- for (i = -1; i <= 1; i++)
- for (j = -1; j <= 1; j++)
- if (!(f_info[cave[y + j][x + i].feat].flags1 & FF1_PERMANENT)) cave_set_feat(y + j, x + i, d_info[dungeon_type].floor1);
+ for (int i = -1; i <= 1; i++)
+ {
+ for (int j = -1; j <= 1; j++)
+ {
+ if (!(f_info[cave[y + j][x + i].feat].flags & FF_PERMANENT))
+ {
+ cave_set_feat(y + j, x + i, d_info[dungeon_type].floor1);
+ }
+ }
+ }
/* Stagger around */
while (!cave_valid_bold(y, x))
{
- int d = 1;
-
/* Pick a location */
- scatter(&ny, &nx, y, x, d);
+ int ny, nx;
+ scatter(&ny, &nx, y, x, 1);
/* Stagger */
y = ny;
@@ -2958,15 +2974,14 @@ void monster_death(int m_idx)
bool_ mon_take_hit(int m_idx, int dam, bool_ *fear, cptr note)
{
monster_type *m_ptr = &m_list[m_idx];
- monster_race *r_ptr = race_inf(m_ptr);
- s32b div, new_exp, new_exp_frac;
-
+ auto const r_idx = m_ptr->r_idx;
+ auto const r_ptr = m_ptr->race();
/* Redraw (later) if needed */
- if (health_who == m_idx) p_ptr->redraw |= (PR_HEALTH);
+ if (health_who == m_idx) p_ptr->redraw |= (PR_FRAME);
/* Some mosnters are immune to death */
- if (r_ptr->flags7 & RF7_NO_DEATH) return FALSE;
+ if (r_ptr->flags & RF_NO_DEATH) return FALSE;
/* Wake it up */
m_ptr->csleep = 0;
@@ -2990,7 +3005,7 @@ bool_ mon_take_hit(int m_idx, int dam, bool_ *fear, cptr note)
/* Extract monster name */
monster_desc(m_name, m_ptr, 0);
- if ((r_ptr->flags7 & RF7_DG_CURSE) && (randint(2) == 1))
+ if ((r_ptr->flags & RF_DG_CURSE) && (randint(2) == 1))
{
int curses = 2 + randint(5);
@@ -3004,7 +3019,7 @@ bool_ mon_take_hit(int m_idx, int dam, bool_ *fear, cptr note)
while (--curses);
}
- if (speak_unique && (r_ptr->flags2 & (RF2_CAN_SPEAK)))
+ if (r_ptr->flags & RF_CAN_SPEAK)
{
char line_got[80];
/* Dump a message */
@@ -3013,10 +3028,6 @@ bool_ mon_take_hit(int m_idx, int dam, bool_ *fear, cptr note)
msg_format("%^s says: %s", m_name, line_got);
}
-
- /* Make a sound */
- sound(SOUND_KILL);
-
/* Death by Missile/Spell attack */
if (note)
{
@@ -3030,10 +3041,10 @@ bool_ mon_take_hit(int m_idx, int dam, bool_ *fear, cptr note)
}
/* Death by Physical attack -- non-living monster */
- else if ((r_ptr->flags3 & (RF3_DEMON)) ||
- (r_ptr->flags3 & (RF3_UNDEAD)) ||
- (r_ptr->flags2 & (RF2_STUPID)) ||
- (r_ptr->flags3 & (RF3_NONLIVING)) ||
+ else if ((r_ptr->flags & RF_DEMON) ||
+ (r_ptr->flags & RF_UNDEAD) ||
+ (r_ptr->flags & RF_STUPID) ||
+ (r_ptr->flags & RF_NONLIVING) ||
(strchr("Evg", r_ptr->d_char)))
{
cmsg_format(TERM_L_RED, "You have destroyed %s.", m_name);
@@ -3046,15 +3057,15 @@ bool_ mon_take_hit(int m_idx, int dam, bool_ *fear, cptr note)
}
/* Maximum player level */
- div = p_ptr->max_plv;
+ const s32b div = p_ptr->max_plv;
if (m_ptr->status < MSTATUS_FRIEND)
{
/* Give some experience for the kill */
- new_exp = ((long)r_ptr->mexp * m_ptr->level) / div;
+ int new_exp = ((long)r_ptr->mexp * m_ptr->level) / div;
/* Handle fractional experience */
- new_exp_frac = ((((long)r_ptr->mexp * m_ptr->level) % div)
+ const s32b new_exp_frac = ((((long)r_ptr->mexp * m_ptr->level) % div)
* 0x10000L / div) + p_ptr->exp_frac;
/* Keep track of experience */
@@ -3074,18 +3085,15 @@ bool_ mon_take_hit(int m_idx, int dam, bool_ *fear, cptr note)
if (!note)
{
- object_type *o_ptr;
- u32b f1, f2, f3, f4, f5, esp;
-
/* Access the weapon */
- o_ptr = &p_ptr->inventory[INVEN_WIELD];
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ object_type *o_ptr = &p_ptr->inventory[INVEN_WIELD];
+ auto const flags = object_flags(o_ptr);
/* Can the weapon gain levels ? */
- if ((o_ptr->k_idx) && (f4 & TR4_LEVELS))
+ if ((o_ptr->k_idx) && (flags & TR_LEVELS))
{
/* Give some experience for the kill */
- new_exp = ((long)r_ptr->mexp * m_ptr->level) / (div * 2);
+ const int new_exp = ((long)r_ptr->mexp * m_ptr->level) / (div * 2);
/* Gain experience */
o_ptr->exp += new_exp;
@@ -3094,7 +3102,7 @@ bool_ mon_take_hit(int m_idx, int dam, bool_ *fear, cptr note)
}
/* When the player kills a Unique, it stays dead */
- if (r_ptr->flags1 & (RF1_UNIQUE))
+ if (r_ptr->flags & RF_UNIQUE)
{
r_ptr->max_num = 0;
}
@@ -3103,7 +3111,7 @@ bool_ mon_take_hit(int m_idx, int dam, bool_ *fear, cptr note)
monster_death(m_idx);
/* Eru doesn't appreciate good monster death */
- if (r_ptr->flags3 & RF3_GOOD)
+ if (r_ptr->flags & RF_GOOD)
{
inc_piety(GOD_ERU, -7 * m_ptr->level);
inc_piety(GOD_MANWE, -10 * m_ptr->level);
@@ -3115,46 +3123,49 @@ bool_ mon_take_hit(int m_idx, int dam, bool_ *fear, cptr note)
}
/* Manwe appreciate evil monster death */
- if (r_ptr->flags3 & RF3_EVIL)
+ if (r_ptr->flags & RF_EVIL)
{
- int inc = m_ptr->level / 2;
+ int inc = std::max(1, m_ptr->level / 2);
- if (!inc) inc = 1;
- PRAY_GOD(GOD_MANWE) inc_piety(GOD_MANWE, inc);
+ if (praying_to(GOD_MANWE))
+ {
+ inc_piety(GOD_MANWE, inc);
+ }
+
+ inc = std::max(2, inc);
- if (inc < 2) inc = 2;
inc_piety(GOD_TULKAS, inc / 2);
- PRAY_GOD(GOD_TULKAS)
+
+ if (praying_to(GOD_TULKAS))
{
inc_piety(GOD_TULKAS, inc / 2);
- if (r_ptr->flags3 & RF3_DEMON) inc_piety(GOD_TULKAS, inc);
+ if (r_ptr->flags & RF_DEMON)
+ {
+ inc_piety(GOD_TULKAS, inc);
+ }
}
}
/* Yavanna likes when corruption is destroyed */
- if ((r_ptr->flags3 & RF3_NONLIVING) || (r_ptr->flags3 & RF3_DEMON) || (r_ptr->flags3 & RF3_UNDEAD))
+ if ((r_ptr->flags & RF_NONLIVING) || (r_ptr->flags & RF_DEMON) || (r_ptr->flags & RF_UNDEAD))
{
- int inc = m_ptr->level / 2;
-
- if (!inc) inc = 1;
+ int inc = std::max(1, m_ptr->level / 2);
inc_piety(GOD_YAVANNA, inc);
}
/* Yavanna doesnt like any killing in her name */
- PRAY_GOD(GOD_YAVANNA)
+ if (praying_to(GOD_YAVANNA))
{
- int inc = m_ptr->level / 2;
-
- if (!inc) inc = 1;
+ int inc = std::max(1, m_ptr->level / 2);
inc_piety(GOD_YAVANNA, -inc);
/* Killing animals in her name is a VERY bad idea */
- if (r_ptr->flags3 & RF3_ANIMAL)
+ if (r_ptr->flags & RF_ANIMAL)
inc_piety(GOD_YAVANNA, -(inc * 3));
}
/* SHould we absorb its soul? */
- if (p_ptr->absorb_soul && (!(r_ptr->flags3 & RF3_UNDEAD)) && (!(r_ptr->flags3 & RF3_NONLIVING)))
+ if (p_ptr->absorb_soul && (!(r_ptr->flags & RF_UNDEAD)) && (!(r_ptr->flags & RF_NONLIVING)))
{
msg_print("You absorb the life of the dying soul.");
hp_player(1 + (m_ptr->level / 2) + get_skill_scale(SKILL_NECROMANCY, 40));
@@ -3164,7 +3175,7 @@ bool_ mon_take_hit(int m_idx, int dam, bool_ *fear, cptr note)
* XXX XXX XXX Mega-Hack -- Remove random quest rendered
* impossible
*/
- if (r_ptr->flags1 & (RF1_UNIQUE))
+ if (r_ptr->flags & RF_UNIQUE)
{
int i;
@@ -3183,7 +3194,7 @@ bool_ mon_take_hit(int m_idx, int dam, bool_ *fear, cptr note)
* XXX XXX XXX Not yet completed quest is
* to kill a unique you've just killed
*/
- if (r_ptr == &r_info[q_ptr->r_idx])
+ if (r_idx == q_ptr->r_idx)
{
/* Invalidate it */
q_ptr->type = 0;
@@ -3191,29 +3202,23 @@ 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->flags & RF_UNIQUE)
{
char note[80];
- /* Get true name even if blinded/hallucinating */
- cptr monst = (r_name + r_ptr->name);
-
/* Write note */
- sprintf(note, "Killed %s", monst);
+ sprintf(note, "Killed %s", r_ptr->name);
add_note(note, 'U');
}
/* Recall even invisible uniques or winners */
- if (m_ptr->ml || (r_ptr->flags1 & (RF1_UNIQUE)))
+ if (m_ptr->ml || (r_ptr->flags & RF_UNIQUE))
{
/* Count kills this life */
if (r_ptr->r_pkills < MAX_SHORT) r_ptr->r_pkills++;
- /* Count kills in all lives */
- if (r_ptr->r_tkills < MAX_SHORT) r_ptr->r_tkills++;
-
/* Hack -- Auto-recall */
monster_race_track(m_ptr->r_idx, m_ptr->ego);
}
@@ -3228,59 +3233,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);
@@ -3295,14 +3249,13 @@ void get_screen_size(int *wid_p, int *hgt_p)
Term_get_size(wid_p, hgt_p);
*hgt_p -= ROW_MAP + 1;
*wid_p -= COL_MAP + 1;
- if (use_bigtile) *wid_p /= 2;
}
/*
* Calculates current boundaries
* Called below.
*/
-static void panel_bounds(void)
+static void panel_bounds()
{
int wid, hgt;
@@ -3385,7 +3338,7 @@ bool_ change_panel(int dy, int dx)
*
* The map is reprinted if necessary, and "TRUE" is returned.
*/
-void verify_panel(void)
+void verify_panel()
{
int y = p_ptr->py;
int x = p_ptr->px;
@@ -3424,7 +3377,7 @@ void verify_panel(void)
if (max_pcol_min < 0) max_pcol_min = 0;
/* An option: center on player */
- if (center_player)
+ if (options->center_player)
{
/* Center vertically */
prow_min = y - panel_hgt;
@@ -3498,7 +3451,10 @@ void verify_panel(void)
panel_col_min = pcol_min;
/* Hack -- optional disturb on "panel change" */
- if (disturb_panel && !center_player) disturb(0, 0);
+ if (options->disturb_panel && !options->center_player)
+ {
+ disturb();
+ }
/* Recalculate the boundaries */
panel_bounds();
@@ -3517,7 +3473,7 @@ void verify_panel(void)
/*
* Map resizing whenever the main term changes size
*/
-void resize_map(void)
+void resize_map()
{
/* Only if the dungeon exists */
if (!character_dungeon) return;
@@ -3550,7 +3506,7 @@ void resize_map(void)
p_ptr->update |= (PU_UN_VIEW | PU_VIEW | PU_MONSTERS | PU_MON_LITE);
/* Redraw everything */
- p_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP);
+ p_ptr->redraw |= (PR_WIPE | PR_FRAME | PR_MAP);
/* Hack -- update */
handle_stuff();
@@ -3566,7 +3522,7 @@ void resize_map(void)
/*
* Redraw a term when it is resized
*/
-void resize_window(void)
+void resize_window()
{
/* Only if the dungeon exists */
if (!character_dungeon) return;
@@ -3598,19 +3554,16 @@ void resize_window(void)
/*
* Monster health description
*/
-cptr look_mon_desc(int m_idx)
+static cptr look_mon_desc(int m_idx)
{
- monster_type *m_ptr = &m_list[m_idx];
- monster_race *r_ptr = race_inf(m_ptr);
-
bool_ living = TRUE;
- int perc;
-
/* Determine if the monster is "living" (vs "undead") */
- if (r_ptr->flags3 & (RF3_UNDEAD)) living = FALSE;
- if (r_ptr->flags3 & (RF3_DEMON)) living = FALSE;
- if (r_ptr->flags3 & (RF3_NONLIVING)) living = FALSE;
+ monster_type *m_ptr = &m_list[m_idx];
+ auto const r_ptr = m_ptr->race();
+ if (r_ptr->flags & RF_UNDEAD) living = FALSE;
+ if (r_ptr->flags & RF_DEMON) living = FALSE;
+ if (r_ptr->flags & RF_NONLIVING) living = FALSE;
if (strchr("Egv", r_ptr->d_char)) living = FALSE;
@@ -3623,7 +3576,7 @@ cptr look_mon_desc(int m_idx)
/* Calculate a health "percentage" */
- perc = 100L * m_ptr->hp / m_ptr->maxhp;
+ const int perc = 100L * m_ptr->hp / m_ptr->maxhp;
if (perc >= 60)
{
@@ -3645,69 +3598,6 @@ cptr look_mon_desc(int m_idx)
-/*
- * Angband sorting algorithm -- quick sort in place
- *
- * Note that the details of the data we are sorting is hidden,
- * and we rely on the "ang_sort_comp()" and "ang_sort_swap()"
- * function hooks to interact with the data, which is given as
- * two pointers, and which may have any user-defined form.
- */
-void ang_sort_aux(vptr u, vptr v, int p, int q)
-{
- int z, a, b;
-
- /* Done sort */
- if (p >= q) return;
-
- /* Pivot */
- z = p;
-
- /* Begin */
- a = p;
- b = q;
-
- /* Partition */
- while (TRUE)
- {
- /* Slide i2 */
- while (!(*ang_sort_comp)(u, v, b, z)) b--;
-
- /* Slide i1 */
- while (!(*ang_sort_comp)(u, v, z, a)) a++;
-
- /* Done partition */
- if (a >= b) break;
-
- /* Swap */
- (*ang_sort_swap)(u, v, a, b);
-
- /* Advance */
- a++, b--;
- }
-
- /* Recurse left side */
- ang_sort_aux(u, v, p, b);
-
- /* Recurse right side */
- ang_sort_aux(u, v, b + 1, q);
-}
-
-
-/*
- * Angband sorting algorithm -- quick sort in place
- *
- * Note that the details of the data we are sorting is hidden,
- * and we rely on the "ang_sort_comp()" and "ang_sort_swap()"
- * function hooks to interact with the data, which is given as
- * two pointers, and which may have any user-defined form.
- */
-void ang_sort(vptr u, vptr v, int n)
-{
- /* Sort the array */
- ang_sort_aux(u, v, 0, n - 1);
-}
-
/*** Targetting Code ***/
@@ -3727,8 +3617,10 @@ void ang_sort(vptr u, vptr v, int n)
* Future versions may restrict the ability to target "trappers"
* and "mimics", but the semantics is a little bit weird.
*/
-bool_ target_able(int m_idx)
+static bool target_able(int m_idx)
{
+ auto const &r_info = game->edit_data.r_info;
+
monster_type *m_ptr = &m_list[m_idx];
/* Monster must be alive */
@@ -3747,7 +3639,7 @@ bool_ target_able(int m_idx)
if (is_friend(m_ptr) > 0) return (FALSE);
/* Honor flag */
- if (r_info[m_ptr->r_idx].flags7 & RF7_NO_TARGET) return (FALSE);
+ if (r_info[m_ptr->r_idx].flags & RF_NO_TARGET) return (FALSE);
/* XXX XXX XXX Hack -- Never target trappers */
/* if (CLEAR_ATTR && (CLEAR_CHAR)) return (FALSE); */
@@ -3764,7 +3656,7 @@ bool_ target_able(int m_idx)
*
* We return TRUE if the target is "okay" and FALSE otherwise.
*/
-bool_ target_okay(void)
+bool_ target_okay()
{
/* Accept stationary targets */
if (target_who < 0) return (TRUE);
@@ -3793,108 +3685,37 @@ bool_ target_okay(void)
/*
- * Sorting hook -- comp function -- by "distance to player"
- *
- * We use "u" and "v" to point to arrays of "x" and "y" positions,
- * and sort the arrays by double-distance to the player.
- */
-static bool_ ang_sort_comp_distance(vptr u, vptr v, int a, int b)
-{
- byte *x = (byte*)(u);
- byte *y = (byte*)(v);
-
- int da, db, kx, ky;
-
- /* Absolute distance components */
- kx = x[a];
- kx -= p_ptr->px;
- kx = ABS(kx);
- ky = y[a];
- ky -= p_ptr->py;
- ky = ABS(ky);
-
- /* Approximate Double Distance to the first point */
- da = ((kx > ky) ? (kx + kx + ky) : (ky + ky + kx));
-
- /* Absolute distance components */
- kx = x[b];
- kx -= p_ptr->px;
- kx = ABS(kx);
- ky = y[b];
- ky -= p_ptr->py;
- ky = ABS(ky);
-
- /* Approximate Double Distance to the first point */
- db = ((kx > ky) ? (kx + kx + ky) : (ky + ky + kx));
-
- /* Compare the distances */
- return (da <= db);
-}
-
-
-/*
- * Sorting hook -- swap function -- by "distance to player"
- *
- * We use "u" and "v" to point to arrays of "x" and "y" positions,
- * and sort the arrays by distance to the player.
- */
-static void ang_sort_swap_distance(vptr u, vptr v, int a, int b)
-{
- byte *x = (byte*)(u);
- byte *y = (byte*)(v);
-
- byte temp;
-
- /* Swap "x" */
- temp = x[a];
- x[a] = x[b];
- x[b] = temp;
-
- /* Swap "y" */
- temp = y[a];
- y[a] = y[b];
- y[b] = temp;
-}
-
-
-
-/*
* Hack -- help "select" a location (see below)
*/
-static s16b target_pick(int y1, int x1, int dy, int dx)
+static s16b target_pick(point p, int dy, int dx, std::vector<point> const &points)
{
- int i, v;
-
- int x2, y2, x3, y3, x4, y4;
-
int b_i = -1, b_v = 9999;
-
/* Scan the locations */
- for (i = 0; i < temp_n; i++)
+ for (std::size_t i = 0; i < points.size(); i++)
{
/* Point 2 */
- x2 = temp_x[i];
- y2 = temp_y[i];
+ int x2 = points[i].x();
+ int y2 = points[i].y();
/* Directed distance */
- x3 = (x2 - x1);
- y3 = (y2 - y1);
+ int x3 = (x2 - p.x());
+ int y3 = (y2 - p.y());
/* Verify quadrant */
if (dx && (x3 * dx <= 0)) continue;
if (dy && (y3 * dy <= 0)) continue;
/* Absolute distance */
- x4 = ABS(x3);
- y4 = ABS(y3);
+ int x4 = ABS(x3);
+ int y4 = ABS(y3);
/* Verify quadrant */
if (dy && !dx && (x4 > y4)) continue;
if (dx && !dy && (y4 > x4)) continue;
/* Approximate Double Distance */
- v = ((x4 > y4) ? (x4 + x4 + y4) : (y4 + y4 + x4));
+ int v = ((x4 > y4) ? (x4 + x4 + y4) : (y4 + y4 + x4));
/* XXX XXX XXX Penalize location */
@@ -3916,10 +3737,8 @@ static s16b target_pick(int y1, int x1, int dy, int dx)
*/
static bool_ target_set_accept(int y, int x)
{
- cave_type *c_ptr;
-
- s16b this_o_idx, next_o_idx = 0;
-
+ auto const &r_info = game->edit_data.r_info;
+ auto const &f_info = game->edit_data.f_info;
/* Player grid is always interesting */
if ((y == p_ptr->py) && (x == p_ptr->px)) return (TRUE);
@@ -3930,10 +3749,10 @@ static bool_ target_set_accept(int y, int x)
/* Examine the grid */
- c_ptr = &cave[y][x];
+ cave_type *c_ptr = &cave[y][x];
/* Visible monsters */
- if (c_ptr->m_idx && c_ptr->m_idx < max_r_idx)
+ if (c_ptr->m_idx && c_ptr->m_idx < static_cast<int>(r_info.size()))
{
monster_type *m_ptr = &m_list[c_ptr->m_idx];
@@ -3942,26 +3761,21 @@ static bool_ target_set_accept(int y, int x)
}
/* Scan all objects in the grid */
- for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
+ for (auto const this_o_idx: c_ptr->o_idxs)
{
- object_type * o_ptr;
-
/* Acquire object */
- o_ptr = &o_list[this_o_idx];
-
- /* Acquire next object */
- next_o_idx = o_ptr->next_o_idx;
+ object_type *o_ptr = &o_list[this_o_idx];
/* Memorized object */
- if (o_ptr->marked) return (TRUE);
+ if (o_ptr->marked)
+ {
+ return (TRUE);
+ }
}
/* Interesting memorized features */
if (c_ptr->info & (CAVE_MARK))
{
- /* Traps are interesting */
- if (c_ptr->info & (CAVE_TRDT)) return (TRUE);
-
/* Hack -- Doors are boring */
if (c_ptr->feat == FEAT_OPEN) return (FALSE);
if (c_ptr->feat == FEAT_BROKEN) return (FALSE);
@@ -3969,7 +3783,7 @@ static bool_ target_set_accept(int y, int x)
(c_ptr->feat <= FEAT_DOOR_TAIL)) return (FALSE);
/* Accept 'naturally' interesting features */
- if (f_info[c_ptr->feat].flags1 & FF1_NOTICE) return (TRUE);
+ if (f_info[c_ptr->feat].flags & FF_NOTICE) return (TRUE);
}
/* Nope */
@@ -3982,42 +3796,42 @@ static bool_ target_set_accept(int y, int x)
*
* Return the number of target_able monsters in the set.
*/
-static void target_set_prepare(int mode)
+static std::vector<point> target_set_prepare(int mode)
{
- int y, x;
-
- /* Reset "temp" array */
- temp_n = 0;
+ std::vector<point> points;
- /* Scan the current panel */
- for (y = panel_row_min; y <= panel_row_max; y++)
+ // Scan the current panel
+ for (int y = panel_row_min; y <= panel_row_max; y++)
{
- for (x = panel_col_min; x <= panel_col_max; x++)
+ for (int x = panel_col_min; x <= panel_col_max; x++)
{
cave_type *c_ptr = &cave[y][x];
- /* Require line of sight, unless "look" is "expanded" */
- if (!expand_look && !player_has_los_bold(y, x)) continue;
-
- /* Require "interesting" contents */
+ // Require "interesting" contents
if (!target_set_accept(y, x)) continue;
- /* Require target_able monsters for "TARGET_KILL" */
+ // Require target_able monsters for "TARGET_KILL"
if ((mode & (TARGET_KILL)) && !target_able(c_ptr->m_idx)) continue;
- /* Save the location */
- temp_x[temp_n] = x;
- temp_y[temp_n] = y;
- temp_n++;
+ // Save the location
+ points.push_back(point(x,y));
}
}
- /* Set the sort hooks */
- ang_sort_comp = ang_sort_comp_distance;
- ang_sort_swap = ang_sort_swap_distance;
+ // Sort the points by distance to player; we'll
+ // use a stable sort to avoid equidistant targets
+ // "swapping" priorities.
+ std::stable_sort(
+ std::begin(points),
+ std::end(points),
+ [](point i, point j) -> bool {
+ auto di = distance(p_ptr->py, p_ptr->px, i.y(), i.x());
+ auto dj = distance(p_ptr->py, p_ptr->px, j.y(), j.x());
+ return di < dj;
+ }
+ );
- /* Sort the positions */
- ang_sort(temp_x, temp_y, temp_n);
+ return points;
}
@@ -4079,9 +3893,13 @@ bool_ target_object(int y, int x, int mode, cptr info, bool_ *boring,
*/
static int target_set_aux(int y, int x, int mode, cptr info)
{
- cave_type *c_ptr = &cave[y][x];
+ auto const &d_info = game->edit_data.d_info;
+ auto const &st_info = game->edit_data.st_info;
+ auto const &wf_info = game->edit_data.wf_info;
+ auto const &f_info = game->edit_data.f_info;
+ auto const &k_info = game->edit_data.k_info;
- s16b this_o_idx, next_o_idx = 0;
+ cave_type *c_ptr = &cave[y][x];
cptr s1, s2, s3;
@@ -4142,19 +3960,20 @@ static int target_set_aux(int y, int x, int mode, cptr info)
if (c_ptr->m_idx)
{
monster_type *m_ptr = &m_list[c_ptr->m_idx];
- monster_race *r_ptr = race_inf(m_ptr);
+ auto const r_ptr = m_ptr->race();
/* Mimics special treatment -- looks like an object */
- if ((r_ptr->flags9 & RF9_MIMIC) && (m_ptr->csleep))
+ if ((r_ptr->flags & RF_MIMIC) && (m_ptr->csleep))
{
- object_type *o_ptr;
-
/* Acquire object */
- o_ptr = &o_list[m_ptr->hold_o_idx];
+ object_type *o_ptr = &o_list[m_ptr->mimic_o_idx()];
if (o_ptr->marked)
{
- if (target_object(y, x, mode, info, &boring, o_ptr, out_val, &s1, &s2, &s3, &query)) break;
+ if (target_object(y, x, mode, info, &boring, o_ptr, out_val, &s1, &s2, &s3, &query))
+ {
+ break;
+ }
}
}
else
@@ -4192,7 +4011,7 @@ static int target_set_aux(int y, int x, int mode, cptr info)
Term_save();
/* Recall on screen */
- screen_roff(m_ptr->r_idx, m_ptr->ego, 0);
+ screen_roff(m_ptr->r_idx, m_ptr->ego);
/* Hack -- Complete the prompt (again) */
Term_addstr( -1, TERM_WHITE, format(" [r,%s]", info));
@@ -4233,9 +4052,10 @@ static int target_set_aux(int y, int x, int mode, cptr info)
if (m_ptr->mflag & MFLAG_PARTIAL) mstat = " (partial) ";
/* Describe, and prompt for recall */
- sprintf(out_val, "%s%s%s%s (level %d, %s%s)%s%s[r,%s]",
+ sprintf(out_val, "%s%s%s%s (level %d, %s%s%s)%s%s[r,%s]",
s1, s2, s3, m_name,
m_ptr->level, look_mon_desc(c_ptr->m_idx),
+ (m_ptr->csleep) ? ", asleep" : "",
(m_ptr->mflag & MFLAG_QUEST) ? ", quest" : "",
(m_ptr->smart & SM_CLONED ? " (clone)" : ""),
(mstat), info);
@@ -4266,26 +4086,22 @@ static int target_set_aux(int y, int x, int mode, cptr info)
s1 = "It is ";
/* Hack -- take account of gender */
- if (r_ptr->flags1 & (RF1_FEMALE)) s1 = "She is ";
- else if (r_ptr->flags1 & (RF1_MALE)) s1 = "He is ";
+ if (r_ptr->flags & RF_FEMALE) s1 = "She is ";
+ else if (r_ptr->flags & RF_MALE) s1 = "He is ";
/* Use a preposition */
s2 = "carrying ";
/* Scan all objects being carried */
- for (this_o_idx = m_ptr->hold_o_idx; this_o_idx; this_o_idx = next_o_idx)
+ std::size_t i = 0;
+ for (; i < m_ptr->hold_o_idxs.size(); i++)
{
- char o_name[80];
-
- object_type *o_ptr;
-
/* Acquire object */
- o_ptr = &o_list[this_o_idx];
-
- /* Acquire next object */
- next_o_idx = o_ptr->next_o_idx;
+ auto this_o_idx = m_ptr->hold_o_idxs.at(i);
+ object_type *o_ptr = &o_list[this_o_idx];
/* Obtain an object description */
+ char o_name[80];
object_desc(o_name, o_ptr, TRUE, 3);
/* Describe the object */
@@ -4295,17 +4111,26 @@ static int target_set_aux(int y, int x, int mode, cptr info)
query = inkey();
/* Always stop at "normal" keys */
- if ((query != '\r') && (query != '\n') && (query != ' ')) break;
+ if ((query != '\r') && (query != '\n') && (query != ' '))
+ {
+ break;
+ }
/* Sometimes stop at "space" key */
- if ((query == ' ') && !(mode & (TARGET_LOOK))) break;
+ if ((query == ' ') && !(mode & (TARGET_LOOK)))
+ {
+ break;
+ }
/* Change the intro */
s2 = "also carrying ";
}
- /* Double break */
- if (this_o_idx) break;
+ /* Double break? */
+ if (i != m_ptr->hold_o_idxs.size())
+ {
+ break;
+ }
/* Use a preposition */
s2 = "on ";
@@ -4313,55 +4138,27 @@ static int target_set_aux(int y, int x, int mode, cptr info)
}
}
-
-
/* 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;
-
- /* Describe it */
- if (o_ptr->marked)
+ std::size_t i = 0;
+ for (; i < c_ptr->o_idxs.size(); i++)
{
- if (target_object(y, x, mode, info, &boring, o_ptr, out_val, &s1, &s2, &s3, &query)) break;
- }
- }
-
- /* Double break */
- if (this_o_idx) break;
-
- /* Actual traps */
- if ((c_ptr->info & (CAVE_TRDT)) && c_ptr->t_idx)
- {
- cptr name = "a trap", s4;
+ /* Acquire object */
+ auto this_o_idx = c_ptr->o_idxs.at(i);
+ object_type *o_ptr = &o_list[this_o_idx];
- /* Name trap */
- if (t_info[c_ptr->t_idx].ident)
- {
- s4 = format("(%s)", t_name + t_info[c_ptr->t_idx].name);
+ /* Describe it */
+ if (o_ptr->marked && target_object(y, x, mode, info, &boring, o_ptr, out_val, &s1, &s2, &s3, &query))
+ {
+ break;
+ }
}
- else
+
+ /* Double break? */
+ if (i != c_ptr->o_idxs.size())
{
- s4 = "an unknown trap";
+ break;
}
-
- /* Display a message */
- sprintf(out_val, "%s%s%s%s [%s]", s1, s2, s3, name, s4);
- prt(out_val, 0, 0);
- move_cursor_relative(y, x);
- query = inkey();
-
- /* Stop on everything but "return" */
- if ((query != '\r') && (query != '\n')) break;
-
- /* Repeat forever */
- continue;
}
/* Feature (apply "mimic") */
@@ -4384,16 +4181,16 @@ static int target_set_aux(int y, int x, int mode, cptr info)
/* Terrain feature if needed */
if (boring || (feat >= FEAT_GLYPH))
{
- cptr name;
+ std::string name;
/* Hack -- special handling for building doors */
if (feat == FEAT_SHOP)
{
- name = st_name + st_info[c_ptr->special].name;
+ name = st_info[c_ptr->special].name;
}
else
{
- name = f_name + f_info[feat].name;
+ name = f_info[feat].name;
}
/* Hack -- handle unknown grids */
@@ -4421,20 +4218,20 @@ static int target_set_aux(int y, int x, int mode, cptr info)
if ((feat == FEAT_MORE) && c_ptr->special)
{
s3 = "";
- name = d_text + d_info[c_ptr->special].text;
+ name = d_info[c_ptr->special].text;
}
if (p_ptr->wild_mode && (feat == FEAT_TOWN))
{
+ auto const &wilderness = game->wilderness;
+ auto const &wf = wf_info[wilderness(x, y).feat];
+
s3 = "";
- name = format("%s(%s)",
- wf_name + wf_info[wild_map[y][x].feat].name,
- wf_text + wf_info[wild_map[y][x].feat].text);
+ name = fmt::format("{}({})", wf.name, wf.text);
}
if ((feat == FEAT_FOUNTAIN) && (c_ptr->info & CAVE_IDNT))
{
- object_kind *k_ptr;
int tv, sv;
if (c_ptr->special <= SV_POTION_LAST)
@@ -4448,19 +4245,18 @@ static int target_set_aux(int y, int x, int mode, cptr info)
sv = c_ptr->special - SV_POTION_LAST;
}
- k_ptr = &k_info[lookup_kind(tv, sv)];
- info = k_name + k_ptr->name;
+ info = k_info[lookup_kind(tv, sv)].name;
}
/* Display a message */
if (!wizard)
{
- sprintf(out_val, "%s%s%s%s [%s]", s1, s2, s3, name, info);
+ sprintf(out_val, "%s%s%s%s [%s]", s1, s2, s3, name.c_str(), info);
}
else
{
sprintf(out_val, "%s%s%s%s [%s] (%d:%d:%d)",
- s1, s2, s3, name, info,
+ s1, s2, s3, name.c_str(), info,
c_ptr->feat, c_ptr->mimic, c_ptr->special);
}
prt(out_val, 0, 0);
@@ -4537,8 +4333,6 @@ bool_ target_set(int mode)
char info[80];
- cave_type *c_ptr;
-
int screen_wid, screen_hgt;
int panel_wid, panel_hgt;
@@ -4558,7 +4352,7 @@ bool_ target_set(int mode)
/* Prepare the "temp" array */
- target_set_prepare(mode);
+ std::vector<point> points = target_set_prepare(mode);
/* Start near the player */
m = 0;
@@ -4567,13 +4361,13 @@ bool_ target_set(int mode)
while (!done)
{
/* Interesting grids */
- if (flag && temp_n)
+ if (flag && points.size())
{
- y = temp_y[m];
- x = temp_x[m];
+ y = points[m].y();
+ x = points[m].x();
/* Access */
- c_ptr = &cave[y][x];
+ cave_type *c_ptr = &cave[y][x];
/* Allow target */
if (target_able(c_ptr->m_idx))
@@ -4630,10 +4424,9 @@ bool_ target_set(int mode)
case '*':
case '+':
{
- if (++m == temp_n)
+ if (++m == points.size())
{
m = 0;
- if (!expand_list) done = TRUE;
}
break;
}
@@ -4642,8 +4435,7 @@ bool_ target_set(int mode)
{
if (m-- == 0)
{
- m = temp_n - 1;
- if (!expand_list) done = TRUE;
+ m = points.size() - 1;
}
break;
}
@@ -4699,7 +4491,7 @@ bool_ target_set(int mode)
if (d)
{
/* Find a new monster */
- i = target_pick(temp_y[m], temp_x[m], ddy[d], ddx[d]);
+ i = target_pick(points[m], ddy[d], ddx[d], points);
/* Scroll to find interesting grid */
if (i < 0)
@@ -4713,14 +4505,13 @@ bool_ target_set(int mode)
/* Note panel change */
if (change_panel(dy, dx))
{
- int ty = temp_y[m];
- int tx = temp_x[m];
+ auto const t = points[m];
/* Recalculate interesting grids */
target_set_prepare(mode);
/* Find a new monster */
- i = target_pick(ty, tx, dy, dx);
+ i = target_pick(t, dy, dx, points);
/* Restore panel if needed */
if (i < 0)
@@ -4742,9 +4533,6 @@ bool_ target_set(int mode)
/* Arbitrary grids */
else
{
- /* Access */
- c_ptr = &cave[y][x];
-
/* Default prompt */
strcpy(info, "q,t,p,m,+,-,'dir'");
@@ -4872,9 +4660,6 @@ bool_ target_set(int mode)
}
}
- /* Forget */
- temp_n = 0;
-
/* Clear the top line */
prt("", 0, 0);
@@ -4939,7 +4724,10 @@ bool_ get_aim_dir(int *dp)
dir = command_dir;
/* Hack -- auto-target if requested */
- if (use_old_target && target_okay()) dir = 5;
+ if (options->use_old_target && target_okay())
+ {
+ dir = 5;
+ }
/* Ask until satisfied */
while (!dir)
@@ -5111,438 +4899,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]);
- (void)gain_random_corruption(0);
- 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.
*/
@@ -5603,166 +4959,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_ lose_all_corruptions(void)
-{
- exec_lua("lose_all_corruptions()");
- return (FALSE);
-}
-
-bool_ get_hack_dir(int *dp)
-{
- int dir;
- cptr p;
- char command;
-
-
- /* Initialize */
- (*dp) = 0;
-
- /* Global direction */
- dir = 0;
-
- /* (No auto-targetting */
-
- /* Ask until satisfied */
- while (!dir)
- {
- /* Choose a prompt */
- if (!target_okay())
- {
- p = "Direction ('*' to choose a target, Escape to cancel)? ";
- }
- else
- {
- p = "Direction ('5' for target, '*' to re-target, Escape to cancel)? ";
- }
-
- /* Get a command (or Cancel) */
- if (!get_com(p, &command)) break;
-
- /* Convert various keys to "standard" keys */
- switch (command)
- {
- /* Use current target */
- case 'T':
- case 't':
- case '.':
- case '5':
- case '0':
- {
- dir = 5;
- break;
- }
-
- /* Set new target */
- case '*':
- {
- if (target_set(TARGET_KILL)) dir = 5;
- break;
- }
-
- default:
- {
- /* Look up the direction */
- dir = get_keymap_dir(command);
-
- break;
- }
- }
-
- /* Verify requested targets */
- if ((dir == 5) && !target_okay()) dir = 0;
-
- /* Error */
- if (!dir) bell();
- }
-
- /* No direction */
- if (!dir) return (FALSE);
-
- /* Save the direction */
- command_dir = dir;
-
- /* Check for confusion */
- if (p_ptr->confused)
- {
- /* XXX XXX XXX */
- /* Random direction */
- dir = ddd[rand_int(8)];
- }
-
- /* Notice confusion */
- if (command_dir != dir)
- {
- /* Warn the user */
- msg_print("You are confused.");
- }
-
- /* Save direction */
- (*dp) = dir;
-
- /* A "valid" direction was entered */
- 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
*/
@@ -5772,25 +4968,28 @@ void set_grace(s32b v)
if (v > 300000) v = 300000;
p_ptr->grace = v;
p_ptr->update |= PU_BONUS;
- p_ptr->redraw |= (PR_PIETY);
+ p_ptr->redraw |= (PR_FRAME);
handle_stuff();
}
-bool_ test_object_wish(char *name, object_type *o_ptr, object_type *forge, char *what)
+static bool_ test_object_wish(char *name, object_type *o_ptr, object_type *forge, const char *what)
{
- int i, j, jb, save_aware;
+ auto &k_info = game->edit_data.k_info;
+ auto const &e_info = game->edit_data.e_info;
+
+ int save_aware;
char buf[200];
/* try all objects, this *IS* a very ugly and slow method :( */
- for (i = 0; i < max_k_idx; i++)
+ for (std::size_t i = 0; i < k_info.size(); i++)
{
- object_kind *k_ptr = &k_info[i];
+ auto k_ptr = &k_info[i];
o_ptr = forge;
if (!k_ptr->name) continue;
- if (k_ptr->flags3 & TR3_NORM_ART) continue;
- if (k_ptr->flags3 & TR3_INSTA_ART) continue;
+ if (k_ptr->flags & TR_NORM_ART) continue;
+ if (k_ptr->flags & TR_INSTA_ART) continue;
if (k_ptr->tval == TV_GOLD) continue;
object_prep(o_ptr, i);
@@ -5810,9 +5009,9 @@ bool_ test_object_wish(char *name, object_type *o_ptr, object_type *forge, char
(o_ptr->tval == TV_ROD_MAIN && strstr(name, "rod of")))
{
/* try all ego */
- for (j = max_e_idx - 1; j >= 0; j--)
+ for (std::size_t j = 0; j < e_info.size(); j++)
{
- ego_item_type *e_ptr = &e_info[j];
+ auto e_ptr = &e_info[j];
bool_ ok = FALSE;
if (j && !e_ptr->name) continue;
@@ -5838,9 +5037,9 @@ bool_ test_object_wish(char *name, object_type *o_ptr, object_type *forge, char
}
/* try all ego */
- for (jb = max_e_idx - 1; jb >= 0; jb--)
+ for (std::size_t jb = 0; jb < e_info.size(); jb++)
{
- ego_item_type *eb_ptr = &e_info[jb];
+ auto eb_ptr = &e_info[jb];
bool_ ok = FALSE;
if (jb && !eb_ptr->name) continue;
@@ -5877,7 +5076,7 @@ bool_ test_object_wish(char *name, object_type *o_ptr, object_type *forge, char
object_desc(buf, o_ptr, FALSE, 0);
strlower(buf);
- if (!stricmp(buf, name))
+ if (iequals(buf, name))
{
/* Don't search any more */
return TRUE;
@@ -5894,7 +5093,7 @@ bool_ test_object_wish(char *name, object_type *o_ptr, object_type *forge, char
return FALSE;
}
-void clean_wish_name(char *buf, char *name)
+static void clean_wish_name(char *buf, char *name)
{
char *p;
int i, j;
@@ -5931,13 +5130,17 @@ void clean_wish_name(char *buf, char *name)
/*
* Allow the player to make a wish
*/
-void make_wish(void)
+void make_wish()
{
- char buf[200], name[200], *mname;
- int i, j, mstatus = MSTATUS_ENEMY;
+ auto const &re_info = game->edit_data.re_info;
+ auto const &r_info = game->edit_data.r_info;
+
+ char name[200], *mname;
+ int mstatus = MSTATUS_ENEMY;
object_type forge, *o_ptr = &forge;
/* Make an empty string */
+ char buf[200];
buf[0] = 0;
/* Ask for the wish */
@@ -5989,43 +5192,54 @@ void make_wish(void)
else mstatus = MSTATUS_PET;
mname = name + 10;
}
- else mname = name;
- for (i = 1; i < max_r_idx; i++)
+ else
+ {
+ mname = name;
+ }
+
+ for (std::size_t i = 1; i < r_info.size(); i++)
{
- monster_race *r_ptr = &r_info[i];
+ auto r_ptr = &r_info[i];
if (!r_ptr->name) continue;
- if (r_ptr->flags9 & RF9_SPECIAL_GENE) continue;
- if (r_ptr->flags9 & RF9_NEVER_GENE) continue;
- if (r_ptr->flags1 & RF1_UNIQUE) continue;
+ if (r_ptr->flags & RF_SPECIAL_GENE) continue;
+ if (r_ptr->flags & RF_NEVER_GENE) continue;
+ if (r_ptr->flags & RF_UNIQUE) continue;
- sprintf(buf, "%s", r_ptr->name + r_name);
+ sprintf(buf, "%s", r_ptr->name);
strlower(buf);
if (strstr(mname, buf))
{
/* try all ego */
- for (j = max_re_idx - 1; j >= 0; j--)
+ for (std::size_t j = 0; j < re_info.size(); j++)
{
- monster_ego *re_ptr = &re_info[j];
+ auto re_ptr = &re_info[j];
if (j && !re_ptr->name) continue;
- if (!mego_ok(i, j)) continue;
+ if (!mego_ok(r_ptr, j)) continue;
if (j)
{
- if (re_ptr->before) sprintf(buf, "%s %s", re_name + re_ptr->name, r_ptr->name + r_name);
- else sprintf(buf, "%s %s", r_ptr->name + r_name, re_name + re_ptr->name);
+ if (re_ptr->before)
+ {
+ sprintf(buf, "%s %s", re_ptr->name, r_ptr->name);
+ }
+ else
+ {
+ sprintf(buf, "%s %s", r_ptr->name, re_ptr->name);
+ }
}
else
{
- sprintf(buf, "%s", r_ptr->name + r_name);
+ sprintf(buf, "%s", r_ptr->name);
}
+
strlower(buf);
- if (!stricmp(mname, buf))
+ if (iequals(mname, buf))
{
int wy = p_ptr->py, wx = p_ptr->px;
int attempts = 100;
@@ -6038,7 +5252,9 @@ void make_wish(void)
/* Create the monster */
if (place_monster_one(wy, wx, i, j, FALSE, mstatus))
+ {
msg_print("Your wish becomes truth!");
+ }
/* Don't search any more */
return;
@@ -6053,15 +5269,15 @@ void make_wish(void)
* Corrupted have a 1/3 chance of losing a mutation each time this is called,
* assuming they have any in the first place
*/
-void corrupt_corrupted(void)
+static void corrupt_corrupted()
{
if (magik(45))
{
- lose_corruption(0);
+ lose_corruption();
}
else
{
- gain_random_corruption(0);
+ gain_random_corruption();
}
/* We are done. */
@@ -6069,67 +5285,39 @@ void corrupt_corrupted(void)
}
/*
- * 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
*/
-void switch_subrace(int racem, bool_ copy_old)
+void switch_subrace(std::size_t racem, bool_ copy_old)
{
- if ((racem < 0) && (racem >= max_rmp_idx)) return;
+ auto &race_mod_info = game->edit_data.race_mod_info;
+
+ assert(racem < race_mod_info.size());
/* If we switch to the saved subrace, we copy over the old subrace data */
if (copy_old && (racem == SUBRACE_SAVE))
{
- s32b old_title = race_mod_info[SUBRACE_SAVE].title;
- s32b old_desc = race_mod_info[SUBRACE_SAVE].desc;
-
- COPY(&race_mod_info[SUBRACE_SAVE], &race_mod_info[p_ptr->pracem], player_race_mod);
-
- race_mod_info[SUBRACE_SAVE].title = old_title;
- race_mod_info[SUBRACE_SAVE].desc = old_desc;
- strcpy(race_mod_info[SUBRACE_SAVE].title + rmp_name, race_mod_info[p_ptr->pracem].title + rmp_name);
+ // Keep old description
+ auto old_desc = race_mod_info[SUBRACE_SAVE].description;
+ // Copy everything
+ race_mod_info[SUBRACE_SAVE] = race_mod_info[p_ptr->pracem];
+ // Reinstate description
+ race_mod_info[SUBRACE_SAVE].description = old_desc;
}
p_ptr->pracem = racem;
rmp_ptr = &race_mod_info[p_ptr->pracem];
}
-cptr get_subrace_title(int racem)
-{
- return race_mod_info[racem].title + rmp_name;
-}
-
-void set_subrace_title(int racem, cptr name)
-{
- strcpy(race_mod_info[racem].title + rmp_name, name);
-}
-
/*
* Rebirth, recalc hp & exp/level
*/
void do_rebirth()
{
/* Experience factor */
- p_ptr->expfact = rp_ptr->r_exp + rmp_ptr->r_exp + cp_ptr->c_exp;
+ p_ptr->expfact = rp_ptr->ps.exp + rmp_ptr->ps.exp + cp_ptr->ps.exp;
/* Hitdice */
- p_ptr->hitdie = rp_ptr->r_mhp + rmp_ptr->r_mhp + cp_ptr->c_mhp;
+ p_ptr->hitdie = rp_ptr->ps.mhp + rmp_ptr->ps.mhp + cp_ptr->ps.mhp;
/* Recalc HP */
do_cmd_rerate();
@@ -6139,20 +5327,9 @@ void do_rebirth()
p_ptr->max_plv = p_ptr->lev;
/* Redraw/calc stuff */
- p_ptr->redraw |= (PR_BASIC);
+ p_ptr->redraw |= (PR_FRAME);
p_ptr->update |= (PU_BONUS);
handle_stuff();
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;
-}
diff --git a/src/xtra2.hpp b/src/xtra2.hpp
new file mode 100644
index 00000000..9edcec1e
--- /dev/null
+++ b/src/xtra2.hpp
@@ -0,0 +1,89 @@
+#pragma once
+
+#include "h-basic.h"
+#include "monster_race_fwd.hpp"
+#include "object_type_fwd.hpp"
+#include "player_race_mod_fwd.hpp"
+
+#include <memory>
+
+void do_rebirth();
+void switch_subrace(std::size_t racem, bool_ copy_old);
+void drop_from_wild();
+bool_ set_roots(int v, s16b ac, s16b dam);
+bool_ set_project(int v, s16b gf, s16b dam, s16b rad, s16b flag);
+bool_ set_parasite(int v, int r);
+bool_ set_disrupt_shield(int v);
+bool_ set_prob_travel(int v);
+bool_ set_absorb_soul(int v);
+bool_ set_tim_breath(int v, bool_ magical);
+bool_ set_tim_precognition(int v);
+bool_ set_tim_deadly(int v);
+bool_ set_tim_reflect(int v);
+bool_ set_tim_thunder(int v, int p1, int p2);
+bool_ set_strike(int v);
+bool_ set_tim_regen(int v, int p);
+bool_ set_tim_ffall(int v);
+bool_ set_tim_fly(int v);
+bool_ set_poison(int v);
+bool_ set_holy(int v);
+void set_grace(s32b v);
+bool_ set_mimic(int v, int p, int level);
+bool_ set_no_breeders(int v);
+bool_ set_invis(int v,int p);
+bool_ set_lite(int v);
+bool_ set_blind(int v);
+bool_ set_confused(int v);
+bool_ set_poisoned(int v);
+bool_ set_afraid(int v);
+bool_ set_paralyzed(int v);
+void dec_paralyzed();
+bool_ set_image(int v);
+bool_ set_fast(int v, int p);
+bool_ set_light_speed(int v);
+bool_ set_slow(int v);
+bool_ set_shield(int v, int p, s16b o, s16b d1, s16b d2);
+bool_ set_blessed(int v);
+bool_ set_hero(int v);
+bool_ set_shero(int v);
+bool_ set_protevil(int v);
+bool_ set_invuln(int v);
+bool_ set_tim_invis(int v);
+bool_ set_tim_infra(int v);
+bool_ set_mental_barrier(int v);
+bool_ set_oppose_acid(int v);
+bool_ set_oppose_elec(int v);
+bool_ set_oppose_fire(int v);
+bool_ set_oppose_cold(int v);
+bool_ set_oppose_pois(int v);
+bool_ set_oppose_cc(int v);
+bool_ set_stun(int v);
+bool_ set_cut(int v);
+bool_ set_food(int v);
+void check_experience();
+void check_experience_obj(object_type *o_ptr);
+void gain_exp(s32b amount);
+void lose_exp(s32b amount);
+int get_coin_type(std::shared_ptr<monster_race const> r_ptr);
+void monster_death(int m_idx);
+bool_ mon_take_hit(int m_idx, int dam, bool_ *fear, cptr note);
+bool_ change_panel(int dy, int dx);
+void verify_panel();
+bool_ target_okay();
+bool_ target_set(int mode);
+bool_ get_aim_dir(int *dp);
+bool_ get_rep_dir(int *dp);
+bool_ set_shadow(int v);
+bool_ set_tim_esp(int v);
+bool_ tgp_pt(int *x, int * y);
+bool_ tgt_pt (int *x, int *y);
+void do_poly_self();
+bool_ curse_weapon();
+bool_ curse_armor();
+void make_wish();
+void create_between_gate(int dist, int y, int x);
+
+extern "C" {
+ void resize_map();
+ void resize_window();
+}
diff --git a/src/z-form.c b/src/z-form.c
index b3d5d005..90d71294 100644
--- a/src/z-form.c
+++ b/src/z-form.c
@@ -5,8 +5,8 @@
#include "z-form.h"
#include "z-util.h"
-#include "z-virt.h"
+#include <stdlib.h>
/*
* Here is some information about the routines in this file.
@@ -17,10 +17,10 @@
* (using only the first "max length" bytes), and return the "length"
* of the resulting string, not including the (mandatory) terminator.
*
- * The format strings allow the basic "sprintf()" format sequences, though
- * some of them are processed slightly more carefully or portably, as well
- * as a few "special" sequences, including the "%r" and "%v" sequences, and
- * the "capilitization" sequences of "%C", "%S", and "%V".
+ * The format strings allow the basic "sprintf()" format sequences,
+ * though some of them are processed slightly more carefully or
+ * portably, as well as a few "special" sequences, including the
+ * "capilitization" sequences of "%C", "%S", and "%V".
*
* Note that some "limitations" are enforced by the current implementation,
* for example, no "format sequence" can exceed 100 characters, including any
@@ -99,13 +99,6 @@
*
* Format("%V", vptr v)
* Note -- possibly significant mode flag
- * Format("%v", vptr v)
- * Append the object "v", using the current "user defined print routine".
- * User specified modifiers, often ignored.
- *
- * Format("%r", vstrnfmt_aux_func *fp)
- * Set the "user defined print routine" (vstrnfmt_aux) to "fp".
- * No legal modifiers.
*
*
* For examples below, assume "int n = 0; int m = 100; char buf[100];",
@@ -126,12 +119,6 @@
* For example: "s = buf; n = vstrnfmt(s+n, 100-n, ...); ..." will allow
* multiple bounded "appends" to "buf", with constant access to "strlen(buf)".
*
- * For example: "format("The %r%v was destroyed!", obj_desc, obj);"
- * (where "obj_desc(buf, max, fmt, obj)" will "append" a "description"
- * of the given object to the given buffer, and return the total length)
- * will return a "useful message" about the object "obj", for example,
- * "The Large Shield was destroyed!".
- *
* For example: "format("%^-.*s", i, txt)" will produce a string containing
* the first "i" characters of "txt", left justified, with the first non-space
* character capitilized, if reasonable.
@@ -140,40 +127,6 @@
-
-/*
- * The "type" of the "user defined print routine" pointer
- */
-typedef uint (*vstrnfmt_aux_func)(char *buf, uint max, cptr fmt, vptr arg);
-
-/*
- * The "default" user defined print routine. Ignore the "fmt" string.
- */
-static uint vstrnfmt_aux_dflt(char *buf, uint max, cptr fmt, vptr arg)
-{
- uint len;
- char tmp[32];
-
- /* XXX XXX */
- fmt = fmt ? fmt : 0;
-
- /* Pointer display */
- sprintf(tmp, "<<%p>>", arg);
- len = strlen(tmp);
- if (len >= max) len = max - 1;
- tmp[len] = '\0';
- strcpy(buf, tmp);
- return (len);
-}
-
-/*
- * The "current" user defined print routine. It can be changed
- * dynamically by sending the proper "%r" sequence to "vstrnfmt()"
- */
-static vstrnfmt_aux_func vstrnfmt_aux = vstrnfmt_aux_dflt;
-
-
-
/*
* Basic "vararg" format function.
*
@@ -316,19 +269,6 @@ uint vstrnfmt(char *buf, uint max, cptr fmt, va_list vp)
continue;
}
- /* Hack -- Pre-process "%r" */
- if (*s == 'r')
- {
- /* Extract the next argument, and save it (globally) */
- vstrnfmt_aux = va_arg(vp, vstrnfmt_aux_func);
-
- /* Skip the "r" */
- s++;
-
- /* Continue */
- continue;
- }
-
/* Begin the "aux" string */
q = 0;
@@ -576,23 +516,6 @@ uint vstrnfmt(char *buf, uint max, cptr fmt, va_list vp)
break;
}
- /* User defined data */
- case 'V':
- case 'v':
- {
- vptr arg;
-
- /* Access next argument */
- arg = va_arg(vp, vptr);
-
- /* Format the "user data" */
- (void)vstrnfmt_aux(tmp, 1000, aux, arg);
-
- /* Done */
- break;
- }
-
-
/* Oops */
default:
{
@@ -608,19 +531,7 @@ uint vstrnfmt(char *buf, uint max, cptr fmt, va_list vp)
/* Mega-Hack -- handle "capitilization" */
if (do_xtra)
{
- /* Now append "tmp" to "buf" */
- for (q = 0; tmp[q]; q++)
- {
- /* Notice first non-space */
- if (!isspace(tmp[q]))
- {
- /* Capitalize if possible */
- if (islower(tmp[q])) tmp[q] = toupper(tmp[q]);
-
- /* Done */
- break;
- }
- }
+ capitalize(tmp);
}
/* Now append "tmp" to "buf" */
@@ -647,16 +558,20 @@ 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;
+ static size_t format_len = 0;
/* Initial allocation */
if (!format_buf)
{
format_len = 1024;
- C_MAKE(format_buf, format_len, char);
+ format_buf = calloc(format_len, sizeof(char));
+ if (format_buf == NULL)
+ {
+ abort(); // Nothing sensible we can do
+ }
}
/* Null format yields last result */
@@ -674,9 +589,13 @@ char *vformat(cptr fmt, va_list vp)
if (len < format_len - 1) break;
/* Grow the buffer */
- C_KILL(format_buf, format_len, char);
+ free(format_buf);
format_len = format_len * 2;
- C_MAKE(format_buf, format_len, char);
+ format_buf = calloc(format_len, sizeof(char));
+ if (format_buf == NULL)
+ {
+ abort(); // Nothing sensible we can do
+ }
}
/* Return the new buffer */
@@ -708,30 +627,6 @@ uint strnfmt(char *buf, uint max, cptr fmt, ...)
}
-/*
- * Do a vstrnfmt (see above) into a buffer of unknown size.
- * Since the buffer size is unknown, the user better verify the args.
- */
-uint strfmt(char *buf, cptr fmt, ...)
-{
- uint len;
-
- va_list vp;
-
- /* Begin the Varargs Stuff */
- va_start(vp, fmt);
-
- /* Build the string, assume 32K buffer */
- len = vstrnfmt(buf, 32767, fmt, vp);
-
- /* End the Varargs Stuff */
- va_end(vp);
-
- /* Return the number of bytes written */
- return (len);
-}
-
-
/*
@@ -762,29 +657,6 @@ char *format(cptr fmt, ...)
/*
- * Vararg interface to plog()
- */
-void plog_fmt(cptr fmt, ...)
-{
- char *res;
- va_list vp;
-
- /* Begin the Varargs Stuff */
- va_start(vp, fmt);
-
- /* Format the args */
- res = vformat(fmt, vp);
-
- /* End the Varargs Stuff */
- va_end(vp);
-
- /* Call plog */
- plog(res);
-}
-
-
-
-/*
* Vararg interface to quit()
*/
void quit_fmt(cptr fmt, ...)
@@ -804,28 +676,3 @@ void quit_fmt(cptr fmt, ...)
/* Call quit() */
quit(res);
}
-
-
-
-/*
- * Vararg interface to core()
- */
-void core_fmt(cptr fmt, ...)
-{
- char *res;
- va_list vp;
-
- /* Begin the Varargs Stuff */
- va_start(vp, fmt);
-
- /* If requested, Do a virtual fprintf to stderr */
- res = vformat(fmt, vp);
-
- /* End the Varargs Stuff */
- va_end(vp);
-
- /* Call core() */
- core(res);
-}
-
-
diff --git a/src/z-form.h b/src/z-form.h
index 2dcfa96c..f67d1484 100644
--- a/src/z-form.h
+++ b/src/z-form.h
@@ -1,7 +1,4 @@
-/* File z-form.h */
-
-#ifndef INCLUDED_Z_FORM_H
-#define INCLUDED_Z_FORM_H
+#pragma once
#ifdef __cplusplus
extern "C" {
@@ -17,38 +14,24 @@ extern "C" {
* See "z-form.c" for more detailed information about the routines,
* including a list of the legal "format sequences".
*
- * This file makes use of both "z-util.c" and "z-virt.c"
+ * This file makes use "z-util.c"
*/
/**** Available Functions ****/
/* Format arguments into given bounded-length buffer */
-extern uint vstrnfmt(char *buf, uint max, cptr fmt, va_list vp);
+uint vstrnfmt(char *buf, uint max, cptr fmt, va_list vp);
/* Simple interface to "vstrnfmt()" */
-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);
+uint strnfmt(char *buf, uint max, cptr fmt, ...);
/* Simple interface to "vformat()" */
-extern char *format(cptr fmt, ...);
-
-/* Vararg interface to "plog()", using "format()" */
-extern void plog_fmt(cptr fmt, ...);
+char *format(cptr fmt, ...);
/* Vararg interface to "quit()", using "format()" */
-extern void quit_fmt(cptr fmt, ...);
-
-/* Vararg interface to "core()", using "format()" */
-extern void core_fmt(cptr fmt, ...);
+void quit_fmt(cptr fmt, ...);
#ifdef __cplusplus
} /* extern "C" */
#endif
-
-#endif
diff --git a/src/z-rand.c b/src/z-rand.c
deleted file mode 100644
index ca5b49ae..00000000
--- a/src/z-rand.c
+++ /dev/null
@@ -1,355 +0,0 @@
-/* File: z-rand.c */
-
-/* Purpose: a simple random number generator -BEN- */
-
-#include "z-rand.h"
-
-
-
-
-/*
- * Angband 2.7.9 introduced a new (optimized) random number generator,
- * based loosely on the old "random.c" from Berkeley but with some major
- * optimizations and algorithm changes. See below for more details.
- *
- * Code by myself (benh@phial.com) and Randy (randy@stat.tamu.edu).
- *
- * This code provides (1) a "decent" RNG, based on the "BSD-degree-63-RNG"
- * used in Angband 2.7.8, but rather optimized, and (2) a "simple" RNG,
- * based on the simple "LCRNG" currently used in Angband, but "corrected"
- * to give slightly better values. Both of these are available in two
- * flavors, first, the simple "mod" flavor, which is fast, but slightly
- * biased at high values, and second, the simple "div" flavor, which is
- * less fast (and potentially non-terminating) but which is not biased
- * and is much less subject to low-bit-non-randomness problems.
- *
- * You can select your favorite flavor by proper definition of the
- * "rand_int()" macro in the "defines.h" file.
- *
- * Note that, in Angband 2.8.0, the "state" table will be saved in the
- * savefile, so a special "initialization" phase will be necessary.
- *
- * Note the use of the "simple" RNG, first you activate it via
- * "Rand_quick = TRUE" and "Rand_value = seed" and then it is used
- * automatically used instead of the "complex" RNG, and when you are
- * done, you de-activate it via "Rand_quick = FALSE" or choose a new
- * seed via "Rand_value = seed".
- */
-
-
-/*
- * Random Number Generator -- Linear Congruent RNG
- */
-#define LCRNG(X) ((X) * 1103515245 + 12345)
-
-
-
-/*
- * Use the "simple" LCRNG
- */
-bool_ Rand_quick = TRUE;
-
-
-/*
- * Current "value" of the "simple" RNG
- */
-u32b Rand_value;
-
-
-/*
- * Current "index" for the "complex" RNG
- */
-u16b Rand_place;
-
-/*
- * Current "state" table for the "complex" RNG
- */
-u32b Rand_state[RAND_DEG];
-
-
-
-/*
- * Initialize the "complex" RNG using a new seed
- */
-void Rand_state_init(u32b seed)
-{
- int i, j;
-
- /* Seed the table */
- Rand_state[0] = seed;
-
- /* Propagate the seed */
- for (i = 1; i < RAND_DEG; i++) Rand_state[i] = LCRNG(Rand_state[i - 1]);
-
- /* Cycle the table ten times per degree */
- for (i = 0; i < RAND_DEG * 10; i++)
- {
- /* Acquire the next index */
- j = Rand_place + 1;
- if (j == RAND_DEG) j = 0;
-
- /* Update the table, extract an entry */
- Rand_state[j] += Rand_state[Rand_place];
-
- /* Advance the index */
- Rand_place = j;
- }
-}
-
-
-/*
- * Extract a "random" number from 0 to m-1, via "modulus"
- *
- * Note that "m" should probably be less than 500000, or the
- * results may be rather biased towards low values.
- */
-s32b Rand_mod(s32b m)
-{
- int j;
- u32b r;
-
- /* Hack -- simple case */
- if (m <= 1) return (0);
-
- /* Use the "simple" RNG */
- if (Rand_quick)
- {
- /* Cycle the generator */
- r = (Rand_value = LCRNG(Rand_value));
-
- /* Mutate a 28-bit "random" number */
- r = (r >> 4) % m;
- }
-
- /* Use the "complex" RNG */
- else
- {
- /* Acquire the next index */
- j = Rand_place + 1;
- if (j == RAND_DEG) j = 0;
-
- /* Update the table, extract an entry */
- r = (Rand_state[j] += Rand_state[Rand_place]);
-
- /* Advance the index */
- Rand_place = j;
-
- /* Extract a "random" number */
- r = (r >> 4) % m;
- }
-
- /* Use the value */
- return (r);
-}
-
-
-/*
- * Extract a "random" number from 0 to m-1, via "division"
- *
- * This method selects "random" 28-bit numbers, and then uses
- * division to drop those numbers into "m" different partitions,
- * plus a small non-partition to reduce bias, taking as the final
- * value the first "good" partition that a number falls into.
- *
- * This method has no bias, and is much less affected by patterns
- * in the "low" bits of the underlying RNG's.
- */
-s32b Rand_div(s32b m)
-{
- u32b r, n;
-
- /* Hack -- simple case */
- if (m <= 1) return (0);
-
- /* Partition size */
- n = (0x10000000 / m);
-
- /* Use a simple RNG */
- if (Rand_quick)
- {
- /* Wait for it */
- while (1)
- {
- /* Cycle the generator */
- r = (Rand_value = LCRNG(Rand_value));
-
- /* Mutate a 28-bit "random" number */
- r = ((r >> 4) & 0x0FFFFFFF) / n;
-
- /* Done */
- if (r < (u32b)m) break;
- }
- }
-
- /* Use a complex RNG */
- else
- {
- /* Wait for it */
- while (1)
- {
- int j;
-
- /* Acquire the next index */
- j = Rand_place + 1;
- if (j == RAND_DEG) j = 0;
-
- /* Update the table, extract an entry */
- r = (Rand_state[j] += Rand_state[Rand_place]);
-
- /* Hack -- extract a 28-bit "random" number */
- r = ((r >> 4) & 0x0FFFFFFF) / n;
-
- /* Advance the index */
- Rand_place = j;
-
- /* Done */
- if (r < (u32b)m) break;
- }
- }
-
- /* Use the value */
- return (r);
-}
-
-
-
-
-/*
- * The number of entries in the "randnor_table"
- */
-#define RANDNOR_NUM 256
-
-/*
- * The standard deviation of the "randnor_table"
- */
-#define RANDNOR_STD 64
-
-/*
- * The normal distribution table for the "randnor()" function (below)
- */
-static s16b randnor_table[RANDNOR_NUM] =
-{
- 206, 613, 1022, 1430, 1838, 2245, 2652, 3058,
- 3463, 3867, 4271, 4673, 5075, 5475, 5874, 6271,
- 6667, 7061, 7454, 7845, 8234, 8621, 9006, 9389,
- 9770, 10148, 10524, 10898, 11269, 11638, 12004, 12367,
- 12727, 13085, 13440, 13792, 14140, 14486, 14828, 15168,
- 15504, 15836, 16166, 16492, 16814, 17133, 17449, 17761,
- 18069, 18374, 18675, 18972, 19266, 19556, 19842, 20124,
- 20403, 20678, 20949, 21216, 21479, 21738, 21994, 22245,
-
- 22493, 22737, 22977, 23213, 23446, 23674, 23899, 24120,
- 24336, 24550, 24759, 24965, 25166, 25365, 25559, 25750,
- 25937, 26120, 26300, 26476, 26649, 26818, 26983, 27146,
- 27304, 27460, 27612, 27760, 27906, 28048, 28187, 28323,
- 28455, 28585, 28711, 28835, 28955, 29073, 29188, 29299,
- 29409, 29515, 29619, 29720, 29818, 29914, 30007, 30098,
- 30186, 30272, 30356, 30437, 30516, 30593, 30668, 30740,
- 30810, 30879, 30945, 31010, 31072, 31133, 31192, 31249,
-
- 31304, 31358, 31410, 31460, 31509, 31556, 31601, 31646,
- 31688, 31730, 31770, 31808, 31846, 31882, 31917, 31950,
- 31983, 32014, 32044, 32074, 32102, 32129, 32155, 32180,
- 32205, 32228, 32251, 32273, 32294, 32314, 32333, 32352,
- 32370, 32387, 32404, 32420, 32435, 32450, 32464, 32477,
- 32490, 32503, 32515, 32526, 32537, 32548, 32558, 32568,
- 32577, 32586, 32595, 32603, 32611, 32618, 32625, 32632,
- 32639, 32645, 32651, 32657, 32662, 32667, 32672, 32677,
-
- 32682, 32686, 32690, 32694, 32698, 32702, 32705, 32708,
- 32711, 32714, 32717, 32720, 32722, 32725, 32727, 32729,
- 32731, 32733, 32735, 32737, 32739, 32740, 32742, 32743,
- 32745, 32746, 32747, 32748, 32749, 32750, 32751, 32752,
- 32753, 32754, 32755, 32756, 32757, 32757, 32758, 32758,
- 32759, 32760, 32760, 32761, 32761, 32761, 32762, 32762,
- 32763, 32763, 32763, 32764, 32764, 32764, 32764, 32765,
- 32765, 32765, 32765, 32766, 32766, 32766, 32766, 32767,
-};
-
-
-
-/*
- * Generate a random integer number of NORMAL distribution
- *
- * The table above is used to generate a psuedo-normal distribution,
- * in a manner which is much faster than calling a transcendental
- * function to calculate a true normal distribution.
- *
- * Basically, entry 64*N in the table above represents the number of
- * times out of 32767 that a random variable with normal distribution
- * will fall within N standard deviations of the mean. That is, about
- * 68 percent of the time for N=1 and 95 percent of the time for N=2.
- *
- * The table above contains a "faked" final entry which allows us to
- * pretend that all values in a normal distribution are strictly less
- * than four standard deviations away from the mean. This results in
- * "conservative" distribution of approximately 1/32768 values.
- *
- * Note that the binary search takes up to 16 quick iterations.
- */
-s16b randnor(int mean, int stand)
-{
- s16b tmp;
- s16b offset;
-
- s16b low = 0;
- s16b high = RANDNOR_NUM;
-
- /* Paranoia */
- if (stand < 1) return (mean);
-
- /* Roll for probability */
- tmp = (s16b)rand_int(32768);
-
- /* Binary Search */
- while (low < high)
- {
- int mid = (low + high) >> 1;
-
- /* Move right if forced */
- if (randnor_table[mid] < tmp)
- {
- low = mid + 1;
- }
-
- /* Move left otherwise */
- else
- {
- high = mid;
- }
- }
-
- /* Convert the index into an offset */
- offset = (long)stand * (long)low / RANDNOR_STD;
-
- /* One half should be negative */
- if (rand_int(100) < 50) return (mean - offset);
-
- /* One half should be positive */
- return (mean + offset);
-}
-
-
-
-/*
- * Generates damage for "2d6" style dice rolls
- */
-s32b damroll(s16b num, s16b sides)
-{
- int i;
- s32b sum = 0;
- for (i = 0; i < num; i++) sum += randint(sides);
- return (sum);
-}
-
-
-/*
- * Same as above, but always maximal
- */
-s32b maxroll(s16b num, s16b sides)
-{
- return (num * sides);
-}
-
-
-
diff --git a/src/z-rand.cc b/src/z-rand.cc
new file mode 100644
index 00000000..a35eb08b
--- /dev/null
+++ b/src/z-rand.cc
@@ -0,0 +1,254 @@
+/* File: z-rand.c */
+
+/* Purpose: a simple random number generator -BEN- */
+
+#include "z-rand.hpp"
+
+#include <assert.h>
+#include <cstdint>
+#include <limits>
+#include <random>
+#include <sstream>
+#include <type_traits>
+
+#include "pcg_random.hpp"
+#include "seed.hpp"
+
+/**
+ * Choice of RNG; we use the "statistically most powerful" (per the
+ * documentation) RNG. The "insecure" bit just means that the RNG
+ * is definitely known to *not* be cryptographically secure.
+ */
+using rng_t = pcg64_once_insecure;
+
+/**
+ * Reseed the given RNG.
+ */
+static void reseed_rng(rng_t *rng, seed_t const &seed)
+{
+ assert(rng != nullptr);
+ // Create a seed_seq from the seed data.
+ std::uint32_t data[seed_t::n_uint32];
+ std::seed_seq seed_seq(
+ std::begin(data),
+ std::end(data)
+ );
+ // Seed the RNG.
+ rng->seed(seed_seq);
+}
+
+/**
+ * Allocate a new RNG and initialize with the given seed.
+ */
+static rng_t *new_seeded_rng(seed_t const &seed)
+{
+ rng_t *rng = new rng_t;
+ reseed_rng(rng, seed);
+ return rng;
+}
+
+/**
+ * The "quick" RNG is used for fixed-seed applications.
+ */
+static rng_t *quick_rng()
+{
+ // Note that the "quick_rng" will always be seeded explicitly
+ // whenever it's used, so we don't need to do any seeding here.
+ static rng_t *instance = new rng_t();
+ return instance;
+}
+
+/**
+ * The "complex" RNG is used when we really want non-deterministic
+ * random numbers.
+ */
+static rng_t *complex_rng()
+{
+ static rng_t *instance = new_seeded_rng(seed_t::system());
+ return instance;
+}
+
+
+/**
+ * Current RNG.
+ */
+static rng_t *current_rng = nullptr;
+
+/**
+ * Get the current RNG.
+ */
+static rng_t *get_current_rng()
+{
+ // Do we need to initialize?
+ if (current_rng == nullptr)
+ {
+ // We start with the complex RNG.
+ current_rng = complex_rng();
+ }
+
+ return current_rng;
+}
+
+void set_quick_rng(seed_t const &seed)
+{
+ reseed_rng(quick_rng(), seed);
+ current_rng = quick_rng();
+}
+
+void set_complex_rng()
+{
+ current_rng = complex_rng();
+}
+
+std::string get_complex_rng_state()
+{
+ std::stringstream s;
+ s << *complex_rng();
+ return s.str();
+}
+
+void set_complex_rng_state(std::string const &state)
+{
+ std::stringstream s(state);
+ s >> *complex_rng();
+}
+
+
+
+/*
+ * Stochastic rounding
+ */
+static double round_stochastic(double x)
+{
+ double n;
+ double f = std::modf(x, &n);
+
+ // Round up?
+ if (f > 0.5)
+ {
+ return n + 1;
+ }
+
+ // Round down?
+ if (f < 0.5)
+ {
+ return n - 1;
+ }
+
+ // Tie breaker is random; hence 'stochastic'.
+ std::uniform_int_distribution<int> distribution(0, 1);
+ if (distribution(*get_current_rng()) == 0)
+ {
+ return n - 1;
+ }
+ else
+ {
+ return n + 1;
+ }
+}
+
+
+/*
+ * Generate a random integer number of NORMAL distribution
+ */
+s16b randnor(int mean, int stand)
+{
+ // Get our own return type; we need it for limits and casting.
+ using retval_t = std::result_of<decltype(&randnor)(int, int)>::type;
+
+ // Degenerate case
+ if (stand < 1)
+ {
+ return 0;
+ }
+
+ // Sample from normal distribution
+ std::normal_distribution<double> distribution(mean, stand);
+ double x = distribution(*get_current_rng());
+
+ // Stochastic rounding to avoid rounding bias
+ double rounded_x = round_stochastic(x);
+
+ // Enforce limits of retval_t. Given that we're talking about a normal
+ // distribution, we're usually very unlikely to actually hit these (given
+ // reasonable values for 'mean' and 'stand' parameters), but in (very) rare
+ // cases it's needed to avoid undefined behavior due to the conversion
+ // we're going to do. This does introduce some (very minor) bias, but
+ // it's really unavoidable since retval_t cannot represent all possible
+ // values. We also assuming that a double can accurately represent all
+ // values in the range of retval_t.
+ double clipped_x = std::min(
+ static_cast<double>(std::numeric_limits<retval_t>::max()),
+ std::max(static_cast<double>(std::numeric_limits<retval_t>::min()),
+ rounded_x));
+
+ // Done: We just need to convert to retval_t.
+ return static_cast<retval_t>(clipped_x);
+}
+
+
+
+/*
+ * Generates damage for "2d6" style dice rolls
+ */
+s32b damroll(s16b num, s16b sides)
+{
+ int i;
+ s32b sum = 0;
+ for (i = 0; i < num; i++) sum += randint(sides);
+ return (sum);
+}
+
+
+/*
+ * Same as above, but always maximal
+ */
+s32b maxroll(s16b num, s16b sides)
+{
+ return (num * sides);
+}
+
+bool magik(s32b p) {
+ return rand_int(100) < p;
+}
+
+s32b rand_int(s32b m)
+{
+ /* Degenerate case */
+ if (m < 1)
+ {
+ return 0;
+ }
+ /* Normal case */
+ std::uniform_int_distribution<s32b> distribution(0, m - 1);
+ return distribution(*get_current_rng());
+}
+
+s32b randint(s32b m)
+{
+ /* Degenerate case */
+ if (m < 2)
+ {
+ return 1;
+ }
+ /* Normal case */
+ std::uniform_int_distribution<s32b> distribution(1, m);
+ return distribution(*get_current_rng());
+}
+
+s32b rand_range(s32b a, s32b b)
+{
+ /* Degenerate case */
+ if (b < a)
+ {
+ return a;
+ }
+ /* Normal case */
+ std::uniform_int_distribution<s32b> distribution(a, b);
+ return distribution(*get_current_rng());
+}
+
+s32b rand_spread(s32b a, s32b d)
+{
+ return rand_range(a-d, a+d);
+}
diff --git a/src/z-rand.h b/src/z-rand.h
deleted file mode 100644
index 39cc958c..00000000
--- a/src/z-rand.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/* File: z-rand.h */
-
-#ifndef INCLUDED_Z_RAND_H
-#define INCLUDED_Z_RAND_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "h-basic.h"
-
-
-
-/**** Available constants ****/
-
-
-/*
- * Random Number Generator -- Degree of "complex" RNG -- see "misc.c"
- * This value is hard-coded at 63 for a wide variety of reasons.
- */
-#define RAND_DEG 63
-
-
-
-
-/**** Available macros ****/
-
-
-/*
- * Generates a random long integer X where O<=X<M.
- * The integer X falls along a uniform distribution.
- * For example, if M is 100, you get "percentile dice"
- */
-#define rand_int(M) \
- (Rand_div(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)
- */
-#define rand_range(A,B) \
- ((A) + (rand_int(1+(B)-(A))))
-
-/*
- * 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)
- */
-#define rand_spread(A,D) \
- ((A) + (rand_int(1+(D)+(D))) - (D))
-
-
-/*
- * Generate a random long integer X where 1<=X<=M
- * Also, "correctly" handle the case of M<=1
- */
-#define randint(M) \
- (rand_int(M) + 1)
-
-
-/*
- * Evaluate to TRUE "P" percent of the time
- */
-#define magik(P) \
- (rand_int(100) < (P))
-
-
-
-
-/**** Available Variables ****/
-
-
-extern bool_ Rand_quick;
-extern u32b Rand_value;
-extern u16b Rand_place;
-extern u32b Rand_state[RAND_DEG];
-
-
-/**** Available Functions ****/
-
-
-extern void Rand_state_init(u32b seed);
-extern s32b Rand_mod(s32b m);
-extern s32b Rand_div(s32b m);
-extern s16b randnor(int mean, int stand);
-extern s32b damroll(s16b num, s16b sides);
-extern s32b maxroll(s16b num, s16b sides);
-
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-
-#endif
diff --git a/src/z-rand.hpp b/src/z-rand.hpp
new file mode 100644
index 00000000..b04523c3
--- /dev/null
+++ b/src/z-rand.hpp
@@ -0,0 +1,105 @@
+#pragma once
+
+#include "h-basic.h"
+#include "seed_fwd.hpp"
+
+#include <string>
+
+/**** Available constants ****/
+
+
+/*
+ * Random Number Generator -- Degree of "complex" RNG -- see "misc.c"
+ * This value is hard-coded at 63 for a wide variety of reasons.
+ */
+#define RAND_DEG 63
+
+
+
+
+/**** Available Variables ****/
+
+
+/**
+ * Change to "quick" RNG, using the given seed.
+ */
+void set_quick_rng(seed_t const &seed);
+
+
+/**
+ * Change to "complex" RNG which uses the "non-deterministic" seed.
+ */
+void set_complex_rng();
+
+
+/**
+ * Get a copy of the state of the "complex" RNG.
+ */
+std::string get_complex_rng_state();
+
+
+/**
+ * Set the state of the "complex" RNG. The given array must have
+ * been previously obtained via the get_complex_rng_state() function.
+ */
+void set_complex_rng_state(std::string const &state);
+
+/**** Available Functions ****/
+
+
+void Rand_state_init();
+s16b randnor(int mean, int stand);
+s32b damroll(s16b num, s16b sides);
+s32b maxroll(s16b num, s16b sides);
+
+/**
+ * Evaluate to "true" p percent of the time.
+ */
+bool magik(s32b p);
+
+/*
+ * Generates a random long integer X where 0<=X<M.
+ * The integer X falls along a uniform distribution.
+ * For example, if M is 100, you get "percentile dice"
+ */
+s32b rand_int(s32b m);
+
+/*
+ * Generate a random long integer X where 1<=X<=M
+ * Also, "correctly" handle the case of M<=1
+ */
+s32b randint(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)
+ */
+s32b 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)
+ */
+s32b rand_spread(s32b a, s32b d);
+
+/**
+ * Choose a random element in from the given container.
+ * The container, C, must fulfill the Container concept
+ * whose iterators fulfill the RandomIterator concept.
+ **/
+template <class C> typename C::const_iterator uniform_element(C const &c)
+{
+ return c.cbegin() + rand_int(c.size());
+}
+
+/**
+ * Choose a random element in from the given container.
+ * The container, C, must fulfill the Container concept
+ * whose iterators fulfill the RandomIterator concept.
+ **/
+template <class C> typename C::iterator uniform_element(C &c)
+{
+ return c.begin() + rand_int(c.size());
+}
diff --git a/src/z-term.c b/src/z-term.c
index 4e89ffb7..53b23c02 100644
--- a/src/z-term.c
+++ b/src/z-term.c
@@ -1,5 +1,3 @@
-/* File: z-term.c */
-
/*
* Copyright (c) 1997 Ben Harrison
*
@@ -10,11 +8,8 @@
/* Purpose: a generic, efficient, terminal window package -BEN- */
-#include "angband.h"
-
#include "z-term.h"
-#include "z-virt.h"
/*
@@ -86,13 +81,9 @@
*
* This package allows each "grid" in each window to hold an attr/char
* pair, with each ranging from 0 to 255, and makes very few assumptions
- * about the meaning of any attr/char values. Normally, we assume that
- * "attr 0" is "black", with the semantics that "black" text should be
- * sent to "Term_wipe()" instead of "Term_text()", but this sematics is
- * modified if either the "always_pict" or the "always_text" flags are
- * set. We assume that "char 0" is "dangerous", since placing such a
- * "char" in the middle of a string "terminates" the string, and usually
- * we prevent its use.
+ * about the meaning of any attr/char values. We assume that "attr 0" is
+ * "black", with the semantics that "black" text should be
+ * sent to "Term_wipe()" instead of "Term_text()".
*
* Finally, we use a special attr/char pair, defaulting to "attr 0" and
* "char 32", also known as "black space", when we "erase" or "clear"
@@ -160,8 +151,7 @@
* The new formalism includes a "displayed" screen image (old) which
* is actually seen by the user, a "requested" screen image (scr)
* which is being prepared for display, a "memorized" screen image
- * (mem) which is used to save and restore screen images, and a
- * "temporary" screen image (tmp) which is currently unused.
+ * (mem) which is used to save and restore screen images.
*
*
* Several "flags" are available in each "term" to allow the underlying
@@ -184,16 +174,9 @@
*
* Term->init_hook = Init the term
* Term->nuke_hook = Nuke the term
- * Term->user_hook = Perform user actions
* Term->xtra_hook = Perform extra actions
* Term->curs_hook = Draw (or Move) the cursor
- * Term->wipe_hook = Draw some blank spaces
* Term->text_hook = Draw some text in the window
- * Term->pict_hook = Draw some attr/chars in the window
- *
- * The "Term->user_hook" hook provides a simple hook to an implementation
- * defined function, with application defined semantics. It is available
- * to the program via the "Term_user()" function.
*
* The "Term->xtra_hook" hook provides a variety of different functions,
* based on the first parameter (which should be taken from the various
@@ -208,29 +191,11 @@
* redrawn if "nothing" has happened to the screen (even temporarily).
* This hook is required.
*
- * The "Term->wipe_hook" hook provides this package with a simple way
- * to "erase", starting at "x,y", the next "n" grids. This hook assumes
- * that the input is valid. This hook is required, unless the setting
- * of the "always_pict" or "always_text" flags makes it optional.
- *
* The "Term->text_hook" hook provides this package with a simple way
* to "draw", starting at "x,y", the "n" chars contained in "cp", using
* the attr "a". This hook assumes that the input is valid, and that
* "n" is between 1 and 256 inclusive, but it should NOT assume that
- * the contents of "cp" are null-terminated. This hook is required,
- * unless the setting of the "always_pict" flag makes it optional.
- *
- * The "Term->pict_hook" hook provides this package with a simple way
- * to "draw", starting at "x,y", the "n" attr/char pairs contained in
- * the arrays "ap" and "cp". This hook assumes that the input is valid,
- * and that "n" is between 1 and 256 inclusive, but it should NOT assume
- * that the contents of "cp" are null-terminated. This hook is optional,
- * unless the setting of the "always_pict" or "higher_pict" flags make
- * it required. Note that recently, this hook was changed from taking
- * a byte "a" and a char "c" to taking a length "n", an array of bytes
- * "ap" and an array of chars "cp". Old implementations of this hook
- * should now iterate over all "n" attr/char pairs.
- *
+ * the contents of "cp" are null-terminated.
*
* The game "Angband" uses a set of files called "main-xxx.c", for
* various "xxx" suffixes. Most of these contain a function called
@@ -254,12 +219,6 @@
* files use "white space" ("attr 1" / "char 32") to "erase" or "clear"
* any window, for efficiency.
*
- * The game "Angband" uses the "Term_user" hook to allow any of the
- * "main-xxx.c" files to interact with the user, by calling this hook
- * whenever the user presses the "!" key when the game is waiting for
- * a new command. This could be used, for example, to provide "unix
- * shell commands" to the Unix versions of the game.
- *
* See "main-xxx.c" for a simple skeleton file which can be used to
* create a "visual system" for a new platform when porting Angband.
*/
@@ -271,50 +230,40 @@
*/
term *Term = NULL;
-/* File handler for saving movies */
-FILE *movfile = NULL;
-int do_movies = 0; /* Later set this as a global */
-/* set to 1 if you want movies made */
-time_t lastc;
-int last_paused = 0;
-int cmovie_get_msecond(void);
-
-/* Record cmovies with millisecond frame rate */
-long cmov_last_time_msec;
-long cmov_delta_time_msec;
-
-
/*** Local routines ***/
/*
+ * Calloc wrapper which aborts if NULL is returned by calloc
+ */
+static void *safe_calloc(size_t nmemb, size_t size)
+{
+ void *p = calloc(nmemb, size);
+ if ((nmemb > 0) && (p == NULL))
+ {
+ abort();
+ }
+ return p;
+}
+
+/*
* Nuke a term_win (see below)
*/
static errr term_win_nuke(term_win *s, int w, int h)
{
/* Free the window access arrays */
- C_KILL(s->a, h, byte*);
- C_KILL(s->c, h, char*);
-
- /* Free the window content arrays */
- C_KILL(s->va, h * w, byte);
- C_KILL(s->vc, h * w, char);
-
- /* Free the terrain access arrays */
- C_KILL(s->ta, h, byte*);
- C_KILL(s->tc, h, char*);
+ free(s->a);
+ s->a = NULL;
- /* Free the terrain content arrays */
- C_KILL(s->vta, h * w, byte);
- C_KILL(s->vtc, h * w, char);
+ free(s->c);
+ s->c = NULL;
- /* Free the ego graphics access arrays */
- C_KILL(s->ea, h, byte*);
- C_KILL(s->ec, h, char*);
+ /* Free the window content arrays */
+ free(s->va);
+ s->va = NULL;
- /* Free the ego graphics content arrays */
- C_KILL(s->vea, h * w, byte);
- C_KILL(s->vec, h * w, char);
+ free(s->vc);
+ s->vc = NULL;
/* Success */
return (0);
@@ -329,42 +278,18 @@ static errr term_win_init(term_win *s, int w, int h)
int y;
/* Make the window access arrays */
- C_MAKE(s->a, h, byte*);
- C_MAKE(s->c, h, char*);
+ s->a = safe_calloc(h, sizeof(byte*));
+ s->c = safe_calloc(h, sizeof(char*));
/* Make the window content arrays */
- C_MAKE(s->va, h * w, byte);
- C_MAKE(s->vc, h * w, char);
-
- /* Make the terrain access arrays */
- C_MAKE(s->ta, h, byte*);
- C_MAKE(s->tc, h, char*);
-
- /* Make the terrain content arrays */
- C_MAKE(s->vta, h * w, byte);
- C_MAKE(s->vtc, h * w, char);
-
- /* Make the ego graphics access arrays */
- C_MAKE(s->ea, h, byte*);
- C_MAKE(s->ec, h, char*);
-
- /* Make the ego graphics content arrays */
- C_MAKE(s->vea, h * w, byte);
- C_MAKE(s->vec, h * w, char);
-
+ s->va = safe_calloc(h * w, sizeof(byte));
+ s->vc = safe_calloc(h * w, sizeof(char));
/* Prepare the window access arrays */
for (y = 0; y < h; y++)
{
s->a[y] = s->va + w * y;
s->c[y] = s->vc + w * y;
-
- s->ta[y] = s->vta + w * y;
- s->tc[y] = s->vtc + w * y;
-
- s->ea[y] = s->vea + w * y;
- s->ec[y] = s->vec + w * y;
-
}
/* Success */
@@ -388,28 +313,10 @@ static errr term_win_copy(term_win *s, term_win *f, int w, int h)
byte *s_aa = s->a[y];
char *s_cc = s->c[y];
- byte *f_taa = f->ta[y];
- char *f_tcc = f->tc[y];
-
- byte *s_taa = s->ta[y];
- char *s_tcc = s->tc[y];
-
- byte *f_eaa = f->ea[y];
- char *f_ecc = f->ec[y];
-
- byte *s_eaa = s->ea[y];
- char *s_ecc = s->ec[y];
-
for (x = 0; x < w; x++)
{
*s_aa++ = *f_aa++;
*s_cc++ = *f_cc++;
-
- *s_taa++ = *f_taa++;
- *s_tcc++ = *f_tcc++;
-
- *s_eaa++ = *f_eaa++;
- *s_ecc++ = *f_ecc++;
}
}
@@ -429,25 +336,9 @@ static errr term_win_copy(term_win *s, term_win *f, int w, int h)
/*
- * Execute the "Term->user_hook" hook, if available (see above).
- */
-errr Term_user(int n)
-{
- /* Verify the hook */
- if (!Term->user_hook) return ( -1);
-
- /* Call the hook */
- return ((*Term->user_hook)(n));
-}
-
-/*
* Execute the "Term->xtra_hook" hook, if available (see above).
* And *hacky* get a return code
*/
-long Term_xtra_long;
-char scansubdir_dir[1024];
-int scansubdir_max = 0;
-cptr scansubdir_result[255];
errr Term_xtra(int n, int v)
{
/* Verify the hook */
@@ -475,18 +366,6 @@ static errr Term_curs_hack(int x, int y)
}
/*
- * Hack -- fake hook for "Term_wipe()" (see above)
- */
-static errr Term_wipe_hack(int x, int y, int n)
-{
- /* Compiler silliness */
- if (x || y || n) return ( -2);
-
- /* Oops */
- return ( -1);
-}
-
-/*
* Hack -- fake hook for "Term_text()" (see above)
*/
static errr Term_text_hack(int x, int y, int n, byte a, const char *cp)
@@ -498,18 +377,6 @@ static errr Term_text_hack(int x, int y, int n, byte a, const char *cp)
return ( -1);
}
-/*
- * Hack -- fake hook for "Term_pict()" (see above)
- */
-static errr Term_pict_hack(int x, int y, int n, const byte *ap, const char *cp, const byte *tap, const char *tcp, const byte *eap, const char *ecp)
-{
- /* Compiler silliness */
- if (x || y || n || ap || cp || tap || tcp || eap || ecp) return ( -2);
-
- /* Oops */
- return ( -1);
-}
-
/*** Efficient routines ***/
@@ -520,34 +387,20 @@ static errr Term_pict_hack(int x, int y, int n, const byte *ap, const char *cp,
*
* Assumes given location and values are valid.
*/
-void Term_queue_char(int x, int y, byte a, char c, byte ta, char tc, byte ea, char ec)
+void Term_queue_char(int x, int y, byte a, char c)
{
term_win *scrn = Term->scr;
byte *scr_aa = &scrn->a[y][x];
char *scr_cc = &scrn->c[y][x];
- byte *scr_taa = &scrn->ta[y][x];
- char *scr_tcc = &scrn->tc[y][x];
-
- byte *scr_eaa = &scrn->ea[y][x];
- char *scr_ecc = &scrn->ec[y][x];
-
/* Hack -- Ignore non-changes */
- if ((*scr_aa == a) && (*scr_cc == c) &&
- (*scr_taa == ta) && (*scr_tcc == tc) &&
- (*scr_eaa == ea) && (*scr_ecc == ec)) return;
+ if ((*scr_aa == a) && (*scr_cc == c)) return;
/* Save the "literal" information */
*scr_aa = a;
*scr_cc = c;
- *scr_taa = ta;
- *scr_tcc = tc;
-
- *scr_eaa = ea;
- *scr_ecc = ec;
-
/* Check for new min/max row info */
if (y < Term->y1) Term->y1 = y;
if (y > Term->y2) Term->y2 = y;
@@ -558,89 +411,6 @@ void Term_queue_char(int x, int y, byte a, char c, byte ta, char tc, byte ea, ch
}
-/*
- * Mentally draw a string of attr/chars at a given location
- *
- * Assumes given location and values are valid.
- *
- * This function is designed to be fast, with no consistancy checking.
- * It is used to update the map in the game.
- */
-void Term_queue_line(int x, int y, int n, byte *a, char *c, byte *ta, char *tc, byte *ea, char *ec)
-{
- term_win *scrn = Term->scr;
-
- int x1 = -1;
- int x2 = -1;
-
- byte *scr_aa = &scrn->a[y][x];
- char *scr_cc = &scrn->c[y][x];
-
- byte *scr_taa = &scrn->ta[y][x];
- char *scr_tcc = &scrn->tc[y][x];
-
- byte *scr_eaa = &scrn->ea[y][x];
- char *scr_ecc = &scrn->ec[y][x];
-
- while (n--)
- {
-
- /* Hack -- Ignore non-changes */
- if ((*scr_aa == *a) && (*scr_cc == *c) &&
- (*scr_taa == *ta) && (*scr_tcc == *tc) &&
- (*scr_eaa == *ea) && (*scr_ecc == *ec))
- {
- x++;
- a++;
- c++;
- ta++;
- tc++;
- ea++;
- ec++;
- scr_aa++;
- scr_cc++;
- scr_taa++;
- scr_tcc++;
- scr_eaa++;
- scr_ecc++;
- continue;
- }
-
- /* Save the "literal" information */
- *scr_taa++ = *ta++;
- *scr_tcc++ = *tc++;
-
- /* Save the "literal" information */
- *scr_eaa++ = *ea++;
- *scr_ecc++ = *ec++;
-
- /* Save the "literal" information */
- *scr_aa++ = *a++;
- *scr_cc++ = *c++;
-
- /* Track minimum changed column */
- if (x1 < 0) x1 = x;
-
- /* Track maximum changed column */
- x2 = x;
-
- x++;
- }
-
- /* Expand the "change area" as needed */
- if (x1 >= 0)
- {
- /* Check for new min/max row info */
- if (y < Term->y1) Term->y1 = y;
- if (y > Term->y2) Term->y2 = y;
-
- /* Check for new min/max col info in this row */
- if (x1 < Term->x1[y]) Term->x1[y] = x1;
- if (x2 > Term->x2[y]) Term->x2[y] = x2;
- }
-}
-
-
/*
* Mentally draw some attr/chars at a given location
@@ -657,40 +427,19 @@ void Term_queue_chars(int x, int y, int n, byte a, cptr s)
byte *scr_aa = Term->scr->a[y];
char *scr_cc = Term->scr->c[y];
- byte *scr_taa = Term->scr->ta[y];
- char *scr_tcc = Term->scr->tc[y];
-
- byte *scr_eaa = Term->scr->ea[y];
- char *scr_ecc = Term->scr->ec[y];
-
/* Queue the attr/chars */
for ( ; n; x++, s++, n--)
{
int oa = scr_aa[x];
int oc = scr_cc[x];
- int ota = scr_taa[x];
- int otc = scr_tcc[x];
-
- int oea = scr_eaa[x];
- int oec = scr_ecc[x];
-
/* Hack -- Ignore non-changes */
- if ((oa == a) && (oc == *s) &&
- (ota == 0) && (otc == 0) &&
- (oea == 0) && (oec == 0)) continue;
-
+ if ((oa == a) && (oc == *s)) continue;
/* Save the "literal" information */
scr_aa[x] = a;
scr_cc[x] = *s;
- scr_taa[x] = 0;
- scr_tcc[x] = 0;
-
- scr_taa[x] = 0;
- scr_tcc[x] = 0;
-
/* Note the "range" of window updates */
if (x1 < 0) x1 = x;
x2 = x;
@@ -710,321 +459,11 @@ void Term_queue_chars(int x, int y, int n, byte a, cptr s)
}
-
-/*** Refresh routines ***/
-
-
/*
- * Flush a row of the current window (see "Term_fresh")
- *
- * Display text using "Term_pict()"
+ * Blank attribute/character
*/
-static void Term_fresh_row_pict(int y, int x1, int x2)
-{
- int x;
-
- byte *old_aa = Term->old->a[y];
- char *old_cc = Term->old->c[y];
-
- byte *scr_aa = Term->scr->a[y];
- char *scr_cc = Term->scr->c[y];
-
- byte *old_taa = Term->old->ta[y];
- char *old_tcc = Term->old->tc[y];
-
- byte *scr_taa = Term->scr->ta[y];
- char *scr_tcc = Term->scr->tc[y];
-
- byte ota;
- char otc;
-
- byte nta;
- char ntc;
-
- byte *old_eaa = Term->old->ea[y];
- char *old_ecc = Term->old->ec[y];
-
- byte *scr_eaa = Term->scr->ea[y];
- char *scr_ecc = Term->scr->ec[y];
-
- byte oea;
- char oec;
-
- byte nea;
- char nec;
-
-
-
- /* Pending length */
- int fn = 0;
-
- /* Pending start */
- int fx = 0;
-
- byte oa;
- char oc;
-
- byte na;
- char nc;
-
- /* Scan "modified" columns */
- for (x = x1; x <= x2; x++)
- {
- /* See what is currently here */
- oa = old_aa[x];
- oc = old_cc[x];
-
- /* See what is desired there */
- na = scr_aa[x];
- nc = scr_cc[x];
-
- ota = old_taa[x];
- otc = old_tcc[x];
-
- nta = scr_taa[x];
- ntc = scr_tcc[x];
-
- oea = old_eaa[x];
- oec = old_ecc[x];
-
- nea = scr_eaa[x];
- nec = scr_ecc[x];
-
- /* Handle unchanged grids */
- if ((na == oa) && (nc == oc) &&
- (nta == ota) && (ntc == otc) &&
- (nea == oea) && (nec == oec))
- {
- /* Flush */
- if (fn)
- {
- /* Draw pending attr/char pairs */
- (void)((*Term->pict_hook)(fx, y, fn,
- &scr_aa[fx], &scr_cc[fx],
- &scr_taa[fx], &scr_tcc[fx],
- &scr_eaa[fx], &scr_ecc[fx]));
-
- /* Forget */
- fn = 0;
- }
-
- /* Skip */
- continue;
- }
- /* Save new contents */
- old_aa[x] = na;
- old_cc[x] = nc;
-
- old_taa[x] = nta;
- old_tcc[x] = ntc;
-
- old_eaa[x] = nea;
- old_ecc[x] = nec;
-
- /* Restart and Advance */
- if (fn++ == 0) fx = x;
- }
-
- /* Flush */
- if (fn)
- {
- /* Draw pending attr/char pairs */
- (void)((*Term->pict_hook)(fx, y, fn,
- &scr_aa[fx], &scr_cc[fx],
- &scr_taa[fx], &scr_tcc[fx],
- &scr_eaa[fx], &scr_ecc[fx]));
- }
-}
-
-
-
-/*
- * Flush a row of the current window (see "Term_fresh")
- *
- * Display text using "Term_text()" and "Term_wipe()",
- * but use "Term_pict()" for high-bit attr/char pairs
- */
-static void Term_fresh_row_both(int y, int x1, int x2)
-{
- int x;
-
- byte *old_aa = Term->old->a[y];
- char *old_cc = Term->old->c[y];
-
- byte *scr_aa = Term->scr->a[y];
- char *scr_cc = Term->scr->c[y];
-
- byte *old_taa = Term->old->ta[y];
- char *old_tcc = Term->old->tc[y];
- byte *scr_taa = Term->scr->ta[y];
- char *scr_tcc = Term->scr->tc[y];
-
- byte ota;
- char otc;
- byte nta;
- char ntc;
-
- byte *old_eaa = Term->old->ea[y];
- char *old_ecc = Term->old->ec[y];
- byte *scr_eaa = Term->scr->ea[y];
- char *scr_ecc = Term->scr->ec[y];
-
- byte oea;
- char oec;
- byte nea;
- char nec;
-
- /* The "always_text" flag */
- int always_text = Term->always_text;
-
- /* Pending length */
- int fn = 0;
-
- /* Pending start */
- int fx = 0;
-
- /* Pending attr */
- byte fa = Term->attr_blank;
-
- byte oa;
- char oc;
-
- byte na;
- char nc;
-
- /* Scan "modified" columns */
- for (x = x1; x <= x2; x++)
- {
- /* See what is currently here */
- oa = old_aa[x];
- oc = old_cc[x];
-
- /* See what is desired there */
- na = scr_aa[x];
- nc = scr_cc[x];
-
- ota = old_taa[x];
- otc = old_tcc[x];
-
- nta = scr_taa[x];
- ntc = scr_tcc[x];
-
- oea = old_eaa[x];
- oec = old_ecc[x];
-
- nea = scr_eaa[x];
- nec = scr_ecc[x];
-
- /* Handle unchanged grids */
- if ((na == oa) && (nc == oc) &&
- (nta == ota) && (ntc == otc) &&
- (nea == oea) && (nec == oec))
- {
- /* Flush */
- if (fn)
- {
- /* Draw pending chars (normal) */
- if (fa || always_text)
- {
- (void)((*Term->text_hook)(fx, y, fn, fa, &scr_cc[fx]));
- }
- /* Draw pending chars (black) */
- else
- {
- (void)((*Term->wipe_hook)(fx, y, fn));
- }
- /* Forget */
- fn = 0;
- }
-
- /* Skip */
- continue;
- }
-
- /* Save new contents */
- old_aa[x] = na;
- old_cc[x] = nc;
-
- old_taa[x] = nta;
- old_tcc[x] = ntc;
-
- old_eaa[x] = nea;
- old_ecc[x] = nec;
-
- /* 2nd byte of bigtile */
- if (na == 255) continue;
-
- /* Handle high-bit attr/chars */
- if (na & 0x80)
- {
- /* Flush */
- if (fn)
- {
- /* Draw pending chars (normal) */
- if (fa || always_text)
- {
- (void)((*Term->text_hook)(fx, y, fn, fa, &scr_cc[fx]));
- }
- /* Draw pending chars (black) */
- else
- {
- (void)((*Term->wipe_hook)(fx, y, fn));
- }
- /* Forget */
- fn = 0;
- }
-
- /* Hack -- Draw the special attr/char pair */
- (void)((*Term->pict_hook)(x, y, 1, &na, &nc, &nta, &ntc, &nea, &nec));
-
- /* Skip */
- continue;
- }
-
- /* Notice new color */
- if (fa != na)
- {
- /* Flush */
- if (fn)
- {
- /* Draw the pending chars */
- if (fa || always_text)
- {
- (void)((*Term->text_hook)(fx, y, fn, fa, &scr_cc[fx]));
- }
- /* Hack -- Erase "leading" spaces */
- else
- {
- (void)((*Term->wipe_hook)(fx, y, fn));
- }
- /* Forget */
- fn = 0;
- }
-
- /* Save the new color */
- fa = na;
- }
-
- /* Restart and Advance */
- if (fn++ == 0) fx = x;
- }
-
- /* Flush */
- if (fn)
- {
- /* Draw pending chars (normal) */
- if (fa || always_text)
- {
- (void)((*Term->text_hook)(fx, y, fn, fa, &scr_cc[fx]));
- }
- /* Draw pending chars (black) */
- else
- {
- (void)((*Term->wipe_hook)(fx, y, fn));
- }
- }
-}
-
+static const byte ATTR_BLANK = TERM_WHITE;
+static const char CHAR_BLANK = ' ';
/*
* Flush a row of the current window (see "Term_fresh")
@@ -1041,9 +480,6 @@ static void Term_fresh_row_text(int y, int x1, int x2)
byte *scr_aa = Term->scr->a[y];
char *scr_cc = Term->scr->c[y];
- /* The "always_text" flag */
- int always_text = Term->always_text;
-
/* Pending length */
int fn = 0;
@@ -1051,7 +487,7 @@ static void Term_fresh_row_text(int y, int x1, int x2)
int fx = 0;
/* Pending attr */
- byte fa = Term->attr_blank;
+ byte fa = ATTR_BLANK;
byte oa;
char oc;
@@ -1076,17 +512,7 @@ static void Term_fresh_row_text(int y, int x1, int x2)
/* Flush */
if (fn)
{
- /* Draw pending chars (normal) */
- if (fa || always_text)
- {
- (void)((*Term->text_hook)(fx, y, fn, fa, &scr_cc[fx]));
- }
-
- /* Draw pending chars (black) */
- else
- {
- (void)((*Term->wipe_hook)(fx, y, fn));
- }
+ (void)((*Term->text_hook)(fx, y, fn, fa, &scr_cc[fx]));
/* Forget */
fn = 0;
@@ -1107,16 +533,7 @@ static void Term_fresh_row_text(int y, int x1, int x2)
if (fn)
{
/* Draw the pending chars */
- if (fa || always_text)
- {
- (void)((*Term->text_hook)(fx, y, fn, fa, &scr_cc[fx]));
- }
-
- /* Hack -- Erase "leading" spaces */
- else
- {
- (void)((*Term->wipe_hook)(fx, y, fn));
- }
+ (void)((*Term->text_hook)(fx, y, fn, fa, &scr_cc[fx]));
/* Forget */
fn = 0;
@@ -1133,17 +550,7 @@ static void Term_fresh_row_text(int y, int x1, int x2)
/* Flush */
if (fn)
{
- /* Draw pending chars (normal) */
- if (fa || always_text)
- {
- (void)((*Term->text_hook)(fx, y, fn, fa, &scr_cc[fx]));
- }
-
- /* Draw pending chars (black) */
- else
- {
- (void)((*Term->wipe_hook)(fx, y, fn));
- }
+ (void)((*Term->text_hook)(fx, y, fn, fa, &scr_cc[fx]));
}
}
@@ -1172,21 +579,9 @@ static void Term_fresh_row_text(int y, int x1, int x2)
* Note that "Term_xtra(TERM_XTRA_CLEAR,0)" must erase the entire screen,
* including the cursor, if needed, and may place the cursor anywhere.
*
- * Note that "Term_xtra(TERM_XTRA_FROSH,y)" will be always be called
- * after any row "y" has been "flushed", unless the "Term->never_frosh"
- * flag is set, and "Term_xtra(TERM_XTRA_FRESH,0)" will be called after
+ * Note that "Term_xtra(TERM_XTRA_FRESH,0)" will be called after
* all of the rows have been "flushed".
*
- * Note the use of three different functions to handle the actual flush,
- * based on the settings of the "Term->always_pict" and "Term->higher_pict"
- * flags (see below).
- *
- * The three helper functions (above) work by collecting similar adjacent
- * grids into stripes, and then sending each stripe to "Term->pict_hook",
- * "Term->text_hook", or "Term->wipe_hook", based on the settings of the
- * "Term->always_pict" and "Term->higher_pict" flags, which select which
- * of the helper functions to call to flush each row.
- *
* The helper functions currently "skip" any grids which already contain
* the desired contents. This may or may not be the best method, especially
* when the desired content fits nicely into the current stripe. For example,
@@ -1209,18 +604,6 @@ static void Term_fresh_row_text(int y, int x1, int x2)
* and situations in which two grids in the same row are changed, but
* the grids between them are unchanged.
*
- * If the "Term->always_pict" flag is set, then "Term_fresh_row_pict()"
- * will be used instead of "Term_fresh_row_text()". This allows all the
- * modified grids to be collected into stripes of attr/char pairs, which
- * are then sent to the "Term->pict_hook" hook, which can draw these pairs
- * in whatever way it would like.
- *
- * If the "Term->higher_pict" flag is set, then "Term_fresh_row_both()"
- * will be used instead of "Term_fresh_row_text()". This allows all the
- * "special" attr/char pairs (in which both the attr and char have the
- * high-bit set) to be sent (one pair at a time) to the "Term->pict_hook"
- * hook, which can draw these pairs in whatever way it would like.
- *
* Normally, the "Term_wipe()" function is used only to display "blanks"
* that were induced by "Term_clear()" or "Term_erase()", and then only
* if the "attr_blank" and "char_blank" fields have not been redefined
@@ -1228,18 +611,8 @@ static void Term_fresh_row_text(int y, int x1, int x2)
* the "Term_wipe()" function is used to display all "black" text, such
* as the default "spaces" created by "Term_clear()" and "Term_erase()".
*
- * Note that the "Term->always_text" flag will disable the use of the
- * "Term_wipe()" function hook entirely, and force all text, even text
- * drawn in the color "black", to be explicitly drawn. This is useful
- * for machines which implement "Term_wipe()" by just drawing spaces.
- *
- * Note that the "Term->always_pict" flag will disable the use of the
- * "Term_wipe()" function entirely, and force everything, even text
- * drawn in the attr "black", to be explicitly drawn.
- *
* Note that if no "black" text is ever drawn, and if "attr_blank" is
- * not "zero", then the "Term_wipe" hook will never be used, even if
- * the "Term->always_text" flag is not set.
+ * not "zero", then the "Term_wipe" hook will never be used.
*
* This function does nothing unless the "Term" is "mapped", which allows
* certain systems to optimize the handling of "closed" windows.
@@ -1296,26 +669,14 @@ errr Term_fresh(void)
/* Paranoia -- use "fake" hooks to prevent core dumps */
if (!Term->curs_hook) Term->curs_hook = Term_curs_hack;
- if (!Term->wipe_hook) Term->wipe_hook = Term_wipe_hack;
if (!Term->text_hook) Term->text_hook = Term_text_hack;
- if (!Term->pict_hook) Term->pict_hook = Term_pict_hack;
/* Handle "total erase" */
if (Term->total_erase)
{
- byte na = Term->attr_blank;
- char nc = Term->char_blank;
-
- if ((do_movies == 1) && IN_MAINWINDOW)
- {
- if (!cmovie_get_msecond())
- {
- fprintf(movfile, "S:%ld:\n", cmov_delta_time_msec);
- }
- fprintf(movfile, "C:\n");
- last_paused = 0;
- }
+ byte na = ATTR_BLANK;
+ char nc = CHAR_BLANK;
/* Physically erase the entire window */
Term_xtra(TERM_XTRA_CLEAR, 0);
@@ -1329,25 +690,12 @@ errr Term_fresh(void)
byte *aa = old->a[y];
char *cc = old->c[y];
- byte *taa = old->ta[y];
- char *tcc = old->tc[y];
-
- byte *eaa = old->ea[y];
- char *ecc = old->ec[y];
-
-
/* Wipe each column */
for (x = 0; x < w; x++)
{
/* Wipe each grid */
*aa++ = na;
*cc++ = nc;
-
- *taa++ = na;
- *tcc++ = nc;
-
- *eaa++ = na;
- *ecc++ = nc;
}
}
@@ -1382,41 +730,8 @@ errr Term_fresh(void)
byte oa = old_aa[tx];
char oc = old_cc[tx];
- byte *old_taa = old->ta[ty];
- char *old_tcc = old->tc[ty];
-
- byte ota = old_taa[tx];
- char otc = old_tcc[tx];
-
- byte *old_eaa = old->ea[ty];
- char *old_ecc = old->ec[ty];
-
- byte oea = old_eaa[tx];
- char oec = old_ecc[tx];
-
- /* Hack -- use "Term_pict()" always */
- if (Term->always_pict)
- {
- (void)((*Term->pict_hook)(tx, ty, 1, &oa, &oc, &ota, &otc, &oea, &oec));
- }
-
- /* Hack -- use "Term_pict()" sometimes */
- else if (Term->higher_pict && (oa & 0x80))
- {
- (void)((*Term->pict_hook)(tx, ty, 1, &oa, &oc, &ota, &otc, &oea, &oec));
- }
-
/* Hack -- restore the actual character */
- else if (oa || Term->always_text)
- {
- (void)((*Term->text_hook)(tx, ty, 1, oa, &oc));
- }
-
- /* Hack -- erase the grid */
- else
- {
- (void)((*Term->wipe_hook)(tx, ty, 1));
- }
+ (void)((*Term->text_hook)(tx, ty, 1, oa, &oc));
}
}
@@ -1460,40 +775,12 @@ errr Term_fresh(void)
/* Flush each "modified" row */
if (x1 <= x2)
{
- if ((do_movies == 1) && IN_MAINWINDOW)
- {
- /* Most magic happens here */
- cmovie_record_line(y);
- last_paused = 0;
- }
-
- /* Always use "Term_pict()" */
- if (Term->always_pict)
- {
- /* Flush the row */
- Term_fresh_row_pict(y, x1, x2);
- }
-
- /* Sometimes use "Term_pict()" */
- else if (Term->higher_pict)
- {
- /* Flush the row */
- Term_fresh_row_both(y, x1, x2);
- }
-
- /* Never use "Term_pict()" */
- else
- {
- /* Flush the row */
- Term_fresh_row_text(y, x1, x2);
- }
+ /* Flush the row */
+ Term_fresh_row_text(y, x1, x2);
/* This row is all done */
Term->x1[y] = w;
Term->x2[y] = 0;
-
- /* Hack -- Flush that row (if allowed) */
- if (!Term->never_frosh) Term_xtra(TERM_XTRA_FROSH, y);
}
}
@@ -1629,7 +916,7 @@ errr Term_draw(int x, int y, byte a, char c)
if (!c) return ( -2);
/* Queue it for later */
- Term_queue_char(x, y, a, c, 0, 0, 0, 0);
+ Term_queue_char(x, y, a, c);
/* Success */
return (0);
@@ -1663,7 +950,7 @@ errr Term_addch(byte a, char c)
if (!c) return ( -2);
/* Queue the given character for display */
- Term_queue_char(Term->scr->cx, Term->scr->cy, a, c, 0, 0, 0, 0);
+ Term_queue_char(Term->scr->cx, Term->scr->cy, a, c);
/* Advance the cursor */
Term->scr->cx++;
@@ -1782,18 +1069,12 @@ errr Term_erase(int x, int y, int n)
int x1 = -1;
int x2 = -1;
- int na = Term->attr_blank;
- int nc = Term->char_blank;
+ int na = ATTR_BLANK;
+ int nc = CHAR_BLANK;
byte *scr_aa;
char *scr_cc;
- byte *scr_taa;
- char *scr_tcc;
-
- byte *scr_eaa;
- char *scr_ecc;
-
/* Place cursor */
if (Term_gotoxy(x, y)) return ( -1);
@@ -1804,12 +1085,6 @@ errr Term_erase(int x, int y, int n)
scr_aa = Term->scr->a[y];
scr_cc = Term->scr->c[y];
- scr_taa = Term->scr->ta[y];
- scr_tcc = Term->scr->tc[y];
-
- scr_eaa = Term->scr->ea[y];
- scr_ecc = Term->scr->ec[y];
-
if (n > 0 && (byte)scr_cc[x] == 255 && scr_aa[x] == 255)
{
x--;
@@ -1829,12 +1104,6 @@ errr Term_erase(int x, int y, int n)
scr_aa[x] = na;
scr_cc[x] = nc;
- scr_taa[x] = 0;
- scr_tcc[x] = 0;
-
- scr_eaa[x] = 0;
- scr_ecc[x] = 0;
-
/* Track minimum changed column */
if (x1 < 0) x1 = x;
@@ -1871,8 +1140,8 @@ errr Term_clear(void)
int w = Term->wid;
int h = Term->hgt;
- byte na = Term->attr_blank;
- char nc = Term->char_blank;
+ byte na = ATTR_BLANK;
+ char nc = CHAR_BLANK;
/* Cursor usable */
Term->scr->cu = 0;
@@ -1886,23 +1155,11 @@ errr Term_clear(void)
byte *scr_aa = Term->scr->a[y];
char *scr_cc = Term->scr->c[y];
- byte *scr_taa = Term->scr->ta[y];
- char *scr_tcc = Term->scr->tc[y];
-
- byte *scr_eaa = Term->scr->ea[y];
- char *scr_ecc = Term->scr->ec[y];
-
/* Wipe each column */
for (x = 0; x < w; x++)
{
scr_aa[x] = na;
scr_cc[x] = nc;
-
- scr_taa[x] = 0;
- scr_tcc[x] = 0;
-
- scr_eaa[x] = 0;
- scr_ecc[x] = 0;
}
/* This row has changed */
@@ -1930,17 +1187,6 @@ errr Term_clear(void)
*/
errr Term_redraw(void)
{
- /* Pat */
- if ((do_movies == 1) && IN_MAINWINDOW)
- {
- if (!cmovie_get_msecond())
- {
- fprintf(movfile, "S:%ld:\n", cmov_delta_time_msec);
- }
- last_paused = 1;
- }
- /* Endpat */
-
/* Force "total erase" */
Term->total_erase = TRUE;
@@ -1995,6 +1241,10 @@ errr Term_redraw_section(int x1, int y1, int x2, int y2)
}
+void Term_bell()
+{
+ Term_xtra(TERM_XTRA_NOISE, 0);
+}
/*** Access routines ***/
@@ -2018,8 +1268,15 @@ errr Term_get_cursor(int *v)
errr Term_get_size(int *w, int *h)
{
/* Access the cursor */
- (*w) = Term->wid;
- (*h) = Term->hgt;
+ if (w)
+ {
+ (*w) = Term->wid;
+ }
+
+ if (h)
+ {
+ (*h) = Term->hgt;
+ }
/* Success */
return (0);
@@ -2149,20 +1406,8 @@ errr Term_inkey(char *ch, bool_ wait, bool_ take)
/* Assume no key */
(*ch) = '\0';
- /* Hack -- get bored */
- if (!Term->never_bored)
- {
- /* Process random events */
- Term_xtra(TERM_XTRA_BORED, 0);
- }
-
- /* PatN */
- if ((do_movies == 1) && (last_paused == 0) && (!cmovie_get_msecond()))
- {
- fprintf(movfile, "S:%ld:\n", cmov_delta_time_msec);
- last_paused = 1;
- }
- /* PatNEnd */
+ /* Process queued UI events */
+ Term_xtra(TERM_XTRA_BORED, 0);
/* Wait */
if (wait)
@@ -2218,7 +1463,7 @@ errr Term_save(void)
if (!Term->mem)
{
/* Allocate window */
- MAKE(Term->mem, term_win);
+ Term->mem = safe_calloc(1, sizeof(struct term_win));
/* Initialize window */
term_win_init(Term->mem, w, h);
@@ -2241,7 +1486,7 @@ term_win* Term_save_to(void)
term_win *save;
/* Allocate window */
- MAKE(save, term_win);
+ save = safe_calloc(1, sizeof(struct term_win));
/* Initialize window */
term_win_init(save, w, h);
@@ -2269,7 +1514,7 @@ errr Term_load(void)
if (!Term->mem)
{
/* Allocate window */
- MAKE(Term->mem, term_win);
+ Term->mem = safe_calloc(1, sizeof(struct term_win));
/* Initialize window */
term_win_init(Term->mem, w, h);
@@ -2297,7 +1542,7 @@ errr Term_load(void)
/*
* Same as previous but allow to save more than one
*/
-errr Term_load_from(term_win *save, bool_ final)
+errr Term_load_from(term_win *save)
{
int y;
@@ -2326,52 +1571,7 @@ errr Term_load_from(term_win *save, bool_ final)
Term->y2 = h - 1;
/* Free is requested */
- if (final)
- FREE(save, term_win);
-
- /* Success */
- return (0);
-}
-
-/*
- * Exchange the "requested" screen with the "tmp" screen
- */
-errr Term_exchange(void)
-{
- int y;
-
- int w = Term->wid;
- int h = Term->hgt;
-
- term_win *exchanger;
-
-
- /* Create */
- if (!Term->tmp)
- {
- /* Allocate window */
- MAKE(Term->tmp, term_win);
-
- /* Initialize window */
- term_win_init(Term->tmp, w, h);
- }
-
- /* Swap */
- exchanger = Term->scr;
- Term->scr = Term->tmp;
- Term->tmp = exchanger;
-
- /* Assume change */
- for (y = 0; y < h; y++)
- {
- /* Assume change */
- Term->x1[y] = 0;
- Term->x2[y] = w - 1;
- }
-
- /* Assume change */
- Term->y1 = 0;
- Term->y2 = h - 1;
+ free(save);
/* Success */
return (0);
@@ -2392,18 +1592,13 @@ errr Term_resize(int w, int h)
term_win *hold_old;
term_win *hold_scr;
term_win *hold_mem;
- term_win *hold_tmp;
-
- /* Resizing is forbidden */
- if (Term->fixed_shape) return ( -1);
/* Ignore illegal changes */
if ((w < 1) || (h < 1)) return ( -1);
/* Ignore non-changes */
- if ((Term->wid == w) && (Term->hgt == h) && (arg_bigtile == use_bigtile)) return (1);
- use_bigtile = arg_bigtile;
+ if ((Term->wid == w) && (Term->hgt == h)) return (1);
/* Minimum dimensions */
wid = MIN(Term->wid, w);
@@ -2422,15 +1617,12 @@ errr Term_resize(int w, int h)
/* Save old window */
hold_mem = Term->mem;
- /* Save old window */
- hold_tmp = Term->tmp;
-
/* Create new scanners */
- C_MAKE(Term->x1, h, byte);
- C_MAKE(Term->x2, h, byte);
+ Term->x1 = safe_calloc(h, sizeof(byte));
+ Term->x2 = safe_calloc(h, sizeof(byte));
/* Create new window */
- MAKE(Term->old, term_win);
+ Term->old = safe_calloc(1, sizeof(struct term_win));
/* Initialize new window */
term_win_init(Term->old, w, h);
@@ -2439,7 +1631,7 @@ errr Term_resize(int w, int h)
term_win_copy(Term->old, hold_old, wid, hgt);
/* Create new window */
- MAKE(Term->scr, term_win);
+ Term->scr = safe_calloc(1, sizeof(struct term_win));
/* Initialize new window */
term_win_init(Term->scr, w, h);
@@ -2451,7 +1643,7 @@ errr Term_resize(int w, int h)
if (hold_mem)
{
/* Create new window */
- MAKE(Term->mem, term_win);
+ Term->mem = safe_calloc(1, sizeof(struct term_win));
/* Initialize new window */
term_win_init(Term->mem, w, h);
@@ -2460,28 +1652,18 @@ errr Term_resize(int w, int h)
term_win_copy(Term->mem, hold_mem, wid, hgt);
}
- /* If needed */
- if (hold_tmp)
- {
- /* Create new window */
- MAKE(Term->tmp, term_win);
-
- /* Initialize new window */
- term_win_init(Term->tmp, w, h);
-
- /* Save the contents */
- term_win_copy(Term->tmp, hold_tmp, wid, hgt);
- }
-
/* Free some arrays */
- C_KILL(hold_x1, Term->hgt, byte);
- C_KILL(hold_x2, Term->hgt, byte);
+ free(hold_x1);
+ hold_x1 = NULL;
+ free(hold_x2);
+ hold_x2 = NULL;
/* Nuke */
term_win_nuke(hold_old, Term->wid, Term->hgt);
/* Kill */
- KILL(hold_old, term_win);
+ free(hold_old);
+ hold_old = NULL;
/* Illegal cursor */
if (Term->old->cx >= w) Term->old->cu = 1;
@@ -2491,7 +1673,8 @@ errr Term_resize(int w, int h)
term_win_nuke(hold_scr, Term->wid, Term->hgt);
/* Kill */
- KILL(hold_scr, term_win);
+ free(hold_scr);
+ hold_scr = NULL;
/* Illegal cursor */
if (Term->scr->cx >= w) Term->scr->cu = 1;
@@ -2504,27 +1687,14 @@ errr Term_resize(int w, int h)
term_win_nuke(hold_mem, Term->wid, Term->hgt);
/* Kill */
- KILL(hold_mem, term_win);
+ free(hold_mem);
+ hold_mem = NULL;
/* Illegal cursor */
if (Term->mem->cx >= w) Term->mem->cu = 1;
if (Term->mem->cy >= h) Term->mem->cu = 1;
}
- /* If needed */
- if (hold_tmp)
- {
- /* Nuke */
- term_win_nuke(hold_tmp, Term->wid, Term->hgt);
-
- /* Kill */
- KILL(hold_tmp, term_win);
-
- /* Illegal cursor */
- if (Term->tmp->cx >= w) Term->tmp->cu = 1;
- if (Term->tmp->cy >= h) Term->tmp->cu = 1;
- }
-
/* Save new size */
Term->wid = w;
Term->hgt = h;
@@ -2624,13 +1794,15 @@ errr term_nuke(term *t)
term_win_nuke(t->old, w, h);
/* Kill "displayed" */
- KILL(t->old, term_win);
+ free(t->old);
+ t->old = NULL;
/* Nuke "requested" */
term_win_nuke(t->scr, w, h);
/* Kill "requested" */
- KILL(t->scr, term_win);
+ free(t->scr);
+ t->scr = NULL;
/* If needed */
if (t->mem)
@@ -2639,25 +1811,19 @@ errr term_nuke(term *t)
term_win_nuke(t->mem, w, h);
/* Kill "memorized" */
- KILL(t->mem, term_win);
- }
-
- /* If needed */
- if (t->tmp)
- {
- /* Nuke "temporary" */
- term_win_nuke(t->tmp, w, h);
-
- /* Kill "temporary" */
- KILL(t->tmp, term_win);
+ free(t->mem);
+ t->mem = NULL;
}
/* Free some arrays */
- C_KILL(t->x1, h, byte);
- C_KILL(t->x2, h, byte);
+ free(t->x1);
+ t->x1 = NULL;
+ free(t->x2);
+ t->x2 = NULL;
/* Free the input queue */
- C_KILL(t->key_queue, t->key_size, char);
+ free(t->key_queue);
+ t->key_queue = NULL;
/* Success */
return (0);
@@ -2675,7 +1841,7 @@ errr term_init(term *t, int w, int h, int k)
int y;
/* Wipe it */
- (void)WIPE(t, term);
+ memset(t, 0, sizeof(term));
/* Prepare the input queue */
@@ -2685,7 +1851,7 @@ errr term_init(term *t, int w, int h, int k)
t->key_size = k;
/* Allocate the input queue */
- C_MAKE(t->key_queue, t->key_size, char);
+ t->key_queue = safe_calloc(t->key_size, sizeof(char));
/* Save the size */
@@ -2693,19 +1859,19 @@ errr term_init(term *t, int w, int h, int k)
t->hgt = h;
/* Allocate change arrays */
- C_MAKE(t->x1, h, byte);
- C_MAKE(t->x2, h, byte);
+ t->x1 = safe_calloc(h, sizeof(byte));
+ t->x2 = safe_calloc(h, sizeof(byte));
/* Allocate "displayed" */
- MAKE(t->old, term_win);
+ t->old = safe_calloc(1, sizeof(struct term_win));
/* Initialize "displayed" */
term_win_init(t->old, w, h);
/* Allocate "requested" */
- MAKE(t->scr, term_win);
+ t->scr = safe_calloc(1, sizeof(struct term_win));
/* Initialize "requested" */
term_win_init(t->scr, w, h);
@@ -2727,50 +1893,6 @@ errr term_init(term *t, int w, int h, int k)
t->total_erase = TRUE;
- /* Default "blank" */
- t->attr_blank = 0;
- t->char_blank = ' ';
-
-
/* Success */
return (0);
}
-
-/*
- * Determine if we are called in the same second as the last time?
- * This *ASSUMES* that time_t is seconds past something. Is this portable?
- */
-int cmovie_get_msecond(void)
-{
-#ifndef USE_PRECISE_CMOVIE
- /* Not very precise, but portable */
- time_t thisc;
-
- thisc = time(NULL);
-
- cmov_delta_time_msec = 300;
-
- if (thisc == lastc)
- {
- return 1;
- }
- return 0;
-#else /* Very precise but needs main-foo.c to define TERM_XTRA_GET_DELAY */
-Term_xtra(TERM_XTRA_GET_DELAY, 0);
-
- cmov_delta_time_msec = Term_xtra_long - cmov_last_time_msec;
- cmov_last_time_msec = Term_xtra_long;
- return 0;
-#endif
-}
-
-void cmovie_init_second()
-{
-#ifndef USE_PRECISE_CMOVIE
- /* Not very precise, but portable */
- cmov_last_time_msec = 0;
-#else /* Precise but need main-foo.c to have TERM_XTRA_GET_DELAY */
- Term_xtra(TERM_XTRA_GET_DELAY, 0);
- cmov_last_time_msec = Term_xtra_long;
-#endif
-}
diff --git a/src/z-term.h b/src/z-term.h
index 31e5b308..92f09577 100644
--- a/src/z-term.h
+++ b/src/z-term.h
@@ -17,8 +17,6 @@ extern "C" {
#include "h-basic.h"
-#define IN_MAINWINDOW (Term == term_screen)
-
/*
* A term_win is a "window" for a Term
*
@@ -48,18 +46,6 @@ struct term_win
byte *va;
char *vc;
- byte **ta;
- char **tc;
-
- byte *vta;
- char *vtc;
-
- byte **ea;
- char **ec;
-
- byte *vea;
- char *vec;
-
};
@@ -67,19 +53,9 @@ struct term_win
/*
* An actual "term" structure
*
- * - Extra "user" info (used by application)
- *
* - Extra "data" info (used by implementation)
*
*
- * - Flag "user_flag"
- * An extra "user" flag (used by application)
- *
- *
- * - Flag "data_flag"
- * An extra "data" flag (used by implementation)
- *
- *
* - Flag "active_flag"
* This "term" is "active"
*
@@ -89,39 +65,13 @@ struct term_win
* - Flag "total_erase"
* This "term" should be fully erased
*
- * - Flag "fixed_shape"
- * This "term" is not allowed to resize
- *
* - Flag "icky_corner"
* This "term" has an "icky" corner grid
*
* - Flag "soft_cursor"
* This "term" uses a "software" cursor
*
- * - Flag "always_pict"
- * Use the "Term_pict()" routine for all text
- *
- * - Flag "higher_pict"
- * Use the "Term_pict()" routine for special text
- *
- * - Flag "always_text"
- * Use the "Term_text()" routine for invisible text
- *
- * - Flag "unused_flag"
- * Reserved for future use
- *
- * - Flag "never_bored"
- * Never call the "TERM_XTRA_BORED" action
- *
- * - Flag "never_frosh"
- * Never call the "TERM_XTRA_FROSH" action
- *
*
- * - Value "attr_blank"
- * Use this "attr" value for "blank" grids
- *
- * - Value "char_blank"
- * Use this "char" value for "blank" grids
*
*
* - Ignore this pointer
@@ -151,14 +101,10 @@ struct term_win
* - Hook for init-ing the term
* - Hook for nuke-ing the term
*
- * - Hook for user actions
- *
* - Hook for extra actions
*
* - Hook for placing the cursor
*
- * - Hook for drawing some blank spaces
- *
* - Hook for drawing a string of chars using an attr
*
* - Hook for drawing a sequence of special attr/char pairs
@@ -168,35 +114,17 @@ typedef struct term term;
struct term
{
- vptr user;
-
vptr data;
- bool_ user_flag;
-
- bool_ data_flag;
-
bool_ active_flag;
bool_ mapped_flag;
bool_ total_erase;
- bool_ fixed_shape;
bool_ icky_corner;
bool_ soft_cursor;
- bool_ always_pict;
- bool_ higher_pict;
- bool_ always_text;
- bool_ unused_flag;
- bool_ never_bored;
- bool_ never_frosh;
-
- byte attr_blank;
- char char_blank;
char *key_queue;
-
u16b key_head;
u16b key_tail;
- u16b key_xtra;
u16b key_size;
byte wid;
@@ -211,31 +139,48 @@ struct term
term_win *old;
term_win *scr;
- term_win *tmp;
term_win *mem;
void (*init_hook)(term *t);
void (*nuke_hook)(term *t);
- errr (*user_hook)(int n);
-
errr (*xtra_hook)(int n, int v);
errr (*curs_hook)(int x, int y);
- errr (*wipe_hook)(int x, int y, int n);
-
errr (*text_hook)(int x, int y, int n, byte a, cptr s);
- void (*resize_hook)(void);
-
- errr (*pict_hook)(int x, int y, int n, const byte *ap, const char *cp, const byte *tap, const char *tcp, const byte *eap, const char *ecp);
+ void (*resize_hook)();
};
+/*** Color constants ***/
+
+/*
+ * Angband "attributes" (with symbols, and base (R,G,B) codes)
+ *
+ * The "(R,G,B)" codes are given in "fourths" of the "maximal" value,
+ * and should "gamma corrected" on most (non-Macintosh) machines.
+ */
+#define TERM_DARK 0 /* 'd' */ /* 0,0,0 */
+#define TERM_WHITE 1 /* 'w' */ /* 4,4,4 */
+#define TERM_SLATE 2 /* 's' */ /* 2,2,2 */
+#define TERM_ORANGE 3 /* 'o' */ /* 4,2,0 */
+#define TERM_RED 4 /* 'r' */ /* 3,0,0 */
+#define TERM_GREEN 5 /* 'g' */ /* 0,2,1 */
+#define TERM_BLUE 6 /* 'b' */ /* 0,0,4 */
+#define TERM_UMBER 7 /* 'u' */ /* 2,1,0 */
+#define TERM_L_DARK 8 /* 'D' */ /* 1,1,1 */
+#define TERM_L_WHITE 9 /* 'W' */ /* 3,3,3 */
+#define TERM_VIOLET 10 /* 'v' */ /* 4,0,4 */
+#define TERM_YELLOW 11 /* 'y' */ /* 4,4,0 */
+#define TERM_L_RED 12 /* 'R' */ /* 4,0,0 */
+#define TERM_L_GREEN 13 /* 'G' */ /* 0,4,0 */
+#define TERM_L_BLUE 14 /* 'B' */ /* 0,4,4 */
+#define TERM_L_UMBER 15 /* 'U' */ /* 3,2,1 */
@@ -251,11 +196,8 @@ struct term
*
* The "TERM_XTRA_EVENT" action uses "v" to "wait" for an event
* The "TERM_XTRA_SHAPE" action uses "v" to "show" the cursor
- * The "TERM_XTRA_FROSH" action uses "v" for the index of the row
- * The "TERM_XTRA_SOUND" action uses "v" for the index of a sound
* The "TERM_XTRA_ALIVE" action uses "v" to "activate" (or "close")
* The "TERM_XTRA_LEVEL" action uses "v" to "resume" (or "suspend")
- * The "TERM_XTRA_DELAY" action uses "v" as a "millisecond" value
*
* The other actions do not need a "v" code, so "zero" is used.
*/
@@ -263,77 +205,61 @@ struct term
#define TERM_XTRA_FLUSH 2 /* Flush all pending events */
#define TERM_XTRA_CLEAR 3 /* Clear the entire window */
#define TERM_XTRA_SHAPE 4 /* Set cursor shape (optional) */
-#define TERM_XTRA_FROSH 5 /* Flush one row (optional) */
#define TERM_XTRA_FRESH 6 /* Flush all rows (optional) */
#define TERM_XTRA_NOISE 7 /* Make a noise (optional) */
-#define TERM_XTRA_SOUND 8 /* Make a sound (optional) */
#define TERM_XTRA_BORED 9 /* Handle stuff when bored (optional) */
#define TERM_XTRA_REACT 10 /* React to global changes (optional) */
#define TERM_XTRA_ALIVE 11 /* Change the "hard" level (optional) */
#define TERM_XTRA_LEVEL 12 /* Change the "soft" level (optional) */
-#define TERM_XTRA_DELAY 13 /* Delay some milliseconds (optional) */
-#define TERM_XTRA_GET_DELAY 14 /* Get the cuyrrent time in milliseconds (optional) */
-#define TERM_XTRA_SCANSUBDIR 15 /* Scan for subdir in a dir */
#define TERM_XTRA_RENAME_MAIN_WIN 16 /* Rename the main game window */
/**** Available Variables ****/
extern term *Term;
-extern FILE *movfile;
-extern int do_movies;
-extern int last_paused;
-
/**** Available Functions ****/
-extern errr Term_user(int n);
-extern errr Term_xtra(int n, int v);
-extern long Term_xtra_long;
-extern char scansubdir_dir[1024];
-extern int scansubdir_max;
-extern cptr scansubdir_result[255];
-
-extern void Term_queue_char(int x, int y, byte a, char c, byte ta, char tc, byte ea, char ec);
-extern void Term_queue_line(int x, int y, int n, byte *a, char *c, byte *ta, char *tc, byte *ea, char *ec);
-extern void Term_queue_chars(int x, int y, int n, byte a, cptr s);
-
-extern errr Term_fresh(void);
-extern errr Term_set_cursor(int v);
-extern errr Term_gotoxy(int x, int y);
-extern errr Term_draw(int x, int y, byte a, char c);
-extern errr Term_addch(byte a, char c);
-extern errr Term_addstr(int n, byte a, cptr s);
-extern errr Term_putch(int x, int y, byte a, char c);
-extern errr Term_putstr(int x, int y, int n, byte a, cptr s);
-extern errr Term_erase(int x, int y, int n);
-extern errr Term_clear(void);
-extern errr Term_redraw(void);
-extern errr Term_redraw_section(int x1, int y1, int x2, int y2);
-
-extern errr Term_get_cursor(int *v);
-extern errr Term_get_size(int *w, int *h);
-extern errr Term_locate(int *x, int *y);
-extern errr Term_what(int x, int y, byte *a, char *c);
-
-extern errr Term_flush(void);
-extern errr Term_keypress(int k);
-extern errr Term_key_push(int k);
-extern errr Term_inkey(char *ch, bool_ wait, bool_ take);
-
-extern errr Term_save(void);
-extern term_win* Term_save_to(void);
-extern errr Term_load(void);
-extern errr Term_load_from(term_win *save, bool_ final);
-
-extern errr Term_exchange(void);
-
-extern errr Term_resize(int w, int h);
-
-extern errr Term_activate(term *t);
-
-extern errr term_nuke(term *t);
-extern errr term_init(term *t, int w, int h, int k);
+errr Term_xtra(int n, int v);
+
+void Term_queue_char(int x, int y, byte a, char c);
+void Term_queue_chars(int x, int y, int n, byte a, cptr s);
+
+errr Term_fresh();
+errr Term_set_cursor(int v);
+errr Term_gotoxy(int x, int y);
+errr Term_draw(int x, int y, byte a, char c);
+errr Term_addch(byte a, char c);
+errr Term_addstr(int n, byte a, cptr s);
+errr Term_putch(int x, int y, byte a, char c);
+errr Term_putstr(int x, int y, int n, byte a, cptr s);
+errr Term_erase(int x, int y, int n);
+errr Term_clear();
+errr Term_redraw();
+errr Term_redraw_section(int x1, int y1, int x2, int y2);
+void Term_bell();
+
+errr Term_get_cursor(int *v);
+errr Term_get_size(int *w, int *h);
+errr Term_locate(int *x, int *y);
+errr Term_what(int x, int y, byte *a, char *c);
+
+errr Term_flush();
+errr Term_keypress(int k);
+errr Term_key_push(int k);
+errr Term_inkey(char *ch, bool_ wait, bool_ take);
+
+errr Term_save();
+term_win* Term_save_to();
+errr Term_load();
+errr Term_load_from(term_win *save);
+
+errr Term_resize(int w, int h);
+
+errr Term_activate(term *t);
+
+errr term_nuke(term *t);
+errr term_init(term *t, int w, int h, int k);
#ifdef __cplusplus
} /* extern "C" */
diff --git a/src/z-util.c b/src/z-util.c
index 7c5374f3..0304a1da 100644
--- a/src/z-util.c
+++ b/src/z-util.c
@@ -4,122 +4,7 @@
#include "z-util.h"
-
-
-/*
- * Global variables for temporary use
- */
-char char_tmp = 0;
-byte byte_tmp = 0;
-sint sint_tmp = 0;
-uint uint_tmp = 0;
-long long_tmp = 0;
-huge huge_tmp = 0;
-errr errr_tmp = 0;
-
-
-/*
- * Global pointers for temporary use
- */
-cptr cptr_tmp = NULL;
-vptr vptr_tmp = NULL;
-
-
-
-
-/*
- * Constant bool meaning true
- */
-bool_ bool_true = 1;
-
-/*
- * Constant bool meaning false
- */
-bool_ bool_false = 0;
-
-
-/*
- * Global NULL cptr
- */
-cptr cptr_null = NULL;
-
-
-/*
- * Global NULL vptr
- */
-vptr vptr_null = NULL;
-
-
-
-/*
- * Global SELF vptr
- */
-vptr vptr_self = (vptr)(&vptr_self);
-
-
-
-/*
- * Convenient storage of the program name
- */
-cptr argv0 = NULL;
-
-
-
-/*
- * A routine that does nothing
- */
-void func_nothing(void)
-{
- /* Do nothing */
-}
-
-
-/*
- * A routine that always returns "success"
- */
-errr func_success(void)
-{
- return (0);
-}
-
-
-/*
- * A routine that always returns a simple "problem code"
- */
-errr func_problem(void)
-{
- return (1);
-}
-
-
-/*
- * A routine that always returns a simple "failure code"
- */
-errr func_failure(void)
-{
- return ( -1);
-}
-
-
-
-/*
- * A routine that always returns "true"
- */
-bool_ func_true(void)
-{
- return (1);
-}
-
-
-/*
- * A routine that always returns "false"
- */
-bool_ func_false(void)
-{
- return (0);
-}
-
-
+#include <assert.h>
/*
@@ -150,6 +35,27 @@ bool_ suffix(cptr s, cptr t)
}
+/**
+ * Captialize letter
+ */
+void capitalize(char *s)
+{
+ char *p = s;
+ assert(s != NULL);
+
+ for (; *p; p++)
+ {
+ if (!isspace(*p))
+ {
+ if (islower(*p))
+ {
+ *p = toupper(*p);
+ }
+ /* Done */
+ break;
+ }
+ }
+}
/*
@@ -167,7 +73,7 @@ void plog(cptr str)
if (plog_aux) (*plog_aux)(str);
/* Just do a labeled fprintf to stderr */
- else (void)(fprintf(stderr, "%s: %s\n", argv0 ? argv0 : "???", str));
+ else (void)(fprintf(stderr, "%s\n", str));
}
@@ -200,35 +106,3 @@ void quit(cptr str)
/* Failure */
(void)(exit( -1));
}
-
-
-
-/*
- * Redefinable "core" action
- */
-void (*core_aux)(cptr) = NULL;
-
-/*
- * Dump a core file, after printing a warning message
- * As with "quit()", try to use the "core_aux()" hook first.
- */
-void core(cptr str)
-{
- char *crash = NULL;
-
- /* Use the aux function */
- if (core_aux) (*core_aux)(str);
-
- /* Dump the warning string */
- if (str) plog(str);
-
- /* Attempt to Crash */
- (*crash) = (*crash);
-
- /* Be sure we exited */
- quit("core() failed");
-}
-
-
-
-
diff --git a/src/z-util.h b/src/z-util.h
index 11dbdb4e..d2fa79dc 100644
--- a/src/z-util.h
+++ b/src/z-util.h
@@ -1,7 +1,4 @@
-/* File z-util.h */
-
-#ifndef INCLUDED_Z_UTIL_H
-#define INCLUDED_Z_UTIL_H
+#pragma once
#ifdef __cplusplus
extern "C" {
@@ -11,81 +8,34 @@ extern "C" {
/*
- * Extremely basic stuff, like global temp and constant variables.
- * Also, some very useful low level functions, such as "streq()".
- * All variables and functions in this file are "addressable".
+ * Extremely basic stuff, like "streq()".
*/
-/**** Available variables ****/
-
-/* Temporary Vars */
-extern char char_tmp;
-extern byte byte_tmp;
-extern sint sint_tmp;
-extern uint uint_tmp;
-extern long long_tmp;
-extern huge huge_tmp;
-extern errr errr_tmp;
-
-/* Temporary Pointers */
-extern cptr cptr_tmp;
-extern vptr vptr_tmp;
-
-
-/* Constant pointers (NULL) */
-extern cptr cptr_null;
-extern vptr vptr_null;
-
-
-/* A bizarre vptr that always points at itself */
-extern vptr vptr_self;
-
-
-/* A cptr to the name of the program */
-extern cptr argv0;
-
-
/* Aux functions */
extern void (*plog_aux)(cptr);
extern void (*quit_aux)(cptr);
-extern void (*core_aux)(cptr);
/**** Available Functions ****/
-/* Function that does nothing */
-extern void func_nothing(void);
-
-/* Functions that return basic "errr" codes */
-extern errr func_success(void);
-extern errr func_problem(void);
-extern errr func_failure(void);
-
-/* Functions that return bools */
-extern bool_ func_true(void);
-extern bool_ func_false(void);
-
/* Test equality, prefix, suffix */
-extern bool_ streq(cptr s, cptr t);
-extern bool_ prefix(cptr s, cptr t);
-extern bool_ suffix(cptr s, cptr t);
+bool_ streq(cptr s, cptr t);
+bool_ prefix(cptr s, cptr t);
+bool_ suffix(cptr s, cptr t);
+
+/* Capitalize the first letter of string. Ignores whitespace at the start of string. */
+void capitalize(char *s);
/* Print an error message */
-extern void plog(cptr str);
+void plog(cptr str);
/* Exit, with optional message */
-extern void quit(cptr str);
-
-/* Dump core, with optional message */
-extern void core(cptr str);
-
+void quit(cptr str);
#ifdef __cplusplus
} /* extern "C" */
#endif
-
-#endif
diff --git a/src/z-virt.c b/src/z-virt.c
deleted file mode 100644
index c9277166..00000000
--- a/src/z-virt.c
+++ /dev/null
@@ -1,187 +0,0 @@
-/* File: z-virt.c */
-
-/*
- * Copyright (c) 1997 Ben Harrison
- *
- * 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.
- */
-
-/* Purpose: Memory management routines -BEN- */
-
-#include "z-virt.h"
-
-#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
- */
-vptr (*rnfree_aux)(vptr, huge) = NULL;
-
-/*
- * Free some memory (allocated by ralloc), return NULL
- */
-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));
-
- /* Use "free" */
- free ((char*)(p));
-
- /* Done */
- return (NULL);
-}
-
-
-/*
- * Optional auxiliary "rpanic" function
- */
-vptr (*rpanic_aux)(huge) = NULL;
-
-/*
- * The system is out of memory, so panic. If "rpanic_aux" is set,
- * it can be used to free up some memory and do a new "ralloc()",
- * or if not, it can be used to save things, clean up, and exit.
- * By default, this function simply crashes the computer.
- */
-vptr rpanic(huge len)
-{
- /* Hopefully, we have a real "panic" function */
- if (rpanic_aux) return ((*rpanic_aux)(len));
-
- /* Attempt to crash before icky things happen */
- core("Out of Memory!");
-
- /* Paranoia */
- return ((vptr)(NULL));
-}
-
-
-/*
- * Optional auxiliary "ralloc" function
- */
-vptr (*ralloc_aux)(huge) = NULL;
-
-
-/*
- * Allocate some memory
- */
-vptr ralloc(huge len)
-{
- vptr mem;
-
- /* 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);
-
- /* Use malloc() to allocate some memory */
- else mem = ((vptr)(malloc((size_t)(len))));
-
- /* We were able to acquire memory */
- if (!mem) mem = rpanic(len);
-
- /* Return the memory, if any */
- return (mem);
-}
-
-
-
-
-/*
- * Allocate a constant string, containing the same thing as 'str'
- */
-cptr string_make(cptr str)
-{
- huge len = 0;
- cptr t = str;
- char *s, *res;
-
- /* Simple sillyness */
- if (!str) return (str);
-
- /* Get the number of chars in the string, including terminator */
- while (str[len++]) /* loop */;
-
- /* Allocate space for the string */
- s = res = (char*)(ralloc(len));
-
- /* Copy the string (with terminator) */
- while ((*s++ = *t++) != 0) /* loop */;
-
- /* Return the allocated, initialized, string */
- return (res);
-}
-
-
-/*
- * Un-allocate a string allocated above.
- * Depends on no changes being made to the string.
- */
-errr string_free(cptr str)
-{
- huge len = 0;
-
- /* Succeed on non-strings */
- if (!str) return (0);
-
- /* Count the number of chars in 'str' plus the terminator */
- while (str[len++]) /* loop */;
-
- /* Kill the buffer of chars we must have allocated above */
- rnfree((vptr)(str), len);
-
- /* Success */
- return (0);
-}
-
-
diff --git a/src/z-virt.h b/src/z-virt.h
deleted file mode 100644
index a7880f2f..00000000
--- a/src/z-virt.h
+++ /dev/null
@@ -1,168 +0,0 @@
-/* File: z-virt.h */
-
-/*
- * Copyright (c) 1997 Ben Harrison
- *
- * 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.
- */
-
-#ifndef INCLUDED_Z_VIRT_H
-#define INCLUDED_Z_VIRT_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "h-basic.h"
-
-#ifdef CHECK_MEMORY_LEAKS
-#include <leak_detector.h>
-#endif
-
-/*
- * Memory management routines.
- *
- * Set ralloc_aux to modify the memory allocation routine.
- * Set rnfree_aux to modify the memory de-allocation routine.
- * Set rpanic_aux to let the program react to memory failures.
- *
- * These routines work best as a *replacement* for malloc/free.
- *
- * The string_make() and string_free() routines handle dynamic strings.
- * A dynamic string is a string allocated at run-time, which should not
- * be modified once it has been created.
- *
- * Note the macros below which simplify the details of allocation,
- * deallocation, setting, clearing, casting, size extraction, etc.
- *
- * The macros MAKE/C_MAKE and KILL/C_KILL have a "procedural" metaphor,
- * and they actually modify their arguments.
- *
- * Note that, for some reason, some allocation macros may disallow
- * "stars" in type names, but you can use typedefs to circumvent
- * this. For example, instead of "type **p; MAKE(p,type*);" you
- * can use "typedef type *type_ptr; type_ptr *p; MAKE(p,type_ptr)".
- *
- * Note that it is assumed that "memset()" will function correctly,
- * in particular, that it returns its first argument.
- */
-
-
-
-/**** Available macros ****/
-
-
-/* Size of 'N' things of type 'T' */
-#define C_SIZE(N,T) \
- ((huge)((N)*(sizeof(T))))
-
-/* Size of one thing of type 'T' */
-#define SIZE(T) \
- ((huge)(sizeof(T)))
-
-
-/* Wipe an array of type T[N], at location P, and return P */
-#define C_WIPE(P,N,T) \
- (memset((char*)(P),0,C_SIZE(N,T)))
-
-/* Wipe a thing of type T, at location P, and return P */
-#define WIPE(P,T) \
- (memset((char*)(P),0,SIZE(T)))
-
-
-/* Load an array of type T[N], at location P1, from another, at location P2 */
-#define C_COPY(P1,P2,N,T) \
- (memcpy((char*)(P1),(char*)(P2),C_SIZE(N,T)))
-
-/* Load a thing of type T, at location P1, from another, at location P2 */
-#define COPY(P1,P2,T) \
- (memcpy((char*)(P1),(char*)(P2),SIZE(T)))
-
-
-/* Free an array of N things of type T at P, return NULL */
-#define C_FREE(P,N,T) \
- (rnfree(P,C_SIZE(N,T)))
-
-/* Free one thing of type T at P, return NULL */
-#define FREE(P,T) \
- (rnfree(P,SIZE(T)))
-
-
-/* Allocate, and return, an array of type T[N] */
-#define C_RNEW(N,T) \
- (ralloc(C_SIZE(N,T)))
-
-/* Allocate, and return, a thing of type T */
-#define RNEW(T) \
- (ralloc(SIZE(T)))
-
-
-/* Allocate, wipe, and return an array of type T[N] */
-#define C_ZNEW(N,T) \
- (C_WIPE(C_RNEW(N,T),N,T))
-
-/* Allocate, wipe, and return a thing of type T */
-#define ZNEW(T) \
- (WIPE(RNEW(T),T))
-
-
-/* Allocate a wiped array of type T[N], assign to pointer P */
-#define C_MAKE(P,N,T) \
- ((P)=C_ZNEW(N,T))
-
-/* Allocate a wiped thing of type T, assign to pointer P */
-#define MAKE(P,T) \
- ((P)=ZNEW(T))
-
-
-/* Free an array of type T[N], at location P, and set P to NULL */
-#define C_KILL(P,N,T) \
- ((P)=C_FREE(P,N,T))
-
-/* Free a thing of type T, at location P, and set P to NULL */
-#define KILL(P,T) \
- ((P)=FREE(P,T))
-
-
-
-/**** Available variables ****/
-
-/* Replacement hook for "rnfree()" */
-extern vptr (*rnfree_aux)(vptr, huge);
-
-/* Replacement hook for "rpanic()" */
-extern vptr (*rpanic_aux)(huge);
-
-/* Replacement hook for "ralloc()" */
-extern vptr (*ralloc_aux)(huge);
-
-
-/**** Available functions ****/
-
-/* De-allocate a given amount of memory */
-extern vptr rnfree(vptr p, huge len);
-
-/* Panic, attempt to Allocate 'len' bytes */
-extern vptr rpanic(huge len);
-
-/* Allocate (and return) 'len', or dump core */
-extern vptr ralloc(huge len);
-
-/* Create a "dynamic string" */
-extern cptr string_make(cptr str);
-
-/* Free a string allocated with "string_make()" */
-extern errr string_free(cptr str);
-
-
-
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-
-
-#endif
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);