summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/.cvsignore8
-rw-r--r--src/.gitignore3
-rw-r--r--src/CMakeLists.txt182
-rw-r--r--src/ability_type.hpp27
-rw-r--r--src/ability_type_fwd.hpp3
-rw-r--r--src/activation.hpp13
-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.hpp60
-rw-r--r--src/artifact_type_fwd.hpp3
-rw-r--r--src/between_exit.hpp18
-rw-r--r--src/birth.cc (renamed from src/birth.c)777
-rw-r--r--src/birth.h14
-rw-r--r--src/birth.hpp9
-rw-r--r--src/birther.hpp35
-rw-r--r--src/bldg.cc (renamed from src/bldg.c)903
-rw-r--r--src/bldg.hpp9
-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)1116
-rw-r--r--src/cave.hpp55
-rw-r--r--src/cave_type.hpp65
-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)762
-rw-r--r--src/cmd1.hpp25
-rw-r--r--src/cmd2.cc (renamed from src/cmd2.c)1015
-rw-r--r--src/cmd2.hpp33
-rw-r--r--src/cmd3.cc (renamed from src/cmd3.c)745
-rw-r--r--src/cmd3.hpp24
-rw-r--r--src/cmd4.cc (renamed from src/cmd4.c)941
-rw-r--r--src/cmd4.hpp28
-rw-r--r--src/cmd5.cc (renamed from src/cmd5.c)1092
-rw-r--r--src/cmd5.hpp16
-rw-r--r--src/cmd6.cc (renamed from src/cmd6.c)5105
-rw-r--r--src/cmd6.hpp18
-rw-r--r--src/cmd7.c7652
-rw-r--r--src/cmd7.cc4466
-rw-r--r--src/cmd7.hpp28
-rw-r--r--src/cmovie.c496
-rw-r--r--src/config.h185
-rw-r--r--src/corrupt.cc1003
-rw-r--r--src/corrupt.hpp47
-rw-r--r--src/defines.h1106
-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)1171
-rw-r--r--src/dungeon.h14
-rw-r--r--src/dungeon.hpp6
-rw-r--r--src/dungeon.pkg1607
-rw-r--r--src/dungeon_info_type.hpp72
-rw-r--r--src/dungeon_info_type_fwd.hpp3
-rw-r--r--src/effect_type.hpp17
-rw-r--r--src/ego_item_type.hpp68
-rw-r--r--src/ego_item_type_fwd.hpp3
-rw-r--r--src/externs.h1851
-rw-r--r--src/fate.hpp22
-rw-r--r--src/feature_type.hpp37
-rw-r--r--src/feature_type_fwd.hpp3
-rw-r--r--src/files.cc (renamed from src/files.c)1206
-rw-r--r--src/files.h17
-rw-r--r--src/files.hpp27
-rw-r--r--src/flags_group.hpp20
-rw-r--r--src/gen_evol.cc (renamed from src/gen_evol.c)18
-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)596
-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)101
-rw-r--r--src/gods.hpp13
-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.cc742
-rw-r--r--src/help.hpp11
-rw-r--r--src/help_info.hpp17
-rw-r--r--src/hiscore.cc85
-rw-r--r--src/hiscore.hpp83
-rw-r--r--src/hist_type.hpp16
-rw-r--r--src/hist_type_fwd.hpp3
-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/squelch/automatizer.hpp156
-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.hpp49
-rw-r--r--src/include/tome/squelch/tree_printer_fwd.hpp10
-rw-r--r--src/init1.cc (renamed from src/init1.c)2382
-rw-r--r--src/init1.hpp26
-rw-r--r--src/init2.c2918
-rw-r--r--src/init2.cc1494
-rw-r--r--src/init2.h14
-rw-r--r--src/init2.hpp9
-rw-r--r--src/inscription_info_type.hpp14
-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/levels.cc (renamed from src/levels.c)15
-rw-r--r--src/levels.hpp13
-rw-r--r--src/loadsave.cc (renamed from src/loadsave.c)2649
-rw-r--r--src/loadsave.h16
-rw-r--r--src/loadsave.hpp7
-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.h205
-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.cc277
-rw-r--r--src/lua_bind.hpp34
-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.c217
-rw-r--r--src/main-gtk2.c3077
-rw-r--r--src/main-sdl.c219
-rw-r--r--src/main-sla.c455
-rw-r--r--src/main-win.c1080
-rw-r--r--src/main-x11.c832
-rw-r--r--src/main-xaw.c1888
-rw-r--r--src/main-xxx.c785
-rw-r--r--src/main.c389
-rw-r--r--src/martial_arts.hpp18
-rw-r--r--src/melee1.cc (renamed from src/melee1.c)105
-rw-r--r--src/melee1.hpp7
-rw-r--r--src/melee2.cc (renamed from src/melee2.c)1058
-rw-r--r--src/melee2.hpp12
-rw-r--r--src/messages.cc368
-rw-r--r--src/messages.hpp9
-rw-r--r--src/meta_class_type.hpp10
-rw-r--r--src/meta_class_type_fwd.hpp3
-rw-r--r--src/mimic.cc728
-rw-r--r--src/mimic.hpp10
-rw-r--r--src/module_type.hpp64
-rw-r--r--src/modules.c274
-rw-r--r--src/modules.cc1279
-rw-r--r--src/modules.h15
-rw-r--r--src/modules.hpp11
-rw-r--r--src/monster.pkg2324
-rw-r--r--src/monster1.cc (renamed from src/monster1.c)159
-rw-r--r--src/monster1.hpp5
-rw-r--r--src/monster2.cc (renamed from src/monster2.c)627
-rw-r--r--src/monster2.hpp52
-rw-r--r--src/monster3.cc (renamed from src/monster3.c)74
-rw-r--r--src/monster3.hpp20
-rw-r--r--src/monster_blow.hpp19
-rw-r--r--src/monster_ego.hpp81
-rw-r--r--src/monster_ego_fwd.hpp3
-rw-r--r--src/monster_power.hpp14
-rw-r--r--src/monster_race.hpp116
-rw-r--r--src/monster_race_fwd.hpp3
-rw-r--r--src/monster_type.cc8
-rw-r--r--src/monster_type.hpp98
-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)43
-rw-r--r--src/notes.hpp6
-rw-r--r--src/obj_theme.hpp15
-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)1225
-rw-r--r--src/object1.hpp46
-rw-r--r--src/object2.cc (renamed from src/object2.c)614
-rw-r--r--src/object2.hpp69
-rw-r--r--src/object_filter.cc98
-rw-r--r--src/object_filter.hpp99
-rw-r--r--src/object_kind.hpp83
-rw-r--r--src/object_kind_fwd.hpp3
-rw-r--r--src/object_type.hpp104
-rw-r--r--src/object_type_fwd.hpp3
-rw-r--r--src/option_type.hpp40
-rw-r--r--src/options.cc89
-rw-r--r--src/options.hpp89
-rw-r--r--src/owner_type.hpp39
-rw-r--r--src/owner_type_fwd.hpp3
-rw-r--r--src/player.pkg3519
-rw-r--r--src/player_c.pkg1060
-rw-r--r--src/player_class.hpp105
-rw-r--r--src/player_class_fwd.hpp3
-rw-r--r--src/player_defs.hpp6
-rw-r--r--src/player_race.hpp83
-rw-r--r--src/player_race_fwd.hpp3
-rw-r--r--src/player_race_mod.hpp87
-rw-r--r--src/player_race_mod_fwd.hpp3
-rw-r--r--src/player_sex.hpp17
-rw-r--r--src/player_sex_fwd.hpp3
-rw-r--r--src/player_spec.hpp38
-rw-r--r--src/player_spec_fwd.hpp3
-rw-r--r--src/player_type.hpp423
-rw-r--r--src/player_type_fwd.hpp3
-rw-r--r--src/plots.c473
-rw-r--r--src/plots.h48
-rw-r--r--src/power_type.hpp19
-rw-r--r--src/powers.cc (renamed from src/powers.c)319
-rw-r--r--src/powers.hpp74
-rw-r--r--src/q_betwen.cc (renamed from src/q_betwen.c)74
-rw-r--r--src/q_betwen.hpp5
-rw-r--r--src/q_bounty.cc170
-rw-r--r--src/q_bounty.hpp8
-rw-r--r--src/q_dragons.cc (renamed from src/q_dragons.c)38
-rw-r--r--src/q_dragons.hpp5
-rw-r--r--src/q_eol.cc (renamed from src/q_eol.c)99
-rw-r--r--src/q_eol.hpp5
-rw-r--r--src/q_evil.cc (renamed from src/q_evil.c)39
-rw-r--r--src/q_evil.hpp5
-rw-r--r--src/q_fireprof.cc577
-rw-r--r--src/q_fireprof.hpp7
-rw-r--r--src/q_god.cc1212
-rw-r--r--src/q_god.hpp6
-rw-r--r--src/q_haunted.cc (renamed from src/q_haunted.c)40
-rw-r--r--src/q_haunted.hpp5
-rw-r--r--src/q_hobbit.cc (renamed from src/q_hobbit.c)125
-rw-r--r--src/q_hobbit.hpp5
-rw-r--r--src/q_invas.cc (renamed from src/q_invas.c)97
-rw-r--r--src/q_invas.hpp5
-rw-r--r--src/q_library.cc526
-rw-r--r--src/q_library.hpp8
-rw-r--r--src/q_main.cc (renamed from src/q_main.c)106
-rw-r--r--src/q_main.hpp7
-rw-r--r--src/q_narsil.cc (renamed from src/q_narsil.c)68
-rw-r--r--src/q_narsil.hpp5
-rw-r--r--src/q_nazgul.c116
-rw-r--r--src/q_nazgul.cc145
-rw-r--r--src/q_nazgul.hpp5
-rw-r--r--src/q_nirna.cc (renamed from src/q_nirna.c)46
-rw-r--r--src/q_nirna.hpp5
-rw-r--r--src/q_one.cc (renamed from src/q_one.c)142
-rw-r--r--src/q_one.hpp5
-rw-r--r--src/q_poison.cc (renamed from src/q_poison.c)81
-rw-r--r--src/q_poison.hpp5
-rw-r--r--src/q_rand.cc (renamed from src/q_rand.c)314
-rw-r--r--src/q_rand.hpp8
-rw-r--r--src/q_shroom.cc (renamed from src/q_shroom.c)214
-rw-r--r--src/q_shroom.hpp5
-rw-r--r--src/q_spider.cc (renamed from src/q_spider.c)45
-rw-r--r--src/q_spider.hpp5
-rw-r--r--src/q_thief.cc (renamed from src/q_thief.c)53
-rw-r--r--src/q_thief.hpp5
-rw-r--r--src/q_thrain.cc (renamed from src/q_thrain.c)99
-rw-r--r--src/q_thrain.hpp5
-rw-r--r--src/q_troll.cc (renamed from src/q_troll.c)80
-rw-r--r--src/q_troll.hpp5
-rw-r--r--src/q_ultrae.cc (renamed from src/q_ultrae.c)5
-rw-r--r--src/q_ultrae.hpp5
-rw-r--r--src/q_ultrag.cc (renamed from src/q_ultrag.c)82
-rw-r--r--src/q_ultrag.hpp5
-rw-r--r--src/q_wight.cc (renamed from src/q_wight.c)67
-rw-r--r--src/q_wight.hpp5
-rw-r--r--src/q_wolves.cc (renamed from src/q_wolves.c)40
-rw-r--r--src/q_wolves.hpp5
-rw-r--r--src/quark.cc96
-rw-r--r--src/quark.hpp12
-rw-r--r--src/quest.cc17
-rw-r--r--src/quest.hpp3
-rwxr-xr-xsrc/quest.pkg170
-rw-r--r--src/quest_type.hpp27
-rw-r--r--src/randart.cc (renamed from src/randart.c)79
-rw-r--r--src/randart.hpp9
-rw-r--r--src/randart_gen_type.hpp9
-rw-r--r--src/randart_gen_type_fwd.hpp3
-rw-r--r--src/randart_part_type.hpp43
-rw-r--r--src/randart_part_type_fwd.hpp3
-rw-r--r--src/random_artifact.hpp18
-rw-r--r--src/random_quest.hpp10
-rw-r--r--src/random_spell.hpp21
-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.hpp22
-rw-r--r--src/rune_spell.hpp15
-rw-r--r--src/rune_spell_fwd.hpp3
-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/script.cc30
-rw-r--r--src/script.h12
-rw-r--r--src/set_type.hpp28
-rw-r--r--src/set_type_fwd.hpp3
-rw-r--r--src/skill_type.hpp37
-rw-r--r--src/skill_type_fwd.hpp3
-rw-r--r--src/skills.cc (renamed from src/skills.c)690
-rw-r--r--src/skills.hpp27
-rw-r--r--src/skills_defs.hpp63
-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/spells.pkg2448
-rw-r--r--src/spells1.cc (renamed from src/spells1.c)686
-rw-r--r--src/spells1.hpp32
-rw-r--r--src/spells2.cc (renamed from src/spells2.c)3093
-rw-r--r--src/spells2.hpp115
-rw-r--r--src/spells3.cc4606
-rw-r--r--src/spells3.hpp445
-rw-r--r--src/spells4.cc541
-rw-r--r--src/spells4.hpp42
-rw-r--r--src/spells5.cc2395
-rw-r--r--src/spells5.hpp9
-rw-r--r--src/spells6.cc402
-rw-r--r--src/spells6.hpp7
-rw-r--r--src/squelch/CMakeLists.txt9
-rw-r--r--src/squelch/automatizer.cc278
-rw-r--r--src/squelch/condition.cc1078
-rw-r--r--src/squelch/condition_metadata.cc496
-rw-r--r--src/squelch/cursor.cc96
-rw-r--r--src/squelch/object_status.cc153
-rw-r--r--src/squelch/rule.cc332
-rw-r--r--src/squelch/tree_printer.cc89
-rw-r--r--src/squeltch.c553
-rw-r--r--src/squeltch.cc593
-rw-r--r--src/squeltch.hpp13
-rw-r--r--src/stairs_direction.hpp3
-rw-r--r--src/stats.hpp11
-rw-r--r--src/status.cc (renamed from src/status.c)70
-rw-r--r--src/status.hpp3
-rw-r--r--src/store.cc (renamed from src/store.c)1398
-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_info_type.hpp32
-rw-r--r--src/store_info_type_fwd.hpp3
-rw-r--r--src/store_type.hpp43
-rw-r--r--src/store_type_fwd.hpp3
-rw-r--r--src/tables.cc (renamed from src/tables.c)822
-rw-r--r--src/tables.h12
-rw-r--r--src/tables.hpp82
-rw-r--r--src/tactic_info_type.hpp17
-rw-r--r--src/terrain.hpp19
-rw-r--r--src/timer_type.hpp18
-rw-r--r--src/timer_type_fwd.hpp3
-rw-r--r--src/town_type.hpp21
-rw-r--r--src/town_type_fwd.hpp3
-rw-r--r--src/trap_type.hpp24
-rw-r--r--src/trap_type_fwd.hpp3
-rw-r--r--src/traps.cc (renamed from src/traps.c)201
-rw-r--r--src/traps.hpp13
-rw-r--r--src/tval_desc.hpp17
-rw-r--r--src/types.h2522
-rw-r--r--src/util.cc (renamed from src/util.c)1058
-rw-r--r--src/util.h22
-rw-r--r--src/util.hpp74
-rw-r--r--src/util.pkg2683
-rw-r--r--src/variable.cc (renamed from src/variable.c)743
-rw-r--r--src/variable.h39
-rw-r--r--src/variable.hpp308
-rw-r--r--src/vault_type.hpp24
-rw-r--r--src/vault_type_fwd.hpp3
-rw-r--r--src/wild.cc (renamed from src/wild.c)132
-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.hpp25
-rw-r--r--src/wilderness_type_info_fwd.hpp3
-rw-r--r--src/wizard1.cc (renamed from src/wizard1.c)323
-rw-r--r--src/wizard1.hpp3
-rw-r--r--src/wizard2.cc (renamed from src/wizard2.c)280
-rw-r--r--src/wizard2.hpp8
-rw-r--r--src/xtra1.cc (renamed from src/xtra1.c)1120
-rw-r--r--src/xtra1.hpp24
-rw-r--r--src/xtra2.cc (renamed from src/xtra2.c)1630
-rw-r--r--src/xtra2.hpp96
-rw-r--r--src/z-form.c191
-rw-r--r--src/z-form.h21
-rw-r--r--src/z-rand.cc (renamed from src/z-rand.c)25
-rw-r--r--src/z-rand.hpp (renamed from src/z-rand.h)91
-rw-r--r--src/z-term.c1094
-rw-r--r--src/z-term.h128
-rw-r--r--src/z-util.c172
-rw-r--r--src/z-util.h60
-rw-r--r--src/z-virt.c187
-rw-r--r--src/z-virt.h168
-rw-r--r--src/z_pack.pkg398
518 files changed, 48481 insertions, 100210 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..098f3b10
--- /dev/null
+++ b/src/.gitignore
@@ -0,0 +1,3 @@
+/harness
+/tome
+*.plist
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 932fef4b..f4b2d2db 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,29 +1,137 @@
-# 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)
+
+# Add subdirectories
+ADD_SUBDIRECTORY (squelch)
+
+# 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
+ gen_evol.cc
+ gen_maze.cc
+ generate.cc
+ gods.cc
+ help.cc
+ hiscore.cc
+ hooks.cc
+ init1.cc
+ init2.cc
+ joke.cc
+ levels.cc
+ loadsave.cc
+ lua_bind.cc
+ melee1.cc
+ melee2.cc
+ messages.cc
+ mimic.cc
+ modules.cc
+ monster_type.cc
+ monster1.cc
+ monster2.cc
+ monster3.cc
+ notes.cc
+ object1.cc
+ object2.cc
+ object_filter.cc
+ options.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
+ quark.cc
+ quest.cc
+ randart.cc
+ range.cc
+ script.cc
+ skills.cc
+ spell_type.cc
+ spells1.cc
+ spells2.cc
+ spells3.cc
+ spells4.cc
+ spells5.cc
+ spells6.cc
+ squeltch.cc
+ status.cc
+ store.cc
+ tables.cc
+ traps.cc
+ util.cc
+ variable.cc
+ wild.cc
+ wizard1.cc
+ wizard2.cc
+ xtra1.cc
+ xtra2.cc
+ z-form.c
+ z-rand.cc
+ z-term.c
+ z-util.c
+)
-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 (PROGRAM)
+SET(SRCS_PROGRAM
+ main-gcu.c
+ main-gtk2.c
+ main-sdl.c
+ main-x11.c
+ main.c
+)
+
+# Sources (TEST)
+SET(SRCS_TESTS
+ ../tests/get_level_device.cc
+ ../tests/harness.cc
+ ../tests/lua_get_level.cc
+)
+
+ADD_LIBRARY(game
+ ${SRCS_COMMON}
)
# Need a few additional source files for Windows.
if(WIN32)
- SET(SRCS ${SRCS} main-win.c readdib.c)
+ SET(SRCS ${SRCS} main-win.c)
# Resource files require a little workaround.
if(MINGW)
# Workaround for resource compilation for mingw on CMake.
@@ -38,33 +146,13 @@ if(WIN32)
endif(MINGW)
endif(WIN32)
-
-# Macro for defining tolua targets.
-MACRO(TOLUA_FILE MODULE_NAME OUTPUT_FILE_NAME)
- ADD_CUSTOM_COMMAND(
- OUTPUT ${OUTPUT_FILE_NAME}
- COMMAND tolua -n ${MODULE_NAME} -o ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_FILE_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/${MODULE_NAME}.pkg
- DEPENDS tolua ${CMAKE_CURRENT_SOURCE_DIR}/${MODULE_NAME}.pkg
- )
- SET_SOURCE_FILES_PROPERTIES("${OUTPUT_FILE_NAME}" PROPERTIES GENERATED TRUE)
-ENDMACRO(TOLUA_FILE)
-
-# Process all the needed modules.
-TOLUA_FILE(monster w_mnster.c)
-TOLUA_FILE(player w_player.c)
-TOLUA_FILE(player_c w_play_c.c)
-TOLUA_FILE(z_pack w_z_pack.c)
-TOLUA_FILE(object w_obj.c)
-TOLUA_FILE(util w_util.c)
-TOLUA_FILE(spells w_spells.c)
-TOLUA_FILE(quest w_quest.c)
-TOLUA_FILE(dungeon w_dun.c)
-
# 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})
+ADD_EXECUTABLE(tome ${EXECUTABLE_OPTIONS} ${SRCS_PROGRAM})
+TARGET_LINK_LIBRARIES(tome game squelch ${LIBS})
+
+# test harness executable
+ADD_EXECUTABLE(harness ${EXECUTABLE_OPTIONS} ${SRCS_TESTS})
+TARGET_LINK_LIBRARIES(harness game squelch ${LIBS})
# Installation
INSTALL(TARGETS tome
diff --git a/src/ability_type.hpp b/src/ability_type.hpp
new file mode 100644
index 00000000..ea8a921d
--- /dev/null
+++ b/src/ability_type.hpp
@@ -0,0 +1,27 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * Abilities.
+ */
+struct ability_type
+{
+ const char *name; /* Name */
+ char *desc; /* Description */
+
+ const char *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/ability_type_fwd.hpp b/src/ability_type_fwd.hpp
new file mode 100644
index 00000000..bade8638
--- /dev/null
+++ b/src/ability_type_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct ability_type;
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_entry.hpp b/src/alloc_entry.hpp
new file mode 100644
index 00000000..41ec3b66
--- /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; /* The actual index */
+
+ byte level; /* Base dungeon level */
+ byte prob1; /* Probability, pass 1 */
+ byte prob2; /* Probability, pass 2 */
+ byte prob3; /* 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..7a4340aa
--- /dev/null
+++ b/src/artifact_type.hpp
@@ -0,0 +1,60 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * 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; /* Artifact name */
+ char *text; /* Artifact description */
+
+ 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 ?*/
+};
diff --git a/src/artifact_type_fwd.hpp b/src/artifact_type_fwd.hpp
new file mode 100644
index 00000000..f3862d5a
--- /dev/null
+++ b/src/artifact_type_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct artifact_type;
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..f3897496 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,58 @@
* not for profit purposes provided that this copyright and statement are
* included in all such copies.
*/
-
-#include "angband.h"
+#include "birth.hpp"
+#include "birth.h"
+
+#include "ability_type.hpp"
+#include "artifact_type.hpp"
+#include "corrupt.hpp"
+#include "cmd4.hpp"
+#include "cmd5.hpp"
+#include "dungeon_info_type.hpp"
+#include "files.h"
+#include "files.hpp"
+#include "gods.hpp"
+#include "help.hpp"
+#include "hist_type.hpp"
+#include "hooks.hpp"
+#include "init2.hpp"
+#include "mimic.hpp"
+#include "messages.hpp"
+#include "meta_class_type.hpp"
+#include "modules.hpp"
+#include "monster2.hpp"
+#include "monster_race.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_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 "trap_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 <string>
/*
* How often the autoroller will update the display and pause
@@ -55,7 +101,7 @@ static s32b auto_round;
static s32b last_round;
/* Human */
-static char *human_syllable1[] =
+static const char *human_syllable1[] =
{
"Ab", "Ac", "Ad", "Af", "Agr", "Ast", "As", "Al", "Adw", "Adr", "Ar",
"B", "Br", "C", "Cr", "Ch", "Cad", "D", "Dr", "Dw", "Ed", "Eth", "Et",
@@ -65,7 +111,7 @@ static char *human_syllable1[] =
"Tr", "Th", "V", "Y", "Z", "W", "Wic",
};
-static char *human_syllable2[] =
+static const char *human_syllable2[] =
{
"a", "ae", "au", "ao", "are", "ale", "ali", "ay", "ardo", "e", "ei",
"ea", "eri", "era", "ela", "eli", "enda", "erra", "i", "ia", "ie",
@@ -73,7 +119,7 @@ static char *human_syllable2[] =
"ore", "u", "y",
};
-static char *human_syllable3[] =
+static const char *human_syllable3[] =
{
"a", "and", "b", "bwyn", "baen", "bard", "c", "ctred", "cred", "ch",
"can", "d", "dan", "don", "der", "dric", "dfrid", "dus", "f", "g",
@@ -92,7 +138,7 @@ static char *human_syllable3[] =
*/
static void create_random_name(int race, char *name)
{
- char *syl1, *syl2, *syl3;
+ const char *syl1, *syl2, *syl3;
int idx;
@@ -183,12 +229,6 @@ static void save_prev_data(void)
}
previous_char.luck = p_ptr->luck_base;
- /* Save the chaos patron */
- previous_char.chaos_patron = p_ptr->chaos_patron;
-
- /* Save the weapon specialty */
- previous_char.weapon = 0;
-
/* Save the history */
for (i = 0; i < 4; i++)
{
@@ -223,12 +263,6 @@ static void load_prev_data(bool_ save)
}
temp.luck = p_ptr->luck_base;
- /* Save the chaos patron */
- temp.chaos_patron = p_ptr->chaos_patron;
-
- /* Save the weapon specialty */
- temp.weapon = 0;
-
/* Save the history */
for (i = 0; i < 4; i++)
{
@@ -254,9 +288,6 @@ static void load_prev_data(bool_ save)
p_ptr->luck_base = previous_char.luck;
p_ptr->luck_max = previous_char.luck;
- /* Load the chaos patron */
- p_ptr->chaos_patron = previous_char.chaos_patron;
-
/* Load the history */
for (i = 0; i < 4; i++)
{
@@ -281,12 +312,6 @@ static void load_prev_data(bool_ save)
}
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++)
{
@@ -341,22 +366,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++;
- }
}
}
@@ -425,25 +438,11 @@ static void get_stats(void)
/* Obtain a "bonus" for "race" and "class" */
bonus = rp_ptr->r_adj[i] + rmp_ptr->r_adj[i] + cp_ptr->c_adj[i];
- /* Variable stat maxes */
- if (p_ptr->maximize)
- {
- /* Start fully healed */
- p_ptr->stat_cur[i] = p_ptr->stat_max[i];
+ /* 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;
@@ -463,12 +462,6 @@ static void get_extra(void)
{
int i, j, min_value, max_value;
-#ifdef SHOW_LIFE_RATE
-
- int percent;
-
-#endif
-
/* Level one */
p_ptr->max_plv = p_ptr->lev = 1;
@@ -476,11 +469,8 @@ static void get_extra(void)
/* 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;
+ /* Initialize quest */
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;
@@ -521,16 +511,6 @@ static void get_extra(void)
p_ptr->tactic = 4;
p_ptr->movement = 4;
-
-#ifdef SHOW_LIFE_RATE
-
- percent = (int)(((long)player_hp[PY_MAX_LEVEL - 1] * 200L) /
- (p_ptr->hitdie + ((PY_MAX_LEVEL - 1) * p_ptr->hitdie)));
-
- msg_format("Current Life Rating is %d/100.", percent);
- msg_print(NULL);
-
-#endif /* SHOW_LIFE_RATE */
}
@@ -572,7 +552,7 @@ static void get_history(void)
while ((chart != bg[i].chart) || (roll > bg[i].roll)) i++;
/* Acquire the textual history */
- (void)strcat(buf, bg[i].info + rp_text);
+ (void)strcat(buf, bg[i].info);
/* Add in the social class */
social_class += (int)(bg[i].bonus) - 50;
@@ -641,7 +621,7 @@ static void get_history(void)
/*
* Fill the random_artifacts array with relevant info.
*/
-errr init_randart(void)
+static errr init_randart(void)
{
int i;
@@ -822,30 +802,20 @@ static void player_wipe(void)
{
int i, j;
- bool_ *powers;
- bool_ *corruptions;
-
/* 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);
+ static_assert(std::is_pod<player_type>::value, "Cannot memset non-POD type");
+ memset(p_ptr, 0, sizeof(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++)
{
@@ -872,12 +842,12 @@ static void player_wipe(void)
}
/* Wipe the quests */
- for (i = 0; i < MAX_Q_IDX_INIT; i++)
+ for (i = 0; i < MAX_Q_IDX; i++)
{
quest[i].status = QUEST_STATUS_UNTAKEN;
- for (j = 0; j < 4; j++)
+ for (auto &quest_data : quest[i].data)
{
- quest[i].data[j] = 0;
+ quest_data = 0;
}
}
@@ -922,9 +892,6 @@ static void player_wipe(void)
/* Reset "aware" */
k_ptr->aware = FALSE;
- /* Reset "know" */
- k_ptr->know = FALSE;
-
/* Reset "artifact" */
k_ptr->artifact = 0;
}
@@ -956,13 +923,6 @@ 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;
@@ -1001,12 +961,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;
@@ -1042,16 +996,20 @@ 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 (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;
}
@@ -1083,6 +1041,35 @@ void outfit_obj(int tv, int sv, int pval, int dd, int ds)
/*
+ * Give the player an object.
+ */
+static void player_outfit_object(int qty, int tval, int sval)
+{
+ object_type forge;
+ object_type *q_ptr = &forge;
+ object_prep(q_ptr, lookup_kind(tval, sval));
+ q_ptr->number = qty;
+ object_aware(q_ptr);
+ object_known(q_ptr);
+ (void)inven_carry(q_ptr, FALSE);
+}
+
+
+/*
+ * Give player a spell book.
+ */
+static void player_outfit_spellbook(cptr spell_name)
+{
+ object_type forge;
+ object_type *q_ptr = &forge;
+ object_prep(q_ptr, lookup_kind(TV_BOOK, 255));
+ q_ptr->pval = find_spell(spell_name);
+ q_ptr->ident |= IDENT_MENTAL | IDENT_KNOWN;
+ inven_carry(q_ptr, FALSE);
+}
+
+
+/*
* Init players with some belongings
*
* Having an item makes the player "aware" of its purpose.
@@ -1090,33 +1077,155 @@ void outfit_obj(int tv, int sv, int pval, int dd, int ds)
static void player_outfit(void)
{
int i;
+ cptr class_name = spp_ptr->title;
+ cptr 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);
+ }
+
+ /*
+ * Provide spell books
+ */
+ if (game_module_idx == MODULE_TOME)
+ {
+ if (streq(class_name, "Ranger"))
+ {
+ player_outfit_spellbook("Phase Door");
+ }
+ }
+ if (streq(class_name, "Geomancer"))
+ {
+ player_outfit_spellbook("Geyser");
+ }
+ if (streq(class_name, "Priest(Eru)"))
+ {
+ player_outfit_spellbook("See the Music");
+ }
+ if (streq(class_name, "Priest(Manwe)"))
+ {
+ player_outfit_spellbook("Manwe's Blessing");
}
+ if (streq(class_name, "Druid"))
+ {
+ player_outfit_spellbook("Charm Animal");
+ }
+ if (streq(class_name, "Dark-Priest"))
+ {
+ player_outfit_spellbook("Curse");
+ }
+ if (streq(class_name, "Paladin"))
+ {
+ player_outfit_spellbook("Divine Aim");
+ }
+ if (game_module_idx == MODULE_THEME)
+ {
+ /* Priests */
+ if (streq(class_name, "Stonewright"))
+ {
+ player_outfit_spellbook("Firebrand");
+ }
+ if (streq(class_name, "Priest(Varda)"))
+ {
+ player_outfit_spellbook("Light of Valinor");
+ }
+ if (streq(class_name, "Priest(Ulmo)"))
+ {
+ player_outfit_spellbook("Song of Belegaer");
+ }
+ if (streq(class_name, "Priest(Mandos)"))
+ {
+ player_outfit_spellbook("Tears of Luthien");
+ }
+
+ /* Dragons */
+ if (streq(subrace_name, "Red"))
+ {
+ player_outfit_spellbook("Globe of Light");
+ }
+ if (streq(subrace_name, "Black"))
+ {
+ player_outfit_spellbook("Geyser");
+ }
+ if (streq(subrace_name, "Green"))
+ {
+ player_outfit_spellbook("Noxious Cloud");
+ }
+ if (streq(subrace_name, "Blue"))
+ {
+ player_outfit_spellbook("Stone Skin");
+ }
+ if (streq(subrace_name, "White"))
+ {
+ player_outfit_spellbook("Sense Monsters");
+ }
+ if (streq(subrace_name, "Ethereal"))
+ {
+ player_outfit_spellbook("Recharge");
+ }
- process_hooks(HOOK_BIRTH_OBJECTS, "()");
+ /* Demons */
+ if (streq(subrace_name, "(Aewrog)"))
+ {
+ player_outfit_spellbook("Charm");
+ }
+ if (streq(subrace_name, "(Narrog)"))
+ {
+ player_outfit_spellbook("Phase Door");
+ }
+ /* Peace-mages */
+ if (streq(class_name, "Peace-mage"))
+ {
+ player_outfit_spellbook("Phase Door");
+ }
+
+ /* Wainriders */
+ if (streq(class_name, "Wainrider"))
+ {
+ player_outfit_spellbook("Curse");
+ }
+ }
+
+ if (streq(class_name, "Mimic"))
{
object_type forge;
object_type *q_ptr = &forge;
+
+ object_prep(q_ptr, lookup_kind(TV_CLOAK, SV_MIMIC_CLOAK));
+ q_ptr->pval2 = resolve_mimic_name("Mouse");
+ q_ptr->ident |= IDENT_MENTAL | IDENT_KNOWN;
+ inven_carry(q_ptr, FALSE);
+ }
+
+ if (game_module_idx == MODULE_THEME)
+ {
+ /* Give everyone a scroll of WoR. */
+ player_outfit_object(1, TV_SCROLL, SV_SCROLL_WORD_OF_RECALL);
+
+ /* Identify everything in pack. */
+ identify_pack_fully();
+ }
+
+ if (streq(rmp_ptr->title, "Vampire"))
+ {
+ player_gain_corruption(CORRUPT_VAMPIRE_TEETH);
+ player_gain_corruption(CORRUPT_VAMPIRE_STRENGTH);
+ player_gain_corruption(CORRUPT_VAMPIRE_VAMPIRE);
+ }
+
+ process_hooks_new(HOOK_BIRTH_OBJECTS, NULL, NULL);
+ meta_inertia_control_hook_birth_objects();
+
+ {
/* Hack -- Give the player some food */
- object_prep(q_ptr, lookup_kind(TV_FOOD, SV_FOOD_RATION));
- q_ptr->number = (byte)rand_range(3, 7);
- object_aware(q_ptr);
- object_known(q_ptr);
- (void)inven_carry(q_ptr, FALSE);
+ int qty = (byte)rand_range(3, 7);
+ player_outfit_object(qty, TV_FOOD, SV_FOOD_RATION);
}
{
@@ -1167,154 +1276,11 @@ static void player_outfit(void)
}
-/* Possible number(and layout) or random quests */
-#define MAX_RANDOM_QUESTS_TYPES ((8 * 3) + (8 * 1))
-int random_quests_types[MAX_RANDOM_QUESTS_TYPES] =
-{
- 1, 5, 6, 7, 10, 11, 12, 14, /* Princess type */
- 1, 5, 6, 7, 10, 11, 12, 14, /* Princess type */
- 1, 5, 6, 7, 10, 11, 12, 14, /* Princess type */
- 20, 13, 15, 16, 9, 17, 18, 8, /* Hero Sword Quest */
-};
-
-/* Enforce OoD monsters until this level */
-#define RQ_LEVEL_CAP 49
-
-static void gen_random_quests(int n)
-{
- int step, lvl, i, k;
- int old_type = dungeon_type;
-
- /* Factor dlev value by 1000 to keep precision */
- step = (98 * 1000) / n;
-
- lvl = step / 2;
-
- quest[QUEST_RANDOM].status = QUEST_STATUS_TAKEN;
-
- for (i = 0; i < n; i++)
- {
- monster_race *r_ptr = &r_info[2];
-
- int rl = (lvl / 1000) + 1;
-
- int min_level;
-
- int tries = 5000;
-
- random_quest *q_ptr = &random_quests[rl];
-
- int j;
-
- /* Find the appropriate dungeon */
- for (j = 0; j < max_d_idx; j++)
- {
- dungeon_info_type *d_ptr = &d_info[j];
-
- if (!(d_ptr->flags1 & DF1_PRINCIPAL)) continue;
-
- if ((d_ptr->mindepth <= rl) && (rl <= d_ptr->maxdepth))
- {
- dungeon_type = j;
- break;
- }
- }
-
- q_ptr->type = random_quests_types[rand_int(MAX_RANDOM_QUESTS_TYPES)];
-
- /* XXX XXX XXX Try until valid choice is found */
- while (tries)
- {
- bool_ ok;
-
- tries--;
-
- /* Random monster 5 - 10 levels out of depth */
- q_ptr->r_idx = get_mon_num(rl + 4 + randint(6));
-
- if (!q_ptr->r_idx) continue;
-
- r_ptr = &r_info[q_ptr->r_idx];
-
- /* Accept only monsters that can be generated */
- if (r_ptr->flags9 & RF9_SPECIAL_GENE) continue;
- if (r_ptr->flags9 & RF9_NEVER_GENE) continue;
-
- /* Accept only monsters that are not breeders */
- if (r_ptr->flags4 & RF4_MULTIPLY) continue;
-
- /* Forbid joke monsters */
- if (r_ptr->flags8 & RF8_JOKEANGBAND) continue;
-
- /* Accept only monsters that are not friends */
- if (r_ptr->flags7 & RF7_PET) continue;
-
- /* Refuse nazguls */
- if (r_ptr->flags7 & RF7_NAZGUL) continue;
-
- /* Accept only monsters that are not good */
- if (r_ptr->flags3 & RF3_GOOD) continue;
-
- /* Assume no explosion attacks */
- ok = TRUE;
-
- /* Reject monsters with exploding attacks */
- for (k = 0; k < 4; k++)
- {
- if (r_ptr->blow[k].method == RBM_EXPLODE) ok = FALSE;
- }
- if (!ok) continue;
-
- /* No mutliple uniques */
- if ((r_ptr->flags1 & RF1_UNIQUE) &&
- ((q_ptr->type != 1) || (r_ptr->max_num == -1))) continue;
-
- /* No single non uniques */
- if ((!(r_ptr->flags1 & RF1_UNIQUE)) && (q_ptr->type == 1)) continue;
-
- /* Level restriction */
- min_level = (rl > RQ_LEVEL_CAP) ? RQ_LEVEL_CAP : rl;
-
- /* Accept monsters matching the level restriction */
- if (r_ptr->level > min_level) break;
- }
-
- /* Arg could not find anything ??? */
- if (!tries)
- {
- if (wizard) message_add(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;
- }
-
- q_ptr->done = FALSE;
-
- if (wizard) message_add(MESSAGE_MSG,
- format("Quest for %d on lvl %d",
- q_ptr->r_idx, rl), TERM_RED);
- }
-
- lvl += step;
- }
-
- dungeon_type = old_type;
-}
-
int dump_classes(s16b *classes, int sel, u32b *restrictions)
{
int n = 0;
char buf[80];
- char *desc;
-
- cptr str;
-
- C_MAKE(desc, c_head->text_size, char);
/* Clean up */
clear_from(12);
@@ -1327,7 +1293,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,14 +1302,20 @@ 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, 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->flags1 & PR1_EXPERIMENTAL)
+ {
+ desc += "\nEXPERIMENTAL";
+ }
+
+ print_desc(desc.c_str());
if (!(restrictions[classes[n] / 32] & BIT(classes[n])) ||
cp_ptr->flags1 & PR1_EXPERIMENTAL)
@@ -1363,8 +1334,6 @@ int dump_classes(s16b *classes, int sel, u32b *restrictions)
n++;
}
- C_FREE(desc, c_head->text_size, char);
-
return (n);
}
@@ -1373,11 +1342,6 @@ int dump_specs(int sel)
int n = 0;
char buf[80];
- char *desc;
-
- cptr str;
-
- C_MAKE(desc, c_head->text_size, char);
/* Clean up */
clear_from(12);
@@ -1392,7 +1356,6 @@ int dump_specs(int sel)
/* Analyze */
p_ptr->pspec = n;
spp_ptr = &class_info[p_ptr->pclass].spec[p_ptr->pspec];
- str = spp_ptr->title + c_name;
if (sel == n)
{
@@ -1401,14 +1364,20 @@ int dump_specs(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, 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->flags1 & PR1_EXPERIMENTAL)
+ {
+ desc += "\nEXPERIMENTAL";
+ }
+
+ print_desc(desc.c_str());
if (spp_ptr->flags1 & PR1_EXPERIMENTAL)
c_put_str(TERM_BLUE, buf, 18 + (n / 4), 1 + 20 * (n % 4));
@@ -1424,8 +1393,6 @@ int dump_specs(int sel)
}
}
- C_FREE(desc, c_head->text_size, char);
-
return (n);
}
@@ -1434,11 +1401,6 @@ int dump_races(int sel)
int n = 0;
char buf[80];
- char *desc;
-
- cptr str;
-
- C_MAKE(desc, rp_head->text_size, char);
/* Clean up */
clear_from(12);
@@ -1450,7 +1412,6 @@ int dump_races(int sel)
/* Analyze */
p_ptr->prace = n;
rp_ptr = &race_info[p_ptr->prace];
- str = rp_ptr->title + rp_name;
if (sel == n)
{
@@ -1459,14 +1420,20 @@ 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);
/* 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->flags1 & PR1_EXPERIMENTAL)
+ {
+ desc += "\nEXPERIMENTAL";
+ }
+
+ print_desc(desc.c_str());
if (rp_ptr->flags1 & PR1_EXPERIMENTAL)
c_put_str(TERM_BLUE, buf, 18 + (n / 5), 1 + 15 * (n % 5));
@@ -1482,8 +1449,6 @@ int dump_races(int sel)
}
}
- C_FREE(desc, rp_head->text_size, char);
-
return (n);
}
@@ -1493,11 +1458,6 @@ int dump_rmods(int sel, int *racem, int max)
int n = 0;
char buf[80];
- char *desc;
-
- cptr str;
-
- C_MAKE(desc, rmp_head->text_size, char);
/* Clean up */
clear_from(12);
@@ -1510,7 +1470,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,16 +1479,22 @@ 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);
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->desc;
+ if (rmp_ptr->flags1 & PR1_EXPERIMENTAL)
+ {
+ desc += "\nEXPERIMENTAL";
+ }
+
+ print_desc(desc.c_str());
if (rmp_ptr->flags1 & PR1_EXPERIMENTAL)
c_put_str(TERM_BLUE, buf, 18 + (n / 5), 1 + 15 * (n % 5));
@@ -1545,8 +1510,6 @@ int dump_rmods(int sel, int *racem, int max)
}
}
- C_FREE(desc, rmp_head->text_size, char);
-
return (n);
}
@@ -1615,14 +1578,10 @@ static bool_ player_birth_aux_ask()
{
int i, k, n, v, sel;
- s32b tmp;
-
int racem[100], max_racem = 0;
u32b restrictions[2];
- cptr str;
-
char c;
char p2 = ')';
@@ -1632,8 +1591,6 @@ static bool_ player_birth_aux_ask()
s16b *class_types;
- s32b allow_quest;
-
/*** Intro ***/
/* Clear screen */
@@ -1711,10 +1668,9 @@ static bool_ player_birth_aux_ask()
/* 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);
+ strnfmt(buf, 200, "%c%c %s", I2A(n), p2, sp_ptr->title);
put_str(buf, 21 + (n / 5), 2 + 15 * (n % 5));
}
@@ -1747,10 +1703,9 @@ static bool_ player_birth_aux_ask()
/* 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);
+ c_put_str(TERM_L_BLUE, sp_ptr->title, 3, 9);
/* Clean up */
clear_from(15);
@@ -1772,7 +1727,6 @@ static bool_ player_birth_aux_ask()
/* Extra info */
Term_putstr(5, 16, -1, TERM_WHITE,
"Your 'race' determines various intrinsic factors and bonuses.");
- hack_corruption = FALSE;
/* Dump races */
sel = 0;
@@ -1795,7 +1749,10 @@ static bool_ player_birth_aux_ask()
}
k = (islower(c) ? A2I(c) : -1);
if ((k >= 0) && (k < n)) break;
- if (c == '?') exec_lua(format("ingame_help('select_context', 'race', '%s')", race_info[sel].title + rp_name));
+ if (c == '?')
+ {
+ help_race(race_info[sel].title);
+ }
else if (c == '=')
{
screen_save();
@@ -1840,10 +1797,9 @@ 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, 4, 9);
/* Get a random name */
if (!do_quick_start) create_random_name(p_ptr->prace, player_name);
@@ -1918,7 +1874,10 @@ static bool_ player_birth_aux_ask()
while (!(BIT(racem[k]) & rmp_ptr->choice[racem[k] / 32]));
break;
}
- else if (c == '?') exec_lua(format("ingame_help('select_context', 'subrace', '%s')", race_mod_info[racem[sel]].title + rmp_name));
+ else if (c == '?')
+ {
+ help_subrace(race_mod_info[racem[sel]].title);
+ }
k = (islower(c) ? A2I(c) : -1);
if ((k >= 0) && (k < max_racem) &&
@@ -2061,7 +2020,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();
@@ -2140,7 +2102,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 +2150,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, 5, 9);
/* Clean up */
clear_from(15);
@@ -2200,22 +2164,23 @@ static bool_ player_birth_aux_ask()
p_ptr->pgod = k;
set_grace(previous_char.grace);
}
- else if (PRACE_FLAG(PR1_NO_GOD))
+ else if (race_flags1_p(PR1_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 +2208,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 +2221,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 +2265,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_flags1_p(PR1_GOD_FRIEND))
{
set_grace(200);
}
@@ -2335,10 +2299,9 @@ 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;
+ p_ptr->astral = (race_flags2_p(PR2_ASTRAL)) ? TRUE : FALSE;
/*
* A note by pelpel. (remove this please)
@@ -2354,23 +2317,16 @@ static bool_ player_birth_aux_ask()
/* Set the recall dungeon accordingly */
- call_lua("get_module_info", "(s)", "d", "base_dungeon", &tmp);
- dungeon_type = tmp;
+ dungeon_type = DUNGEON_BASE;
p_ptr->recall_dungeon = dungeon_type;
max_dlv[dungeon_type] = d_info[dungeon_type].mindepth;
if (p_ptr->astral)
{
- s32b x, y, astral_dun;
-
- call_lua("get_module_info", "(s)", "d", "astral_dungeon", &astral_dun);
- dungeon_type = astral_dun;
-
/* Somewhere in the misty mountains */
- call_lua("get_module_info", "(s)", "d", "astral_wild_x", &x);
- call_lua("get_module_info", "(s)", "d", "astral_wild_y", &y);
- p_ptr->wilderness_x = x;
- p_ptr->wilderness_y = y;
+ dungeon_type = DUNGEON_ASTRAL;
+ p_ptr->wilderness_x = DUNGEON_ASTRAL_WILD_X;
+ p_ptr->wilderness_y = DUNGEON_ASTRAL_WILD_Y;
}
/* Clean up */
@@ -2379,8 +2335,7 @@ static bool_ player_birth_aux_ask()
/*** User enters number of quests ***/
/* Heino Vander Sanden and Jimmy De Laet */
- call_lua("get_module_info", "(s)", "d", "rand_quest", &allow_quest);
- if (!ironman_rooms && allow_quest)
+ if (!ironman_rooms)
{
if (do_quick_start)
{
@@ -2437,16 +2392,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;
@@ -2539,12 +2491,6 @@ static bool_ player_birth_aux_point(void)
/* 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 +2504,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];
@@ -2700,8 +2630,6 @@ static bool_ player_birth_aux_auto()
char inp[80];
-#ifdef ALLOW_AUTOROLLER
-
/* Initialize */
if (autoroll)
{
@@ -2802,8 +2730,6 @@ static bool_ player_birth_aux_auto()
}
}
-#endif /* ALLOW_AUTOROLLER */
-
/* Roll */
while (TRUE)
{
@@ -2821,7 +2747,7 @@ static bool_ player_birth_aux_auto()
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);
+ c_put_str(TERM_L_BLUE, spp_ptr->title, 5, 9);
/* Label stats */
put_str("STR:", 2 + A_STR, 61);
@@ -2896,17 +2822,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;
}
}
@@ -2931,12 +2848,6 @@ static bool_ player_birth_aux_auto()
/* 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)
{
@@ -3360,17 +3271,14 @@ void player_birth(void)
select_default_melee();
/* Make a note file if that option is set */
- if (take_notes)
- {
- add_note_type(NOTE_BIRTH);
- }
+ add_note_type(NOTE_BIRTH);
/* Note player birth in the message recall */
- message_add(MESSAGE_MSG, " ", TERM_L_BLUE);
- message_add(MESSAGE_MSG, " ", TERM_L_BLUE);
- message_add(MESSAGE_MSG, "====================", TERM_L_BLUE);
- message_add(MESSAGE_MSG, " ", TERM_L_BLUE);
- message_add(MESSAGE_MSG, " ", TERM_L_BLUE);
+ message_add(" ", TERM_L_BLUE);
+ message_add(" ", TERM_L_BLUE);
+ message_add("====================", TERM_L_BLUE);
+ message_add(" ", TERM_L_BLUE);
+ message_add(" ", TERM_L_BLUE);
/* Hack -- outfit the player */
player_outfit();
@@ -3415,7 +3323,10 @@ void player_birth(void)
}
d_ptr->t_level[num] = lev;
- if (wizard) message_add(MESSAGE_MSG, format("Random dungeon town: d_idx:%d, lev:%d", i, lev), TERM_WHITE);
+ if (wizard)
+ {
+ message_add(format("Random dungeon town: d_idx:%d, lev:%d", i, lev), TERM_WHITE);
+ }
/* Create the town */
init_town(d_ptr->t_idx[num], d_ptr->t_level[num]);
@@ -3458,9 +3369,6 @@ void player_birth(void)
wild_map[j][i].known = FALSE;
}
}
-
- /* Select bounty monsters. */
- select_bounties();
}
@@ -3488,9 +3396,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");
@@ -3561,9 +3466,6 @@ int load_savefile_names()
strncpy(player_base, savefile_names[max], 32);
process_player_name(TRUE);
- /* File type is 'SAVE' */
- FILE_TYPE(FILE_TYPE_SAVE);
-
/* Try to open the savefile */
fd = fd_open(savefile, O_RDONLY);
@@ -3600,9 +3502,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");
@@ -3616,7 +3515,7 @@ void save_savefile_names()
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,
+ spp_ptr->title,
(!death) ? "alive" : "dead");
for (i = 0; i < max; i++)
@@ -3694,7 +3593,7 @@ savefile_try_again:
{
s32b can_use;
- call_lua("module_savefile_loadable", "(s)", "d", savefile_module[k], &can_use);
+ can_use = module_savefile_loadable(savefile_module[k]);
if (can_use)
{
savefile_idx[m++] = k;
diff --git a/src/birth.h b/src/birth.h
new file mode 100644
index 00000000..41620bfa
--- /dev/null
+++ b/src/birth.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#include "h-basic.h"
+
+// C linkage required for these functions since main-* code uses them.
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern bool_ no_begin_screen;
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/src/birth.hpp b/src/birth.hpp
new file mode 100644
index 00000000..fb036ecc
--- /dev/null
+++ b/src/birth.hpp
@@ -0,0 +1,9 @@
+#pragma once
+
+#include "h-basic.h"
+
+extern void print_desc_aux(cptr txt, int y, int x);
+extern void save_savefile_names(void);
+extern bool_ begin_screen(void);
+extern void get_height_weight(void);
+extern void player_birth(void);
diff --git a/src/birther.hpp b/src/birther.hpp
new file mode 100644
index 00000000..f517fb9d
--- /dev/null
+++ b/src/birther.hpp
@@ -0,0 +1,35 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * Player information during the birth process.
+ */
+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;
+
+ char history[4][60];
+
+ bool_ quick_ok;
+};
diff --git a/src/bldg.c b/src/bldg.cc
index 48e94e9f..7095e8c3 100644
--- a/src/bldg.c
+++ b/src/bldg.cc
@@ -13,10 +13,34 @@
* 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 "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 "owner_type.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,7 +49,7 @@ 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 *s_ptr, int state)
{
owner_type *ow_ptr = &ow_info[s_ptr->owner];
@@ -96,12 +120,10 @@ void show_building(store_type *s_ptr)
store_info_type *st_ptr = &st_info[s_ptr->st_idx];
- store_action_type *ba_ptr;
-
for (i = 0; i < 6; i++)
{
- ba_ptr = &ba_info[st_ptr->actions[i]];
+ store_action_type *ba_ptr = &ba_info[st_ptr->actions[i]];
if (ba_ptr->letter != '.')
{
@@ -176,130 +198,13 @@ void show_building(store_type *s_ptr)
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);
+ strnfmt(tmp_str, 80, ") %s %s", ba_ptr->name, buff);
c_put_str(action_color, tmp_str, 21 + (i / 2), 2 + 17 + (30 * (i % 2)));
}
}
}
-/* reset timed flags */
-static void reset_tim_flags()
-{
- p_ptr->fast = 0; /* Timed -- Fast */
- p_ptr->slow = 0; /* Timed -- Slow */
- p_ptr->blind = 0; /* Timed -- Blindness */
- p_ptr->paralyzed = 0; /* Timed -- Paralysis */
- p_ptr->confused = 0; /* Timed -- Confusion */
- p_ptr->afraid = 0; /* Timed -- Fear */
- p_ptr->image = 0; /* Timed -- Hallucination */
- p_ptr->poisoned = 0; /* Timed -- Poisoned */
- p_ptr->cut = 0; /* Timed -- Cut */
- p_ptr->stun = 0; /* Timed -- Stun */
-
- p_ptr->protevil = 0; /* Timed -- Protection */
- p_ptr->protgood = 0; /* Timed -- Protection */
- p_ptr->invuln = 0; /* Timed -- Invulnerable */
- p_ptr->hero = 0; /* Timed -- Heroism */
- p_ptr->shero = 0; /* Timed -- Super Heroism */
- p_ptr->shield = 0; /* Timed -- Shield Spell */
- p_ptr->blessed = 0; /* Timed -- Blessed */
- p_ptr->tim_invis = 0; /* Timed -- Invisibility */
- p_ptr->tim_infra = 0; /* Timed -- Infra Vision */
-
- p_ptr->oppose_acid = 0; /* Timed -- oppose acid */
- p_ptr->oppose_elec = 0; /* Timed -- oppose lightning */
- p_ptr->oppose_fire = 0; /* Timed -- oppose heat */
- p_ptr->oppose_cold = 0; /* Timed -- oppose cold */
- p_ptr->oppose_pois = 0; /* Timed -- oppose poison */
-
- p_ptr->confusing = 0; /* Touch of Confusion */
-}
-
-
-/*
- * arena commands
- */
-static void arena_comm(int cmd)
-{
- char tmp_str[80];
-
- monster_race *r_ptr;
-
- cptr name;
-
-
- switch (cmd)
- {
- case BACT_ARENA:
- {
- if (p_ptr->arena_number == MAX_ARENA_MONS)
- {
- clear_bldg(5, 19);
- prt(" Arena Victor!", 5, 0);
- prt("Congratulations! You have defeated all before you.", 7, 0);
- prt("For that, receive the prize: 10,000 gold pieces", 8, 0);
- prt("", 10, 0);
- prt("", 11, 0);
- p_ptr->au += 10000;
- msg_print("Press the space bar to continue");
- msg_print(NULL);
- p_ptr->arena_number++;
- }
- else if (p_ptr->arena_number > MAX_ARENA_MONS)
- {
- msg_print("You enter the arena briefly and bask in your glory.");
- msg_print(NULL);
- }
- else
- {
- p_ptr->inside_arena = TRUE;
- p_ptr->exit_bldg = FALSE;
- reset_tim_flags();
- p_ptr->leaving = TRUE;
- p_ptr->oldpx = p_ptr->px;
- p_ptr->oldpy = p_ptr->py;
- leave_bldg = TRUE;
- }
-
- break;
- }
-
- case BACT_POSTER:
- {
- if (p_ptr->arena_number == MAX_ARENA_MONS)
- msg_print("You are victorious. Enter the arena for the ceremony.");
- else if (p_ptr->arena_number > MAX_ARENA_MONS)
- msg_print("You have won against all foes.");
- else
- {
- r_ptr = &r_info[arena_monsters[p_ptr->arena_number]];
- name = (r_name + r_ptr->name);
- strnfmt(tmp_str, 80, "Do I hear any challenges against: %s", name);
- msg_print(tmp_str);
- msg_print(NULL);
- }
-
- break;
- }
-
- case BACT_ARENA_RULES:
- {
- /* Save screen */
- screen_save();
-
- /* Peruse the arena help file */
- (void)show_file("arena.txt", NULL, 0, 0);
-
- /* Load screen */
- screen_load();
-
- break;
- }
- }
-}
-
-
/*
* display fruit for dice slots
*/
@@ -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_flags1_p(PR1_VAMPIRE)) || (p_ptr->mimic_form == resolve_mimic_name("Vampire")));
switch (cmd)
{
@@ -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(plots[plot]);
return (TRUE);
}
@@ -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, u32b f1, u32b f2, u32b f3, byte color)
{
char tmp_str[80];
@@ -1023,7 +897,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);
}
@@ -1033,34 +907,28 @@ static bool_ item_tester_hook_melee_weapon(object_type *o_ptr)
*/
static bool_ compare_weapons(void)
{
- 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 +939,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);
@@ -1223,380 +1091,6 @@ static bool_ research_item(void)
}
-/*
- * 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
@@ -1638,22 +1132,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)
{
@@ -1685,9 +1163,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 +1196,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:
{
@@ -1880,30 +1344,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 +1393,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)
@@ -2078,121 +1467,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..0daebbee
--- /dev/null
+++ b/src/bldg.hpp
@@ -0,0 +1,9 @@
+#pragma once
+
+#include "h-basic.h"
+#include "store_type_fwd.hpp"
+
+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 enter_quest(void);
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..5ff31019 100644
--- a/src/cave.c
+++ b/src/cave.cc
@@ -1,10 +1,30 @@
-/* File: cave.c */
-
-/* Purpose: low level dungeon routines -BEN- */
-
-
-#include "angband.h"
-
+#include "cave.hpp"
+
+#include "cave_type.hpp"
+#include "feature_type.hpp"
+#include "hook_enter_dungeon_in.hpp"
+#include "monster2.hpp"
+#include "monster_race.hpp"
+#include "monster_type.hpp"
+#include "object1.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 "trap_type.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
@@ -347,24 +367,16 @@ 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);
@@ -376,106 +388,69 @@ 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;
+ // Cached state which keeps a list of all the "live" monster race entries.
+ static std::vector<size_t> *instance = nullptr;
- switch (graphics_mode)
+ // First-time initialization
+ if (!instance)
{
- /* Text mode */
- case GRAPHICS_NONE:
- {
- n = strlen(image_monster_hack);
-
- /* Random symbol from set above */
- *cp = (image_monster_hack[rand_int(n)]);
-
- /* Random color */
- *ap = randint(15);
-
- break;
- }
-
- /* Normal graphics */
- default:
+ // Create the list of "live" indexes
+ instance = new std::vector<size_t>();
+ // Start at 1 to avoid 'player'
+ for (size_t i = 1; i < max_r_idx; 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);
+ // 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;
+}
-/*
- * Hack -- Legal object codes
- */
-static cptr image_object_hack = "?/|\\\"!$()_-=[]{},~";
-
-/*
- * Hardcoded IBM pseudo-graphics code points have been removed
- * for the same reason as stated above -- pelpel
- */
/*
- * Mega-Hack -- Hallucinatory object
+ * Generate visual for hallucinatory object
*/
static void image_object(byte *ap, char *cp)
{
- int n;
+ // Cached state which keeps a list of the "live" object_kind entries.
+ static std::vector<size_t> *instance = nullptr;
- switch (graphics_mode)
+ // 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 < max_k_idx; 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 +473,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))
{
@@ -594,7 +551,7 @@ 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];
@@ -866,60 +823,25 @@ 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;
-
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;
+ auto feat = c_ptr->feat;
/* Apply "mimic" field */
if (c_ptr->mimic)
@@ -932,12 +854,7 @@ void map_info(int y, int x, byte *ap, char *cp, byte *tap, char *tcp,
}
/* Access floor */
- f_ptr = &f_info[feat];
-
-
- /* Reset attr/char */
- *eap = 0;
- *ecp = 0;
+ feature_type *f_ptr = &f_info[feat];
/**** Layer 1 -- Terrain feature ****/
@@ -965,8 +882,7 @@ 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;
}
@@ -975,67 +891,39 @@ void map_info(int y, int x, byte *ap, char *cp, byte *tap, char *tcp,
if ((info & (CAVE_TRDT)) && (feat != FEAT_ILLUS_WALL))
{
/* Trap index */
- t_idx = c_ptr->t_idx;
+ auto t_idx = c_ptr->t_idx;
- if (use_graphics &&
- (t_info[t_idx].g_attr != 0) &&
- (t_info[t_idx].g_char != 0))
+ /*
+ * 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)
{
-
- 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;
- }
-
+ c = f_info[FEAT_TRAP].x_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;
+ /* 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;
+ /* 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;
+ tmp = dun_level + dungeon_type + feat;
- a = tmp % 16;
- }
- }
+ a = tmp % 16;
}
}
/**** Step 2 -- Apply special random effects ****/
- if (!avoid_other && !avoid_shimmer && attr_mutable)
+ if (!avoid_other && !avoid_shimmer)
{
/* Special terrain effect */
if (c_ptr->effect)
@@ -1069,8 +957,7 @@ void map_info(int y, int x, byte *ap, char *cp, byte *tap, char *tcp,
if (view_special_lite &&
((f_ptr->flags1 & (FF1_FLOOR | FF1_REMEMBER)) == FF1_FLOOR))
{
- if (!p_ptr->wild_mode && !(info & (CAVE_TRDT)) &&
- (attr_mutable || (graf_new && feat_supports_lighting(feat))))
+ if (!p_ptr->wild_mode && !(info & (CAVE_TRDT)))
{
/* Handle "seen" grids */
if (info & (CAVE_SEEN))
@@ -1078,62 +965,30 @@ void map_info(int y, int x, byte *ap, char *cp, byte *tap, char *tcp,
/* Only lit by "torch" light */
if (view_yellow_lite && !(info & (CAVE_GLOW)))
{
- if (graf_new)
- {
- /* Use a brightly lit tile */
- c += 2;
- }
- else
- {
- /* Use "yellow" */
- a = TERM_YELLOW;
- }
+ /* 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)
{
- 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];
}
}
}
@@ -1142,8 +997,7 @@ void map_info(int y, int x, byte *ap, char *cp, byte *tap, char *tcp,
else if (view_granite_lite &&
(f_ptr->flags1 & (FF1_NO_VISION | FF1_DOOR)))
{
- if (!p_ptr->wild_mode && !(info & (CAVE_TRDT)) &&
- (attr_mutable || (graf_new && feat_supports_lighting(feat))))
+ if (!p_ptr->wild_mode && !(info & (CAVE_TRDT)))
{
/* Handle "seen" grids */
if (info & (CAVE_SEEN))
@@ -1154,44 +1008,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)
{
- 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 +1051,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;
@@ -1234,15 +1060,10 @@ void map_info(int y, int x, byte *ap, char *cp, byte *tap, char *tcp,
if (feat != FEAT_MON_TRAP)
{
- 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];
/* Memorized objects */
if (o_ptr->marked)
@@ -1254,8 +1075,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 (!avoid_other && (k_info[o_ptr->k_idx].flags5 & TR5_ATTR_MULTI))
{
*ap = get_shimmer_color();
}
@@ -1275,14 +1095,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)
{
- 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 +1112,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 (!avoid_other && (k_info[o_ptr->k_idx].flags5 & TR5_ATTR_MULTI))
{
*ap = get_shimmer_color();
}
@@ -1309,30 +1126,6 @@ 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;
@@ -1347,16 +1140,6 @@ void map_info(int y, int x, byte *ap, char *cp, byte *tap, char *tcp,
*ap = a;
}
- /* Special attr/char codes */
- else if (!attr_mutable)
- {
- /* Use char */
- *cp = c;
-
- /* Use attr */
- *ap = a;
- }
-
/* Multi-hued monster */
else if (r_ptr->flags1 & (RF1_ATTR_MULTI))
{
@@ -1436,12 +1219,8 @@ void map_info(int y, int x, byte *ap, char *cp, byte *tap, char *tcp,
{
monster_race *r_ptr = &r_info[p_ptr->body_monster];
- /* Reset attr/char */
- *eap = 0;
- *ecp = 0;
-
/* Get the "player" attr */
- if (!avoid_other && attr_mutable && (r_ptr->flags1 & RF1_ATTR_MULTI))
+ if (!avoid_other && (r_ptr->flags1 & RF1_ATTR_MULTI))
{
a = get_shimmer_color();
}
@@ -1453,67 +1232,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 (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;
- }
+ int percent = p_ptr->chp * 10 / p_ptr->mhp;
- case GRAPHICS_OLD:
+ if (percent < 7)
{
- if (player_symbols)
- {
- a = BMP_FIRST_PC_CLASS + p_ptr->pclass;
- c = BMP_FIRST_PC_RACE + p_ptr->prace;
- }
-
- break;
+ c = I2D(percent);
+ if (percent < 3) a = TERM_L_RED;
}
-
- case GRAPHICS_ISO:
- case GRAPHICS_NEW:
- {
- if (p_ptr->pracem)
- {
- player_race_mod *rmp_ptr = &race_mod_info[p_ptr->pracem];
-
- /* Desired attr */
- *eap = rmp_ptr->g_attr;
-
- /* Desired char */
- *ecp = rmp_ptr->g_char;
- }
-
- /* +AKH 20020421 - Health dispay for graphics, too */
- if (player_char_health && (graphics_mode == GRAPHICS_NEW))
- {
- int percent = p_ptr->chp * 14 / p_ptr->mhp;
-
- if (percent < 10)
- {
- *eap = 10;
- *ecp = 32 + 14 - percent;
- }
- }
-
- break;
- }
-
}
/* Save the info */
@@ -1525,48 +1253,28 @@ 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;
-
byte a;
byte c;
- bool_ use_graphics_hack = use_graphics;
- byte graphics_mode_hack = graphics_mode;
-
-
- /* Temporarily disable graphics mode -- for some random effects XXX */
- use_graphics = FALSE;
- graphics_mode = GRAPHICS_NONE;
-
/**** Preparation ****/
/* Access the grid */
- c_ptr = &cave[y][x];
+ 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;
+ auto feat = c_ptr->feat;
/* Apply "mimic" field */
if (c_ptr->mimic)
@@ -1579,7 +1287,7 @@ void map_info_default(int y, int x, byte *ap, char *cp)
}
/* Access floor */
- f_ptr = &f_info[feat];
+ feature_type *f_ptr = &f_info[feat];
/**** Layer 1 -- Terrain feature ****/
@@ -1617,7 +1325,7 @@ void map_info_default(int y, int x, byte *ap, char *cp)
if ((info & (CAVE_TRDT)) && (feat != FEAT_ILLUS_WALL))
{
/* Trap index */
- t_idx = c_ptr->t_idx;
+ auto t_idx = c_ptr->t_idx;
/*
* If trap is set on a floor grid that is not
@@ -1781,15 +1489,10 @@ void map_info_default(int y, int x, byte *ap, char *cp)
if (feat != FEAT_MON_TRAP)
{
- 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 objects */
if (o_ptr->marked)
@@ -1822,14 +1525,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)
{
- 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 +1542,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].flags5 & TR5_ATTR_MULTI))
{
*ap = get_shimmer_color();
}
@@ -1856,8 +1556,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;
@@ -1968,10 +1666,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 +1675,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 +1704,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 +1755,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,12 +1772,11 @@ 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)
{
- 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;
}
}
@@ -2146,39 +1815,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);
}
}
@@ -2210,33 +1857,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);
}
}
@@ -2392,11 +2020,6 @@ 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;
@@ -2406,9 +2029,6 @@ void display_map(int *cy, int *cx)
/* 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
*/
@@ -2435,32 +2055,22 @@ void display_map(int *cy, int *cx)
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);
- }
-
- /* 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] = ' ';
+ // Nothing there.
+ ma.push_back(std::vector<byte>(wid + 2, TERM_WHITE));
+ mc.push_back(std::vector<char>(wid + 2, ' '));
- /* 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 +2089,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,54 +2141,12 @@ 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;
@@ -3203,38 +2771,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)
@@ -3292,8 +2828,6 @@ errr vinfo_init(void)
long m;
- vinfo_hack *hack;
-
int num_grids = 0;
int queue_head = 0;
@@ -3302,8 +2836,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 +2848,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 +2865,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 +2896,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 +2947,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 +3035,6 @@ errr vinfo_init(void)
}
- /* Kill hack */
- KILL(hack, vinfo_hack);
-
-
/* Success */
return (0);
}
@@ -3808,31 +3332,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 */
@@ -4109,7 +3614,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,8 +3621,8 @@ 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;
@@ -4287,32 +3791,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;
@@ -4548,12 +4026,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)
{
- 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;
}
}
@@ -4888,7 +4365,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 +4404,10 @@ void object_track(object_type *o_ptr)
*
* The first arg indicates a major disturbance, which affects search.
*
- * The second arg is currently unused, but could induce output flush.
- *
* All disturbance cancels repeated commands, resting, and running.
*/
-void disturb(int stop_search, int unused_flag)
+void disturb(int stop_search)
{
- /* Unused */
- unused_flag = unused_flag;
-
/* Cancel auto-commands */
/* command_new = 0; */
@@ -4946,7 +4418,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 +4428,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 */
@@ -4979,7 +4451,7 @@ void disturb(int stop_search, int unused_flag)
p_ptr->update |= (PU_BONUS);
/* Redraw the state */
- p_ptr->redraw |= (PR_STATE);
+ p_ptr->redraw |= (PR_FRAME);
}
/* Flush the input if requested */
@@ -4987,33 +4459,16 @@ void disturb(int stop_search, int unused_flag)
}
-/*
- * Hack -- Check if a level is a "quest" level
- */
-int is_quest(int level)
-{
- int i = random_quest_number();
-
- /* Check quests */
- if (p_ptr->inside_quest)
- return (p_ptr->inside_quest);
-
- if (i) return (QUEST_RANDOM);
-
- /* Nope */
- return (0);
-}
-
/*
* Return the index of the random quest on this level
* (or zero)
*/
-int random_quest_number()
+static int random_quest_number()
{
if ((dun_level >= 1) && (dun_level < MAX_RANDOM_QUEST) &&
- (dungeon_flags1 & DF1_PRINCIPAL) &&
- (random_quests[dun_level].type) &&
+ (dungeon_flags1 & DF1_PRINCIPAL) &&
+ (random_quests[dun_level].type) &&
(!random_quests[dun_level].done) &&
(!is_randhero(dun_level)))
{
@@ -5025,6 +4480,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 +4527,167 @@ 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)
+{
+ return (f_info[c->feat].flags1 & FF1_FLOOR) && (c->feat != FEAT_MON_TRAP);
+}
+
+
+
+/**
+ * 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)
+{
+ return
+ (f_info[c->feat].flags1 & FF1_FLOOR) &&
+ !(f_info[c->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-
+ */
+bool cave_sight_bold(int y, int x)
+{
+ return cave_sight_grid(&cave[y][x]);
+}
+
+bool cave_sight_grid(cave_type const *c)
+{
+ return !(f_info[c->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
+ */
+bool cave_clean_bold(int y, int x)
+{
+ return
+ (f_info[cave[y][x].feat].flags1 & FF1_FLOOR) &&
+ (cave[y][x].feat != FEAT_MON_TRAP) &&
+ (cave[y][x].o_idxs.empty()) &&
+ !(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
+ */
+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)
+{
+ return
+ (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_idxs.empty()) &&
+ (cave[y][x].m_idx == 0);
+}
+
+bool cave_naked_bold2(int y, int x)
+{
+ return
+ (f_info[cave[y][x].feat].flags1 & FF1_FLOOR) &&
+ (cave[y][x].feat != FEAT_MON_TRAP) &&
+ (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)
+{
+ return 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
+ */
+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..64f67dba
--- /dev/null
+++ b/src/cave.hpp
@@ -0,0 +1,55 @@
+#pragma once
+
+#include "h-basic.h"
+#include "cave_type_fwd.hpp"
+#include "object_type_fwd.hpp"
+
+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_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 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);
+extern int is_quest(int level);
+extern int new_effect(int type, int dam, int time, int cy, int cx, int rad, s32b flags);
+extern bool cave_floor_bold(int y, int x);
+extern bool cave_floor_grid(cave_type const *c);
+extern bool cave_plain_floor_bold(int y, int x);
+extern bool cave_plain_floor_grid(cave_type const *c);
+extern bool cave_sight_bold(int y, int x);
+extern bool cave_sight_grid(cave_type const *c);
+extern bool cave_clean_bold(int y, int x);
+extern bool cave_empty_bold(int y, int x);
+extern bool cave_naked_bold(int y, int x);
+extern bool cave_naked_bold2(int y, int x);
+extern bool cave_perma_bold(int y, int x);
+extern bool cave_perma_grid(cave_type const *c);
+extern bool player_has_los_bold(int y, int x);
+extern 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..958ace1d
--- /dev/null
+++ b/src/cave_type.hpp
@@ -0,0 +1,65 @@
+#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 t_idx = 0; /* trap index (in t_list) or zero */
+
+ 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..f4066915 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,47 @@
* 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_type.hpp"
+#include "files.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_type.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "options.hpp"
+#include "player_type.hpp"
+#include "quark.hpp"
+#include "skills.hpp"
+#include "spells1.hpp"
+#include "spells2.hpp"
+#include "spells3.hpp"
+#include "tables.hpp"
+#include "traps.hpp"
+#include "trap_type.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,7 +237,7 @@ 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);
+ auto const r_ptr = m_ptr->race();
u32b f1, f2, f3, f4, f5, esp;
@@ -524,30 +560,23 @@ s16b tot_dam_aux(object_type *o_ptr, int tdam, monster_type *m_ptr,
*/
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;
+ int 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 (int y = (p_ptr->py - 1); y <= (p_ptr->py + 1); y++)
{
- for (x = (p_ptr->px - 1); x <= (p_ptr->px + 1); x++)
+ for (int 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];
+ cave_type *c_ptr = &cave[y][x];
/* Invisible trap */
if ((c_ptr->t_idx != 0) && !(c_ptr->info & CAVE_TRDT))
@@ -559,7 +588,7 @@ void search(void)
msg_print("You have found a trap.");
/* Disturb */
- disturb(0, 0);
+ disturb(0);
}
/* Secret door */
@@ -574,20 +603,13 @@ void search(void)
lite_spot(y, x);
/* Disturb */
- disturb(0, 0);
+ disturb(0);
}
/* Scan all objects in the grid */
- for (this_o_idx = c_ptr->o_idx; this_o_idx;
- this_o_idx = next_o_idx)
+ 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];
/* Skip non-chests */
if (o_ptr->tval != TV_CHEST) continue;
@@ -605,7 +627,7 @@ void search(void)
object_known(o_ptr);
/* Notice it */
- disturb(0, 0);
+ disturb(0);
}
}
}
@@ -641,7 +663,7 @@ static void hit_trap(void)
/* Disturb the player */
- disturb(0, 0);
+ disturb(0);
/* Get the cave grid */
c_ptr = &cave[p_ptr->py][p_ptr->px];
@@ -652,7 +674,7 @@ static void hit_trap(void)
{
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);
+ t_info[c_ptr->t_idx].name);
}
}
}
@@ -660,10 +682,7 @@ static void hit_trap(void)
void touch_zap_player(monster_type *m_ptr)
{
- int aura_damage = 0;
-
- monster_race *r_ptr = race_inf(m_ptr);
-
+ auto r_ptr = m_ptr->race();
if (r_ptr->flags2 & (RF2_AURA_FIRE))
{
@@ -671,7 +690,7 @@ void touch_zap_player(monster_type *m_ptr)
{
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 */
@@ -696,7 +715,7 @@ void touch_zap_player(monster_type *m_ptr)
{
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 */
@@ -725,8 +744,6 @@ static void carried_monster_attack(s16b m_idx, bool_ *fear, bool_ *mdeath,
monster_race *r_ptr;
- monster_race *tr_ptr = race_inf(t_ptr);
-
int ap_cnt;
int ac, rlev, pt;
@@ -811,7 +828,7 @@ static void carried_monster_attack(s16b m_idx, bool_ *fear, bool_ *mdeath,
if (!effect || check_hit2(power, rlev, ac))
{
/* Always disturbing */
- disturb(1, 0);
+ disturb(1);
/* Describe the attack method */
switch (method)
@@ -984,7 +1001,7 @@ 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);
@@ -1147,6 +1164,7 @@ 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))
@@ -1204,7 +1222,7 @@ static void carried_monster_attack(s16b m_idx, bool_ *fear, bool_ *mdeath,
case RBM_CHARGE:
{
/* Disturb */
- disturb(1, 0);
+ disturb(1);
/* Message */
msg_format("%s misses %s.", sym_name, t_name);
@@ -1247,9 +1265,7 @@ static void incarnate_monster_attack(s16b m_idx, bool_ *fear, bool_ *mdeath,
{
monster_type *t_ptr = &m_list[m_idx];
- monster_race *r_ptr;
-
- monster_race *tr_ptr = race_inf(t_ptr);
+ auto tr_ptr = t_ptr->race();
int ap_cnt;
@@ -1268,7 +1284,7 @@ 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;
@@ -1324,13 +1340,13 @@ static void incarnate_monster_attack(s16b m_idx, bool_ *fear, bool_ *mdeath,
visible = TRUE;
/* Extract the attack "power" */
- effect = get_attack_power(effect);
+ power = get_attack_power(effect);
/* Monster hits */
if (!effect || check_hit2(power, rlev, ac))
{
/* Always disturbing */
- disturb(1, 0);
+ disturb(1);
/* Describe the attack method */
switch (method)
@@ -1503,7 +1519,7 @@ 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);
@@ -1723,7 +1739,7 @@ static void incarnate_monster_attack(s16b m_idx, bool_ *fear, bool_ *mdeath,
case RBM_CHARGE:
{
/* Disturb */
- disturb(1, 0);
+ disturb(1);
/* Message */
msg_format("You miss %s.", t_name);
@@ -1813,12 +1829,10 @@ 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 */
@@ -1891,12 +1905,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,12 +1924,11 @@ 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);
-
+ auto const r_ptr = m_ptr->race();
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;
@@ -1954,6 +1965,11 @@ 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)
@@ -2007,6 +2023,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))
@@ -2044,7 +2061,7 @@ 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;
@@ -2149,12 +2166,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;
@@ -2183,7 +2194,7 @@ void py_attack(int y, int x, int max_blow)
int weap;
/* Disturb the player */
- disturb(0, 0);
+ disturb(0);
if (r_info[p_ptr->body_monster].flags1 & RF1_NEVER_BLOW)
{
@@ -2209,15 +2220,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);
@@ -2295,7 +2300,10 @@ 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;
@@ -2437,7 +2445,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 +2472,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(MELKOR_CURSE, 100, 1);
if (lv >= 10)
{
@@ -2475,7 +2483,7 @@ void py_attack(int y, int x, int max_blow)
if (chance < 1) chance = 1;
if ((p_ptr->grace > 5000) && magik(chance))
{
- exec_lua(format("do_melkor_curse(%d)", c_ptr->m_idx));
+ do_melkor_curse(c_ptr->m_idx);
}
}
}
@@ -2672,7 +2680,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;
}
@@ -2733,127 +2741,6 @@ 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)
{
bool_ pass_wall;
@@ -2862,7 +2749,7 @@ bool_ player_can_enter(byte feature)
/* 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_flags1_p(PR1_SEMI_WRAITH)))
pass_wall = TRUE;
else
pass_wall = FALSE;
@@ -2900,7 +2787,7 @@ bool_ player_can_enter(byte feature)
pass_wall ||
(has_ability(AB_TREE_WALK)) ||
(p_ptr->mimic_form == resolve_mimic_name("Ent")) ||
- ((p_ptr->grace >= 9000) && (p_ptr->praying) && (p_ptr->pgod == GOD_YAVANNA)))
+ ((p_ptr->grace >= 9000) && praying_to(GOD_YAVANNA)))
return (TRUE);
}
@@ -2928,6 +2815,119 @@ bool_ player_can_enter(byte feature)
}
/*
+ * 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)
+{
+ 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);
+
+ /* 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);
+}
+
+/*
* Move player in the given direction, with the given "pickup" flag.
*
* This routine should (probably) always induce energy expenditure.
@@ -2944,7 +2944,7 @@ void move_player_aux(int dir, int do_pickup, int run, bool_ disarm)
monster_type *m_ptr;
- monster_race *r_ptr = &r_info[p_ptr->body_monster], *mr_ptr;
+ monster_race *r_ptr = &r_info[p_ptr->body_monster];
char m_name[80];
@@ -3096,11 +3096,27 @@ void move_player_aux(int dir, int do_pickup, int run, bool_ disarm)
}
/* Some hooks */
- if (process_hooks(HOOK_MOVE, "(d,d)", y, x)) return;
+ {
+ hook_move_in in = { y, x };
+ if (process_hooks_new(HOOK_MOVE, &in, NULL)) {
+ return; /* Prevent movement */
+ }
+ }
+
+ if (p_ptr->dripping_tread > 0)
+ {
+ geomancy_random_floor(y, x, FALSE);
+ p_ptr->dripping_tread -= 1;
+ if (p_ptr->dripping_tread == 0)
+ {
+ msg_print("You stop dripping raw elemental energies.");
+ }
+ }
+
/* Get the monster */
m_ptr = &m_list[c_ptr->m_idx];
- mr_ptr = race_inf(m_ptr);
+ auto const mr_ptr = m_ptr->race();
if (p_ptr->inventory[INVEN_WIELD].art_name)
{
@@ -3114,8 +3130,7 @@ void move_player_aux(int dir, int do_pickup, int run, bool_ disarm)
/* 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;
@@ -3167,13 +3182,6 @@ 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))
{
@@ -3188,7 +3196,7 @@ void move_player_aux(int dir, int do_pickup, int run, bool_ disarm)
oktomove = FALSE;
/* Disturb the player */
- disturb(0, 0);
+ disturb(0);
if (p_ptr->prob_travel)
{
@@ -3223,7 +3231,7 @@ void move_player_aux(int dir, int do_pickup, int run, bool_ disarm)
else
feat = 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,61 +3243,35 @@ 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;
+ int feat;
- if (c_ptr->mimic) feat = c_ptr->mimic;
- else
- feat = f_info[c_ptr->feat].mimic;
+ 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);
+ msg_format("There is %s.", f_info[feat].block);
- if (!(p_ptr->confused || p_ptr->stun || p_ptr->image))
- energy_use = 0;
- }
- else
- {
- do_cmd_tunnel_aux(y, x, dir);
- return;
- }
+ if (!(p_ptr->confused || p_ptr->stun || p_ptr->image))
+ energy_use = 0;
}
}
@@ -3297,20 +3279,6 @@ void move_player_aux(int dir, int do_pickup, int run, bool_ disarm)
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
@@ -3328,7 +3296,7 @@ void move_player_aux(int dir, int do_pickup, int run, bool_ disarm)
if (old_dtrap && !new_dtrap)
{
/* Disturb player */
- disturb(0, 0);
+ disturb(0);
/* but don't take a turn */
energy_use = 0;
@@ -3363,9 +3331,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);
@@ -3383,13 +3348,13 @@ void move_player_aux(int dir, int do_pickup, int run, bool_ disarm)
{
cmsg_print(TERM_VIOLET, "You leave a trap detected zone.");
if (running) msg_print(NULL);
- p_ptr->redraw |= (PR_DTRAP);
+ p_ptr->redraw |= (PR_FRAME);
}
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);
+ p_ptr->redraw |= (PR_FRAME);
}
/* Update stuff */
@@ -3402,16 +3367,16 @@ 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);
}
else
{
- msg_print(f_text + f_info[feat].text);
+ msg_print(f_info[feat].text);
}
/* Flush message while running */
@@ -3437,7 +3402,7 @@ void move_player_aux(int dir, int do_pickup, int run, bool_ disarm)
if (c_ptr->feat == FEAT_SHOP)
{
/* Disturb */
- disturb(0, 0);
+ disturb(0);
/* Hack -- Enter store */
command_new = '_';
@@ -3446,7 +3411,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);
@@ -3460,7 +3425,7 @@ void move_player_aux(int dir, int do_pickup, int run, bool_ disarm)
!(f_info[cave[y][x].feat].flags1 & FF1_DOOR))
{
/* Disturb */
- disturb(0, 0);
+ disturb(0);
if (!(c_ptr->info & (CAVE_TRDT)))
{
@@ -3479,7 +3444,7 @@ void move_player_aux(int dir, int do_pickup, int run, bool_ disarm)
else if (c_ptr->inscription)
{
/* Disturb */
- disturb(0, 0);
+ disturb(0);
msg_format("There is an inscription here: %s",
inscription_info[c_ptr->inscription].text);
@@ -3881,9 +3846,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 +3857,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 +3865,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 +3878,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);
@@ -4101,7 +4055,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 +4087,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))
@@ -4262,7 +4216,7 @@ void run_step(int dir)
msg_print("You cannot run in that direction.");
/* Disturb */
- disturb(0, 0);
+ disturb(0);
/* Done */
return;
@@ -4282,7 +4236,7 @@ void run_step(int dir)
if (run_test())
{
/* Disturb */
- disturb(0, 0);
+ disturb(0);
/* Done */
return;
@@ -4302,45 +4256,6 @@ void run_step(int dir)
/*
- * 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)
@@ -4353,7 +4268,7 @@ void do_cmd_pet(void)
char power_desc[36][80];
- bool_ flag, redraw;
+ bool_ flag;
int ask;
@@ -4432,80 +4347,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, "");
-
- /* Show list */
- redraw = TRUE;
-
- /* Save the screen */
- character_icky = TRUE;
- Term_save();
-
- prt("", y++, x);
+ /* Save the screen */
+ character_icky = TRUE;
+ Term_save();
- 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 +4443,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)
@@ -4788,35 +4675,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 +4713,6 @@ bool_ do_cmd_integrate_body()
p_ptr->wraith_form = FALSE;
p_ptr->disembodied = FALSE;
do_cmd_redraw();
-
- return TRUE;
}
/*
@@ -4962,18 +4843,17 @@ 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)
{
@@ -4984,34 +4864,28 @@ bool_ execute_inscription(byte i, byte y, byte x)
if (!(r_ptr->flags1 & RF1_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)
{
diff --git a/src/cmd1.hpp b/src/cmd1.hpp
new file mode 100644
index 00000000..3ae44ed2
--- /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"
+
+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 do_cmd_pet(void);
+extern void do_cmd_integrate_body();
+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);
diff --git a/src/cmd2.c b/src/cmd2.cc
index 2d05c125..cfdeab44 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,7 +6,55 @@
* included in all such copies.
*/
-#include "angband.h"
+#include "cmd2.hpp"
+
+#include "bldg.hpp"
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "cmd1.hpp"
+#include "dungeon_info_type.hpp"
+#include "feature_type.hpp"
+#include "files.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_type.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_kind.hpp"
+#include "options.hpp"
+#include "player_type.hpp"
+#include "skills.hpp"
+#include "spells1.hpp"
+#include "spells2.hpp"
+#include "spells3.hpp"
+#include "stats.hpp"
+#include "tables.hpp"
+#include "trap_type.hpp"
+#include "traps.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(void);
@@ -74,6 +118,17 @@ 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);
+}
+
/*
* Go up one level
@@ -93,7 +148,10 @@ void do_cmd_go_up(void)
c_ptr = &cave[p_ptr->py][p_ptr->px];
/* Can we ? */
- if (process_hooks(HOOK_STAIR, "(s)", "up")) return;
+ if (stair_hooks(STAIRS_UP))
+ {
+ return;
+ }
/* Normal up stairs */
if ((c_ptr->feat == FEAT_LESS) || (c_ptr->feat == FEAT_WAY_LESS))
@@ -318,7 +376,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)
@@ -454,10 +515,13 @@ void do_cmd_go_down(void)
dungeon_info_type *d_ptr = &d_info[c_ptr->special];
/* Do the lua scripts refuse ? ;) */
- if (process_hooks(HOOK_ENTER_DUNGEON, "(d)", c_ptr->special))
{
- dun_level = old_dun;
- return;
+ 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 +543,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);
}
else
{
@@ -519,7 +582,7 @@ void do_cmd_search(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;
@@ -538,31 +601,9 @@ void do_cmd_search(void)
*/
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);
- }
+ p_ptr->update |= (PU_BONUS);
+ p_ptr->redraw |= (PR_FRAME);
+ p_ptr->searching = !p_ptr->searching;
}
@@ -574,20 +615,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; */
@@ -711,7 +746,7 @@ static void chest_trap(int y, int x, s16b o_idx)
{
t_info[o_ptr->pval].ident = TRUE;
msg_format("You identified the trap as %s.",
- t_name + t_info[trap].name);
+ t_info[trap].name);
}
}
@@ -1100,8 +1135,7 @@ void do_cmd_open(void)
return;
}
- /* Option: Pick a direction */
- if (easy_open)
+ /* Pick a direction if there's an obvious target */
{
int num_doors, num_chests;
@@ -1135,7 +1169,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 +1224,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(0);
}
@@ -1270,8 +1301,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 +1332,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 +1377,7 @@ void do_cmd_close(void)
}
/* Cancel repeat unless we may continue */
- if (!more) disturb(0, 0);
+ if (!more) disturb(0);
}
@@ -1380,7 +1410,7 @@ static bool_ do_cmd_tunnel_test(int y, int x)
if (!(f_info[cave[y][x].feat].flags1 & FF1_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,7 +1464,7 @@ 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)
{
int skill_req = 0, skill_req_1pct = 0;
cave_type *c_ptr = &cave[y][x];
@@ -1471,7 +1501,7 @@ bool_ do_cmd_tunnel_aux(int y, int x, int dir)
/* Titanium */
if (f_ptr->flags1 & FF1_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,7 +1518,7 @@ 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 */
@@ -1513,7 +1543,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 +1623,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 +1657,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;
}
}
@@ -1658,7 +1688,7 @@ 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 */
@@ -1681,7 +1711,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;
}
}
@@ -1738,7 +1768,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;
@@ -1791,124 +1821,7 @@ 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(0);
}
@@ -1999,7 +1912,7 @@ static bool_ do_cmd_disarm_chest(int y, int x, s16b o_idx)
*
* Returns TRUE if repeated commands may continue
*/
-bool_ do_cmd_disarm_aux(int y, int x, int dir, int do_pickup)
+static bool_ do_cmd_disarm_aux(int y, int x, int dir, int do_pickup)
{
int i, j, power;
@@ -2018,9 +1931,13 @@ bool_ do_cmd_disarm_aux(int y, int x, int dir, int do_pickup)
/* Access trap name */
if (t_info[c_ptr->t_idx].ident)
- name = (t_name + t_info[c_ptr->t_idx].name);
+ {
+ name = t_info[c_ptr->t_idx].name;
+ }
else
+ {
name = "unknown trap";
+ }
/* Get the "disarm" factor */
i = p_ptr->skill_dis;
@@ -2119,8 +2036,7 @@ void do_cmd_disarm(void)
bool_ more = FALSE;
- /* Option: Pick a direction */
- if (easy_disarm)
+ /* Pick a direction if there's an obvious choice */
{
int num_traps, num_chests;
@@ -2145,7 +2061,7 @@ void do_cmd_disarm(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;
@@ -2204,7 +2120,7 @@ void do_cmd_disarm(void)
}
/* Cancel repeat unless told not to */
- if (!more) disturb(0, 0);
+ if (!more) disturb(0);
}
@@ -2309,7 +2225,7 @@ static bool_ do_cmd_bash_aux(int y, int x, int dir)
msg_print("You are off-balance.");
/* Hack -- Lose balance ala paralysis */
- (void)set_paralyzed(p_ptr->paralyzed + 2 + rand_int(2));
+ (void)set_paralyzed(2 + rand_int(2));
}
/* Result */
@@ -2356,7 +2272,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 +2329,7 @@ void do_cmd_bash(void)
}
/* Unless valid action taken, cancel bash */
- if (!more) disturb(0, 0);
+ if (!more) disturb(0);
}
@@ -2444,7 +2360,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;
@@ -2501,7 +2417,7 @@ void do_cmd_alter(void)
}
/* Cancel repetition unless we can continue */
- if (!more) disturb(0, 0);
+ if (!more) disturb(0);
}
@@ -2626,7 +2542,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;
@@ -2668,7 +2584,179 @@ static void do_cmd_walk_jump(int pickup, bool_ disarm)
}
/* Cancel repeat unless we may continue */
- if (!more) disturb(0, 0);
+ if (!more) disturb(0);
+}
+
+
+/*
+ * 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, 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);
}
@@ -2748,7 +2836,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;
@@ -2780,7 +2868,7 @@ void do_cmd_stay(int pickup)
if (c_ptr->feat == FEAT_SHOP)
{
/* Disturb */
- disturb(0, 0);
+ disturb(0);
/* Hack -- enter store */
command_new = '_';
@@ -2800,7 +2888,7 @@ void do_cmd_rest(void)
/* 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;
@@ -2870,7 +2958,7 @@ void do_cmd_rest(void)
p_ptr->update |= (PU_BONUS);
/* Redraw the state */
- p_ptr->redraw |= (PR_STATE);
+ p_ptr->redraw |= (PR_FRAME);
/* Handle stuff */
handle_stuff();
@@ -3052,8 +3140,6 @@ void do_cmd_fire(void)
char o_name[80];
- cptr q, s;
-
int msec = delay_factor * delay_factor * delay_factor;
@@ -3082,14 +3168,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);
@@ -3231,7 +3318,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 +3327,7 @@ void do_cmd_fire(void)
else
{
/* Pause anyway, for consistancy */
- Term_xtra(TERM_XTRA_DELAY, msec);
+ sleep_for(milliseconds(msec));
}
@@ -3250,7 +3337,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;
@@ -3461,7 +3548,7 @@ void do_cmd_fire(void)
*/
void do_cmd_throw(void)
{
- int dir, item;
+ int dir;
s32b special = 0;
@@ -3480,8 +3567,6 @@ void do_cmd_throw(void)
object_type *q_ptr;
- object_type *o_ptr;
-
bool_ hit_body = FALSE;
bool_ hit_wall = FALSE;
@@ -3494,20 +3579,20 @@ void do_cmd_throw(void)
int msec = delay_factor * delay_factor * delay_factor;
- cptr q, s;
-
- u32b f1, f2, f3, f4, f5, esp;
-
-
/* Get an item */
- q = "Throw which item? ";
- s = "You have nothing to throw.";
- if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return;
+ 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);
+ u32b f1, f2, f3, f4, f5, esp;
object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
/* Hack - Cannot throw away 'no drop' cursed items */
@@ -3647,7 +3732,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 +3741,7 @@ void do_cmd_throw(void)
else
{
/* Pause anyway, for consistancy */
- Term_xtra(TERM_XTRA_DELAY, msec);
+ sleep_for(milliseconds(msec));
}
@@ -3666,7 +3751,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;
@@ -3974,7 +4059,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 +4068,7 @@ void do_cmd_boomerang(void)
else
{
/* Pause anyway, for consistancy */
- Term_xtra(TERM_XTRA_DELAY, msec);
+ sleep_for(milliseconds(msec));
}
@@ -3993,7 +4078,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;
@@ -4150,7 +4235,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,188 +4244,16 @@ void do_cmd_boomerang(void)
else
{
/* Pause anyway, for consistancy */
- Term_xtra(TERM_XTRA_DELAY, msec);
+ sleep_for(milliseconds(msec));
}
}
}
-/*
- * Try to ``walk'' using phase door.
- */
-void do_cmd_unwalk()
-{
- int dir, y, x, feat;
-
- cave_type *c_ptr;
-
- bool_ more = FALSE;
-
-
- if (!get_rep_dir(&dir)) return;
-
- y = p_ptr->py + ddy[dir];
- x = p_ptr->px + ddx[dir];
-
- c_ptr = &cave[y][x];
- feat = c_ptr->feat;
-
- /* Must have knowledge to know feature XXX XXX */
- if (!(c_ptr->info & (CAVE_MARK))) feat = FEAT_NONE;
-
- /* Take a turn */
- energy_use = 100;
- energy_use *= (p_ptr->wild_mode) ? (5 * (MAX_HGT + MAX_WID) / 2) : 1;
-
-
- /* Allow repeated command */
- if (command_arg)
- {
- /* Set repeat count */
- command_rep = command_arg - 1;
-
- /* Redraw the state */
- p_ptr->redraw |= (PR_STATE);
-
- /* Cancel the arg */
- command_arg = 0;
- }
-
-
- /* Attack monsters */
- if (c_ptr->m_idx > 0)
- {
- /* Attack */
- py_attack(y, x, -1);
- }
-
- /* Exit the area */
- else if ((!dun_level) && (!p_ptr->wild_mode) &&
- ((x == 0) || (x == cur_wid - 1) || (y == 0) || (y == cur_hgt - 1)))
- {
- /* Can the player enter the grid? */
- if (player_can_enter(c_ptr->mimic))
- {
- /* Hack: move to new area */
- if ((y == 0) && (x == 0))
- {
- p_ptr->wilderness_y--;
- p_ptr->wilderness_x--;
- p_ptr->oldpy = cur_hgt - 2;
- p_ptr->oldpx = cur_wid - 2;
- ambush_flag = FALSE;
- }
-
- else if ((y == 0) && (x == MAX_WID - 1))
- {
- p_ptr->wilderness_y--;
- p_ptr->wilderness_x++;
- p_ptr->oldpy = cur_hgt - 2;
- p_ptr->oldpx = 1;
- ambush_flag = FALSE;
- }
-
- else if ((y == MAX_HGT - 1) && (x == 0))
- {
- p_ptr->wilderness_y++;
- p_ptr->wilderness_x--;
- p_ptr->oldpy = 1;
- p_ptr->oldpx = cur_wid - 2;
- ambush_flag = FALSE;
- }
-
- else if ((y == MAX_HGT - 1) && (x == MAX_WID - 1))
- {
- p_ptr->wilderness_y++;
- p_ptr->wilderness_x++;
- p_ptr->oldpy = 1;
- p_ptr->oldpx = 1;
- ambush_flag = FALSE;
- }
-
- else if (y == 0)
- {
- p_ptr->wilderness_y--;
- p_ptr->oldpy = cur_hgt - 2;
- p_ptr->oldpx = x;
- ambush_flag = FALSE;
- }
-
- else if (y == cur_hgt - 1)
- {
- p_ptr->wilderness_y++;
- p_ptr->oldpy = 1;
- p_ptr->oldpx = x;
- ambush_flag = FALSE;
- }
-
- else if (x == 0)
- {
- p_ptr->wilderness_x--;
- p_ptr->oldpx = cur_wid - 2;
- p_ptr->oldpy = y;
- ambush_flag = FALSE;
- }
-
- else if (x == cur_wid - 1)
- {
- p_ptr->wilderness_x++;
- p_ptr->oldpx = 1;
- p_ptr->oldpy = y;
- ambush_flag = FALSE;
- }
-
- p_ptr->leaving = TRUE;
-
- return;
- }
- }
-
- /* Hack -- Ignore weird terrain types. */
- else if (!cave_floor_grid(c_ptr))
- {
- teleport_player(10);
- }
-
- /* Enter quests */
- else if (((feat >= FEAT_QUEST_ENTER) && (feat <= FEAT_QUEST_UP)) ||
- ((feat >= FEAT_LESS) && (feat <= FEAT_MORE)))
- {
- move_player(dir, always_pickup, TRUE);
- more = FALSE;
- }
-
- /* Hack -- Ignore wilderness mofe. */
- else if (p_ptr->wild_mode)
- {
- /* Chance to not blink right */
- if (magik(15))
- {
- do
- {
- dir = rand_range(1, 9);
- }
- while (dir == 5);
- }
-
- move_player(dir, always_pickup, TRUE);
- }
-
- /* Walking semantics */
- else
- {
- teleport_player_directed(10, dir);
- }
-
- /* Cancel repetition unless we can continue */
- if (!more) disturb(0, 0);
-}
-
-
static bool_ tport_vertically(bool_ how)
{
- /* arena or quest -KMW- */
- if ((p_ptr->inside_arena) || (p_ptr->inside_quest))
+ /* quest? */
+ if (p_ptr->inside_quest)
{
msg_print("There is no effect.");
return (FALSE);
@@ -4542,13 +4455,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 +4469,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,6 +4489,43 @@ 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.
*/
@@ -4584,7 +4536,7 @@ void do_cmd_sacrifice(void)
/* Check valididty */
if ((on_what < FEAT_ALTAR_HEAD) || (on_what > FEAT_ALTAR_TAIL))
{
- show_god_info(FALSE);
+ show_god_info();
return;
}
else
@@ -4592,7 +4544,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 +4562,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 +4590,18 @@ void do_cmd_sacrifice(void)
}
else
{
+ /* Get an item */
int item;
- object_type *o_ptr;
+ if (!get_item(&item,
+ "Sacrifice which item? ",
+ "You have nothing to sacrifice.",
+ (USE_INVEN),
+ item_tester_hook_sacrificable))
+ {
+ return;
+ }
- /* Restrict choices to food */
- item_tester_hook = item_tester_hook_sacrifiable;
-
- /* Get an item */
- if (!get_item(&item, "Sacrifice which item? ", "You have nothing to sacrifice.", (USE_INVEN))) return;
- o_ptr = get_object(item);
+ object_type *o_ptr = get_object(item);
/* Piety for corpses is based on monster level */
if (o_ptr->tval == TV_CORPSE)
@@ -4657,7 +4612,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 +4621,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 +4637,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 +4753,16 @@ 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;
-
- 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,10 +4770,10 @@ 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;
@@ -4875,7 +4788,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 +4798,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 +4825,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 +4833,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 +4841,7 @@ void do_cmd_steal()
}
/* Accept that choice */
- item = monst_list[k];
+ item = objects[k];
done = TRUE;
break;
@@ -4966,17 +4879,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_flags1_p(PR1_EASE_STEAL))
{
s32b max_point;
@@ -4990,8 +4897,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 +4908,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 +4920,7 @@ void do_cmd_steal()
inven_carry(o_ptr, FALSE);
}
- /* Delete it */
+ /* Delete source item */
o_list[item].k_idx = 0;
}
@@ -5028,24 +4936,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 +4955,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 +5004,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..142238ab
--- /dev/null
+++ b/src/cmd2.hpp
@@ -0,0 +1,33 @@
+#pragma once
+
+#include "h-basic.h"
+#include "object_type_fwd.hpp"
+#include <vector>
+
+extern std::vector<s16b> show_monster_inven(int m_idx);
+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 void do_cmd_tunnel(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_immovable_special(void);
+extern void fetch(int dir, int wgt, bool_ require_los);
+extern void do_cmd_sacrifice(void);
+extern void do_cmd_steal(void);
diff --git a/src/cmd3.c b/src/cmd3.cc
index 02dbc1c4..59e61719 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,9 +5,43 @@
* 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 "gods.hpp"
+#include "hook_drop_in.hpp"
+#include "hook_wield_in.hpp"
+#include "hooks.hpp"
+#include "monster1.hpp"
+#include "monster_race.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_kind.hpp"
+#include "object_type.hpp"
+#include "options.hpp"
+#include "player_type.hpp"
+#include "quark.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 <memory>
+#include <utility>
/*
* Display p_ptr->inventory
@@ -28,16 +58,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();
@@ -89,16 +113,10 @@ void do_cmd_equip(void)
character_icky = TRUE;
Term_save();
- /* Hack -- show empty slots */
- item_tester_full = TRUE;
-
/* Display the equipment */
- show_equip();
+ show_equip_full();
- /* Hack -- undo the hack above */
- item_tester_full = FALSE;
-
- /* Build a prompt */
+ /* Show prompt */
{
s32b total_weight = calc_total_weight();
@@ -139,7 +157,7 @@ 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);
@@ -201,27 +219,27 @@ void do_cmd_wield(void)
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);
@@ -254,7 +272,13 @@ 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);
@@ -309,19 +333,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;
@@ -440,7 +451,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);
}
@@ -452,23 +463,18 @@ void do_cmd_wield(void)
*/
void do_cmd_takeoff(void)
{
- int item;
-
- object_type *o_ptr;
-
- cptr q, s;
-
-
/* Get an item */
- q = "Take off which item? ";
- s = "You are not wearing anything to take off.";
- if (!get_item(&item, q, s, (USE_EQUIP))) return;
+ 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))
@@ -490,7 +496,7 @@ void do_cmd_takeoff(void)
/* Recalculate hitpoint */
p_ptr->update |= (PU_HP);
- p_ptr->redraw |= (PR_MH);
+ p_ptr->redraw |= (PR_FRAME);
}
@@ -499,27 +505,24 @@ void do_cmd_takeoff(void)
*/
void do_cmd_drop(void)
{
- int item, amt = 1;
-
- object_type *o_ptr;
-
- u32b f1, f2, f3, f4, f5, esp;
-
- cptr q, s;
-
-
/* Get an item */
- q = "Drop which item? ";
- s = "You have nothing to drop.";
- if (!get_item(&item, q, s, (USE_EQUIP | USE_INVEN))) return;
+ 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_type *o_ptr = get_object(item);
+ u32b f1, f2, f3, f4, f5, esp;
object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
/* 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))
@@ -545,8 +548,8 @@ void do_cmd_drop(void)
}
}
-
/* See how many items */
+ int amt = 1;
if (o_ptr->number > 1)
{
/* Get a quantity */
@@ -569,37 +572,33 @@ void do_cmd_drop(void)
*/
void do_cmd_destroy(void)
{
- int item, amt = 1;
-
int old_number;
bool_ force = FALSE;
- object_type *o_ptr;
-
char o_name[80];
char out_val[160];
- cptr q, s;
-
- u32b f1, f2, f3, f4, f5, esp;
-
-
/* Hack -- force destruction */
if (command_arg > 0) force = TRUE;
/* Get an item */
- q = "Destroy which item? ";
- s = "You have nothing to destroy.";
- if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR | USE_AUTO))) return;
+ 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,17 +618,15 @@ 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;
+ u32b f1, f2, f3, f4, f5, esp;
object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
if ((f4 & TR4_CURSE_NO_DROP) && cursed_p(o_ptr))
@@ -678,7 +675,7 @@ void do_cmd_destroy(void)
/* Create an automatizer rule */
if (automatizer_create)
{
- automatizer_add_rule(o_ptr, TRUE);
+ automatizer_add_rule(o_ptr);
}
/*
@@ -705,24 +702,21 @@ void do_cmd_destroy(void)
*/
void do_cmd_observe(void)
{
- int item;
-
- object_type *o_ptr;
-
- char o_name[80];
-
- cptr q, s;
-
-
/* Get an item */
- q = "Examine which item? ";
- s = "You have nothing to examine.";
- if (!get_item(&item, q, s, (USE_EQUIP | USE_INVEN | USE_FLOOR))) return;
+ 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 */
@@ -740,20 +734,18 @@ void do_cmd_observe(void)
*/
void do_cmd_uninscribe(void)
{
- int item;
-
- object_type *o_ptr;
-
- cptr q, s;
-
-
/* Get an item */
- q = "Un-inscribe which item? ";
- s = "You have nothing to un-inscribe.";
- if (!get_item(&item, q, s, (USE_EQUIP | USE_INVEN | USE_FLOOR))) return;
+ 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)
@@ -781,26 +773,21 @@ void do_cmd_uninscribe(void)
*/
void do_cmd_inscribe(void)
{
- int item;
-
- object_type *o_ptr;
-
- char o_name[80];
-
- char out_val[80];
-
- cptr q, s;
-
-
/* Get an item */
- q = "Inscribe which item? ";
- s = "You have nothing to inscribe.";
- if (!get_item(&item, q, s, (USE_EQUIP | USE_INVEN | USE_FLOOR))) return;
+ 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 */
@@ -808,6 +795,7 @@ void do_cmd_inscribe(void)
msg_print(NULL);
/* Start with nothing */
+ char out_val[80];
strcpy(out_val, "");
/* Use old inscription */
@@ -818,7 +806,7 @@ void do_cmd_inscribe(void)
}
/* 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);
@@ -836,17 +824,15 @@ 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;
}
@@ -855,30 +841,25 @@ static bool_ item_tester_refill_lantern(object_type *o_ptr)
*/
static void do_cmd_refill_lamp(void)
{
- int item;
-
- object_type *o_ptr;
- object_type *j_ptr;
-
- cptr q, s;
-
-
- /* Restrict the choices */
- item_tester_hook = item_tester_refill_lantern;
-
/* Get an item */
- q = "Refill with which flask? ";
- s = "You have no flasks of oil.";
- if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return;
+ 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,14 +888,14 @@ 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;
}
@@ -923,31 +904,25 @@ static bool_ item_tester_refill_torch(object_type *o_ptr)
*/
static void do_cmd_refill_torch(void)
{
- int item;
-
- object_type *o_ptr;
-
- object_type *j_ptr;
-
- cptr q, s;
-
-
- /* Restrict the choices */
- item_tester_hook = item_tester_refill_torch;
-
/* Get an item */
- q = "Refuel with which torch? ";
- s = "You have no extra torches.";
- if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return;
+ 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;
@@ -1269,107 +1244,75 @@ 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);
- }
+ /* 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 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);
- }
-
+ /* Punt to index */
+ return w1 < w2;
+}
- /* Sort by monster experience */
- if (*why >= 1)
- {
- /* Extract experience */
- z1 = r_info[w1].mexp;
- z2 = r_info[w2].mexp;
+/**
+ * Sort by monster level.
+ */
+static bool compare_monster_level(int w1, int w2)
+{
+ /* Extract levels */
+ byte z1 = r_info[w1].level;
+ byte z2 = r_info[w2].level;
+
+ /* Compare levels */
+ if (z1 < z2) return true;
+ if (z1 > z2) return false;
+
+ /* Punt to monster experience. */
+ return compare_monster_experience(w1, w2);
+}
- /* Compare experience */
- if (z1 < z2) return (TRUE);
- if (z1 > z2) return (FALSE);
- }
+/**
+ * Sort by total number of kills
+ */
+static bool compare_total_kills(int w1, int w2)
+{
+ /* Extract total kills */
+ s16b z1 = r_info[w1].r_tkills;
+ s16b z2 = r_info[w2].r_tkills;
+ /* Compare total kills */
+ if (z1 < z2) return true;
+ if (z1 > z2) return false;
- /* Compare indexes */
- return (w1 <= w2);
+ /* Punt to monster level. */
+ return compare_monster_level(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;
-
+ /* 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 total number of kills. */
+ return compare_total_kills(w1, w2);
}
-
/*
* Hack -- Display the "name" and "attr/chars" of a monster race
*/
@@ -1404,18 +1347,16 @@ static void roff_top(int r_idx)
}
/* 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, "'):");
}
@@ -1435,7 +1376,7 @@ static void roff_top(int r_idx)
*/
void do_cmd_query_symbol(void)
{
- int i, n, r_idx;
+ int i, r_idx;
char sym, query;
@@ -1456,11 +1397,7 @@ 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, "
@@ -1507,11 +1444,9 @@ 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<u16b> who;
+ for (i = 1; i < max_r_idx; i++)
{
monster_race *r_ptr = &r_info[i];
@@ -1529,22 +1464,21 @@ void do_cmd_query_symbol(void)
{
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,41 +1496,34 @@ 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)
@@ -1657,10 +1584,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,17 +1597,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);
}
@@ -1689,7 +1613,7 @@ void do_cmd_query_symbol(void)
*/
bool_ research_mon()
{
- int i, n, r_idx;
+ int i, r_idx;
char sym, query;
@@ -1714,13 +1638,8 @@ bool_ research_mon()
bool_ recall = FALSE;
- u16b why = 0;
-
monster_race *r2_ptr;
- u16b *who;
-
-
/* Hack -- Remember "cheat_know" flag */
oldcheat = cheat_know;
@@ -1728,9 +1647,6 @@ bool_ research_mon()
/* 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)
{
@@ -1751,7 +1667,8 @@ bool_ research_mon()
/* Collect matching monsters */
- for (n = 0, i = 1; i < max_r_idx; i++)
+ std::vector<u16b> who;
+ for (i = 1; i < max_r_idx; i++)
{
monster_race *r_ptr = &r_info[i];
@@ -1768,15 +1685,14 @@ bool_ research_mon()
if (uniq && !(r_ptr->flags1 & (RF1_UNIQUE))) 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);
-
/* Restore the "cheat_know" flag */
cheat_know = oldcheat;
@@ -1784,24 +1700,14 @@ bool_ research_mon()
}
- /* 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);
- }
+ /* Sort by level */
+ std::sort(std::begin(who), std::end(who), compare_monster_level);
/* Start at the end */
- i = n - 1;
+ i = who.size() - 1;
notpicked = TRUE;
@@ -1872,10 +1778,11 @@ bool_ research_mon()
/* 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;
}
}
@@ -1884,8 +1791,7 @@ bool_ research_mon()
{
if (i-- == 0)
{
- i = n - 1;
- if (!expand_list) break;
+ i = who.size() - 1;
}
}
}
@@ -1894,9 +1800,6 @@ bool_ research_mon()
/* 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;
@@ -1957,131 +1860,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 +1914,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 +1943,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 +1955,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);
@@ -2299,7 +2078,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 +2089,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..48677b77
--- /dev/null
+++ b/src/cmd3.hpp
@@ -0,0 +1,24 @@
+#pragma once
+
+#include "h-basic.h"
+
+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);
diff --git a/src/cmd4.c b/src/cmd4.cc
index c4440428..4b6c040c 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,43 @@
* 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_info_type.hpp"
+#include "feature_type.hpp"
+#include "files.hpp"
+#include "hooks.hpp"
+#include "init1.hpp"
+#include "levels.hpp"
+#include "messages.hpp"
+#include "monster2.hpp"
+#include "monster_race.hpp"
+#include "monster_type.hpp"
+#include "notes.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_kind.hpp"
+#include "player_type.hpp"
+#include "skills.hpp"
+#include "squeltch.hpp"
+#include "tables.hpp"
+#include "town_type.hpp"
+#include "trap_type.hpp"
+#include "util.hpp"
+#include "util.h"
+#include "variable.h"
+#include "variable.hpp"
+#include "xtra1.hpp"
+#include "z-rand.hpp"
+
+#include <cassert>
+#include <memory>
+#include <string>
+#include <vector>
+#include <algorithm>
/*
* Hack -- redraw the screen
@@ -59,7 +89,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);
@@ -208,7 +238,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();
}
@@ -448,63 +478,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 +532,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 +557,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 +569,6 @@ static void do_cmd_options_cheat(cptr info)
case '2':
{
k = (k + 1) % n;
-
break;
}
@@ -552,10 +576,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 +589,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,6 +607,54 @@ static void do_cmd_options_cheat(cptr info)
}
}
}
+
+
+}
+
+
+
+/*
+ * Cheating options
+ */
+static option_type cheat_info[6] =
+{
+ { &cheat_peek, FALSE, 0, 0, "cheat_peek", "Peek into object creation" },
+ { &cheat_hear, FALSE, 0, 1, "cheat_hear", "Peek into monster creation" },
+ { &cheat_room, FALSE, 0, 2, "cheat_room", "Peek into dungeon creation" },
+ { &cheat_xtra, FALSE, 0, 3, "cheat_xtra", "Peek into something else" },
+ { &cheat_know, FALSE, 0, 4, "cheat_know", "Know complete monster info" },
+ { &cheat_live, FALSE, 0, 5, "cheat_live", "Allow player to avoid death" }
+};
+
+/*
+ * Interact with some options for cheating
+ */
+static void do_cmd_options_cheat(cptr info)
+{
+ // Calculate number of cheat options
+ size_t n = std::distance(std::begin(cheat_info), std::end(cheat_info));
+
+ // Build the vector of options we're going to interact with
+ std::vector<option_type *> options;
+ options.reserve(n);
+ for (auto &option : cheat_info)
+ {
+ options.push_back(&option);
+ }
+
+ // Interact
+ interact_with_options(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 &option: options)
+ {
+ if (*option->o_var)
+ {
+ noscore |= (option->o_page * 256 + option->o_bit);
+ }
+ }
}
@@ -727,152 +805,27 @@ 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)
+ // Scrape together all the options from the relevant page.
+ std::vector<option_type *> options;
+ options.reserve(64); // Seems a reasonable number; anything more would be unusable anyway
+ for (size_t i = 0; option_info[i].o_desc; i++)
{
- /* 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)
+ if (option_info[i].o_page == page)
{
- 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;
- }
+ options.push_back(&option_info[i]);
}
}
+
+ // Interact with the options
+ interaction_mode_t interaction_mode = read_only
+ ? interaction_mode_t::READ_ONLY
+ : interaction_mode_t::READ_WRITE;
+ interact_with_options(options, info, interaction_mode);
}
@@ -1070,9 +1023,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");
@@ -1442,9 +1392,6 @@ void do_cmd_options(void)
/* Restore the screen */
screen_load();
-
- /* Set the ingame help */
- ingame_help(p_ptr->help.enabled);
}
@@ -1485,9 +1432,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 +1511,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 +1585,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");
@@ -1718,9 +1656,6 @@ void do_cmd_macros(void)
/* Keymap mode */
mode = get_keymap_mode();
- /* File type is "TEXT" */
- FILE_TYPE(FILE_TYPE_TEXT);
-
/* Enter "icky" mode */
character_icky = TRUE;
@@ -2000,11 +1935,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 +1956,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 */
@@ -2085,10 +2016,6 @@ void do_cmd_visuals(void)
char buf[1024];
- /* File type is "TEXT" */
- FILE_TYPE(FILE_TYPE_TEXT);
-
-
/* Enter "icky" mode */
character_icky = TRUE;
@@ -2182,11 +2109,12 @@ void do_cmd_visuals(void)
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));
+ static_cast<unsigned int>(r_ptr->x_attr),
+ static_cast<unsigned int>(r_ptr->x_char));
}
/* All done */
@@ -2236,7 +2164,7 @@ void do_cmd_visuals(void)
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,
@@ -2290,7 +2218,7 @@ void do_cmd_visuals(void)
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,
@@ -2328,33 +2256,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,
@@ -2369,10 +2283,10 @@ void do_cmd_visuals(void)
/* Analyze */
if (i == 'n') r = (r + max_r_idx + 1) % max_r_idx;
if (i == 'N') r = (r + max_r_idx - 1) % max_r_idx;
- if (i == 'a') r_ptr->x_attr = (byte)(ca + 1);
- if (i == 'A') r_ptr->x_attr = (byte)(ca - 1);
- if (i == 'c') r_ptr->x_char = (byte)(cc + 1);
- if (i == 'C') r_ptr->x_char = (byte)(cc - 1);
+ if (i == 'a') r_ptr->x_attr = (ca + 1);
+ if (i == 'A') r_ptr->x_attr = (ca - 1);
+ if (i == 'c') r_ptr->x_char = (cc + 1);
+ if (i == 'C') r_ptr->x_char = (cc - 1);
}
}
@@ -2389,41 +2303,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,
@@ -2438,10 +2338,10 @@ void do_cmd_visuals(void)
/* Analyze */
if (i == 'n') k = (k + max_k_idx + 1) % max_k_idx;
if (i == 'N') k = (k + max_k_idx - 1) % max_k_idx;
- if (i == 'a') k_info[k].x_attr = (byte)(ca + 1);
- if (i == 'A') k_info[k].x_attr = (byte)(ca - 1);
- if (i == 'c') k_info[k].x_char = (byte)(cc + 1);
- if (i == 'C') k_info[k].x_char = (byte)(cc - 1);
+ if (i == 'a') k_info[k].x_attr = (ca + 1);
+ if (i == 'A') k_info[k].x_attr = (ca - 1);
+ if (i == 'c') k_info[k].x_char = (cc + 1);
+ if (i == 'C') k_info[k].x_char = (cc - 1);
}
}
@@ -2458,41 +2358,27 @@ void do_cmd_visuals(void)
{
feature_type *f_ptr = &f_info[f];
- byte da = (byte)f_ptr->d_attr;
- char dc = (byte)f_ptr->d_char;
- byte ca = (byte)f_ptr->x_attr;
- char cc = (byte)f_ptr->x_char;
+ byte da = f_ptr->d_attr;
+ char dc = f_ptr->d_char;
+ byte ca = f_ptr->x_attr;
+ char cc = f_ptr->x_char;
/* Label the object */
Term_putstr(5, 17, -1, TERM_WHITE,
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,
@@ -2507,10 +2393,10 @@ void do_cmd_visuals(void)
/* Analyze */
if (i == 'n') f = (f + max_f_idx + 1) % max_f_idx;
if (i == 'N') f = (f + max_f_idx - 1) % max_f_idx;
- if (i == 'a') f_info[f].x_attr = (byte)(ca + 1);
- if (i == 'A') f_info[f].x_attr = (byte)(ca - 1);
- if (i == 'c') f_info[f].x_char = (byte)(cc + 1);
- if (i == 'C') f_info[f].x_char = (byte)(cc - 1);
+ if (i == 'a') f_info[f].x_attr = (ca + 1);
+ if (i == 'A') f_info[f].x_attr = (ca - 1);
+ if (i == 'c') f_info[f].x_char = (cc + 1);
+ if (i == 'C') f_info[f].x_char = (cc - 1);
if (i == 'd')
{
f_info[f].x_char = f_ptr->d_char;
@@ -2562,10 +2448,6 @@ void do_cmd_colors(void)
char buf[1024];
- /* File type is "TEXT" */
- FILE_TYPE(FILE_TYPE_TEXT);
-
-
/* Enter "icky" mode */
character_icky = TRUE;
@@ -2735,16 +2617,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);
@@ -2790,16 +2672,8 @@ void do_cmd_note(void)
/* Ignore empty notes */
if (!buf[0] || (buf[0] == ' ')) return;
- if (take_notes)
- {
- /* Add note to file */
- add_note(buf, ' ');
- }
- else
- {
- /* Add note to message recall */
- msg_format("Note: %s", buf);
- }
+ /* Add note to file */
+ add_note(buf, ' ');
}
@@ -2808,16 +2682,11 @@ void do_cmd_note(void)
*/
void do_cmd_version(void)
{
- cptr author, email;
-
- call_lua("get_module_info", "(s,d)", "s", "author", 1, &author);
- call_lua("get_module_info", "(s,d)", "s", "author", 2, &email);
-
/* Silly message */
msg_format("You are playing %s made by %s (%s).",
get_version_string(),
- author, email);
- call_lua("patchs_display", "()", "");
+ modules[game_module_idx].meta.author.name,
+ modules[game_module_idx].meta.author.email);
}
@@ -2858,7 +2727,7 @@ void do_cmd_feeling(void)
}
/* Hooked feelings ? */
- if (process_hooks(HOOK_FEELING, "(d)", is_quest(dun_level)))
+ if (process_hooks_new(HOOK_FEELING, NULL, NULL))
{
return;
}
@@ -3037,127 +2906,103 @@ 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)
{
- /* 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 */
+ (void)(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 */
+ (void)(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;
}
@@ -3174,13 +3019,6 @@ void do_cmd_knowledge_artifacts(void)
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;
@@ -3188,6 +3026,7 @@ void do_cmd_knowledge_artifacts(void)
fff = my_fopen(file_name, "w");
/* Scan the artifacts */
+ std::unique_ptr<bool_[]> okay(new bool_[max_a_idx]);
for (k = 0; k < max_a_idx; k++)
{
artifact_type *a_ptr = &a_info[k];
@@ -3205,6 +3044,7 @@ void do_cmd_knowledge_artifacts(void)
okay[k] = TRUE;
}
+ std::unique_ptr<bool_[]> okayk(new bool_[max_k_idx]);
for (k = 0; k < max_k_idx; k++)
{
object_kind *k_ptr = &k_info[k];
@@ -3229,18 +3069,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;
@@ -3267,21 +3100,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;
@@ -3410,9 +3236,6 @@ void do_cmd_knowledge_artifacts(void)
/* Remove the file */
fd_kill(file_name);
-
- C_FREE(okay, max_a_idx, bool_);
- C_FREE(okayk, max_k_idx, bool_);
}
@@ -3449,7 +3272,7 @@ void do_cmd_knowledge_traps(void)
if (!t_ptr->ident) continue;
/* Hack -- Build the trap name */
- fprintf(fff, " %s\n", t_name + t_ptr->name);
+ fprintf(fff, " %s\n", t_ptr->name);
}
/* Close the file */
@@ -3463,54 +3286,28 @@ void do_cmd_knowledge_traps(void)
}
+static int monster_get_race_level(int r_idx) {
+ /* Hack -- Morgoth is always last */
+ if (r_idx == 862) {
+ return 20000;
+ }
+ /* Otherwise, we'll use the real level. */
+ return r_info[r_idx].level;
+}
+
+static bool compare_monster_level(int r_idx1, int r_idx2) {
+ return monster_get_race_level(r_idx1) < monster_get_race_level(r_idx2);
+}
+
/*
* Display known uniques
*
* Note that the player ghosts are ignored. XXX XXX XXX
*/
-static void insert_sort_unique(int *sort_uniques, int *num, int r_idx)
-{
- int i, j;
-
- monster_race *r_ptr = &r_info[r_idx];
-
- int level = r_ptr->level;
-
-
- /* Hack -- Morgoth is always at the bottom of the list */
- if (r_idx == 862) level = 20000;
-
- /* Find the place */
- for (i = 0; i < *num; i++)
- {
- monster_race *r2_ptr = &r_info[sort_uniques[i]];
- int level2 = r2_ptr->level;
-
- if (sort_uniques[i] == 862) level2 = 20000;
-
- if (level < level2) break;
- }
-
- /* Move the remaining items */
- for (j = *num - 1; j >= i; j--)
- {
- sort_uniques[j + 1] = sort_uniques[j];
- }
-
- /* Insert it */
- sort_uniques[i] = r_idx;
- (*num)++;
-}
-
-
static void do_cmd_knowledge_uniques(void)
{
int k;
- int *sort_uniques;
-
- int num = 0;
-
FILE *fff;
char file_name[1024];
@@ -3522,26 +3319,30 @@ static void do_cmd_knowledge_uniques(void)
/* Open a new file */
fff = my_fopen(file_name, "w");
- C_MAKE(sort_uniques, max_r_idx, int);
-
- /* Sort the monster races */
+ // Extract the unique race indexes.
+ std::vector<int> unique_r_idxs;
for (k = 1; k < max_r_idx; k++)
{
monster_race *r_ptr = &r_info[k];
/* Only print Uniques */
if (r_ptr->flags1 & (RF1_UNIQUE) &&
- !(r_ptr->flags7 & RF7_PET) &&
- !(r_ptr->flags7 & RF7_NEUTRAL))
+ !(r_ptr->flags7 & RF7_PET) &&
+ !(r_ptr->flags7 & RF7_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),
+ compare_monster_level);
+
+ /* Scan the monster races */
+ for (int r_idx : unique_r_idxs)
{
- monster_race *r_ptr = &r_info[sort_uniques[k]];
+ monster_race *r_ptr = &r_info[r_idx];
/* Only print Uniques */
if (r_ptr->flags1 & (RF1_UNIQUE))
@@ -3554,44 +3355,22 @@ static void do_cmd_knowledge_uniques(void)
/* 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));
- }
+ fprintf(fff, "[[[[[%c%c] [[[[[R%-68s is dead]\n",
+ conv_color[r_ptr->d_attr],
+ r_ptr->d_char,
+ 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));
- }
+ fprintf(fff, "[[[[[%c%c] [[[[[w%-68s is alive]\n",
+ conv_color[r_ptr->d_attr],
+ r_ptr->d_char,
+ r_ptr->name);
}
}
}
}
- C_FREE(sort_uniques, max_r_idx, int);
-
/* Close the file */
my_fclose(fff);
@@ -3603,7 +3382,7 @@ static void do_cmd_knowledge_uniques(void)
}
-void plural_aux(char *name)
+static void plural_aux(char *name)
{
int name_len = strlen(name);
@@ -3734,12 +3513,14 @@ 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,
@@ -3834,7 +3615,7 @@ static void do_cmd_knowledge_kill_count(void)
}
else
{
- fprintf(fff, "You have defeated %ld enemies.\n\n", (long int) Total);
+ fprintf(fff, "You have defeated " FMTs32b " enemies.\n\n", Total);
}
}
@@ -3852,8 +3633,7 @@ static void do_cmd_knowledge_kill_count(void)
if (dead)
{
/* Print a message */
- fprintf(fff, " %s\n",
- (r_name + r_ptr->name));
+ fprintf(fff, " %s\n", r_ptr->name);
Total++;
}
}
@@ -3865,19 +3645,19 @@ 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));
+ fprintf(fff, " 1 pile of %s\n", r_ptr->name);
}
else
{
- fprintf(fff, " 1 %s\n", (r_name + r_ptr->name));
+ fprintf(fff, " 1 %s\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);
}
@@ -3888,7 +3668,7 @@ static void do_cmd_knowledge_kill_count(void)
}
fprintf(fff, "----------------------------------------------\n");
- fprintf(fff, " Total: %ld creature%s killed.\n", (long int) Total, (Total == 1 ? "" : "s"));
+ fprintf(fff, " Total: " FMTs32b " creature%s killed.\n", Total, (Total == 1 ? "" : "s"));
/* Close the file */
my_fclose(fff);
@@ -3987,7 +3767,7 @@ static void do_cmd_knowledge_dungeons(void)
/* Describe the recall depth */
fprintf(fff, " %c%s: Level %d (%d')\n",
(p_ptr->recall_dungeon == y) ? '*' : ' ',
- d_name + d_info[y].name,
+ d_info[y].name,
max_dlv[y], 50 * (max_dlv[y]));
}
}
@@ -4039,7 +3819,7 @@ void do_cmd_knowledge_towns(void)
/* Describe the dungeon town */
fprintf(fff, " %s: Level %d (%d')\n",
- d_name + d_ptr->name,
+ d_ptr->name,
d_ptr->t_level[j],
50 * d_ptr->t_level[j]);
}
@@ -4059,7 +3839,7 @@ void do_cmd_knowledge_towns(void)
/*
* List corruptions
*/
-void do_cmd_knowledge_corruptions(void)
+static void do_cmd_knowledge_corruptions(void)
{
FILE *fff;
@@ -4073,7 +3853,10 @@ void do_cmd_knowledge_corruptions(void)
fff = my_fopen(file_name, "w");
/* Dump the corruptions to file */
- if (fff) dump_corruptions(fff, TRUE);
+ if (fff)
+ {
+ dump_corruptions(fff, TRUE, FALSE);
+ }
/* Close the file */
my_fclose(fff);
@@ -4128,7 +3911,7 @@ static void do_cmd_knowledge_quests(void)
char file_name[1024];
- int *order;
+ int order[MAX_Q_IDX] = { };
int num = 0;
@@ -4141,33 +3924,21 @@ static void do_cmd_knowledge_quests(void)
/* Open a new file */
fff = my_fopen(file_name, "w");
- C_MAKE(order, max_q_idx, int);
-
- for (i = 0; i < max_q_idx; i++)
+ for (i = 0; i < MAX_Q_IDX; i++)
{
insert_sort_quest(order, &num, i);
}
- for (z = 0; z < max_q_idx; z++)
+ for (z = 0; z < MAX_Q_IDX; z++)
{
i = order[z];
- /* 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)
- {
- if (!quest[i].gen_desc(fff))
- {
- continue;
- }
- }
- /* MUST be a lua quest */
- else
+ if (!quest[i].gen_desc(fff))
{
- hook_file = fff;
- exec_lua(format("__quest_dynamic_desc[%d]()", i));
+ continue;
}
}
@@ -4195,8 +3966,6 @@ static void do_cmd_knowledge_quests(void)
}
}
- C_FREE(order, max_q_idx, int);
-
/* Close the file */
my_fclose(fff);
@@ -4258,9 +4027,6 @@ void do_cmd_knowledge(void)
int i;
- /* File type is "TEXT" */
- FILE_TYPE(FILE_TYPE_TEXT);
-
/* Enter "icky" mode */
character_icky = TRUE;
@@ -4288,7 +4054,7 @@ void do_cmd_knowledge(void)
prt("(9) Display current fates", 12, 5);
prt("(0) Display known traps", 13, 5);
prt("(A) Display known dungeon towns", 14, 5);
- if (take_notes) prt("(B) Display notes", 15, 5);
+ prt("(B) Display notes", 15, 5);
/* Prompt */
prt("Command: ", 17, 0);
@@ -4394,8 +4160,7 @@ void do_cmd_knowledge(void)
case 'B':
case 'b':
{
- if (take_notes) do_cmd_knowledge_notes();
- else bell();
+ do_cmd_knowledge_notes();
break;
}
@@ -4427,9 +4192,6 @@ void do_cmd_knowledge(void)
*/
void do_cmd_checkquest(void)
{
- /* File type is "TEXT" */
- FILE_TYPE(FILE_TYPE_TEXT);
-
/* Enter "icky" mode */
character_icky = TRUE;
@@ -4482,16 +4244,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 +4266,10 @@ 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 */
+ u32b days = bst(DAY, turn) + 1;
+ msg_format("This is the %s day of your adventure.",
+ get_day(days));
/* Message */
msg_format("The time is %d:%02d %s.",
@@ -4596,57 +4352,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);
+
+ // Remove the last key, because it is the key to stop recording
+ macro_recorder_current->pop_back();
- /* Ok we remove the last key, because it is the key to stop recording */
- macro_recorder_current[strlen(macro_recorder_current) - 1] = '\0';
+ // Copy out current macro text.
+ std::string macro(*macro_recorder_current);
- /* Stop the recording */
- macro = macro_recorder_current;
- macro_recorder_current = NULL;
+ // 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..4470c94f
--- /dev/null
+++ b/src/cmd4.hpp
@@ -0,0 +1,28 @@
+#pragma once
+
+#include "h-basic.h"
+
+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 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);
diff --git a/src/cmd5.c b/src/cmd5.cc
index b415b166..a1dd5cbf 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,82 @@
* 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 "lua_bind.hpp"
+#include "monster2.hpp"
+#include "monster_race.hpp"
+#include "object1.hpp"
+#include "object2.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 "quark.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(
+ HasFlag5(TR5_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 +112,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
*
@@ -109,35 +226,36 @@ extern void do_cmd_browse_aux(object_type *o_ptr)
u32b f1, f2, f3, f4, f5, esp;
object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
- if (is_school_book(o_ptr))
+ if (is_school_book()(o_ptr))
+ {
browse_school_spell(o_ptr->sval, o_ptr->pval, o_ptr);
+ }
else if (f5 & TR5_SPELL_CONTAIN && o_ptr->pval2 != -1)
+ {
browse_school_spell(255, o_ptr->pval2, o_ptr);
+ }
}
void do_cmd_browse(void)
{
- int item;
-
- cptr q, s;
-
- object_type *o_ptr;
-
- /* Restrict choices to "useful" books */
- item_tester_hook = item_tester_hook_browsable;
-
/* Get an item */
- q = "Browse which book? ";
- s = "You have no books that you can read.";
- if (!get_item(&item, q, s, (USE_INVEN | USE_EQUIP | USE_FLOOR))) return;
+ 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;
@@ -236,7 +354,7 @@ void do_poly_self(void)
/* Polymorph into a less corrupted form */
power -= 10;
- lose_corruption(0);
+ lose_corruption();
}
/*
@@ -265,8 +383,8 @@ void do_poly_self(void)
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)) ? "n" : ""),
+ race_info[new_race].title);
}
else
{
@@ -287,7 +405,7 @@ void do_poly_self(void)
check_experience();
p_ptr->max_plv = p_ptr->lev;
- p_ptr->redraw |= (PR_BASIC);
+ p_ptr->redraw |= (PR_FRAME);
p_ptr->update |= (PU_BONUS);
@@ -326,7 +444,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 +461,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 +488,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 +503,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 +515,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 +533,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);
@@ -582,225 +594,6 @@ void shriek_effect()
}
}
-
-/*
- * Like all the random effect codes, this is *ugly*,
- * and there is not a single line of comment, so I can't tell
- * some fall throughs are really intended. Well, I know it's
- * intended to be bizarre :) -- pelpel
- */
-void wild_magic(int spell)
-{
- int counter = 0;
- int type = SUMMON_BIZARRE1 - 1 + randint(6);
-
- if (type < SUMMON_BIZARRE1) type = SUMMON_BIZARRE1;
- else if (type > SUMMON_BIZARRE6) type = SUMMON_BIZARRE6;
-
- switch (randint(spell) + randint(8) + 1)
- {
- case 1:
- case 2:
- case 3:
- {
- teleport_player(10);
-
- break;
- }
-
- case 4:
- case 5:
- case 6:
- {
- teleport_player(100);
-
- break;
- }
-
- case 7:
- case 8:
- {
- teleport_player(200);
-
- break;
- }
-
- case 9:
- case 10:
- case 11:
- {
- unlite_area(10, 3);
-
- break;
- }
-
- case 12:
- case 13:
- case 14:
- {
- lite_area(damroll(2, 3), 2);
-
- break;
- }
-
- case 15:
- {
- destroy_doors_touch();
-
- break;
- }
-
- case 16:
- case 17:
- {
- wall_breaker();
-
- /* I don't think this is a fall through -- pelpel */
- break;
- }
-
- case 18:
- {
- sleep_monsters_touch();
-
- break;
- }
-
- case 19:
- case 20:
- {
- trap_creation();
-
- break;
- }
-
- case 21:
- case 22:
- {
- door_creation();
-
- break;
- }
-
- case 23:
- case 24:
- case 25:
- {
- aggravate_monsters(1);
-
- break;
- }
-
- case 26:
- {
- /* Prevent destruction of quest levels and town */
- if (!is_quest(dun_level) && dun_level)
- earthquake(p_ptr->py, p_ptr->px, 5);
-
- break;
- }
-
- case 27:
- case 28:
- {
- break;
- }
-
- case 29:
- case 30:
- {
- apply_disenchant(0);
-
- break;
- }
-
- case 31:
- {
- lose_all_info();
-
- break;
- }
-
- case 32:
- {
- fire_ball(GF_CHAOS, 0, spell + 5, 1 + (spell / 10));
-
- break;
- }
-
- case 33:
- {
- wall_stone(p_ptr->py, p_ptr->px);
-
- break;
- }
-
- case 34:
- case 35:
- {
- while (counter++ < 8)
- {
- (void) summon_specific(p_ptr->py, p_ptr->px, (dun_level * 3) / 2, type);
- }
-
- break;
- }
-
- case 36:
- case 37:
- {
- activate_hi_summon();
-
- break;
- }
-
- case 38:
- {
- summon_cyber();
-
- /* I don't think this is a fall through -- pelpel */
- break;
- }
-
- default:
- {
- activate_ty_curse();
- }
- }
-
- return;
-}
-
-
-/*
- * Hack -- Determine if the player is wearing an artefact ring
- * specified by art_type, that should be an index into a_info
- */
-bool_ check_ring(int art_type)
-{
- int i;
-
-
- /* We are only interested in ring slots */
- i = INVEN_RING;
-
- /* Scan the list of rings until we reach the end */
- while (p_ptr->body_parts[i - INVEN_WIELD] == INVEN_RING)
- {
- /* Found the ring we were looking for */
- if (p_ptr->inventory[i].k_idx && (p_ptr->inventory[i].name1 == art_type))
- {
- return (TRUE);
- }
-
- /* Next item */
- i++;
- }
-
- /* Found nothing */
- return (FALSE);
-}
-
/*
* Return the symbiote's name or description.
*/
@@ -822,7 +615,7 @@ cptr symbiote_name(bool_ capitalize)
if (r_ptr->flags1 & RF1_UNIQUE)
{
/* Unique monster; no preceding "your", and ignore our name. */
- strncpy(buf, r_name + r_ptr->name, sizeof(buf));
+ strncpy(buf, r_ptr->name, sizeof(buf));
}
else if (o_ptr->note &&
(s = strstr(quark_str(o_ptr->note), "#named ")) != NULL)
@@ -834,7 +627,7 @@ cptr symbiote_name(bool_ capitalize)
{
/* No special cases, just return "Your <monster type>". */
strcpy(buf, "your ");
- strncpy(buf + 5, r_name + r_ptr->name, sizeof(buf) - 5);
+ strncpy(buf + 5, r_ptr->name, sizeof(buf) - 5);
}
}
@@ -855,7 +648,7 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
int powers[96];
- bool_ flag, redraw;
+ bool_ flag;
int ask, plev = p_ptr->lev;
@@ -918,99 +711,80 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
/* Nothing chosen yet */
flag = FALSE;
- /* No redraw yet */
- redraw = FALSE;
-
/* Get the last label */
label = (num <= 26) ? I2A(num - 1) : I2D(num - 1 - 26);
/* Build a prompt (accept all spells) */
/* Mega Hack -- if no_cost is false, we're actually a Possessor -dsb */
strnfmt(out_val, 78,
- "(Powers a-%c, *=List, ESC=exit) Use which power of your %s? ",
+ "(Powers a-%c, ESC=exit) Use which power of your %s? ",
label, (no_cost ? "symbiote" : "body"));
+ /* Save the screen */
+ character_icky = TRUE;
+ Term_save();
+
/* Get a spell from the user */
- while (!flag && get_com(out_val, &choice))
+ while (!flag)
{
- /* Request redraw */
- if ((choice == ' ') || (choice == '*') || (choice == '?'))
+ /* Show the list */
{
- /* Show the list */
- if (!redraw)
- {
- byte y = 1, x = 0;
- int ctr = 0;
- char dummy[80];
+ byte y = 1, x = 0;
+ int ctr = 0;
+ char dummy[80];
+
+ strcpy(dummy, "");
+
+ prt ("", y++, x);
- strcpy(dummy, "");
+ while (ctr < num)
+ {
+ monster_power *mp_ptr = &monster_powers[powers[ctr]];
+ int mana = mp_ptr->mana / 10;
- /* Show list */
- redraw = TRUE;
+ if (mana > p_ptr->msp) mana = p_ptr->msp;
- /* Save the screen */
- character_icky = TRUE;
- Term_save();
+ if (!mana) mana = 1;
- prt ("", y++, x);
+ label = (ctr < 26) ? I2A(ctr) : I2D(ctr - 26);
- while (ctr < num)
+ if (!no_cost)
{
- monster_power *mp_ptr = &monster_powers[powers[ctr]];
- int mana = mp_ptr->mana / 10;
-
- if (mana > p_ptr->msp) mana = p_ptr->msp;
-
- if (!mana) mana = 1;
-
- label = (ctr < 26) ? I2A(ctr) : I2D(ctr - 26);
-
- if (!no_cost)
- {
- strnfmt(dummy, 80, " %c) %2d %s",
- label, mana, mp_ptr->name);
- }
- else
- {
- strnfmt(dummy, 80, " %c) %s",
- label, mp_ptr->name);
- }
-
- if (ctr < 17)
- {
- prt(dummy, y + ctr, x);
- }
- else
- {
- prt(dummy, y + ctr - 17, x + 40);
- }
-
- ctr++;
+ strnfmt(dummy, 80, " %c) %2d %s",
+ label, mana, mp_ptr->name);
+ }
+ else
+ {
+ strnfmt(dummy, 80, " %c) %s",
+ label, mp_ptr->name);
}
if (ctr < 17)
{
- prt ("", y + ctr, x);
+ prt(dummy, y + ctr, x);
}
else
{
- prt ("", y + 17, x);
+ prt(dummy, y + ctr - 17, x + 40);
}
+
+ ctr++;
}
- /* Hide the list */
+ if (ctr < 17)
+ {
+ prt ("", y + ctr, x);
+ }
else
{
- /* Hide list */
- redraw = FALSE;
-
- /* Restore the screen */
- Term_load();
- character_icky = FALSE;
+ prt ("", y + 17, x);
}
+ }
- /* Redo asking */
- continue;
+ if (!get_com(out_val, &choice))
+ {
+ flag = FALSE;
+ break;
}
if (choice == '\r' && num == 1)
@@ -1064,11 +838,8 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
}
/* Restore the screen */
- if (redraw)
- {
- Term_load();
- character_icky = FALSE;
- }
+ Term_load();
+ character_icky = FALSE;
/* Abort if needed */
if (!flag)
@@ -2079,7 +1850,7 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost
}
/* Redraw mana */
- p_ptr->redraw |= (PR_MANA);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
@@ -2095,99 +1866,123 @@ 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 ? */
+ /* Extract object flags */
+ u32b f1, f2, f3, f4, f5, esp;
object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
- if ((wield_slot(o_ptr) != -1) && (i < INVEN_WIELD) && (f5 & TR5_WIELD_CAST)) continue;
- /* Is it a non-book? */
- if (!is_school_book(o_ptr))
+ /* Must we wield it to cast from it? */
+ if ((wield_slot(o_ptr) != -1) && (i < INVEN_WIELD) && (f5 & TR5_WIELD_CAST))
{
- u32b f1, f2, f3, f4, f5, esp;
-
- /* Extract object flags */
- object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ continue;
+ }
+ /* Is it a non-book? */
+ if (!is_school_book()(o_ptr))
+ {
+ /* Does it contain the appropriate spell? */
if ((f5 & TR5_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);
@@ -2217,21 +2012,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 +2030,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;
+ char choice;
- /* Save the screen */
- character_icky = TRUE;
- Term_save();
+ /* Restore and save screen; this prevents
+ subprompt from leaving garbage when going
+ around the loop multiple times. */
+ Term_load();
+ Term_save();
- /* Display a list of spells */
- call_lua("print_book", "(d,d,O)", "d", sval, pval, o_ptr, &where);
- }
+ /* Display a list of spells */
+ where = print_book(sval, pval, o_ptr);
- /* Hide the list */
- else
- {
- /* Hide list */
- redraw = FALSE;
- where = 1;
-
- /* Restore the screen */
- Term_load();
- character_icky = FALSE;
- }
-
- /* Redo asking */
- continue;
+ /* Input */
+ if (!get_com(out_val, &choice))
+ {
+ flag = FALSE;
+ break;
}
-
/* Note verify */
ask = (isupper(choice));
@@ -2306,38 +2083,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 +2113,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 +2132,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 +2166,22 @@ 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);
- if ((f5 & TR5_SPELL_CONTAIN) && (o_ptr->pval2 == -1))
- return TRUE;
- return FALSE;
+ return ((f5 & TR5_SPELL_CONTAIN) && (o_ptr->pval2 == -1));
}
/*
@@ -2513,50 +2189,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..1b3b062a
--- /dev/null
+++ b/src/cmd5.hpp
@@ -0,0 +1,16 @@
+#pragma once
+
+#include "h-basic.h"
+#include "object_type_fwd.hpp"
+
+extern bool_ is_magestaff(void);
+extern void do_cmd_browse_aux(object_type *o_ptr);
+extern void do_cmd_browse(void);
+extern void fetch(int dir, int wgt, bool_ require_los);
+extern void do_poly_self(void);
+extern cptr symbiote_name(bool_ capitalize);
+extern int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost);
+extern bool_ is_ok_spell(s32b spell_idx, s32b pval);
+extern s32b get_school_spell(cptr do_what, s16b force_book);
+extern void do_cmd_copy_spell(void);
+extern void cast_school_spell(void);
diff --git a/src/cmd6.c b/src/cmd6.cc
index db89c465..0a5595fa 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,8 +6,53 @@
* included in all such copies.
*/
-#include "angband.h"
-
+#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_info_type.hpp"
+#include "ego_item_type.hpp"
+#include "files.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_type.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_kind.hpp"
+#include "object_type.hpp"
+#include "options.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;
/*
* Forward declare
@@ -22,31 +63,41 @@ static bool_ activate_spell(object_type * o_ptr, byte choice);
/*
* General function to find an item by its name
*/
-cptr get_item_hook_find_obj_what;
-bool_ get_item_hook_find_obj(int *item)
+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;
+ };
}
@@ -284,7 +335,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;
@@ -907,13 +958,14 @@ 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;
}
@@ -922,32 +974,28 @@ static bool_ item_tester_hook_eatable(object_type *o_ptr)
*/
void do_cmd_eat_food(void)
{
- int item, ident, lev, fval = 0;
+ int ident, lev, fval = 0;
- object_type *o_ptr;
object_type *q_ptr, forge;
monster_race *r_ptr;
- cptr q, s;
-
bool_ destroy = TRUE;
-
- /* Restrict choices to food */
- item_tester_hook = item_tester_hook_eatable;
-
- /* Set up the extra finder */
- get_item_hook_find_obj_what = "Food full name? ";
- get_item_extra_hook = get_item_hook_find_obj;
-
/* Get an item */
- q = "Eat which item? ";
- s = "You have nothing to eat.";
- if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR | USE_EXTRA))) return;
+ 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);
+ object_type *o_ptr = get_object(item);
/* Sound */
sound(SOUND_EAT);
@@ -963,9 +1011,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 +1102,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;
}
@@ -1246,7 +1296,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;
}
@@ -1441,7 +1491,7 @@ 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_flags1_p(PR1_VAMPIRE)) || (p_ptr->mimic_form == resolve_mimic_name("Vampire")))
{
/* Reduced nutritional benefit */
/* (void)set_food(p_ptr->food + (fval / 10)); -- No more */
@@ -1454,9 +1504,9 @@ void do_cmd_eat_food(void)
}
}
- else if (PRACE_FLAG(PR1_NO_FOOD))
+ else if (race_flags1_p(PR1_NO_FOOD))
{
- if (PRACE_FLAG(PR1_UNDEAD))
+ if (race_flags1_p(PR1_UNDEAD))
{
msg_print("The food of mortals is poor sustenance for you.");
}
@@ -1489,29 +1539,20 @@ void do_cmd_cut_corpse(void)
{
int item, meat = 0, not_meat = 0;
- object_type *o_ptr;
-
- object_type *i_ptr;
-
- object_type object_type_body;
-
- monster_race *r_ptr;
-
- cptr q, s;
-
-
- /* Restrict choices to corpses */
- item_tester_tval = TV_CORPSE;
-
/* Get an item */
- q = "Hack up which corpse? ";
- s = "You have no corpses.";
- if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return;
+ 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];
+ monster_race *r_ptr = &r_info[o_ptr->pval2];
if ((o_ptr->sval != SV_CORPSE_CORPSE) && (o_ptr->sval != SV_CORPSE_HEAD))
{
@@ -1565,7 +1606,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));
@@ -1596,32 +1638,27 @@ void do_cmd_cure_meat(void)
{
int item, num, cure;
- object_type *o_ptr;
-
object_type *i_ptr;
- cptr q, s;
-
-
- /* Restrict choices to corpses */
- item_tester_tval = TV_CORPSE;
- item_tester_hook = item_tester_hook_eatable;
-
/* Get some meat */
- q = "Cure which meat? ";
- s = "You have no meat to cure.";
- if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return;
+ 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 +1681,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 +1744,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 +1773,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;
}
@@ -1771,7 +1815,7 @@ static bool_ quaff_potion(int tval, int sval, int pval, int pval2)
msg_print("The potion makes you vomit!");
(void)set_food(PY_FOOD_STARVE - 1);
(void)set_poisoned(0);
- (void)set_paralyzed(p_ptr->paralyzed + 4);
+ (void)set_paralyzed(4);
ident = TRUE;
break;
@@ -1838,7 +1882,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;
}
@@ -2118,7 +2162,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;
}
@@ -2272,10 +2316,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;
}
@@ -2335,8 +2377,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 +2431,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);
@@ -2440,29 +2491,22 @@ static bool_ quaff_potion(int tval, int sval, int pval, int pval2)
*/
void do_cmd_quaff_potion(void)
{
- int item, ident, lev;
-
- object_type *o_ptr;
-
- object_type *q_ptr, forge;
-
- cptr q, s;
-
-
- /* Restrict choices to potions */
- item_tester_hook = item_tester_hook_quaffable;
-
- /* Set up the extra finder */
- get_item_hook_find_obj_what = "Potion full name? ";
- get_item_extra_hook = get_item_hook_find_obj;
+ 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);
+ object_type *o_ptr = get_object(item);
/* Sound */
@@ -2478,13 +2522,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,22 +2547,6 @@ 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);
@@ -2531,6 +2561,92 @@ void do_cmd_quaff_potion(void)
/*
+ * Fill an empty bottle
+ */
+static void do_cmd_fill_bottle(void)
+{
+ cave_type *c_ptr = &cave[p_ptr->py][p_ptr->px];
+
+ int tval, sval, item, amt = 1;
+
+ object_type *q_ptr, forge;
+
+ /* Is the fountain empty? */
+ /*
+ * This check is redundant as it is done in do_cmd_drink_fountain()
+ * but I keep this because someone might want to call this directly.
+ * -- Kusunose
+ */
+ if (c_ptr->special2 <= 0)
+ {
+ msg_print("The fountain has dried up.");
+ return;
+ }
+
+ /* Determine the tval/sval of the potion */
+ if (c_ptr->special <= SV_POTION_LAST)
+ {
+ tval = TV_POTION;
+ sval = c_ptr->special;
+ }
+ else
+ {
+ tval = TV_POTION2;
+ sval = c_ptr->special - SV_POTION_LAST;
+ }
+
+ /* Get an 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)
+ {
+ /* Get a quantity */
+ amt = get_quantity(NULL, o_ptr->number);
+
+ /* Allow user abort */
+ if (amt <= 0) return;
+ }
+
+ if (amt > c_ptr->special2) amt = c_ptr->special2;
+
+ /* Destroy bottles */
+ inc_stack_size(item, -amt);
+
+ /* Create the potion */
+ q_ptr = &forge;
+ object_prep(q_ptr, lookup_kind(tval, sval));
+ q_ptr->number = amt;
+
+ if (c_ptr->info & CAVE_IDNT)
+ {
+ object_aware(q_ptr);
+ object_known(q_ptr);
+ }
+
+ inven_carry(q_ptr, TRUE);
+
+ c_ptr->special2 -= amt;
+
+ if (c_ptr->special2 <= 0)
+ {
+ cave_set_feat(p_ptr->py, p_ptr->px, FEAT_EMPTY_FOUNTAIN);
+ }
+
+ return;
+}
+
+
+/*
* Drink from a fountain
*/
void do_cmd_drink_fountain(void)
@@ -2606,91 +2722,6 @@ void do_cmd_drink_fountain(void)
/*
- * Fill an empty bottle
- */
-void do_cmd_fill_bottle(void)
-{
- cave_type *c_ptr = &cave[p_ptr->py][p_ptr->px];
-
- int tval, sval, item, amt = 1;
-
- object_type *q_ptr, *o_ptr, forge;
-
- cptr q, s;
-
- /* Is the fountain empty? */
- /*
- * This check is redundant as it is done in do_cmd_drink_fountain()
- * but I keep this because someone might want to call this directly.
- * -- Kusunose
- */
- if (c_ptr->special2 <= 0)
- {
- msg_print("The fountain has dried up.");
- return;
- }
-
- /* Determine the tval/sval of the potion */
- if (c_ptr->special <= SV_POTION_LAST)
- {
- tval = TV_POTION;
- sval = c_ptr->special;
- }
- else
- {
- tval = TV_POTION2;
- sval = c_ptr->special - SV_POTION_LAST;
- }
-
- /* Restrict choices to bottles */
- item_tester_tval = TV_BOTTLE;
-
- /* Get an item */
- q = "Fill which bottle? ";
- s = "You have no bottles to fill.";
- if (!get_item(&item, q, s, (USE_INVEN))) return;
- o_ptr = &p_ptr->inventory[item];
-
- /* Find out how many the player wants */
- if (o_ptr->number > 1)
- {
- /* Get a quantity */
- amt = get_quantity(NULL, o_ptr->number);
-
- /* Allow user abort */
- if (amt <= 0) return;
- }
-
- if (amt > c_ptr->special2) amt = c_ptr->special2;
-
- /* Destroy bottles */
- inc_stack_size(item, -amt);
-
- /* Create the potion */
- q_ptr = &forge;
- object_prep(q_ptr, lookup_kind(tval, sval));
- q_ptr->number = amt;
-
- if (c_ptr->info & CAVE_IDNT)
- {
- object_aware(q_ptr);
- object_known(q_ptr);
- }
-
- inven_carry(q_ptr, TRUE);
-
- c_ptr->special2 -= amt;
-
- if (c_ptr->special2 <= 0)
- {
- cave_set_feat(p_ptr->py, p_ptr->px, FEAT_EMPTY_FOUNTAIN);
- }
-
- return;
-}
-
-
-/*
* Curse the players armor
*/
bool_ curse_armor(void)
@@ -2825,12 +2856,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;
}
@@ -2843,15 +2876,6 @@ static bool_ item_tester_hook_readable(object_type *o_ptr)
*/
void do_cmd_read_scroll(void)
{
- int item, k, used_up, ident, lev;
-
- object_type *o_ptr;
-
- object_type *q_ptr, forge;
-
- cptr q, s;
-
-
/* Check some conditions */
if (p_ptr->blind)
{
@@ -2871,41 +2895,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,13 +2938,11 @@ 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 (int k = 0; k < max_r_idx; k++)
{
monster_race *r_ptr = &r_info[k];
@@ -2960,7 +2983,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,
max_dlv[p_ptr->recall_dungeon]);
ident = TRUE;
@@ -3036,7 +3059,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 +3082,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))
{
@@ -3316,8 +3339,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;
}
@@ -3343,7 +3369,7 @@ void do_cmd_read_scroll(void)
/* 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
{
@@ -3509,6 +3535,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,7 +3583,7 @@ 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);
@@ -3591,21 +3625,6 @@ void do_cmd_read_scroll(void)
/* 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 +3634,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);
+ }
}
@@ -3634,16 +3696,10 @@ void unset_stick_mode()
*/
void do_cmd_use_staff(void)
{
- int item, ident, chance;
-
- s32b obvious, use_charge;
-
- object_type *o_ptr;
+ bool_ obvious, use_charge;
u32b f1, f2, f3, f4, f5, esp;
- cptr q, s;
-
/* No magic */
if (p_ptr->antimagic)
{
@@ -3651,20 +3707,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,17 +3729,21 @@ 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);
@@ -3706,9 +3766,6 @@ void do_cmd_use_staff(void)
if (flush_failure) flush();
msg_print("You failed to use the staff properly.");
sound(SOUND_FAIL);
-
- /* Leave device mode */
- unset_stick_mode();
return;
}
@@ -3718,9 +3775,6 @@ void do_cmd_use_staff(void)
if (flush_failure) flush();
msg_print("The staff has no charges left.");
o_ptr->ident |= (IDENT_EMPTY);
-
- /* Leave device mode */
- unset_stick_mode();
return;
}
@@ -3728,9 +3782,8 @@ void do_cmd_use_staff(void)
/* 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 +3799,6 @@ void do_cmd_use_staff(void)
/* Hack -- some uses are "free" */
if (!use_charge)
{
- /* Leave device mode */
- unset_stick_mode();
-
return;
}
@@ -3798,9 +3848,6 @@ void do_cmd_use_staff(void)
{
floor_item_charges(0 - item);
}
-
- /* Leave device mode */
- unset_stick_mode();
}
@@ -3826,13 +3873,7 @@ void do_cmd_use_staff(void)
*/
void do_cmd_aim_wand(void)
{
- s32b obvious, use_charge;
-
- int item, ident, chance, sval;
-
- object_type *o_ptr;
-
- cptr q, s;
+ bool_ obvious, use_charge;
u32b f1, f2, f3, f4, f5, esp;
@@ -3844,21 +3885,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,14 +3910,18 @@ 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);
@@ -3894,9 +3938,6 @@ void do_cmd_aim_wand(void)
if (flush_failure) flush();
msg_print("You failed to use the wand properly.");
sound(SOUND_FAIL);
-
- /* Leave device mode */
- unset_stick_mode();
return;
}
@@ -3906,22 +3947,14 @@ void do_cmd_aim_wand(void)
if (flush_failure) flush();
msg_print("The wand has no charges left.");
o_ptr->ident |= (IDENT_EMPTY);
-
- /* Leave device mode */
- unset_stick_mode();
return;
}
-
/* Sound */
sound(SOUND_ZAP);
-
- /* 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 +3965,6 @@ void do_cmd_aim_wand(void)
/* Hack -- some uses are "free" */
if (!use_charge)
{
- /* Leave device mode */
- unset_stick_mode();
-
return;
}
@@ -3962,9 +3992,6 @@ void do_cmd_aim_wand(void)
{
floor_item_charges(0 - item);
}
-
- /* Leave device mode */
- unset_stick_mode();
}
@@ -3985,25 +4012,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));
}
@@ -4014,10 +4040,6 @@ 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;
@@ -4029,16 +4051,18 @@ 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;
+ 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);
@@ -4080,14 +4104,10 @@ void do_cmd_zap_rod(void)
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 +4119,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 */
@@ -4513,11 +4531,7 @@ void do_cmd_zap_rod(void)
}
default:
- {
- process_hooks(HOOK_ZAP, "(d,d)", o_ptr->tval, o_ptr->sval);
-
- break;
- }
+ break;
}
@@ -4552,26 +4566,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(),
+ HasFlag3(TR3_ACTIVATE));
+ return instance;
}
-
/*
* Hack -- activate the ring of power
*/
@@ -4616,7 +4620,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...");
@@ -4718,6 +4722,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
@@ -4733,24 +4884,21 @@ void do_cmd_activate(void)
char ch, spell_choice;
- object_type *o_ptr;
-
u32b f1, f2, f3, f4, f5, esp;
- cptr q, s;
-
-
- /* Prepare the hook */
- item_tester_hook = item_tester_hook_activate;
-
/* Get an item */
command_wrk = USE_EQUIP;
- q = "Activate which item? ";
- s = "You have nothing to activate.";
- if (!get_item(&item, q, s, (USE_EQUIP | USE_INVEN))) return;
+ 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);
@@ -4857,12 +5005,6 @@ void do_cmd_activate(void)
/* 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 */
@@ -4964,8 +5106,6 @@ 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)
{
int plev = get_skill(SKILL_DEVICE);
@@ -4984,7 +5124,7 @@ 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 */
+ /* Random Artifacts */
if (!spell && o_ptr->art_name)
spell = o_ptr->xtra2;
@@ -5004,2685 +5144,2742 @@ 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)
+ /* Activations always have positive numbers */
+ assert(spell > 0);
+
+ /* Activate for attack */
+ switch (spell)
{
- if (doit)
+ case ACT_GILGALAD:
{
- call_lua("activate_activation", "(d,d)", "", -spell, item);
- o_ptr->timeout = exec_lua(format("return get_activation_timeout(%d)", -spell));
+ 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;
}
- else
+
+ case ACT_CELEBRIMBOR:
{
- return string_exec_lua(format("return get_activation_desc(%d)", -spell));
+ if (!doit) return "temporary ESP (dur 20+d20) every 20+d50 turns";
+ set_tim_esp(p_ptr->tim_esp + randint(20) + 20);
+
+ o_ptr->timeout = rand_int(50) + 20;
+
+ break;
}
- }
- else
- {
- /* Activate for attack */
- switch (spell)
+
+ case ACT_SKULLCLEAVER:
{
- case ACT_GILGALAD:
- {
- if (!doit) return "starlight (75) every 75+d75 turns";
- for (k = 1; k < 10; k++)
- {
- if (k - 5) fire_beam(GF_LITE, k, 75);
- }
+ if (!doit) return "destruction every 200+d200 turns";
+ destroy_area(p_ptr->py, p_ptr->px, 15);
- o_ptr->timeout = rand_int(75) + 75;
+ o_ptr->timeout = rand_int(200) + 200;
- 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_HARADRIM:
+ {
+ if (!doit) return "berserk strength every 50+d50 turns";
+ set_afraid(0);
+ set_shero(p_ptr->shero + randint(25) + 25);
+ hp_player(30);
- o_ptr->timeout = rand_int(50) + 20;
+ o_ptr->timeout = rand_int(50) + 50;
- break;
- }
+ break;
+ }
- case ACT_SKULLCLEAVER:
- {
- if (!doit) return "destruction every 200+d200 turns";
- destroy_area(p_ptr->py, p_ptr->px, 15, TRUE, FALSE);
+ case ACT_FUNDIN:
+ {
+ if (!doit) return "dispel evil (x4) every 100+d100 turns";
+ dispel_evil(p_ptr->lev * 4);
- o_ptr->timeout = rand_int(200) + 200;
+ o_ptr->timeout = rand_int(100) + 100;
- 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_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));
- o_ptr->timeout = rand_int(50) + 50;
+ o_ptr->timeout = rand_int(7) + 7;
- break;
- }
+ break;
+ }
- case ACT_FUNDIN:
- {
- if (!doit) return "dispel evil (x4) every 100+d100 turns";
- dispel_evil(p_ptr->lev * 4);
+ 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(100) + 100;
+ o_ptr->timeout = rand_int(20) + 20;
- break;
- }
+ break;
+ }
- case ACT_EOL:
- {
- if (!doit) return "mana bolt (9d8) 7+d7 turns";
- if (!get_aim_dir(&dir)) break;
- fire_bolt(GF_MANA, dir, damroll(9, 8));
+ 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(7) + 7;
+ if (!doit) return "analyze monster every 500+d200 turns";
- break;
- }
+ if (!tgt_pt(&x, &y)) 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));
+ c_ptr = &cave[y][x];
+ if (!c_ptr->m_idx) break;
- o_ptr->timeout = rand_int(20) + 20;
+ 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_NUMENOR:
- {
- /* Give full knowledge */
- /* Hack -- Maximal info */
- monster_race *r_ptr;
- cave_type *c_ptr;
- int x, y, m;
+ /* Hack -- maximal drops */
+ r_ptr->r_drop_gold = r_ptr->r_drop_item =
+ (((r_ptr->flags1 & (RF1_DROP_4D2)) ? 8 : 0) +
+ ((r_ptr->flags1 & (RF1_DROP_3D2)) ? 6 : 0) +
+ ((r_ptr->flags1 & (RF1_DROP_2D2)) ? 4 : 0) +
+ ((r_ptr->flags1 & (RF1_DROP_1D2)) ? 2 : 0) +
+ ((r_ptr->flags1 & (RF1_DROP_90)) ? 1 : 0) +
+ ((r_ptr->flags1 & (RF1_DROP_60)) ? 1 : 0));
+
+ /* Hack -- but only "valid" drops */
+ if (r_ptr->flags1 & (RF1_ONLY_GOLD)) r_ptr->r_drop_item = 0;
+ if (r_ptr->flags1 & (RF1_ONLY_ITEM)) r_ptr->r_drop_gold = 0;
+
+ /* Hack -- observe many spells */
+ r_ptr->r_cast_inate = MAX_UCHAR;
+ r_ptr->r_cast_spell = MAX_UCHAR;
+
+ /* Hack -- know all the flags */
+ r_ptr->r_flags1 = r_ptr->flags1;
+ r_ptr->r_flags2 = r_ptr->flags2;
+ r_ptr->r_flags3 = r_ptr->flags3;
+ r_ptr->r_flags4 = r_ptr->flags4;
+ r_ptr->r_flags5 = r_ptr->flags5;
+ r_ptr->r_flags6 = r_ptr->flags6;
+ r_ptr->r_flags7 = r_ptr->flags7;
+ r_ptr->r_flags8 = r_ptr->flags8;
+ r_ptr->r_flags9 = r_ptr->flags9;
+
+ o_ptr->timeout = rand_int(200) + 500;
- 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");
+ (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);
- /* 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.");
+ (void)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)
+ {
+ (void)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;
+ (void)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();
- o_ptr->timeout = rand_int(200) + 100;
+ break;
+ }
- break;
- }
- case ACT_VILYA:
+ /* The Stone of Lore is perilous, for the sake of game balance. */
+ case ACT_STONE_LORE:
+ {
+ if (!doit) return "perilous identify every turn";
+ msg_print("The stone reveals hidden mysteries...");
+ if (!ident_spell()) break;
+
+ if (has_ability(AB_PERFECT_CASTING))
{
- 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 */
+ (void)set_paralyzed(randint(5 * oops + 1));
- break;
+ /* Confusing. */
+ (void)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;
+ (void)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...");
+ (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);
- 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...");
+ (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);
- 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...");
+ (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);
- 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:
+ {
+ (void)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.");
+ (void)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...");
+ (void)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();
+ (void)detect_traps(DEFAULT_RADIUS);
+ (void)detect_doors(DEFAULT_RADIUS);
+ (void)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))
+ {
+ msg_print("A passage opens, and you step through.");
+ }
+ else
{
- if (!doit) return "open a secret passage every 75 turns";
- msg_print("Your pick twists in your hands.");
+ 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)
+ {
+ (void)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);
+ (void)set_fast(p_ptr->fast + 5, 10);
+ }
+ hp_player(30);
+ set_afraid(0);
+ set_shero(p_ptr->shero + randint(50) + 50);
- o_ptr->timeout = rand_int(200) + 100;
+ 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...");
+ (void)detect_monsters_xxx(RF3_ORC, 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;
+ (void)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...");
+ (void)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...");
+ (void)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;
+ (void) 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;
+ (void)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;
+ (void) 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";
+ (void) 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";
+ (void)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.");
+ (void)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));
+ (void)set_afraid(0);
+ (void)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));
+ (void)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...");
+ (void)set_afraid(0);
+ (void)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...");
+ (void)do_res_stat(A_STR, TRUE);
+ (void)do_res_stat(A_INT, TRUE);
+ (void)do_res_stat(A_WIS, TRUE);
+ (void)do_res_stat(A_DEX, TRUE);
+ (void)do_res_stat(A_CON, TRUE);
+ (void)do_res_stat(A_CHR, TRUE);
+ (void)restore_level();
- o_ptr->timeout = 750;
+ 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...");
+ (void)hp_player(700);
+ (void)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...");
+ (void)hp_player(1000);
+ (void)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";
+ (void)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";
+ (void)set_shero(p_ptr->shero + randint(50) + 50);
+ (void)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;
+ (void)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...");
+ (void)set_oppose_acid(p_ptr->oppose_acid + randint(40) + 40);
+ (void)set_oppose_elec(p_ptr->oppose_elec + randint(40) + 40);
+ (void)set_oppose_fire(p_ptr->oppose_fire + randint(40) + 40);
+ (void)set_oppose_cold(p_ptr->oppose_cold + randint(40) + 40);
+ (void)set_oppose_pois(p_ptr->oppose_pois + randint(40) + 40);
- o_ptr->timeout = 200;
+ 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);
- }
+ (void)set_fast(randint(20) + 20, 10);
+ }
+ else
+ {
+ (void)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);
- }
+ (void)set_fast(randint(75) + 75, 10);
+ }
+ else
+ {
+ (void)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";
+ (void)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, probing and identify true every 1000 turns";
+ msg_print("It glows brightly...");
+ detect_all(DEFAULT_RADIUS);
+ probing();
+ 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";
+ (void)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...");
+ (void) alchemy();
- o_ptr->timeout = 500;
+ o_ptr->timeout = 500;
+
+ break;
+ }
+ case ACT_DIM_DOOR:
+ {
+ if (!doit) return "dimension door every 100 turns";
+ if (dungeon_flags2 & DF2_NO_TELEPORT)
+ {
+ msg_print("Not on special levels!");
break;
}
- 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_flags2 & DF2_ASK_LEAVE) || ((dungeon_flags2 & DF2_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");
+ (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);
- 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";
+ (void)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";
+ (void)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";
+ (void)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";
+ (void)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";
+ (void)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";
+ (void)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";
+ (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_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";
+ (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_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";
+ (void)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";
+ (void)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;
- if (!doit) return "light absorption every 80 turns";
+ c_ptr = &cave[y][x];
- 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 (distance(y, x, p_ptr->py, p_ptr->px) > 6) continue;
+
+ if (c_ptr->info & CAVE_GLOW)
{
- if (!in_bounds(y, x)) continue;
+ light++;
+
+ /* No longer in the array */
+ c_ptr->info &= ~(CAVE_TEMP);
+
+ /* Darken the grid */
+ c_ptr->info &= ~(CAVE_GLOW);
- c_ptr = &cave[y][x];
+ /* Hack -- Forget "boring" grids */
+ if (cave_plain_floor_grid(c_ptr) &&
+ !(c_ptr->info & (CAVE_TRDT)))
+ {
+ /* Forget the grid */
+ c_ptr->info &= ~(CAVE_MARK);
- if (distance(y, x, p_ptr->py, p_ptr->px) > 6) continue;
+ /* Notice */
+ note_spot(y, x);
+ }
- if (c_ptr->info & CAVE_GLOW)
+ /* Process affected monsters */
+ if (c_ptr->m_idx)
{
- 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);
+ /* 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;
+
+ /* 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;
+ /* Window stuff */
+ p_ptr->window |= (PW_INVEN | PW_EQUIP);
- /* Done */
- break;
+ /* 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);
+ (void)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);
+ (void)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);
+ (void)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);
+ (void)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";
+
+ 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!'");
+
+ 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!'");
+
+ o_ptr->timeout = 3;
+
+ break;
+ }
+ case ACT_RADAGAST:
+ {
+ if (!doit) return "purity and health every 15000 turns";
+
+ activate_radagast();
+ o_ptr->timeout = 15000;
+
+ break;
+ }
+ case ACT_VALAROMA:
+ {
+ if (!doit) return "banish evil (level x5) every 250 turns";
+
+ activate_valaroma();
+ o_ptr->timeout = 250;
+
+ break;
+ }
+ default:
+ {
+ msg_format("Unknown activation effect: %d.", spell);
+ if ( !doit ) return "Unknown Activation";
+ return NULL;
}
}
diff --git a/src/cmd6.hpp b/src/cmd6.hpp
new file mode 100644
index 00000000..ad6619f6
--- /dev/null
+++ b/src/cmd6.hpp
@@ -0,0 +1,18 @@
+#pragma once
+
+#include "h-basic.h"
+#include "object_type_fwd.hpp"
+
+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_cut_corpse(void);
+extern void do_cmd_cure_meat(void);
+extern void do_cmd_drink_fountain(void);
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..2317f8b9
--- /dev/null
+++ b/src/cmd7.cc
@@ -0,0 +1,4466 @@
+/*
+ * 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 "ego_item_type.hpp"
+#include "files.hpp"
+#include "hooks.hpp"
+#include "mimic.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_type.hpp"
+#include "quark.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"
+
+/*
+ * Describe class powers of Mindcrafters
+ *
+ * 'p' points to a 80 byte long buffer
+ */
+void mindcraft_info(char *p, int power)
+{
+ int plev = get_skill(SKILL_MINDCRAFT);
+
+
+ /* Clear buffer */
+ strcpy(p, "");
+
+ /* Fill the buffer with requested power description */
+ switch (power)
+ {
+ case 0:
+ strnfmt(p, 80, " rad %d", DEFAULT_RADIUS);
+ break;
+ case 1:
+ strnfmt(p, 80, " dam %dd%d", 3 + ((plev - 1) / 4), 3 + plev / 15);
+ break;
+ case 2:
+ strnfmt(p, 80, " range %d", (plev < 25 ? 10 : plev + 2 + p_ptr->to_s * 3));
+ break;
+ case 3:
+ strnfmt(p, 80, " range %d", plev * 5);
+ break;
+ case 4:
+ strnfmt(p, 80, " power %d", plev * (plev < 30 ? 1 : 2));
+ break;
+ case 5:
+ if (plev > 20)
+ strnfmt(p, 80, " dam %dd8 rad %d", 8 + ((plev - 5) / 4), (plev - 20)/8 + 1);
+ else
+ strnfmt(p, 80, " dam %dd8", 8 + ((plev - 5) / 4));
+ break;
+ case 6:
+ strnfmt(p, 80, " dur %d", plev);
+ break;
+ case 7:
+ break;
+ case 8:
+ if (plev < 25)
+ strnfmt(p, 80, " dam %d rad %d", (3 * plev) / 2, 2 + (plev / 10));
+ else
+ strnfmt(p, 80, " dam %d", plev * ((plev - 5) / 10 + 1));
+ break;
+ case 9:
+ strnfmt(p, 80, " dur 11-%d", 10 + plev + plev / 2);
+ break;
+ case 10:
+ strnfmt(p, 80, " dam %dd6 rad %d", plev / 2, 0 + (plev - 25) / 10);
+ break;
+ case 11:
+ strnfmt(p, 80, " dam %d rad %d", plev * (plev > 39 ? 4 : 3), 3 + plev / 10);
+ break;
+ }
+}
+
+
+/*
+ * Describe class powers of Mimics
+ *
+ * 'p' points to a 80 byte long buffer
+ */
+void mimic_info(char *p, int power)
+{
+ int plev = get_skill(SKILL_MIMICRY);
+ object_type *o_ptr = &p_ptr->inventory[INVEN_OUTER];
+
+ /* Clear the buffer */
+ strcpy(p, "");
+
+ /* Fill the buffer with requested power description */
+ switch (power)
+ {
+ case 0:
+ strnfmt(p, 80, " dur %d", k_info[o_ptr->k_idx].pval2 + get_skill_scale(SKILL_MIMICRY, 1000));
+ break;
+ case 1:
+ strnfmt(p, 80, " dur %d+d20", 10 + plev);
+ break;
+ case 2:
+ strnfmt(p, 80, " dur 50+d%d", 50 + (2 * plev));
+ break;
+ case 3:
+ strnfmt(p, 80, " dur 50+d%d", 50 + (2 * plev));
+ break;
+ case 4:
+ strnfmt(p, 80, " dur 50+d%d", 50 + (2 * plev));
+ break;
+ }
+}
+
+/**
+ * Show magic powers that user can choose from
+ */
+static void display_magic_powers(
+ magic_power *powers,
+ int max_powers,
+ void (*power_info)(char *p, int power),
+ int plev,
+ int cast_stat,
+ int y,
+ int x)
+{
+ char psi_desc[80];
+ magic_power spell;
+ int i;
+ int chance = 0;
+ int minfail = 0;
+ char comment[80];
+
+ /* Display a list of spells */
+ prt("", 1, x);
+ prt("", y, x);
+ put_str("Name", y, x + 5);
+ put_str("Lv Mana Fail Info", y, x + 35);
+
+ /* Dump the spells */
+ for (i = 0; i < max_powers; i++)
+ {
+ /* Access the spell */
+ spell = powers[i];
+ if (spell.min_lev > plev)
+ {
+ break;
+ }
+
+ chance = spell.fail;
+ /* Reduce failure rate by "effective" level adjustment */
+ chance -= 3 * (plev - spell.min_lev);
+
+ /* Reduce failure rate by INT/WIS adjustment */
+ chance -= 3 * (adj_mag_stat[p_ptr->stat_ind[cast_stat]] - 1);
+
+ /* Not enough mana to cast */
+ if (spell.mana_cost > p_ptr->csp)
+ {
+ chance += 5 * (spell.mana_cost - p_ptr->csp);
+ }
+
+ /* Extract the minimum failure rate */
+ minfail = adj_mag_fail[p_ptr->stat_ind[cast_stat]];
+
+ /* Failure rate */
+ chance = clamp_failure_chance(chance, minfail);
+
+ /* Get info */
+ power_info(comment, i);
+
+ /* Dump the spell --(-- */
+ strnfmt(psi_desc, 80, " %c) %-30s%2d %4d %3d%%%s",
+ I2A(i), spell.name,
+ spell.min_lev, spell.mana_cost, chance, comment);
+ prt(psi_desc, y + i + 1, x);
+ }
+
+ /* Clear the bottom line */
+ prt("", y + i + 1, x);
+}
+
+/*
+ * Allow user to choose a magic power.
+ *
+ * If a valid spell is chosen, saves it in '*sn' and returns TRUE
+ * If the user hits escape, returns FALSE, and set '*sn' to -1
+ * If there are no legal choices, returns FALSE, and sets '*sn' to -2
+ *
+ * The "prompt" should be "cast", "recite", or "study"
+ * The "known" should be TRUE for cast/pray, FALSE for study
+ *
+ * nb: This function has a (trivial) display bug which will be obvious
+ * when you run it. It's probably easy to fix but I haven't tried,
+ * sorry.
+ */
+static bool_ get_magic_power(int *sn, magic_power *powers, int max_powers,
+ void (*power_info)(char *p, int power), int plev, int cast_stat)
+{
+ int i;
+
+ int num = 0;
+
+ int y = 2;
+
+ int x = 18;
+
+ int info;
+
+ char choice;
+
+ char out_val[160];
+
+ cptr p = "power";
+
+ magic_power spell;
+
+ bool_ flag;
+
+
+ /* Assume cancelled */
+ *sn = ( -1);
+
+ /* Get the spell, if available */
+ if (repeat_pull(sn))
+ {
+ /* Verify the spell */
+ if (powers[*sn].min_lev <= plev)
+ {
+ /* Success */
+ return (TRUE);
+ }
+ }
+
+ /* Nothing chosen yet */
+ flag = FALSE;
+
+ /* Count number of powers that satisfies minimum plev requirement */
+ for (i = 0; i < max_powers; i++)
+ {
+ if (powers[i].min_lev <= plev)
+ {
+ num++;
+ }
+ }
+
+ /* Build a prompt (accept all spells) */
+ strnfmt(out_val, 78, "(%^ss %c-%c, ESC=exit, %c-%c=Info) Use which %s? ",
+ p, I2A(0), I2A(num - 1), toupper(I2A(0)), toupper(I2A(num - 1)), p);
+
+ /* Save the screen */
+ character_icky = TRUE;
+ Term_save();
+
+ /* Show the list */
+ display_magic_powers(powers, max_powers, power_info, plev, cast_stat, y, x);
+
+ /* Get a spell from the user */
+ while (!flag && get_com(out_val, &choice))
+ {
+ /* Note verify */
+ info = (isupper(choice));
+
+ /* Lowercase */
+ if (info) choice = tolower(choice);
+
+ /* Extract request */
+ i = (islower(choice) ? A2I(choice) : -1);
+
+ /* Totally Illegal */
+ if ((i < 0) || (i >= num))
+ {
+ bell();
+ continue;
+ }
+
+ /* Save the spell index */
+ spell = powers[i];
+
+ /* Provides info */
+ if (info)
+ {
+ c_prt(TERM_L_BLUE, spell.desc, 1, 0);
+
+ /* Restore the screen */
+ inkey();
+ Term_load();
+ character_icky = FALSE;
+
+ /* Redisplay choices */
+ display_magic_powers(powers, max_powers, power_info, plev, cast_stat, y, x);
+ continue;
+ }
+
+ /* Stop the loop */
+ flag = TRUE;
+ }
+
+ /* Restore the screen */
+ Term_load();
+ character_icky = FALSE;
+
+ /* Abort if needed */
+ if (!flag) return (FALSE);
+
+ /* Save the choice */
+ (*sn) = i;
+
+
+ repeat_push(*sn);
+
+ /* Success */
+ return (TRUE);
+}
+
+
+/*
+ * do_cmd_cast calls this function if the player's class
+ * is 'mindcrafter'.
+ */
+void do_cmd_mindcraft(void)
+{
+ int n = 0, b = 0;
+
+ int chance;
+
+ int dir;
+
+ int minfail = 0;
+
+ int plev = get_skill(SKILL_MINDCRAFT);
+
+ magic_power spell;
+
+
+ /* No magic */
+ if (p_ptr->antimagic)
+ {
+ msg_print("Your anti-magic field disrupts any magic attempts.");
+ return;
+ }
+
+ /* No magic */
+ if (p_ptr->anti_magic)
+ {
+ msg_print("Your anti-magic shell disrupts any magic attempts.");
+ return;
+ }
+
+
+ /* not if confused */
+ if (p_ptr->confused)
+ {
+ msg_print("You are too confused!");
+ return;
+ }
+
+ /* get power */
+ if (!get_magic_power(&n, mindcraft_powers, MAX_MINDCRAFT_POWERS,
+ mindcraft_info, plev, A_WIS)) return;
+
+ spell = mindcraft_powers[n];
+
+ /* Verify "dangerous" spells */
+ if (spell.mana_cost > p_ptr->csp)
+ {
+ /* Warning */
+ msg_print("You do not have enough mana to use this power.");
+
+ /* Verify */
+ if (!get_check("Attempt it anyway? ")) return;
+ }
+
+ /* Spell failure chance */
+ chance = spell.fail;
+
+ /* Reduce failure rate by "effective" level adjustment */
+ chance -= 3 * (get_skill(SKILL_MINDCRAFT) - spell.min_lev);
+
+ /* Reduce failure rate by INT/WIS adjustment */
+ chance -= 3 * (adj_mag_stat[p_ptr->stat_ind[A_WIS]] - 1);
+
+ /* Not enough mana to cast */
+ if (spell.mana_cost > p_ptr->csp)
+ {
+ chance += 5 * (spell.mana_cost - p_ptr->csp);
+ }
+
+ /* Extract the minimum failure rate */
+ minfail = adj_mag_fail[p_ptr->stat_ind[A_WIS]];
+
+ /* Failure rate */
+ chance = clamp_failure_chance(chance, minfail);
+
+ /* Failed spell */
+ if (rand_int(100) < chance)
+ {
+ if (flush_failure) flush();
+
+ msg_format("You failed to concentrate hard enough!");
+
+ sound(SOUND_FAIL);
+
+ if (randint(100) < (chance / 2))
+ {
+ /* Backfire */
+ b = randint(100);
+ if (b < 5)
+ {
+ msg_print("Oh, no! Your mind has gone blank!");
+ lose_all_info();
+ }
+ else if (b < 15)
+ {
+ msg_print("Weird visions seem to dance before your eyes...");
+ set_image(p_ptr->image + 5 + randint(10));
+ }
+ else if (b < 45)
+ {
+ msg_print("Your brain is addled!");
+ set_confused(p_ptr->confused + randint(8));
+ }
+ else if (b < 90)
+ {
+ set_stun(p_ptr->stun + randint(8));
+ }
+ else
+ {
+ /* Mana storm */
+ msg_print("Your mind unleashes its power in an uncontrollable storm!");
+ project(1, 2 + plev / 10, p_ptr->py, p_ptr->px, plev * 2,
+ GF_MANA, PROJECT_JUMP | PROJECT_KILL | PROJECT_GRID | PROJECT_ITEM);
+ p_ptr->csp = MAX(0, p_ptr->csp - plev * MAX(1, plev / 10));
+ }
+ }
+ }
+
+ /* Successful spells */
+ else
+ {
+ sound(SOUND_ZAP);
+
+ /* spell code */
+ switch (n)
+ {
+ /* Precog */
+ case 0:
+ {
+ /* Magic mapping */
+ if (plev > 44)
+ {
+ wiz_lite();
+ }
+ else if (plev > 19)
+ {
+ map_area();
+ }
+
+ /* Detection */
+ if (plev < 30)
+ {
+ b = detect_monsters_normal(DEFAULT_RADIUS);
+ if (plev > 14) b |= detect_monsters_invis(DEFAULT_RADIUS);
+ if (plev > 4) b |= detect_traps(DEFAULT_RADIUS);
+ }
+ else
+ {
+ b = detect_all(DEFAULT_RADIUS);
+ }
+
+ /* Telepathy */
+ if (plev > 24)
+ {
+ set_tim_esp(p_ptr->tim_esp + plev);
+
+ /* If plvl >= 40, we should have permanent ESP */
+ }
+
+ if (!b) msg_print("You feel safe.");
+
+ break;
+ }
+
+ /* Mindblast */
+ case 1:
+ {
+ if (!get_aim_dir(&dir)) return;
+
+ if (randint(100) < plev * 2)
+ {
+ fire_beam(GF_PSI, dir, damroll(3 + ((plev - 1) / 4), (3 + plev / 15)));
+ }
+ else
+ {
+ fire_ball(GF_PSI, dir, damroll(3 + ((plev - 1) / 4), (3 + plev / 15)), 0);
+ }
+
+ break;
+ }
+
+ /* Minor displace */
+ case 2:
+ {
+ if (plev < 25)
+ {
+ teleport_player(10);
+ }
+ else
+ {
+ int ii, ij;
+
+ if (dungeon_flags2 & DF2_NO_TELEPORT)
+ {
+ msg_print("Not on special levels!");
+ break;
+ }
+
+ msg_print("You open a Void Jumpgate. Choose a destination.");
+
+ if (!tgt_pt(&ii, &ij)) return;
+ p_ptr->energy -= 60 - plev;
+
+ if (!cave_empty_bold(ij, ii) ||
+ (cave[ij][ii].info & CAVE_ICKY) ||
+ (distance(ij, ii, p_ptr->py, p_ptr->px) > plev + 2 + (p_ptr->to_s*3)) ||
+ (rand_int(plev * plev / 2) == 0))
+ {
+ msg_print("You fail to exit the void correctly!");
+ p_ptr->energy -= 100;
+ get_pos_player(10 + p_ptr->to_s / 2, &ij, &ii);
+ }
+
+ cave_set_feat(p_ptr->py, p_ptr->px, FEAT_BETWEEN);
+ cave_set_feat(ij, ii, FEAT_BETWEEN);
+ cave[p_ptr->py][p_ptr->px].special = ii + (ij << 8);
+ cave[ij][ii].special = p_ptr->px + (p_ptr->py << 8);
+ }
+
+ break;
+ }
+
+ /* Major displace */
+ case 3:
+ {
+ if (plev > 29) banish_monsters(plev);
+ teleport_player(plev * 5);
+
+ break;
+ }
+
+ /* Domination */
+ case 4:
+ {
+ if (plev < 30)
+ {
+ if (!get_aim_dir(&dir)) return;
+ fire_ball(GF_DOMINATION, dir, plev, 0);
+ }
+ else
+ {
+ charm_monsters(plev * 2);
+ }
+
+ break;
+ }
+
+ /* Fist of Force --- not 'true' TK */
+ case 5:
+ {
+ if (!get_aim_dir(&dir)) return;
+ fire_ball(GF_SOUND, dir, damroll(8 + ((plev - 5) / 4), 8),
+ (plev > 20 ? (plev - 20) / 8 + 1 : 0));
+
+ break;
+ }
+
+ /* Character Armour */
+ case 6:
+ {
+ set_shield(p_ptr->shield + plev, plev, 0, 0, 0);
+ if (plev > 14) set_oppose_acid(p_ptr->oppose_acid + plev);
+ if (plev > 19) set_oppose_fire(p_ptr->oppose_fire + plev);
+ if (plev > 24) set_oppose_cold(p_ptr->oppose_cold + plev);
+ if (plev > 29) set_oppose_elec(p_ptr->oppose_elec + plev);
+ if (plev > 34) set_oppose_pois(p_ptr->oppose_pois + plev);
+
+ break;
+ }
+
+ /* Psychometry */
+ case 7:
+ {
+ ident_spell();
+ break;
+ }
+
+ /* Mindwave */
+ case 8:
+ {
+ msg_print("Mind-warping forces emanate from your brain!");
+ if (plev < 25)
+ {
+ project(0, 2 + plev / 10, p_ptr->py, p_ptr->px,
+ (plev*3) / 2, GF_PSI, PROJECT_KILL);
+ }
+ else
+ {
+ (void)mindblast_monsters(plev * ((plev - 5) / 10 + 1));
+ }
+
+ break;
+ }
+
+ /* Adrenaline */
+ case 9:
+ {
+ set_afraid(0);
+ set_stun(0);
+ hp_player(plev);
+
+ b = 10 + randint((plev * 3) / 2);
+
+ if (plev < 35)
+ {
+ set_hero(p_ptr->hero + b);
+ }
+ else
+ {
+ set_shero(p_ptr->shero + b);
+ }
+
+ if (!p_ptr->fast)
+ {
+ /* Haste */
+ (void)set_fast(b, plev / 5);
+ }
+ else
+ {
+ (void)set_fast(p_ptr->fast + b, plev / 5);
+ }
+
+ break;
+ }
+
+ /* Psychic Drain */
+ case 10:
+ {
+ if (!get_aim_dir(&dir)) return;
+
+ b = damroll(plev / 2, 6);
+
+ if (fire_ball(GF_PSI_DRAIN, dir, b, 0 + (plev - 25) / 10))
+ {
+ p_ptr->energy -= randint(150);
+ }
+
+ break;
+ }
+
+ /* Telekinesis */
+ case 11:
+ {
+ msg_print("A wave of pure physical force radiates out from your body!");
+ project(0, 3 + plev / 10, p_ptr->py, p_ptr->px,
+ plev * (plev > 39 ? 4 : 3), GF_TELEKINESIS,
+ PROJECT_KILL | PROJECT_ITEM | PROJECT_GRID);
+
+ break;
+ }
+
+ default:
+ {
+ msg_print("Zap?");
+
+ break;
+ }
+ }
+ }
+
+ /* Take a turn */
+ energy_use = 100;
+
+ /* Sufficient mana */
+ if (spell.mana_cost <= p_ptr->csp)
+ {
+ /* Use some mana */
+ p_ptr->csp -= spell.mana_cost;
+ }
+
+ /* Over-exert the player */
+ else
+ {
+ int oops = spell.mana_cost - p_ptr->csp;
+
+ /* No mana left */
+ p_ptr->csp = 0;
+ p_ptr->csp_frac = 0;
+
+ /* Message */
+ msg_print("You faint from the effort!");
+
+ /* Hack -- Bypass free action */
+ (void)set_paralyzed(randint(5 * oops + 1));
+
+ /* Damage WIS (possibly permanently) */
+ if (rand_int(100) < 50)
+ {
+ bool_ perm = (rand_int(100) < 25);
+
+ /* Message */
+ msg_print("You have damaged your mind!");
+
+ /* Reduce constitution */
+ (void)dec_stat(A_WIS, 15 + randint(10), perm);
+ }
+ }
+
+ /* Redraw mana */
+ p_ptr->redraw |= (PR_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()
+{
+ 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(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_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)
+ {
+ if (flush_failure) flush();
+
+ msg_format("You failed to concentrate hard enough!");
+
+ sound(SOUND_FAIL);
+
+ if (randint(100) < (fail / 2))
+ {
+ /* Backfire */
+ b = randint(100);
+
+ if (b < 5)
+ {
+ msg_print("Oh, no! Your mind has gone blank!");
+ lose_all_info();
+ }
+ else if (b < 15)
+ {
+ msg_print("Weird visions seem to dance before your eyes...");
+ set_image(p_ptr->image + 5 + randint(10));
+ }
+ else if (b < 45)
+ {
+ msg_print("Your brain is addled!");
+ set_confused(p_ptr->confused + randint(8));
+ }
+ else
+ {
+ set_stun(p_ptr->stun + randint(8));
+ }
+ }
+ }
+
+ /* Successful spells */
+ else
+ {
+ sound(SOUND_ZAP);
+
+ /* spell code */
+ switch (n)
+ {
+ /* Mimic */
+ case 0:
+ {
+ do_cmd_mimic_lore();
+
+ break;
+ }
+
+ /* Invisibility */
+ case 1:
+ {
+ int ii = 10 + plev + randint(20) + p_ptr->to_s;
+
+ set_invis(p_ptr->tim_invisible + ii, 50);
+ set_tim_invis(p_ptr->tim_invisible + ii);
+
+ break;
+ }
+
+ /* Legs Mimicry */
+ case 2:
+ {
+ /* Extract the value and the flags */
+ u32b value = p_ptr->mimic_extra >> 16;
+ u32b att = p_ptr->mimic_extra & 0xFFFF;
+
+ /* Clear useless things */
+ att &= ~(CLASS_ARMS);
+ att &= ~(CLASS_WALL);
+
+ if (att & CLASS_LEGS)
+ {
+ value += 50 + randint(50 + (2 * plev));
+ }
+ else
+ {
+ msg_print("You mimic a new pair of legs.");
+
+ value = 50 + randint(50 + (2 * plev));
+ att |= (CLASS_LEGS);
+ }
+
+ if (value > 10000) value = 10000;
+
+ p_ptr->mimic_extra = att + (value << 16);
+ p_ptr->update |= (PU_BODY);
+
+ break;
+ }
+
+ /* Wall Mimicry */
+ case 3:
+ {
+ /* Extract the value and the flags */
+ u32b value = p_ptr->mimic_extra >> 16;
+ u32b att = p_ptr->mimic_extra & 0xFFFF;
+
+ /* Clear useless things */
+ att &= ~(CLASS_ARMS);
+ att &= ~(CLASS_LEGS);
+
+ if (att & CLASS_WALL)
+ {
+ value += 50 + randint(50 + (2 * plev));
+ }
+ else
+ {
+ msg_print("You grow an affinity for walls.");
+
+ value = 50 + randint(50 + (2 * plev));
+ att |= (CLASS_WALL);
+ }
+
+ if (value > 10000) value = 10000;
+
+ p_ptr->mimic_extra = att + (value << 16);
+ p_ptr->update |= (PU_BODY);
+
+ break;
+ }
+
+ case 4: /* Arms Mimicry */
+ {
+ /* Extract the value and the flags */
+ u32b value = p_ptr->mimic_extra >> 16;
+ u32b att = p_ptr->mimic_extra & 0xFFFF;
+
+ /* Clear useless things */
+ att &= ~(CLASS_LEGS);
+ att &= ~(CLASS_WALL);
+
+ if (att & CLASS_ARMS)
+ {
+ value += 50 + randint(50 + (2 * plev));
+ }
+ else
+ {
+ msg_print("You mimic a new pair of arms.");
+
+ value = 50 + randint(50 + (2 * plev));
+ att |= (CLASS_ARMS);
+ }
+
+ if (value > 10000) value = 10000;
+
+ p_ptr->mimic_extra = att + (value << 16);
+ p_ptr->update |= (PU_BODY);
+
+ break;
+ }
+
+ default:
+ {
+ msg_print("Zap?");
+
+ break;
+ }
+ }
+ }
+
+
+ /* Take a turn */
+ energy_use = 100;
+
+ /* Sufficient mana */
+ if (spell.mana_cost <= p_ptr->csp)
+ {
+ /* Use some mana */
+ p_ptr->csp -= spell.mana_cost;
+ }
+
+ /* Over-exert the player */
+ else
+ {
+ int oops = spell.mana_cost - p_ptr->csp;
+
+ /* No mana left */
+ p_ptr->csp = 0;
+ p_ptr->csp_frac = 0;
+
+ /* Message */
+ msg_print("You faint from the effort!");
+
+ /* Hack -- Bypass free action */
+ (void)set_paralyzed(randint(5 * oops + 1));
+
+ /* Damage WIS (possibly permanently) */
+ if (rand_int(100) < 50)
+ {
+ bool_ perm = (rand_int(100) < 25);
+
+ /* Message */
+ msg_print("You have damaged your mind!");
+
+ /* Reduce constitution */
+ (void)dec_stat(A_DEX, 15 + randint(10), perm);
+ }
+ }
+
+ /* Redraw mana */
+ p_ptr->redraw |= (PR_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(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);
+}
+
+
+/*
+ * 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_WIPE | PR_FRAME | PR_MAP;
+ energy_use = 100;
+ }
+}
+
+
+/*
+ * Return percentage chance of spell failure.
+ */
+int spell_chance_random(random_spell* rspell)
+{
+ int chance, minfail;
+
+
+ /* Extract the base spell failure rate */
+ chance = rspell->level + 10;
+
+ /* Reduce failure rate by "effective" level adjustment */
+ chance -= 3 * (get_skill(SKILL_THAUMATURGY) - rspell->level);
+
+ /* Reduce failure rate by INT/WIS adjustment */
+ chance -= 3 * (adj_mag_stat[p_ptr->stat_ind[A_INT]] - 1);
+
+ /* Not enough mana to cast */
+ if (rspell->mana > p_ptr->csp)
+ {
+ chance += 5 * (rspell->mana - p_ptr->csp);
+ }
+
+ /* Extract the minimum failure rate */
+ minfail = adj_mag_fail[p_ptr->stat_ind[A_INT]];
+
+ /* Failure rate */
+ return clamp_failure_chance(chance, minfail);
+}
+
+
+
+
+/*
+ * Print a batch of spells.
+ */
+static void print_spell_batch(int batch, int max)
+{
+ char buff[80];
+
+ random_spell* rspell;
+
+ int i;
+
+
+ prt(format(" %-30s Lev Fail Mana Damage ", "Name"), 1, 20);
+
+ for (i = 0; i < max; i++)
+ {
+ rspell = &random_spells[batch * 10 + i];
+
+ if (rspell->untried)
+ {
+ strnfmt(buff, 80, " %c) %-30s (Spell untried) ",
+ I2A(i), rspell->name);
+
+ }
+ else
+ {
+ strnfmt(buff, 80, " %c) %-30s %3d %4d%% %3d %3dd%d ",
+ I2A(i), rspell->name,
+ rspell->level, spell_chance_random(rspell), rspell->mana,
+ rspell->dam_dice, rspell->dam_sides);
+ }
+
+ prt(buff, 2 + i, 20);
+ }
+
+ prt("", 2 + i, 20);
+}
+
+
+
+/*
+ * List ten random spells and ask to pick one.
+ */
+static random_spell* select_spell_from_batch(int batch)
+{
+ char tmp[160];
+
+ char out_val[30];
+
+ char which;
+
+ int mut_max = 10;
+
+ random_spell* ret;
+
+
+ /* Enter "icky" mode */
+ character_icky = TRUE;
+
+ /* Save the screen */
+ Term_save();
+
+ if (spell_num < (batch + 1) * 10)
+ {
+ mut_max = spell_num - batch * 10;
+ }
+
+ strnfmt(tmp, 160, "(a-%c, A-%c to browse, / to rename, - to comment) Select a power: ",
+ I2A(mut_max - 1), I2A(mut_max - 1) - 'a' + 'A');
+
+ prt(tmp, 0, 0);
+
+ while (1)
+ {
+ /* Print power list */
+ print_spell_batch(batch, mut_max);
+
+ /* Get a command */
+ which = inkey();
+
+ /* Abort */
+ if (which == ESCAPE)
+ {
+ /* No selection */
+ ret = NULL;
+
+ /* Leave the command loop */
+ break;
+
+ }
+
+ /* Accept default */
+ if (which == '\r')
+ {
+ /* There are no other choices */
+ if (mut_max == 1)
+ {
+ ret = &random_spells[batch * 10];
+
+ /* Leave the command loop */
+ break;
+ }
+
+ /* Wait for next command */
+ continue;
+ }
+
+ /* Rename */
+ if (which == '/')
+ {
+ prt("Rename which power: ", 0, 0);
+ which = tolower(inkey());
+
+ if (isalpha(which) && (A2I(which) <= mut_max))
+ {
+ strcpy(out_val, random_spells[batch*10 + A2I(which)].name);
+ if (get_string("Name this power: ", out_val, 29))
+ {
+ strcpy(random_spells[batch*10 + A2I(which)].name, out_val);
+ }
+ prt(tmp, 0, 0);
+ }
+ else
+ {
+ bell();
+ prt(tmp, 0, 0);
+ }
+
+ /* Wait for next command */
+ continue;
+ }
+
+ /* Comment */
+ if (which == '-')
+ {
+ prt("Comment which power: ", 0, 0);
+ which = tolower(inkey());
+
+ if (isalpha(which) && (A2I(which) <= mut_max))
+ {
+ strcpy(out_val, random_spells[batch*10 + A2I(which)].desc);
+ if (get_string("Comment this power: ", out_val, 29))
+ {
+ strcpy(random_spells[batch*10 + A2I(which)].desc, out_val);
+ }
+ prt(tmp, 0, 0);
+ }
+ else
+ {
+ bell();
+ prt(tmp, 0, 0);
+ }
+
+ /* Wait for next command */
+ continue;
+ }
+
+ if (isalpha(which) && isupper(which))
+ {
+ which = tolower(which);
+ c_prt(TERM_L_BLUE, format("%s : %s", random_spells[batch*10 + A2I(which)].name, random_spells[batch*10 + A2I(which)].desc), 0, 0);
+ inkey();
+ prt(tmp, 0, 0);
+ continue;
+ }
+ else if (isalpha(which) && (A2I(which) < mut_max))
+ {
+ /* Pick the power */
+ ret = &random_spells[batch * 10 + A2I(which)];
+
+ /* Leave the command loop */
+ break;
+ }
+ else
+ {
+ bell();
+ }
+ }
+
+ /* Restore the screen */
+ Term_load();
+
+ /* Leave "icky" mode */
+ character_icky = FALSE;
+
+ /* Return selection */
+ return (ret);
+}
+
+
+/*
+ * Pick a random spell from a menu
+ */
+static random_spell* select_spell()
+{
+ char tmp[160];
+
+ char which;
+
+ int batch_max = (spell_num - 1) / 10;
+
+ random_spell *ret;
+
+
+ /* Too confused */
+ if (p_ptr->confused)
+ {
+ msg_print("You can't use your powers while confused!");
+ return NULL;
+ }
+
+ /* No spells available */
+ if (spell_num == 0)
+ {
+ msg_print("There are no spells you can cast.");
+ return NULL;
+ }
+
+ /* Enter "icky" mode */
+ character_icky = TRUE;
+
+ /* Save the screen */
+ Term_save();
+
+ strnfmt(tmp, 160, "(a-%c) Select batch of powers: ", I2A(batch_max));
+
+ prt(tmp, 0, 0);
+
+ while (1)
+ {
+ which = inkey();
+
+ if (which == ESCAPE)
+ {
+ Term_load();
+
+ ret = NULL;
+
+ break;
+ }
+
+ if (which == '\r')
+ {
+ if (batch_max == 0)
+ {
+ Term_load();
+
+ ret = select_spell_from_batch(0);
+
+ break;
+ }
+
+ continue;
+ }
+
+ which = tolower(which);
+ if (isalpha(which) && (A2I(which) <= batch_max))
+ {
+ Term_load();
+
+ ret = select_spell_from_batch(A2I(which));
+
+ break;
+ }
+ else
+ {
+ bell();
+ }
+ }
+
+ /* Leave "icky" mode */
+ character_icky = FALSE;
+
+ return (ret);
+}
+
+
+void do_cmd_powermage(void)
+{
+ random_spell *s_ptr;
+
+ u32b proj_flags;
+
+ int dir, chance;
+
+ int ty = 0, tx = 0;
+
+
+ /* No magic */
+ if (p_ptr->antimagic)
+ {
+ msg_print("Your anti-magic field disrupts any magic attempts.");
+ return;
+ }
+
+ /* No magic */
+ if (p_ptr->anti_magic)
+ {
+ msg_print("Your anti-magic shell disrupts any magic attempts.");
+ return;
+ }
+
+
+ s_ptr = select_spell();
+
+ if (s_ptr == NULL) return;
+
+ if (p_ptr->csp < s_ptr->mana)
+ {
+ msg_print("You do not have enough mana.");
+ return;
+ }
+
+ /* Spell failure chance */
+ chance = spell_chance_random(s_ptr);
+
+ /* Failed spell */
+ if (rand_int(100) < chance)
+ {
+ int insanity = (p_ptr->msane - p_ptr->csane) * 100 / p_ptr->msane;
+ char sfail[80];
+
+ /* Flush input if told so */
+ if (flush_failure) flush();
+
+ /* Insane players can see something strange */
+ if (rand_int(100) < insanity)
+ {
+ get_rnd_line("sfail.txt", sfail);
+ msg_format("A cloud of %s appears above you.", sfail);
+ }
+
+ /* Normal failure messages */
+ else
+ {
+ msg_print("You failed to get the spell off!");
+ }
+
+ sound(SOUND_FAIL);
+
+ /* Let time pass */
+ if (is_magestaff()) energy_use = 80;
+ else energy_use = 100;
+
+ /* Mana is spent anyway */
+ p_ptr->csp -= s_ptr->mana;
+
+ /* Window stuff */
+ p_ptr->window |= (PW_PLAYER);
+ p_ptr->redraw |= (PR_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
+ {
+ 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 (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_FRAME);
+ }
+ }
+ }
+ 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(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;
+
+ /* 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);
+
+ (void)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);
+
+ (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_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
+ {
+ 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_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 */
+ (void)set_paralyzed(randint(5 * oops + 1));
+
+ /* Damage CON (possibly permanently) */
+ if (rand_int(100) < 50)
+ {
+ bool_ perm = (rand_int(100) < 25);
+
+ /* Message */
+ msg_print("You have damaged your body!");
+
+ /* Reduce constitution */
+ (void)dec_stat(A_CON, 15 + randint(10), perm);
+ }
+ }
+
+ /* Redraw mana */
+ p_ptr->redraw |= (PR_FRAME);
+
+ /* Window stuff */
+ p_ptr->window |= (PW_PLAYER);
+}
+
+/*
+ * Hook to determine if an object is "runestone"
+ */
+static bool item_tester_hook_runestone(object_type const *o_ptr)
+{
+ return ((o_ptr->tval == TV_RUNE2) &&
+ (o_ptr->sval == RUNE_STONE) &&
+ (o_ptr->pval == 0));
+}
+
+static bool item_tester_hook_runestone_full(object_type const *o_ptr)
+{
+ return ((o_ptr->tval == TV_RUNE2) &&
+ (o_ptr->sval == RUNE_STONE) &&
+ (o_ptr->pval != 0));
+}
+
+/*
+ * 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_FRAME);
+ 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_FRAME);
+
+ 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)
+{
+ s32b rune_combine = 0;
+
+ /* Lambda to use for selecting the secondary rune(s) */
+ auto rune2_filter = [&](object_type const *o_ptr) -> bool {
+ return ((o_ptr->tval == TV_RUNE2) &&
+ (o_ptr->sval != RUNE_STONE) &&
+ (!(rune_combine & BIT(o_ptr->sval))));
+ };
+
+ /* Prompt */
+ const char *const q = "Use which rune? ";
+ const char *const s = "You have no rune to use.";
+
+ /* Extract first rune for the base effect */
+ int type = 0;
+ {
+ int item;
+ if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR), object_filter::TVal(TV_RUNE1)))
+ {
+ return FALSE;
+ }
+
+ object_type *o_ptr = get_object(item);
+ type = o_ptr->sval;
+ }
+
+ /* Choose secondary rune(s) */
+ int rune2 = 0;
+ while (1)
+ {
+ int item;
+ if (!get_item(&item, q, nullptr, (USE_INVEN | USE_FLOOR), rune2_filter))
+ {
+ break;
+ }
+
+ object_type *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);
+ }
+
+ int power_rune = 0;
+ int plev = get_skill(SKILL_RUNECRAFT);
+ s32b 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_FRAME);
+}
+
+
+/*
+ * Print a batch of runespells.
+ */
+static void print_runespell_batch(int batch, int max)
+{
+ char buff[80];
+
+ rune_spell* spell;
+
+ int i;
+
+ s32b power, powerdiv;
+
+ int p, dp;
+
+
+ prt(format(" %-30s Fail Mana Power", "Name"), 1, 20);
+
+ for (i = 0; i < max; i++)
+ {
+ spell = &rune_spells[batch * 10 + i];
+
+ power = spell->mana;
+ rune_calc_power(&power, &powerdiv);
+ p = power;
+ dp = powerdiv;
+
+ strnfmt(buff, 80, " %c) %-30s %4d%% %4d %dd%d ", I2A(i), spell->name,
+ spell_chance_rune(spell), spell->mana, dp, p);
+
+ prt(buff, 2 + i, 20);
+ }
+ prt("", 2 + i, 20);
+}
+
+
+
+/*
+ * List ten random spells and ask to pick one.
+ */
+
+static rune_spell* select_runespell_from_batch(int batch, int *s_idx)
+{
+ char tmp[160];
+
+ char out_val[30];
+
+ char which;
+
+ int mut_max = 10;
+
+ rune_spell* ret;
+
+
+ character_icky = TRUE;
+
+ if (rune_num < (batch + 1) * 10)
+ {
+ mut_max = rune_num - batch * 10;
+ }
+
+ strnfmt(tmp, 160, "(a-%c, * to list, / to rename, - to comment) Select a power: ",
+ I2A(mut_max - 1));
+
+ prt(tmp, 0, 0);
+
+ while (1)
+ {
+ Term_save();
+
+ print_runespell_batch(batch, mut_max);
+
+ which = inkey();
+
+ Term_load();
+
+ if (which == ESCAPE)
+ {
+ *s_idx = -1;
+ ret = NULL;
+ break;
+ }
+ else if ((which == '*') || (which == '?') || (which == ' '))
+ {
+ print_runespell_batch(batch, mut_max);
+ }
+ else if ((which == '\r') && (mut_max == 1))
+ {
+ *s_idx = batch * 10;
+ ret = &rune_spells[batch * 10];
+ break;
+ }
+ else if (which == '/')
+ {
+ prt("Rename which power: ", 0, 0);
+ which = tolower(inkey());
+
+ if (isalpha(which) && (A2I(which) <= mut_max))
+ {
+ strcpy(out_val, rune_spells[batch*10 + A2I(which)].name);
+ if (get_string("Name this power: ", out_val, 29))
+ {
+ strcpy(rune_spells[batch*10 + A2I(which)].name, out_val);
+ }
+ prt(tmp, 0, 0);
+ }
+ else
+ {
+ bell();
+ prt(tmp, 0, 0);
+ }
+ }
+ else
+ {
+ which = tolower(which);
+ if (isalpha(which) && (A2I(which) < mut_max))
+ {
+ *s_idx = batch * 10 + A2I(which);
+ ret = &rune_spells[batch * 10 + A2I(which)];
+ break;
+ }
+ else
+ {
+ bell();
+ }
+ }
+ }
+
+ character_icky = FALSE;
+
+ return (ret);
+}
+
+
+/*
+ * Pick a random spell from a menu
+ */
+
+rune_spell* select_runespell(int *s_idx)
+{
+ char tmp[160];
+
+ char which;
+
+ int batch_max = (rune_num - 1) / 10;
+
+ if (rune_num == 0)
+ {
+ msg_print("There are no runespells you can cast.");
+ return (NULL);
+ }
+
+ character_icky = TRUE;
+ Term_save();
+
+ strnfmt(tmp, 160, "(a-%c) Select batch of powers: ", I2A(batch_max));
+
+ prt(tmp, 0, 0);
+
+ while (1)
+ {
+ which = inkey();
+
+ if (which == ESCAPE)
+ {
+ Term_load();
+ character_icky = FALSE;
+ return (NULL);
+ }
+ else if ((which == '\r') && (batch_max == 0))
+ {
+ Term_load();
+ character_icky = FALSE;
+ return (select_runespell_from_batch(0, s_idx));
+
+ }
+ else
+ {
+ which = tolower(which);
+ if (isalpha(which) && (A2I(which) <= batch_max))
+ {
+ Term_load();
+ character_icky = FALSE;
+ return (select_runespell_from_batch(A2I(which), s_idx));
+ }
+ else
+ {
+ bell();
+ }
+ }
+ }
+}
+
+
+/*
+ * Cast a memorized runespell
+ * Note that the only limits are antimagic & conf, NOT blind
+ */
+void do_cmd_rune_cast()
+{
+ rune_spell *s_ptr;
+
+ int s_idx;
+
+
+ /* Require some mana */
+ if (p_ptr->csp <= 0)
+ {
+ msg_print("You have no mana!");
+ return;
+ }
+
+ /* No magic */
+ if (p_ptr->antimagic)
+ {
+ msg_print("Your anti-magic field disrupts any magic attempts.");
+ return;
+ }
+
+ /* No magic */
+ if (p_ptr->anti_magic)
+ {
+ msg_print("Your anti-magic shell disrupts any magic attempts.");
+ return;
+ }
+
+ /* Not when confused */
+ if (p_ptr->confused)
+ {
+ msg_print("You are too confused!");
+ return;
+ }
+
+ s_ptr = select_runespell(&s_idx);
+
+ if (s_ptr == NULL) return;
+
+ /* Need the runes */
+ if (!test_runespell(s_ptr))
+ {
+ msg_print("You lack some essential rune(s) for this runespell!");
+ return;
+ }
+
+ /* Execute at normal mana cost */
+ p_ptr->csp -= rune_exec(s_ptr, 100);
+
+ /* Safety :) */
+ if (p_ptr->csp < 0) p_ptr->csp = 0;
+
+ /* Take a turn */
+ if (is_magestaff()) energy_use = 80;
+ else energy_use = 100;
+
+ /* Window stuff */
+ p_ptr->window |= (PW_PLAYER);
+ p_ptr->redraw |= (PR_FRAME);
+}
+
+
+/*
+ * Cast a runespell from a carved runestone
+ */
+void do_cmd_runestone()
+{
+ rune_spell s_ptr;
+
+ 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;
+ }
+
+ /* Get an item */
+ if (!get_item(&item,
+ "Cast from which runestone? ",
+ "You have no runestone to cast from.",
+ (USE_INVEN | USE_FLOOR),
+ item_tester_hook_runestone_full))
+ {
+ return;
+ }
+
+ /* Get the item */
+ object_type *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_FRAME);
+}
+
+
+/*
+ * 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 learned the maximum 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_FRAME);
+}
+
+
+/*
+ * Carve a runespell onto a Runestone
+ */
+void do_cmd_rune_carve()
+{
+ rune_spell s_ptr;
+
+ 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;
+
+ /* Get an item */
+ if (!get_item(&item,
+ "Use which runestone? ",
+ "You have no runestone to use.",
+ (USE_INVEN | USE_FLOOR),
+ item_tester_hook_runestone))
+ {
+ return;
+ }
+
+ /* Get the item */
+ object_type *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_FRAME);
+}
+
+
+/*
+ * Remove a runespell
+ */
+void do_cmd_rune_del()
+{
+ rune_spell *s_ptr;
+
+ int s_idx;
+
+ int i;
+
+
+ /* Not when confused */
+ if (p_ptr->confused)
+ {
+ msg_print("You are too confused!");
+ return;
+ }
+
+ s_ptr = select_runespell(&s_idx);
+
+ if (s_ptr == NULL) return;
+
+ /* Delete and move */
+ for (i = s_idx + 1; i < rune_num; i++)
+ {
+ rune_spells[i - 1].type = rune_spells[i].type;
+ rune_spells[i - 1].rune2 = rune_spells[i].rune2;
+ rune_spells[i - 1].mana = rune_spells[i].mana;
+ strcpy(rune_spells[i - 1].name, rune_spells[i].name);
+ }
+ rune_num--;
+
+ /* Take a turn */
+ energy_use = 100;
+
+ /* Window stuff */
+ p_ptr->window |= (PW_PLAYER);
+ p_ptr->redraw |= (PR_FRAME);
+}
+
+
+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 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()
+{
+ 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].flags1 & RF1_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;
+ (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;
+
+ 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(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;
+ }
+ }
+}
+
+
+/*
+ * 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;
+ 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->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;
+
+ /* 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, 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_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, FALSE, TRUE))
+ return;
+
+ break;
+ }
+
+ /* Summon never-moving pet */
+ case 7:
+ {
+ summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_MINE, FALSE);
+
+ break;
+ }
+
+ /* Force Symbiosis */
+ case 8:
+ {
+ int y, x;
+ cave_type *c_ptr;
+ monster_type *m_ptr;
+
+ if (!tgt_pt(&x, &y)) return;
+
+ c_ptr = &cave[y][x];
+
+ if (!c_ptr->m_idx) break;
+
+ m_ptr = &m_list[c_ptr->m_idx];
+ use_symbiotic_power(m_ptr->r_idx, TRUE, FALSE, TRUE);
+
+ break;
+ }
+
+
+ default:
+ {
+ msg_print("Zap?");
+
+ break;
+ }
+ }
+ }
+
+ /* Take a turn */
+ energy_use = 100;
+
+ /* Sufficient mana */
+ if (spell.mana_cost <= p_ptr->csp)
+ {
+ /* Use some mana */
+ p_ptr->csp -= spell.mana_cost;
+ }
+
+ /* Over-exert the player */
+ else
+ {
+ int oops = spell.mana_cost - p_ptr->csp;
+
+ /* No mana left */
+ p_ptr->csp = 0;
+ p_ptr->csp_frac = 0;
+
+ /* Message */
+ msg_print("You faint from the effort!");
+
+ /* Hack -- Bypass free action */
+ (void)set_paralyzed(randint(5 * oops + 1));
+
+ /* Damage CON (possibly permanently) */
+ if (rand_int(100) < 50)
+ {
+ bool_ perm = (rand_int(100) < 25);
+
+ /* Message */
+ msg_print("You have damaged your body!");
+
+ /* Reduce constitution */
+ (void)dec_stat(A_CHR, 15 + randint(10), perm);
+ }
+ }
+
+ /* Redraw mana */
+ p_ptr->redraw |= (PR_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;
+
+ (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.hpp b/src/cmd7.hpp
new file mode 100644
index 00000000..162e5461
--- /dev/null
+++ b/src/cmd7.hpp
@@ -0,0 +1,28 @@
+#pragma once
+
+#include "h-basic.h"
+#include "rune_spell_fwd.hpp"
+#include "object_type_fwd.hpp"
+
+extern void do_cmd_pray(void);
+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 void do_cmd_summoner(void);
+extern void do_cmd_mindcraft(void);
+extern void do_cmd_mimic(void);
+extern void use_ability_blade(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 do_cmd_runecrafter(void);
+extern void do_cmd_symbiotic(void);
+extern s32b sroot(s32b n);
+extern 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 c9f460e7..8ff00f8f 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..f182a9e2
--- /dev/null
+++ b/src/corrupt.cc
@@ -0,0 +1,1003 @@
+#include "corrupt.hpp"
+
+#include "init1.hpp"
+#include "player_race.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>
+
+/**
+ * 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)
+{
+ int i;
+
+ for (i=0; i<4; i++)
+ {
+ if (rmp_ptr->powers[i] == -1)
+ {
+ rmp_ptr->powers[i] = power;
+ return;
+ }
+ }
+}
+
+static void player_gain_vampire_teeth()
+{
+ player_race_mod *rmp_ptr = NULL;
+
+ switch_subrace(SUBRACE_SAVE, TRUE);
+
+ rmp_ptr = &race_mod_info[SUBRACE_SAVE];
+ subrace_add_power(rmp_ptr, PWR_VAMPIRISM);
+ rmp_ptr->flags1 = rmp_ptr->flags1
+ | PR1_VAMPIRE
+ | PR1_UNDEAD
+ | PR1_NO_SUBRACE_CHANGE;
+}
+
+static void player_gain_vampire_strength()
+{
+ player_race_mod *rmp_ptr = &race_mod_info[SUBRACE_SAVE];
+ /* Apply the bonuses/penalities */
+ rmp_ptr->r_mhp = rmp_ptr->r_mhp + 1;
+ rmp_ptr->r_exp = rmp_ptr->r_exp + 100;
+
+ rmp_ptr->r_adj[A_STR] = rmp_ptr->r_adj[A_STR] + 3;
+ rmp_ptr->r_adj[A_INT] = rmp_ptr->r_adj[A_INT] + 2;
+ rmp_ptr->r_adj[A_WIS] = rmp_ptr->r_adj[A_WIS] - 3;
+ rmp_ptr->r_adj[A_DEX] = rmp_ptr->r_adj[A_DEX] - 2;
+ rmp_ptr->r_adj[A_CON] = rmp_ptr->r_adj[A_CON] + 1;
+ rmp_ptr->r_adj[A_CHR] = rmp_ptr->r_adj[A_CHR] - 4;
+
+ /* be reborn! */
+ do_rebirth();
+ cmsg_print(TERM_L_DARK, "You feel death slipping inside.");
+}
+
+static void player_gain_vampire()
+{
+ player_race_mod *rmp_ptr = &race_mod_info[SUBRACE_SAVE];
+
+ /* Be a Vampire and be proud of it */
+ cptr title = rmp_ptr->title;
+ if (streq(title, "Vampire"))
+ {
+ title = "Vampire";
+ rmp_ptr->place = FALSE;
+ set_subrace_title(rmp_ptr, title);
+ }
+ else
+ {
+ char buf[512];
+ sprintf(buf, "Vampire %s", title);
+ set_subrace_title(rmp_ptr, buf);
+ }
+
+ /* Bonus/and .. not bonus :) */
+ rmp_ptr->flags1 = rmp_ptr->flags1 | PR1_HURT_LITE;
+ rmp_ptr->oflags2[2] = rmp_ptr->oflags2[2]
+ | TR2_RES_POIS
+ | TR2_RES_NETHER
+ | TR2_RES_COLD
+ | TR2_RES_DARK
+ | TR2_HOLD_LIFE;
+ rmp_ptr->oflags3[2] = rmp_ptr->oflags3[2]
+ | TR3_LITE1;
+}
+
+/**
+ * Corruptions
+ */
+corruption_type corruptions[CORRUPTIONS_MAX] =
+{
+ /*
+ * BALROG corruptions
+ */
+
+ { /* 0 */
+ { MODULE_TOME, MODULE_THEME, -1 },
+ TERM_ORANGE,
+ NULL /* no group */,
+ "Balrog Aura",
+ "A corrupted wall of flames surrounds you.",
+ "The wall of corrupted flames abandons you.",
+ " Surrounds you with a fiery aura\n"
+ " But it can burn scrolls when you read them",
+ { -1 },
+ { -1 },
+ NULL,
+ -1,
+ },
+
+ { /* 1 */
+ { MODULE_TOME, MODULE_THEME, -1 },
+ TERM_ORANGE,
+ NULL /* no group */,
+ "Balrog Wings",
+ "Wings of shadow grow in your back.",
+ "The wings in your back fall apart.",
+ " Creates ugly, but working, wings allowing you to fly\n"
+ " But it reduces charisma by 4 and dexterity by 2",
+ { -1 },
+ { -1 },
+ NULL,
+ -1,
+ },
+
+ { /* 2 */
+ { MODULE_TOME, MODULE_THEME, -1 },
+ TERM_ORANGE,
+ NULL /* no group */,
+ "Balrog Strength",
+ "Your muscles get unnatural strength.",
+ "Your muscles get weaker again.",
+ " Provides 3 strength and 1 constitution\n"
+ " But it reduces charisma by 1 and dexterity by 3",
+ { -1 },
+ { -1 },
+ NULL,
+ -1,
+ },
+
+ { /* 3 */
+ { MODULE_TOME, MODULE_THEME, -1 },
+ TERM_YELLOW,
+ NULL /* no group */,
+ "Balrog Form",
+ "You feel the might of a Balrog inside you.",
+ "The presence of the Balrog seems to abandon you.",
+ " Allows you to turn into a Balrog at will\n"
+ " You need Balrog Wings, Balrog Aura and Balrog Strength to activate it",
+ { CORRUPT_BALROG_AURA, CORRUPT_BALROG_WINGS, CORRUPT_BALROG_STRENGTH },
+ { -1 },
+ NULL,
+ PWR_BALROG,
+ },
+
+ /*
+ * DEMON corruptions
+ */
+ { /* 4 */
+ { MODULE_TOME, MODULE_THEME, -1 },
+ TERM_RED,
+ NULL /* no group */,
+ "Demon Spirit",
+ "Your spirit opens to corrupted thoughts.",
+ "Your spirit closes again to the corrupted thoughts.",
+ " Increases your intelligence by 1\n"
+ " But reduce your charisma by 2",
+ { -1 },
+ { -1 },
+ NULL,
+ -1,
+ },
+
+ { /* 5 */
+ { MODULE_TOME, MODULE_THEME, -1 },
+ TERM_RED,
+ NULL /* no group */,
+ "Demon Hide",
+ "Your skin grows into a thick hide.",
+ "Your skin returns to a natural state.",
+ " Increases your armour class by your level\n"
+ " Provides immunity to fire at level 40\n"
+ " But reduces speed by your level / 7",
+ { -1 },
+ { -1 },
+ NULL,
+ -1,
+ },
+
+ { /* 6 */
+ { MODULE_TOME, MODULE_THEME, -1 },
+ TERM_RED,
+ NULL /* no group */,
+ "Demon Breath",
+ "Your breath becomes mephitic.",
+ "Your breath is once again normal.",
+ " Provides fire breath\n"
+ " But gives a small chance to spoil potions when you quaff them",
+ { -1 },
+ { -1 },
+ NULL,
+ PWR_BR_FIRE,
+ },
+
+ { /* 7 */
+ { MODULE_TOME, MODULE_THEME, -1 },
+ TERM_L_RED,
+ NULL /* no group */,
+ "Demon Realm",
+ "You feel more attuned to the demon realm.",
+ "You lose your attunement to the demon realm.",
+ " Provides access to the demon school skill and the use of demonic equipment\n"
+ " You need Demon Spirit, Demon Hide and Demon Breath to activate it",
+ { CORRUPT_DEMON_SPIRIT, CORRUPT_DEMON_HIDE, CORRUPT_DEMON_BREATH },
+ { -1 },
+ NULL,
+ -1,
+ },
+
+ /*
+ * Teleportation corruptions
+ */
+
+ { /* 8 */
+ { MODULE_TOME, MODULE_THEME, -1 },
+ TERM_GREEN,
+ NULL /* no group */,
+ "Random teleportation",
+ "Space seems to fizzle around you.",
+ "Space solidify again around you.",
+ " Randomly teleports you around",
+ { -1 },
+ { CORRUPT_ANTI_TELEPORT, -1 },
+ NULL,
+ -1,
+ },
+
+ { /* 9 */
+ { MODULE_TOME, MODULE_THEME, -1 },
+ TERM_GREEN,
+ NULL /* no group */,
+ "Anti-teleportation",
+ "Space continuum freezes around you.",
+ "Space continuum can once more be altered around you.",
+ " Prevents all teleportations, be it of you or monsters",
+ { -1 },
+ { CORRUPT_RANDOM_TELEPORT, -1 },
+ NULL,
+ POWER_COR_SPACE_TIME,
+ },
+
+ /*
+ * Troll blood
+ */
+
+ { /* 10 */
+ { MODULE_TOME, MODULE_THEME, -1 },
+ TERM_GREEN,
+ NULL /* no group */,
+ "Troll Blood",
+ "Your blood thickens, you sense corruption in it.",
+ "Your blood returns to a normal state.",
+ " Troll blood flows in your veins, granting increased regeneration\n"
+ " It also enables you to feel the presence of other troll beings\n"
+ " But it will make your presence more noticeable and aggravating",
+ { -1 },
+ { -1 },
+ NULL,
+ -1,
+ },
+
+ /*
+ * The vampire corruption set
+ */
+
+ { /* 11 */
+ { MODULE_TOME, MODULE_THEME, -1 },
+ TERM_L_DARK,
+ "Vampire",
+ "Vampiric Teeth",
+ "You grow vampiric teeth!",
+ NULL, /* cannot lose */
+ " Your teeth allow you to drain blood to feed yourself\n"
+ " However your stomach now only accepts blood.",
+ { -1 },
+ { -1 },
+ player_gain_vampire_teeth,
+ -1,
+ },
+
+ { /* 12 */
+ { MODULE_TOME, MODULE_THEME, -1 },
+ TERM_L_DARK,
+ "Vampire",
+ "Vampiric Strength",
+ "Your body seems more dead than alive.",
+ NULL, /* cannot lose */
+ " Your body seems somewhat dead\n"
+ " In this near undead state it has improved strength, constitution and intelligence\n"
+ " But reduced dexterity, wisdom and charisma.",
+ { CORRUPT_VAMPIRE_TEETH, -1 },
+ { -1 },
+ player_gain_vampire_strength,
+ -1,
+ },
+
+ { /* 13 */
+ { MODULE_TOME, MODULE_THEME, -1 },
+ TERM_L_DARK,
+ "Vampire",
+ "Vampire",
+ "You die to be reborn in a Vampire form.",
+ NULL, /* cannot lose */
+ " You are a Vampire. As such you resist cold, poison, darkness and nether.\n"
+ " Your life is sustained, but you cannot stand the light of the sun.",
+ { CORRUPT_VAMPIRE_STRENGTH, -1 },
+ { -1 },
+ player_gain_vampire,
+ -1,
+ },
+
+ /*
+ * Activatable corruptions (mutations)
+ */
+
+ { /* 14 */
+ { MODULE_THEME, -1 },
+ TERM_RED,
+ NULL /* no group */,
+ "Ancalagon's Breath",
+ "You gain the ability to spit acid.",
+ "You lose the ability to spit acid.",
+ " Fires an acid ball.\n"
+ " Damage=level Radius 1+(level/30)\n"
+ " Level=9, Cost=9, Stat=DEX, Difficulty=15",
+ { -1 },
+ { -1 },
+ NULL,
+ PWR_SPIT_ACID,
+ },
+
+ { /* 15 */
+ { MODULE_THEME, -1 },
+ TERM_RED,
+ NULL /* no group */,
+ "Smaug's Breath",
+ "You gain the ability to breathe fire.",
+ "You lose the ability to breathe fire.",
+ " Fires a fire ball.\n"
+ " Damage=2*level Radius 1+(level/20)\n"
+ " Level=20, Cost=10, Stat=CON, Difficulty=18",
+ { -1 },
+ { -1 },
+ NULL,
+ PWR_BR_FIRE,
+ },
+
+ { /* 16 */
+ { MODULE_THEME, -1 },
+ TERM_RED,
+ NULL /* no group */,
+ "Glaurung's Gaze",
+ "Your eyes look mesmerizing...",
+ "Your eyes look uninteresting.",
+ " Tries to make a monster your pet.\n"
+ " Power=level\n"
+ " Level=12, Cost=12, Stat=CHR, Difficulty=18",
+ { -1 },
+ { -1 },
+ NULL,
+ PWR_HYPN_GAZE,
+ },
+
+ { /* 17 */
+ { MODULE_THEME, -1 },
+ TERM_RED,
+ NULL /* no group */,
+ "Saruman's Power",
+ "You gain the ability to move objects telekinetically.",
+ "You lose the ability to move objects telekinetically.",
+ " Move an object in line of sight to you.\n"
+ " Max weight equal to (level) pounds\n"
+ " Level=9, Cost=9, Stat=WIS, Difficulty=14",
+ { -1 },
+ { -1 },
+ NULL,
+ PWR_TELEKINES,
+ },
+
+ { /* 18 */
+ { MODULE_THEME, -1 },
+ TERM_RED,
+ NULL /* no group */,
+ "Teleport",
+ "You gain the power of teleportation at will.",
+ "You lose the power of teleportation at will.",
+ " Teleports the player at will.\n"
+ " Distance 10+4*level squares\n"
+ " Level=7, Cost=7, Stat=WIS, Difficulty=15",
+ { -1 },
+ { -1 },
+ NULL,
+ PWR_VTELEPORT,
+ },
+
+ { /* 19 */
+ { MODULE_THEME, -1 },
+ TERM_RED,
+ NULL /* no group */,
+ "Glaurung's Spell",
+ "You gain the power of Mind Blast.",
+ "You lose the power of Mind Blast.",
+ " Fires a mind blasting bolt (psi damage).\n"
+ " Psi Damage (3+(level-1)/5)d3\n"
+ " Level=5, Cost=3, Stat=WIS, Difficulty=15",
+ { -1 },
+ { -1 },
+ NULL,
+ PWR_MIND_BLST,
+ },
+
+ { /* 20 */
+ { MODULE_THEME, -1 },
+ TERM_RED,
+ NULL /* no group */,
+ "Vampiric Drain",
+ "You become vampiric.",
+ "You are no longer vampiric.",
+ " You can drain life from a foe like a vampire.\n"
+ " Drains (level+1d(level))*(level/10) hitpoints,\n"
+ " heals you and satiates you. Doesn't work on all monsters\n"
+ " Level=4, Cost=5, Stat=CON, Difficulty=9",
+ { -1 },
+ { -1 },
+ NULL,
+ PWR_VAMPIRISM,
+ },
+
+ { /* 21 */
+ { MODULE_THEME, -1 },
+ TERM_RED,
+ NULL /* no group */,
+ "Carcharoth's Nose",
+ "You smell a metallic odour.",
+ "You no longer smell a metallic odour.",
+ " You can detect nearby precious metal (treasure).\n"
+ " Radius 25\n"
+ " Level=3, Cost=2, Stat=INT, Difficulty=12",
+ { -1 },
+ { -1 },
+ NULL,
+ PWR_SMELL_MET,
+ },
+
+ { /* 22 */
+ { MODULE_THEME, -1 },
+ TERM_RED,
+ NULL /* no group */,
+ "Huan's Nose",
+ "You smell filthy monsters.",
+ "You no longer smell filthy monsters.",
+ " You can detect nearby monsters.\n"
+ " Radius 25\n"
+ " Level=5, Cost=4, Stat=INT, Difficulty=15",
+ { -1 },
+ { -1 },
+ NULL,
+ PWR_SMELL_MON,
+ },
+
+ { /* 23 */
+ { MODULE_THEME, -1 },
+ TERM_RED,
+ NULL /* no group */,
+ "Blink",
+ "You gain the power of minor teleportation.",
+ "You lose the power of minor teleportation.",
+ " You can teleport yourself short distances (10 squares).\n"
+ " Level=3, Cost=3, Stat=WIS, Difficulty=12",
+ { -1 },
+ { -1 },
+ NULL,
+ PWR_BLINK,
+ },
+
+ { /* 24 */
+ { MODULE_THEME, -1 },
+ TERM_RED,
+ NULL /* no group */,
+ "Eat Rock",
+ "The walls look delicious.",
+ "The walls look unappetizing.",
+ " You can consume solid rock with food benefit,\n"
+ " leaving an empty space behind.\n"
+ " Level=8, Cost=12, Stat=CON, Difficulty=18",
+ { -1 },
+ { -1 },
+ NULL,
+ PWR_EAT_ROCK,
+ },
+
+ { /* 25 */
+ { MODULE_THEME, -1 },
+ TERM_RED,
+ NULL /* no group */,
+ "Swap Position",
+ "You feel like walking a mile in someone else's shoes.",
+ "You feel like staying in your own shoes.",
+ " You can switch locations with another being,\n"
+ " unless it resists teleportation.\n"
+ " Level=15, Cost=12, Stat=DEX, Difficulty=16",
+ { -1 },
+ { -1 },
+ NULL,
+ PWR_SWAP_POS,
+ },
+
+ { /* 26 */
+ { MODULE_THEME, -1 },
+ TERM_RED,
+ NULL /* no group */,
+ "Shriek",
+ "Your vocal cords get much tougher.",
+ "Your vocal cords get much weaker.",
+ " Fires a sound ball and aggravates monsters.\n"
+ " Damage=level*4, Radius=8, centered on player\n"
+ " Level=4, Cost=4, Stat=CON, Difficulty=6",
+ { -1 },
+ { -1 },
+ NULL,
+ PWR_SHRIEK,
+ },
+
+ { /* 27 */
+ { MODULE_THEME, -1 },
+ TERM_RED,
+ NULL /* no group */,
+ "Illuminate",
+ "You can light up rooms with your presence.",
+ "You can no longer light up rooms with your presence.",
+ " You can emit bright light that illuminates an area.\n"
+ " Damage=2d(level/2) Radius=(level/10)+1\n"
+ " Level=3, Cost=2, Stat=INT, Difficulty=10",
+ { -1 },
+ { -1 },
+ NULL,
+ PWR_ILLUMINE,
+ },
+
+ { /* 28 */
+ { MODULE_THEME, -1 },
+ TERM_RED,
+ NULL /* no group */,
+ "Detect Curses",
+ "You can feel evil magics.",
+ "You can no longer feel evil magics.",
+ " You can feel the danger of evil magic.\n"
+ " It detects cursed items in the inventory\n"
+ " Level=7, Cost=14, Stat=WIS, Difficulty=14",
+ { -1 },
+ { -1 },
+ NULL,
+ PWR_DET_CURSE,
+ },
+
+ { /* 29 */
+ { MODULE_THEME, -1 },
+ TERM_RED,
+ NULL /* no group */,
+ "Berserk",
+ "You feel a controlled rage.",
+ "You no longer feel a controlled rage.",
+ " You can drive yourself into a berserk frenzy.\n"
+ " It grants super-heroism. Duration=10+1d(level)\n"
+ " Level=8, Cost=8, Stat=STR, Difficulty=14",
+ { -1 },
+ { -1 },
+ NULL,
+ PWR_BERSERK,
+ },
+
+ { /* 30 */
+ { MODULE_THEME, -1 },
+ TERM_RED,
+ NULL /* no group */,
+ "Midas touch",
+ "You gain the Midas touch.",
+ "You lose the Midas touch.",
+ " You can turn ordinary items to gold.\n"
+ " Turns a non-artifact object into 1/3 its value in gold\n"
+ " Level=10, Cost=5, Stat=INT, Difficulty=12",
+ { -1 },
+ { -1 },
+ NULL,
+ PWR_MIDAS_TCH,
+ },
+
+ { /* 31 */
+ { MODULE_THEME, -1 },
+ TERM_RED,
+ NULL /* no group */,
+ "Grow Mold",
+ "You feel a sudden affinity for mold.",
+ "You feel a sudden dislike for mold.",
+ " You can cause mold to grow near you.\n"
+ " Summons up to 8 molds around the player\n"
+ " Level=1, Cost=6, Stat=CON, Difficulty=14",
+ { -1 },
+ { -1 },
+ NULL,
+ PWR_GROW_MOLD,
+ },
+
+ { /* 32 */
+ { MODULE_THEME, -1 },
+ TERM_RED,
+ NULL /* no group */,
+ "Resist Elements",
+ "You feel like you can protect yourself.",
+ "You feel like you might be vulnerable.",
+ " You can harden yourself to the ravages of the elements.\n"
+ " Level-dependent chance of gaining resistances to the four \n"
+ " elements and poison. Duration=20 + d20\n"
+ " Level=10, Cost=12, Stat=CON, Difficulty=12",
+ { -1 },
+ { -1 },
+ NULL,
+ PWR_RESIST,
+ },
+
+ { /* 33 */
+ { MODULE_THEME, -1 },
+ TERM_RED,
+ NULL /* no group */,
+ "Earthquake",
+ "You gain the ability to wreck the dungeon.",
+ "You lose the ability to wreck the dungeon.",
+ " You can bring down the dungeon around your ears.\n"
+ " Radius=10, center on the player\n"
+ " Level=12, Cost=12, Stat=STR, Difficulty=16",
+ { -1 },
+ { -1 },
+ NULL,
+ PWR_EARTHQUAKE,
+ },
+
+};
+
+/**
+ * Initialize corruptions
+ */
+void init_corruptions()
+{
+ /* Nothing needed currently */
+}
+
+/*
+ * Corruptions
+ */
+bool_ player_has_corruption(int corruption_idx)
+{
+ if (corruption_idx < 0)
+ {
+ return FALSE;
+ }
+
+ return (p_ptr->corruptions[corruption_idx]);
+}
+
+static bool_ player_can_gain_corruption(int corruption_idx)
+{
+ bool_ allowed = TRUE; /* Allowed by default */
+
+ assert(corruption_idx >= 0);
+
+ if (corruption_idx == CORRUPT_TROLL_BLOOD)
+ {
+ /* Ok trolls should not get this one. never. */
+ if (streq(rp_ptr->title, "Troll"))
+ {
+ allowed = FALSE;
+ }
+ }
+
+ /* Theme module adds additional restrictions for Maiar */
+
+ if (game_module_idx == MODULE_THEME)
+ {
+ if (streq(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_flags1_p(PR1_NO_SUBRACE_CHANGE))
+ {
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+static void player_set_corruption(int c, bool_ set)
+{
+ p_ptr->corruptions[c] = set;
+ p_ptr->redraw = p_ptr->redraw | PR_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
+ */
+void dump_corruptions(FILE *fff, bool_ color, bool_ header)
+{
+ int i;
+
+ assert(fff != NULL);
+
+ for (i = 0; i < CORRUPTIONS_MAX; i++)
+ {
+ corruption_type *c_ptr = &corruptions[i];
+
+ if (header)
+ {
+ fprintf(fff, "\n Corruption list:\n");
+ header = FALSE;
+ }
+
+ if (p_ptr->corruptions[i])
+ {
+ byte c = c_ptr->color;
+
+ if (color)
+ {
+ fprintf(fff, "#####%c%s:\n", conv_color[c], c_ptr->name);
+ }
+ else
+ {
+ fprintf(fff, "%s:\n", c_ptr->name);
+ }
+
+ fprintf(fff, "%s\n", c_ptr->desc);
+ }
+ }
+}
+
+/*
+ * Get the power granted by a corruption. Returns -1
+ * if the given corruption does not grant a power.
+ */
+s16b get_corruption_power(int corruption_idx)
+{
+ corruption_type *c_ptr = NULL;
+
+ assert(corruption_idx >= 0);
+ assert(corruption_idx < CORRUPTIONS_MAX);
+
+ c_ptr = &corruptions[corruption_idx];
+
+ if ((c_ptr->power >= 0) && (c_ptr->power < POWER_MAX))
+ {
+ return c_ptr->power;
+ }
+ else
+ {
+ assert(c_ptr->power == -1); /* Sanity check: Should always be the case. */
+ return -1;
+ }
+}
diff --git a/src/corrupt.hpp b/src/corrupt.hpp
new file mode 100644
index 00000000..c200762e
--- /dev/null
+++ b/src/corrupt.hpp
@@ -0,0 +1,47 @@
+#include "h-basic.h"
+
+extern void gain_random_corruption();
+extern void dump_corruptions(FILE *OutFile, bool_ color, bool_ header);
+extern void lose_corruption();
+extern bool_ player_has_corruption(int corruption_idx);
+extern void player_gain_corruption(int corruption_idx);
+extern 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..fc1f61f5 100644
--- a/src/defines.h
+++ b/src/defines.h
@@ -37,20 +37,13 @@
*/
#ifndef IS_CVS
-#define IS_CVS " (ah)"
-/* #define IS_CVS " (ah, git)" */
+/* #define IS_CVS " (ah)" */
+#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.
@@ -128,80 +121,24 @@
#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
- */
-#define MAX_ARENA_MONS 29 /* -KMW- */
-
-/*
* 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 +160,7 @@
/* Mimicry */
#define MAX_MIMIC_POWERS 5
+#define MIMIC_FORMS_MAX 14
/* Symbiosis */
#define MAX_SYMBIOTIC_POWERS 9
@@ -234,19 +172,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 +229,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 +243,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 +258,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 +316,6 @@
#define NASTY_MON 50 /* 1/chance of inflated monster level */
-
/*
* Refueling constants
*/
@@ -460,7 +357,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,67 +378,11 @@
#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)
*/
@@ -589,22 +429,15 @@
#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
@@ -616,6 +449,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 +504,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") ***/
@@ -788,9 +585,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 */
@@ -862,7 +656,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,24 +684,6 @@
#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") ***/
@@ -1375,9 +1161,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 +1189,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 ('~') */
@@ -1462,7 +1251,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
@@ -1938,6 +1726,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
@@ -2050,27 +1839,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
@@ -2238,7 +2006,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
@@ -2275,38 +2042,9 @@
/*
* 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)
@@ -2575,7 +2313,6 @@
#define SUMMON_SHADOWS 55
#define SUMMON_GHOST 56
#define SUMMON_QUYLTHULG 57
-#define SUMMON_LUA 58
/*
@@ -2674,7 +2411,10 @@
#define GF_TRAP_DEMONSOUL 108
#define GF_ATTACK 109
#define GF_CHARM_UNMOVING 110
-#define MAX_GF 111
+#define GF_INSTA_DEATH 111
+#define GF_ELEMENTAL_WALL 112
+#define GF_ELEMENTAL_GROWTH 113
+#define MAX_GF 114
/*
* Some things which induce learning
@@ -2730,7 +2470,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 !!!! */
@@ -2914,9 +2653,6 @@
#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 */
@@ -2925,7 +2661,6 @@
#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
@@ -3094,11 +2829,6 @@
-/*** 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,7 +2902,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
@@ -3413,7 +3142,6 @@
#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 */
/*
@@ -3520,386 +3248,10 @@
#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
@@ -3990,55 +3342,39 @@
#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 +3407,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
@@ -4191,13 +3489,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 +3511,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,8 +3541,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
@@ -4273,7 +3555,6 @@
/* 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 */
@@ -4293,77 +3574,6 @@
#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 +3616,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 +3632,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 +3693,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,69 +3744,6 @@
#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
@@ -4621,11 +3754,6 @@
#define MAX_MELEE 3
-/*
- * Player specialities, should be external but ti would be a mess
- */
-#define MAX_SPEC 20
-
/*
* Spellbinder triggers
@@ -4644,11 +3772,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().
@@ -4689,7 +3817,63 @@
#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..3ec79068 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,94 @@
* 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 "birth.h"
+#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_info_type.hpp"
+#include "feature_type.hpp"
+#include "files.h"
+#include "files.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_type.hpp"
+#include "modules.hpp"
+#include "notes.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_kind.hpp"
+#include "object_type.hpp"
+#include "options.hpp"
+#include "player_race.hpp"
+#include "player_race_mod.hpp"
+#include "player_spec.hpp"
+#include "player_type.hpp"
+#include "powers.hpp"
+#include "quest.hpp"
+#include "quark.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,7 +128,7 @@ 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];
@@ -126,7 +195,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,7 +217,7 @@ 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];
@@ -217,7 +286,7 @@ byte value_check_aux2_magic(object_type *o_ptr)
*/
static bool_ granted_resurrection(void)
{
- PRAY_GOD(GOD_ERU)
+ if (praying_to(GOD_ERU))
{
if (p_ptr->grace > 100000)
{
@@ -228,9 +297,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:
@@ -255,8 +323,7 @@ static byte select_sense(object_type *o_ptr)
case TV_BOOMERANG:
case TV_TRAPKIT:
{
- return 1;
- break;
+ return combat;
}
case TV_POTION:
@@ -267,22 +334,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 +360,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 +391,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 +416,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,6 +473,20 @@ void sense_inventory(void)
squeltch_inventory();
}
+void sense_inventory(void)
+{
+ 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)
@@ -630,7 +696,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 +753,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);
@@ -735,7 +801,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 +810,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,9 +827,9 @@ static void regen_monsters(void)
if (!frac) frac = 1;
/* Hack -- Some monsters regenerate quickly */
+ auto const r_ptr = m_ptr->race();
if (r_ptr->flags2 & (RF2_REGENERATE)) frac *= 2;
-
/* Hack -- Regenerate */
m_ptr->hp += frac;
@@ -772,7 +837,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,7 +848,7 @@ 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;
@@ -799,143 +864,10 @@ bool_ decays(object_type *o_ptr)
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;
+ spell_type *spell = spell_at(-music);
+ return spell_type_produce_effect_lasting(spell);
}
-static void gere_class_special()
-{
- switch (p_ptr->druid_extra2)
- {
- /* Lay a path of mana on the floor */
- case CLASS_MANA_PATH:
- {
- /* Does the player have enought mana ? */
- if (p_ptr->csp < (s32b)(p_ptr->druid_extra & 255))
- {
- p_ptr->druid_extra = 0;
- p_ptr->druid_extra2 = CLASS_NONE;
- msg_print("You stop laying a mana path.");
- }
- else
- {
- /* Use some mana */
- p_ptr->csp -= (p_ptr->druid_extra & 255);
-
- if ((p_ptr->druid_extra >> 8) & CLASS_MANA_PATH_ERASE)
- {
- /* Absorb some of the mana of the grid */
- p_ptr->csp += cave[p_ptr->py][p_ptr->px].mana / 50;
- if (p_ptr->csp > p_ptr->msp) p_ptr->csp = p_ptr->msp;
-
- /* Set the new grid mana */
- cave[p_ptr->py][p_ptr->px].mana = p_ptr->druid_extra & 255;
- }
- else
- {
- int m = cave[p_ptr->py][p_ptr->px].mana;
-
- if (m + (p_ptr->druid_extra & 255) > 255)
- {
- cave[p_ptr->py][p_ptr->px].mana = 255;
- }
- else
- {
- cave[p_ptr->py][p_ptr->px].mana += p_ptr->druid_extra & 255;
- }
- }
- }
-
- break;
- }
-
- /* Lay a path of mana on the floor */
- case CLASS_WINDS_MANA:
- {
- /* Does the player have enought mana ? */
- if (p_ptr->csp < (s32b)(p_ptr->druid_extra & 255))
- {
- p_ptr->druid_extra = CLASS_NONE;
- msg_print("You stop expulsing mana winds.");
- }
- else
- {
- int dam = 0;
-
- /* Use some mana */
- p_ptr->csp -= (p_ptr->druid_extra & 255);
-
- if ((p_ptr->druid_extra >> 8) & CLASS_MANA_PATH_ERASE)
- {
- dam = (p_ptr->druid_extra & 255) + 256;
- }
- else
- {
- dam = (p_ptr->druid_extra & 255);
- }
-
- fire_explosion(p_ptr->py, p_ptr->px, GF_WINDS_MANA, 2, dam);
- }
-
- break;
- }
-
- case CLASS_CANALIZE_MANA:
- {
- if (p_ptr->druid_extra & CLASS_CANALIZE_MANA_EXTRA)
- {
- p_ptr->csp += cave[p_ptr->py][p_ptr->px].mana / 10;
- }
- else
- {
- p_ptr->csp += cave[p_ptr->py][p_ptr->px].mana / 20;
- }
-
- if (p_ptr->csp > p_ptr->msp) p_ptr->csp = p_ptr->msp;
-
- cave[p_ptr->py][p_ptr->px].mana = 0;
-
- break;
- }
-
- /* CLASS_NONE, possibly others? */
- default:
- {
- /* No mana update */
- return;
- }
- }
-
- /* Redraw mana */
- p_ptr->update |= (PU_BONUS);
-
- /* Window stuff */
- p_ptr->window |= (PW_PLAYER);
-}
-
-
static void check_music()
{
int use_mana;
@@ -948,15 +880,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,7 +898,7 @@ static void check_music()
/*
* Generate the feature effect
*/
-void apply_effect(int y, int x)
+static void apply_effect(int y, int x)
{
cave_type *c_ptr = &cave[y][x];
@@ -1012,8 +943,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(0);
+ msg_print("Your corruption takes over you, you teleport!");
+ teleport_player(50);
+ }
+ }
+ }
+ }
+
+ if (player_has_corruption(CORRUPT_ANTI_TELEPORT))
+ {
+ if (p_ptr->corrupt_anti_teleport_stopped)
+ {
+ int amt = p_ptr->msp + p_ptr->csp;
+ amt = amt / 100;
+ if (amt < 1) {
+ amt = 1;
+ }
+ increase_mana(-amt);
+ if (p_ptr->csp == 0)
+ {
+ p_ptr->corrupt_anti_teleport_stopped = FALSE;
+ msg_print("You stop controlling your corruption.");
+ p_ptr->update = p_ptr->update | PU_BONUS;
+ }
+ }
+ }
+}
+
+/*
+ * Shim for accessing Lua variable.
+ */
+static bool_ grace_delay_trigger()
+{
+ p_ptr->grace_delay++;
+
+ if (p_ptr->grace_delay >= 15)
+ {
+ /* reset */
+ p_ptr->grace_delay = 0;
+ /* triggered */
+ return TRUE;
+ }
+ else
+ {
+ /* not triggered */
+ return FALSE;
+ }
+}
+
+/*
+ * Hook for gods
+ */
+static void process_world_gods()
+{
+ const char *race_name = rp_ptr->title;
+ const char *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 (streq(race_name, "Orc") ||
+ streq(race_name, "Troll") ||
+ streq(race_name, "Dragon") ||
+ streq(race_name, "Demon"))
+ {
+ /* Varda hates evil races */
+ inc_piety(GOD_ALL, -2);
+ } else {
+ /* ... and everyone slightly less */
+ inc_piety(GOD_ALL, -1);
+ }
+
+ /* Prayer uses piety */
+ if (p_ptr->praying)
+ {
+ inc_piety(GOD_ALL, -1);
+ }
+ }
+ }
+
+ if (p_ptr->pgod == GOD_ULMO)
+ {
+ if (grace_delay_trigger())
+ {
+ int i;
+ /* Ulmo likes the Edain (except Easterlings) */
+ if (streq(race_name, "Human") ||
+ streq(race_name, "Dunadan") ||
+ streq(race_name, "Druadan") ||
+ streq(race_name, "RohanKnight"))
+ {
+ inc_piety(GOD_ALL, 2);
+ }
+ else if (streq(race_name, "Easterling") ||
+ streq(race_name, "Demon") ||
+ streq(race_name, "Orc"))
+ {
+ /* hated races */
+ inc_piety(GOD_ALL, -2);
+ }
+ else
+ {
+ inc_piety(GOD_ALL, 1);
+ }
+
+ if (p_ptr->praying)
+ {
+ inc_piety(GOD_ALL, -1);
+ }
+
+ /* Gain 1 point for each trident in inventory */
+ for (i = 0; i < INVEN_TOTAL; i++)
+ {
+ if ((p_ptr->inventory[i].tval == TV_POLEARM) &&
+ (p_ptr->inventory[i].sval == SV_TRIDENT))
+ {
+ inc_piety(GOD_ALL, 1);
+ }
+ }
+ }
+ }
+
+ if (p_ptr->pgod == GOD_AULE)
+ {
+ if (grace_delay_trigger())
+ {
+ int i;
+
+ /* Aule likes Dwarves and Dark Elves (Eol's
+ * influence here) */
+ if (!(streq(race_name, "Dwarf") ||
+ streq(race_name, "Petty-dwarf") ||
+ streq(race_name, "Gnome") ||
+ streq(race_name, "Dark-Elf")))
+ {
+ inc_piety(GOD_ALL, -1);
+ }
+
+ /* Search inventory for axe or hammer - Gain 1
+ * point of grace for each hammer or axe */
+ for (i = 0; i < INVEN_TOTAL; i++)
+ {
+ int tval = p_ptr->inventory[i].tval;
+ int sval = p_ptr->inventory[i].sval;
+
+ switch (tval)
+ {
+ case TV_AXE:
+ inc_piety(GOD_ALL, 1);
+ break;
+
+ case TV_HAFTED:
+ if ((sval == SV_WAR_HAMMER) ||
+ (sval == SV_LUCERN_HAMMER) ||
+ (sval == SV_GREAT_HAMMER))
+ {
+ inc_piety(GOD_ALL, 1);
+ }
+ break;
+ }
+ }
+
+ /* Praying may grant you a free stone skin
+ * once in a while */
+ if (p_ptr->praying)
+ {
+ int chance;
+ s32b grace;
+
+ inc_piety(GOD_ALL, -2);
+ grace = p_ptr->grace; /* shorthand */
+
+ chance = 1;
+ if (grace >= 50000)
+ {
+ chance = 50000;
+ }
+ else
+ {
+ chance = 50000 - grace;
+ }
+
+ if (randint(100000) <= 100000 / chance)
+ {
+ s16b type = 0;
+
+ if (grace >= 10000)
+ {
+ type = SHIELD_COUNTER;
+ }
+
+ set_shield(
+ randint(10) + 10 + (grace / 100),
+ 10 + (grace / 100),
+ type,
+ 2 + (grace / 200),
+ 3 + (grace / 400));
+
+ msg_print("Aule casts Stone Skin on you.");
+ }
+ }
+ }
+ }
+
+ if (p_ptr->pgod == GOD_MANDOS)
+ {
+ if (grace_delay_trigger())
+ {
+ /* He loves astral beings */
+ if (streq(subrace_name, "LostSoul"))
+ {
+ inc_piety(GOD_ALL, 1);
+ }
+
+ /* He likes High Elves only, though, as races */
+ if (!streq(race_name, "High-Elf"))
+ {
+ inc_piety(GOD_ALL, -1);
+ }
+
+ /* Really hates vampires and demons */
+ if (streq(subrace_name, "Vampire") ||
+ streq(race_name, "Demon"))
+ {
+ inc_piety(GOD_ALL, -10);
+ }
+ else
+ {
+ inc_piety(GOD_ALL, 2);
+ }
+ /* he really doesn't like to be disturbed */
+ if (p_ptr->praying)
+ {
+ inc_piety(GOD_ALL, -5);
+ }
+ }
+ }
+
+}
/*
* Handle certain things once every 10 game turns
@@ -1058,8 +1254,11 @@ 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();
@@ -1074,13 +1273,11 @@ static void process_world(void)
if (!t_ptr->countdown)
{
t_ptr->countdown = t_ptr->delay;
- call_lua(t_ptr->callback, "()", "");
+ assert(t_ptr->callback != NULL);
+ t_ptr->callback();
}
}
- /* Handle class special actions */
- gere_class_special();
-
/* Check the fate */
if (fate_option && (p_ptr->lev > 10))
{
@@ -1198,115 +1395,10 @@ 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))
{
@@ -1372,7 +1464,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))
{
@@ -1408,7 +1500,7 @@ static void process_world(void)
{
/* 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_flags1_p(PR1_SEMI_WRAITH) && (!p_ptr->wraith_form) && (f_info[cave[p_ptr->py][p_ptr->px].feat].flags1 & FF1_CAN_PASS))
{
int amt = 1 + ((p_ptr->lev) / 5);
@@ -1550,10 +1642,10 @@ static void process_world(void)
{
/* Message */
msg_print("You faint from the lack of food.");
- disturb(1, 0);
+ disturb(1);
/* Hack -- faint (bypass free action) */
- (void)set_paralyzed(p_ptr->paralyzed + 1 + rand_int(5));
+ (void)set_paralyzed(1 + rand_int(5));
}
}
}
@@ -1586,25 +1678,12 @@ static void process_world(void)
if (has_ability(AB_PERFECT_CASTING))
upkeep_divider = 15;
-#ifdef TRACK_FRIENDS
-
- if (wizard) msg_format("Total friends: %d.", total_friends);
-
-#endif /* TRACK_FRIENDS */
-
if (total_friends > 1 + (p_ptr->lev / (upkeep_divider)))
{
upkeep_factor = (total_friend_levels);
if (upkeep_factor > 100) upkeep_factor = 100;
else if (upkeep_factor < 10) upkeep_factor = 10;
-
-#ifdef TRACK_FRIENDS
-
- if (wizard) msg_format("Levels %d, upkeep %d", total_friend_levels,
- upkeep_factor);
-
-#endif /* TRACK_FRIENDS */
}
}
@@ -1615,15 +1694,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 +1704,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 +1716,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_flags1_p(PR1_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_flags1_p(PR1_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 (!strcmp(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 +1791,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)
{
@@ -1770,7 +1858,7 @@ static void process_world(void)
p_ptr->chp--;
/* Display the hitpoints */
- p_ptr->redraw |= (PR_HP);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
@@ -1836,24 +1924,12 @@ 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);
- }
-
/* Timed project */
if (p_ptr->tim_project)
{
@@ -1876,6 +1952,12 @@ static void process_world(void)
(void)set_tim_breath(p_ptr->tim_magic_breath - 1, TRUE);
}
+ /* Timed precognition */
+ if (p_ptr->tim_precognition > 0)
+ {
+ set_tim_precognition(p_ptr->tim_precognition - 1);
+ }
+
/* Timed regen */
if (p_ptr->tim_regen)
{
@@ -1906,12 +1988,6 @@ static void process_world(void)
(void)set_prob_travel(p_ptr->prob_travel - 1);
}
- /* Timed Time Resistance */
- if (p_ptr->tim_res_time)
- {
- (void)set_tim_res_time(p_ptr->tim_res_time - 1);
- }
-
/* Timed Levitation */
if (p_ptr->tim_ffall)
{
@@ -1970,12 +2046,6 @@ static void process_world(void)
(void)set_poison(p_ptr->tim_poison - 1);
}
- /* Timed Fire Aura */
- if (p_ptr->tim_fire_aura)
- {
- (void)set_tim_fire_aura(p_ptr->tim_fire_aura - 1);
- }
-
/* Brightness */
if (p_ptr->tim_lite)
{
@@ -2018,11 +2088,6 @@ static void process_world(void)
(void)set_tim_invis(p_ptr->tim_invis - 1);
}
- if (multi_rew)
- {
- multi_rew = FALSE;
- }
-
/* Timed esp */
if (p_ptr->tim_esp)
{
@@ -2038,7 +2103,7 @@ static void process_world(void)
/* Paralysis */
if (p_ptr->paralyzed)
{
- (void)set_paralyzed(p_ptr->paralyzed - 1);
+ dec_paralyzed();
}
/* Confusion */
@@ -2179,19 +2244,6 @@ static void process_world(void)
(void)set_oppose_nex(p_ptr->oppose_nex - 1);
}
- /* Mental Barrier */
- if (p_ptr->tim_mental_barrier)
- {
- (void)set_mental_barrier(p_ptr->tim_mental_barrier - 1);
- }
-
- /* The rush */
- if (p_ptr->rush)
- {
- (void)set_rush(p_ptr->rush - 1);
- }
-
-
/* Timed mimicry */
if (get_skill(SKILL_MIMICRY))
{
@@ -2214,7 +2266,7 @@ static void process_world(void)
att &= ~(CLASS_LEGS);
att &= ~(CLASS_WALL);
- if (disturb_state) disturb(0, 0);
+ if (disturb_state) disturb(0);
}
p_ptr->update |= (PU_BODY);
@@ -2278,7 +2330,7 @@ static void process_world(void)
if (!(dungeon_flags1 & DF1_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;
}
@@ -2551,7 +2603,7 @@ static void process_world(void)
if (!be_silent)
{
cmsg_print(TERM_L_DARK, "The Black Breath saps your soul!");
- disturb(0, 0);
+ disturb(0);
}
}
@@ -2590,14 +2642,14 @@ static void process_world(void)
/* The light is now out */
else if (o_ptr->timeout < 1)
{
- disturb(0, 0);
+ disturb(0);
cmsg_print(TERM_YELLOW, "Your light has gone out!");
}
/* The light is getting dim */
else if ((o_ptr->timeout < 100) && (o_ptr->timeout % 10 == 0))
{
- if (disturb_minor) disturb(0, 0);
+ if (disturb_minor) disturb(0);
cmsg_print(TERM_YELLOW, "Your light is growing faint.");
}
}
@@ -2619,7 +2671,7 @@ static void process_world(void)
byte chance = 0;
int plev = p_ptr->lev;
- if (PRACE_FLAG(PR1_RESIST_BLACK_BREATH)) chance = 2;
+ if (race_flags1_p(PR1_RESIST_BLACK_BREATH)) chance = 2;
else chance = 5;
if ((rand_int(100) < chance) && (p_ptr->exp > 0))
@@ -2640,11 +2692,11 @@ static void process_world(void)
if (p_ptr->csp < 0)
{
p_ptr->csp = 0;
- disturb(0, 0);
+ disturb(0);
}
/* Redraw */
- p_ptr->redraw |= (PR_MANA);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
@@ -2659,7 +2711,7 @@ static void process_world(void)
if (p_ptr->csp < 0)
{
p_ptr->csp = 0;
- disturb(0, 0);
+ disturb(0);
p_ptr->maintain_sum = 0;
}
@@ -2670,7 +2722,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 +2738,11 @@ static void process_world(void)
if (p_ptr->chp == 0)
{
- disturb(0, 0);
+ disturb(0);
}
/* Redraw */
- p_ptr->redraw |= (PR_HP);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
@@ -2747,7 +2799,7 @@ static void process_world(void)
{
if ((o_ptr->ident & IDENT_CURSED) && !p_ptr->anti_tele)
{
- disturb(0, 0);
+ disturb(0);
/* Teleport player */
teleport_player(40);
@@ -2762,7 +2814,7 @@ static void process_world(void)
}
else if (get_check("Teleport? "))
{
- disturb(0, 0);
+ disturb(0);
teleport_player(50);
}
}
@@ -2899,8 +2951,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 +2958,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())
{
- 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;
}
@@ -3047,7 +3093,7 @@ 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;
}
@@ -3101,7 +3147,7 @@ static void process_world(void)
if (p_ptr->word_recall == 0)
{
/* Disturbing! */
- disturb(0, 0);
+ disturb(0);
/* Determine the level */
if (p_ptr->inside_quest)
@@ -3206,12 +3252,6 @@ static bool_ enter_debug_mode(void)
/*
- * Hack -- Declare the Debug Routines
- */
-extern void do_cmd_debug(void);
-
-
-/*
* Parse and execute the current command
* Give "Warning" on illegal commands.
*
@@ -3224,9 +3264,6 @@ static void process_command(void)
/* 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 +3281,6 @@ static void process_command(void)
break;
}
-#ifdef ALLOW_QUITTING
-
- case KTRL('L'):
- {
- quit("CHEATER");
- break;
- }
-
-#endif
/*** Wizard Commands ***/
@@ -3275,7 +3303,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 +3335,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;
}
@@ -3513,7 +3541,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;
@@ -3665,13 +3693,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 +3771,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 +3801,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 +3821,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 +3831,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 +3843,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 +3855,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 +3888,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 +3900,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 +3912,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 +3924,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_flags1_p(PR1_NO_GOD))
{
msg_print("You cannot worship gods.");
}
@@ -4052,13 +4007,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 +4128,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 '#':
{
@@ -4292,7 +4224,7 @@ 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(void)
{
int i, j;
@@ -4301,13 +4233,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 +4266,7 @@ void process_player(void)
/* Stop resting */
if ((p_ptr->chp == p_ptr->mhp) && (p_ptr->csp >= p_ptr->msp))
{
- disturb(0, 0);
+ disturb(0);
}
}
@@ -4372,9 +4297,9 @@ void process_player(void)
if (stop)
{
- disturb(0, 0);
+ disturb(0);
}
- p_ptr->redraw |= (PR_STATE);
+ p_ptr->redraw |= (PR_FRAME);
}
}
@@ -4384,17 +4309,14 @@ void process_player(void)
/* 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(0);
/* Hack -- Show a Message */
msg_print("Cancelled.");
@@ -4444,7 +4366,7 @@ void process_player(void)
o_ptr = &p_ptr->inventory[item];
/* Disturbing */
- disturb(0, 0);
+ disturb(0);
/* Warning */
msg_print("Your pack overflows!");
@@ -4496,7 +4418,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 +4449,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 +4494,7 @@ void process_player(void)
/* Shimmer monsters if needed */
- if (!avoid_other && !use_graphics && shimmer_monsters)
+ if (!avoid_other && shimmer_monsters)
{
/* Clear the flag */
shimmer_monsters = FALSE;
@@ -4580,17 +4502,14 @@ 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;
@@ -4604,8 +4523,7 @@ void process_player(void)
}
/* Shimmer objects if needed and requested */
- if (!avoid_other && !avoid_shimmer && !use_graphics &&
- shimmer_objects)
+ if (!avoid_other && !avoid_shimmer && shimmer_objects)
{
/* Clear the flag */
shimmer_objects = FALSE;
@@ -4641,7 +4559,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 (!avoid_other && !avoid_shimmer &&
!resting && !running)
{
for (j = panel_row_min; j <= panel_row_max; j++)
@@ -4786,11 +4704,10 @@ static void dungeon(void)
shimmer_monsters = TRUE;
shimmer_objects = TRUE;
repair_monsters = TRUE;
- repair_objects = TRUE;
/* Disturb */
- disturb(1, 0);
+ disturb(1);
/* Track maximum player level */
if (p_ptr->max_plv < p_ptr->lev)
@@ -4881,7 +4798,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);
@@ -5062,7 +4979,7 @@ 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)
@@ -5140,13 +5057,13 @@ static void load_all_pref_files(void)
/* Access the "race" pref file */
- sprintf(buf, "%s.prf", rp_ptr->title + rp_name);
+ sprintf(buf, "%s.prf", rp_ptr->title);
/* 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);
@@ -5157,8 +5074,20 @@ static void load_all_pref_files(void)
/* 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 / (std::string(player_name) + ".atm")))
+ {
+ // Done
+ }
+ else if (automatizer_load(userDirectory / "automat.atm"))
+ {
+ // Done
+ }
}
/*
@@ -5174,7 +5103,8 @@ void play_game(bool_ new_game)
bool_ cheat_death = FALSE;
- hack_corruption = FALSE;
+ /* Initialize player */
+ p_ptr = new player_type();
/* Hack -- Character is "icky" */
character_icky = TRUE;
@@ -5183,11 +5113,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])
{
@@ -5235,8 +5163,6 @@ void play_game(bool_ new_game)
}
}
-#if 1
-
/* Process old character */
if (!new_game)
{
@@ -5244,8 +5170,6 @@ void play_game(bool_ new_game)
process_player_name(FALSE);
}
-#endif
-
/* Init the RNG */
if (Rand_quick)
{
@@ -5296,23 +5220,8 @@ void play_game(bool_ new_game)
/* Roll new character */
if (new_game)
{
- s32b ret;
-
- /* Are we authorized to create new chars? */
- call_lua("get_module_info", "(s)", "d", "allow_birth", &ret);
-
- if (!ret)
- {
- msg_box("Sorry, this module does not allow character creation.", -1, -1);
-
- /* Close stuff */
- close_game();
-
- /* Quit */
- quit(NULL);
- }
-
- process_hooks(HOOK_INIT, "()");
+ /* Show intro */
+ modules[game_module_idx].intro();
/* The dungeon is not ready */
character_dungeon = FALSE;
@@ -5327,17 +5236,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_flags1_p(PR1_UNDEAD))
{
- turn = (10L * DAY / 2) + (START_DAY * 10) + 1;
+ turn = (10L * DAY / 2) + 1;
}
else
{
- turn = (START_DAY * 10) + 1;
+ turn = 1;
}
}
@@ -5382,8 +5290,9 @@ void play_game(bool_ new_game)
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 +5305,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 +5314,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 +5330,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 +5430,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;
}
@@ -5632,7 +5534,6 @@ void play_game(bool_ new_game)
/* New depth -KMW- */
/* dun_level = 0; */
- p_ptr->inside_arena = 0;
leaving_quest = 0;
p_ptr->inside_quest = 0;
@@ -5651,7 +5552,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..1ce166d1
--- /dev/null
+++ b/src/dungeon.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#include "h-basic.h"
+
+// C linkage required for these functions since main-* code uses them.
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void play_game(bool_ new_game);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/src/dungeon.hpp b/src/dungeon.hpp
new file mode 100644
index 00000000..bbe6da87
--- /dev/null
+++ b/src/dungeon.hpp
@@ -0,0 +1,6 @@
+#pragma once
+
+#include <vector>
+
+extern void sense_inventory();
+extern 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_info_type.hpp b/src/dungeon_info_type.hpp
new file mode 100644
index 00000000..5f6fc9d0
--- /dev/null
+++ b/src/dungeon_info_type.hpp
@@ -0,0 +1,72 @@
+#pragma once
+
+#include "h-basic.h"
+#include "rule_type.hpp"
+#include "obj_theme.hpp"
+
+/**
+ * Maximum number of towns per dungeon
+ */
+constexpr int TOWN_DUNGEON = 4;
+
+/* A structure for the != dungeon types */
+struct dungeon_info_type
+{
+ const char *name; /* Name */
+ char *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 */
+};
+
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_item_type.hpp b/src/ego_item_type.hpp
new file mode 100644
index 00000000..f9b6970a
--- /dev/null
+++ b/src/ego_item_type.hpp
@@ -0,0 +1,68 @@
+#pragma once
+
+#include "h-basic.h"
+
+/*
+ * Size of flag rarity tables
+ */
+constexpr int FLAG_RARITY_MAX = 6;
+
+/**
+ * Ego item descriptors.
+ */
+struct ego_item_type
+{
+ const char *name; /* Name (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[FLAG_RARITY_MAX];
+ u32b flags1[FLAG_RARITY_MAX]; /* Ego-Item Flags, set 1 */
+ u32b flags2[FLAG_RARITY_MAX]; /* Ego-Item Flags, set 2 */
+ u32b flags3[FLAG_RARITY_MAX]; /* Ego-Item Flags, set 3 */
+ u32b flags4[FLAG_RARITY_MAX]; /* Ego-Item Flags, set 4 */
+ u32b flags5[FLAG_RARITY_MAX]; /* Ego-Item Flags, set 5 */
+ u32b esp[FLAG_RARITY_MAX]; /* ESP flags */
+ u32b oflags1[FLAG_RARITY_MAX]; /* Ego-Item Obvious Flags, set 1 */
+ u32b oflags2[FLAG_RARITY_MAX]; /* Ego-Item Obvious Flags, set 2 */
+ u32b oflags3[FLAG_RARITY_MAX]; /* Ego-Item Obvious Flags, set 3 */
+ u32b oflags4[FLAG_RARITY_MAX]; /* Ego-Item Obvious Flags, set 4 */
+ u32b oflags5[FLAG_RARITY_MAX]; /* Ego-Item Obvious Flags, set 5 */
+ u32b oesp[FLAG_RARITY_MAX]; /* Obvious ESP flags */
+ u32b fego[FLAG_RARITY_MAX]; /* 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) */
+};
diff --git a/src/ego_item_type_fwd.hpp b/src/ego_item_type_fwd.hpp
new file mode 100644
index 00000000..795f4403
--- /dev/null
+++ b/src/ego_item_type_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct ego_item_type;
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_type.hpp b/src/feature_type.hpp
new file mode 100644
index 00000000..1a79aeb3
--- /dev/null
+++ b/src/feature_type.hpp
@@ -0,0 +1,37 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * Terrain feature descriptor.
+ */
+struct feature_type
+{
+ char *name; /* Name */
+
+ const char *text; /* Text. May point to shared read-only memory, DO NOT FREE! */
+ const char *tunnel; /* Text for tunneling. May point to shared read-only memory, DO NOT FREE! */
+ const char *block; /* Text for blocking. May point to shared read-only memory, DO NOT FREE! */
+
+ 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 */
+};
diff --git a/src/feature_type_fwd.hpp b/src/feature_type_fwd.hpp
new file mode 100644
index 00000000..168ec6c7
--- /dev/null
+++ b/src/feature_type_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct feature_type;
diff --git a/src/files.c b/src/files.cc
index 56e57975..cc168ba5 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,56 @@
* 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 "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 "monster2.hpp"
+#include "monster3.hpp"
+#include "monster_ego.hpp"
+#include "monster_race.hpp"
+#include "monster_type.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_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 "trap_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 <memory>
+#include <unordered_set>
/*
* Extract the first few "tokens" from a buffer
@@ -427,9 +471,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 +506,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 +524,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 +554,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];
@@ -834,33 +882,22 @@ 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;
}
/* Race */
else if (streq(b + 1, "RACEMOD"))
{
- v = rmp_ptr->title + rmp_name;
+ v = rmp_ptr->title;
}
/* Class */
else if (streq(b + 1, "CLASS"))
{
- v = spp_ptr->title + c_name;
+ v = spp_ptr->title;
}
/* Player */
@@ -1027,7 +1064,7 @@ static void prt_lnum(cptr header, s32b num, int row, int col, byte color)
* Print number with header at given row, column
*/
static void prt_num(cptr header, int num, int row, int col, byte color,
- char *space)
+ cptr space)
{
int len = strlen(header);
char out_val[32];
@@ -1560,28 +1597,28 @@ void player_flags(u32b *f1, u32b *f2, u32b *f3, u32b *f4, u32b *f5, u32b *esp)
if (get_skill(SKILL_WATER) >= 30) (*f5) |= TR5_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;
}
- 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)
+ if (p_ptr->praying)
{
if (p_ptr->grace > 5000) (*f2) |= TR2_INVIS;
if (p_ptr->grace > 15000) (*f2) |= TR2_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->praying)
{
if (p_ptr->grace >= 7000) (*f2) |= TR2_FREE_ACT;
if (p_ptr->grace >= 15000) (*f4) |= TR4_FLY;
@@ -1589,12 +1626,54 @@ void player_flags(u32b *f1, u32b *f2, u32b *f3, u32b *f4, u32b *f5, u32b *esp)
}
}
- 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->pgod == GOD_AULE)
+ {
+ if (p_ptr->grace > 5000)
+ {
+ (*f2) |= TR2_RES_FIRE;
+ }
+ }
+
+ if (p_ptr->pgod == GOD_MANDOS)
+ {
+ (*f2) |= TR2_RES_NETHER;
+
+ if ((p_ptr->grace > 10000) &&
+ (p_ptr->praying == TRUE))
+ {
+ (*f3) |= TR3_NO_TELE;
+ }
+
+ if ((p_ptr->grace > 20000) &&
+ (p_ptr->praying == TRUE))
+ {
+ (*f4) |= TR4_IM_NETHER;
+ }
+ }
+
+ if (p_ptr->pgod == GOD_ULMO)
+ {
+ (*f5) |= TR5_WATER_BREATH;
+
+ if ((p_ptr->grace > 1000) &&
+ (p_ptr->praying == TRUE))
+ {
+ (*f2) |= TR2_RES_POIS;
+ }
+
+ if ((p_ptr->grace > 15000) &&
+ (p_ptr->praying == TRUE))
+ {
+ (*f5) |= TR5_MAGIC_BREATH;
+ }
+ }
+
/* Classes */
for (i = 1; i <= p_ptr->lev; i++)
{
@@ -2131,12 +2210,12 @@ void display_player(int mode)
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, spp_ptr->title, 5, 9);
+ c_put_str(TERM_L_BLUE, 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("Age ", (int)p_ptr->age + bst(YEAR, turn), 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, " ");
@@ -2237,11 +2316,17 @@ cptr describe_player_location()
int feat = wild_map[pwy][pwx].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);
+ {
+ sprintf(desc, "on level %d of %s", 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);
+ {
+ sprintf(desc, "in the town of %s", wf_info[feat].name);
+ }
else if (wf_info[feat].entrance)
- sprintf(desc, "near %s", wf_info[feat].name + wf_name);
+ {
+ sprintf(desc, "near %s", wf_info[feat].name);
+ }
else
{
/*
@@ -2278,10 +2363,14 @@ cptr describe_player_location()
}
if (!landmark)
- sprintf(desc, "in %s", wf_info[feat].text + wf_text);
+ {
+ sprintf(desc, "in %s", 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);
+ sprintf(desc, "near %s", wf_info[feat].name);
+ }
else
{
/*
@@ -2303,8 +2392,10 @@ cptr describe_player_location()
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);
+ wf_info[feat].text,
+ ns,
+ ew,
+ wf_info[landmark].name);
}
}
@@ -2412,7 +2503,7 @@ void file_character_print_store(FILE *fff, wilderness_type_info *place, int stor
if (st_ptr->stock_num)
{
/* 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, place->name);
/* Dump all available items */
for (i = 0; i < st_ptr->stock_num; i++)
@@ -2425,46 +2516,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 *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)
+ // Already seen store?
+ if (seen_stores->find(st_ptr) != seen_stores->end())
{
- if (*head == st_ptr) return FALSE;
- ++head;
+ return FALSE;
}
- /* 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
- {
- *store_list = RNEW(store_type *);
- }
-
- /* update data */
- (*store_list)[*store_list_count] = st_ptr;
- ++*store_list_count;
-
+ // Add
+ seen_stores->insert(st_ptr);
return TRUE;
}
@@ -2482,15 +2553,10 @@ errr file_character(cptr name, bool_ full)
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);
@@ -2575,20 +2641,12 @@ 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)
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)
fprintf(fff, "\n Preserve Mode: ON");
else
@@ -2621,7 +2679,7 @@ errr file_character(cptr name, bool_ full)
{
if (max_dlv[y])
fprintf(fff, "\n %s: Level %d (%d')",
- d_name + d_info[y].name,
+ d_info[y].name,
max_dlv[y], 50 * (max_dlv[y]));
}
fprintf(fff, "\n");
@@ -2629,12 +2687,9 @@ errr file_character(cptr name, bool_ full)
if (noscore)
fprintf(fff, "\n You have done something illegal.");
- if (PRACE_FLAGS(PR1_EXPERIMENTAL))
+ if (race_flags1_p(PR1_EXPERIMENTAL))
fprintf(fff, "\n You have done something experimental.");
- if (stupid_monsters)
- fprintf(fff, "\n Your opponents are behaving stupidly.");
-
{
char desc[80];
cptr mimic;
@@ -2644,7 +2699,7 @@ errr file_character(cptr name, bool_ full)
if (p_ptr->tim_mimic)
{
- call_lua("get_mimic_info", "(d,s)", "s", p_ptr->mimic_form, "name", &mimic);
+ mimic = get_mimic_name(p_ptr->mimic_form);
fprintf(fff, "\n You %s disguised as a %s.", (death ? "were" : "are"), mimic);
}
}
@@ -2687,22 +2742,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");
@@ -2736,11 +2781,7 @@ errr file_character(cptr name, bool_ full)
file_character_print_grid(fff, FALSE, FALSE);
/* Dump corruptions */
- if (got_corruptions())
- {
- fprintf(fff, "\n Corruption list:\n");
- dump_corruptions(fff, FALSE);
- }
+ dump_corruptions(fff, FALSE, TRUE);
/* Dump skills */
dump_skills(fff);
@@ -2794,24 +2835,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 (j = 0; j < max_wf_idx; j++)
+ {
+ if (wf_info[j].feat == FEAT_TOWN &&
+ file_character_check_stores(&seen_stores, &wf_info[j], 7))
+ {
+ file_character_print_store(fff, &wf_info[j], 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 (j = 0; j < max_wf_idx; j++)
+ {
+ if (wf_info[j].feat == FEAT_TOWN &&
+ file_character_check_stores(&seen_stores, &wf_info[j], 57))
+ {
+ file_character_print_store(fff, &wf_info[j], 57, full);
+ }
+ }
}
- store_list = C_FREE(store_list, store_list_count, store_type *);
- store_list_count = 0;
text_out_indent = 0;
@@ -2897,9 +2944,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 +2953,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 +3024,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 +3151,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);
}
@@ -3452,9 +3491,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);
@@ -3483,18 +3519,16 @@ bool_ txt_to_html(cptr head, cptr foot, cptr base, cptr ext, bool_ force, bool_
/* Current html file */
FILE *htm = NULL;
- /* Char array type of hyperlink info */
- hyperlink_type *h_ptr;
-
- cptr file_ext;
- cptr link_prefix;
- cptr link_suffix;
+ cptr file_ext = "html";
+ cptr link_prefix = "";
+ cptr link_suffix = "";
/* Pointer to general buffer in the above */
char *buf;
/* 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;
@@ -3505,14 +3539,6 @@ bool_ txt_to_html(cptr head, cptr foot, cptr base, cptr ext, bool_ force, bool_
h_ptr->link_x[i] = -1;
}
- /* Parse it(yeah lua is neat :) */
- tome_dofile_anywhere(ANGBAND_DIR_HELP, "def.aux", TRUE);
-
- /* Ok now get the parameters */
- file_ext = string_exec_lua("return file_ext");
- link_prefix = string_exec_lua("return link_prefix");
- link_suffix = string_exec_lua("return link_suffix");
-
sprintf(buf_name, "%s.%s", base, file_ext);
if ((!force) && file_exist(buf_name)) return FALSE;
@@ -3537,9 +3563,6 @@ bool_ txt_to_html(cptr head, cptr foot, cptr base, cptr ext, bool_ force, bool_
/* Oops */
if (!fff || !htm)
{
- /* Free hyperlink info */
- KILL(h_ptr, hyperlink_type);
-
my_fclose(fff);
my_fclose(htm);
@@ -3783,13 +3806,61 @@ bool_ txt_to_html(cptr head, cptr foot, cptr base, cptr ext, bool_ force, bool_
my_fclose(htm);
my_fclose(fff);
- /* Free hyperlink buffers */
- KILL(h_ptr, hyperlink_type);
-
/* Normal return */
return (TRUE);
}
+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];
+
+ 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';
+}
+
/* Take an help file screenshot(yes yes I know..) */
void help_file_screenshot(cptr name)
{
@@ -3811,9 +3882,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 +3935,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");
@@ -3990,23 +4055,6 @@ void process_player_name(bool_ sf)
}
}
-
-#ifdef MACINTOSH
-
- /* Extract "useful" letters */
- for (i = 0; player_base[i]; i++)
- {
- 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++)
{
@@ -4019,10 +4067,8 @@ void process_player_name(bool_ sf)
else if (strchr("@. _", c)) tmp[k++] = '_';
}
-#endif
-
-#if defined(WINDOWS) || defined(MSDOS)
+#if defined(WINDOWS)
/* Hack -- max length */
if (k > 8) k = 8;
@@ -4037,13 +4083,6 @@ void process_player_name(bool_ sf)
if (!player_base[0]) strcpy(player_base, "PLAYER");
-#ifdef SAVEFILE_MUTABLE
-
- /* Accept */
- sf = TRUE;
-
-#endif
-
/* Change the savefile name */
if (sf)
{
@@ -4194,7 +4233,7 @@ void do_cmd_save_game(void)
if (!is_autosave)
{
/* Disturb the player */
- disturb(1, 0);
+ disturb(1);
}
/* Clear messages */
@@ -4212,9 +4251,6 @@ void do_cmd_save_game(void)
/* The player is not dead */
(void)strcpy(died_from, "(saved)");
- /* Forbid suspend */
- signals_ignore_tstp();
-
/* Save the player */
if (save_player())
{
@@ -4229,9 +4265,6 @@ void do_cmd_save_game(void)
remove_cave_view(FALSE);
- /* Allow suspend again */
- signals_handle_tstp();
-
/* Refresh */
Term_fresh();
@@ -4256,7 +4289,7 @@ void autosave_checkpoint()
/*
* Hack -- Calculates the total number of points earned -JWT-
*/
-long total_points(void)
+static long total_points(void)
{
s16b max_dl = 0, i, k;
long temp, Total = 0;
@@ -4266,13 +4299,11 @@ long total_points(void)
if (!comp_death) comp_death = 1;
if (p_ptr->preserve) mult -= 1; /* Penalize preserve, maximize modes */
- if (p_ptr->maximize) mult -= 1;
+ mult -= 1; /* maximize pentalty, always on */
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 (mult < 2) mult = 2; /* At least 10% of the original score */
/* mult is now between 2 and 40, i.e. 10% and 200% */
@@ -4291,7 +4322,7 @@ long total_points(void)
temp += p_ptr->au / 5;
/* Completing quest increase score */
- for (i = 0; i < max_q_idx; i++)
+ for (i = 0; i < MAX_Q_IDX; i++)
{
if (quest[i].status >= QUEST_STATUS_COMPLETED)
{
@@ -4354,8 +4385,6 @@ long total_points(void)
}
temp += Total * 50;
- temp += total_bounties * 100;
-
if (total_winner) temp += 1000000;
@@ -4384,125 +4413,106 @@ static void center_string(char *buf, cptr str)
/*
- * Redefinable "print_tombstone" action
- */
-bool_ (*tombstone_aux)(void) = NULL;
-
-
-/*
* Display a "tomb-stone"
*/
static void print_tomb(void)
{
- bool_ done = FALSE;
+ cptr p;
- /* Do we use a special tombstone ? */
- if (tombstone_aux)
- {
- /* Use tombstone hook */
- done = (*tombstone_aux)();
- }
+ char tmp[160];
- /* Print the text-tombstone */
- if (!done)
- {
- cptr p;
-
- char tmp[160];
+ char buf[1024];
+ char dummy[80];
- char buf[1024];
- char dummy[80];
+ FILE *fp;
- FILE *fp;
+ time_t ct = time(nullptr);
- time_t ct = time((time_t)0);
+ /* Clear screen */
+ Term_clear();
- /* Clear screen */
- Term_clear();
+ /* Build the filename */
+ path_build(buf, 1024, ANGBAND_DIR_FILE, "dead.txt");
- /* Build the filename */
- path_build(buf, 1024, ANGBAND_DIR_FILE, "dead.txt");
+ /* Open the News file */
+ fp = my_fopen(buf, "r");
- /* Open the News file */
- fp = my_fopen(buf, "r");
+ /* Dump */
+ if (fp)
+ {
+ int i = 0;
- /* Dump */
- if (fp)
+ /* Dump the file to the screen */
+ while (0 == my_fgets(fp, buf, 1024))
{
- 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);
+ /* 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;
- }
+ /* King or Queen */
+ if (total_winner || (p_ptr->lev > PY_MAX_LEVEL))
+ {
+ p = "Magnificent";
+ }
- center_string(buf, player_name);
- put_str(buf, 6, 11);
+ /* Normal */
+ else
+ {
+ p = cp_ptr->titles[(p_ptr->lev - 1) / 5];
+ }
- center_string(buf, "the");
- put_str(buf, 7, 11);
+ center_string(buf, player_name);
+ put_str(buf, 6, 11);
- center_string(buf, p);
- put_str(buf, 8, 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);
+ center_string(buf, spp_ptr->title);
+ put_str(buf, 10, 11);
- (void)sprintf(tmp, "Exp: %ld", (long)p_ptr->exp);
- center_string(buf, tmp);
- put_str(buf, 12, 11);
+ (void)sprintf(tmp, "Level: %d", (int)p_ptr->lev);
+ center_string(buf, tmp);
+ put_str(buf, 11, 11);
- (void)sprintf(tmp, "AU: %ld", (long)p_ptr->au);
- center_string(buf, tmp);
- put_str(buf, 13, 11);
+ (void)sprintf(tmp, "Exp: %ld", (long)p_ptr->exp);
+ center_string(buf, tmp);
+ put_str(buf, 12, 11);
- (void)sprintf(tmp, "Killed on Level %d", dun_level);
- center_string(buf, tmp);
- put_str(buf, 14, 11);
+ (void)sprintf(tmp, "AU: %ld", (long)p_ptr->au);
+ center_string(buf, tmp);
+ put_str(buf, 13, 11);
+ (void)sprintf(tmp, "Killed on Level %d", dun_level);
+ center_string(buf, tmp);
+ put_str(buf, 14, 11);
- if (strlen(died_from) > 24)
- {
- strncpy(dummy, died_from, 24);
- dummy[24] = '\0';
- (void)sprintf(tmp, "by %s.", dummy);
- }
- else
- (void)sprintf(tmp, "by %s.", died_from);
- center_string(buf, tmp);
- put_str(buf, 15, 11);
+ if (strlen(died_from) > 24)
+ {
+ strncpy(dummy, died_from, 24);
+ dummy[24] = '\0';
+ (void)sprintf(tmp, "by %s.", dummy);
+ }
+ else
+ (void)sprintf(tmp, "by %s.", died_from);
+ center_string(buf, tmp);
+ put_str(buf, 15, 11);
- (void)sprintf(tmp, "%-.24s", ctime(&ct));
- center_string(buf, tmp);
- put_str(buf, 17, 11);
- }
+
+ (void)sprintf(tmp, "%-.24s", ctime(&ct));
+ center_string(buf, tmp);
+ put_str(buf, 17, 11);
}
@@ -4609,8 +4619,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,8 +4628,7 @@ 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;
}
@@ -4672,168 +4680,13 @@ 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)
{
int i, j, k, n, place;
byte attr;
@@ -4853,12 +4706,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 +4742,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 +4764,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 +4780,20 @@ 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 */
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,
+ get_player_race_name(pr, ps),
+ class_info[pc].spec[pcs].title,
clev);
/* Append a "maximum level" */
@@ -4949,12 +4803,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 +4828,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 +4846,17 @@ 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)
{
- 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];
+ int highscore_fd;
switch (building)
{
@@ -5079,7 +4893,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,10 +4905,10 @@ void show_highclass(int building)
return;
}
- if (highscore_seek(0)) return;
+ if (highscore_seek(highscore_fd, 0)) return;
for (i = 0; i < MAX_HISCORES; i++)
- if (highscore_read(&the_score)) break;
+ if (highscore_read(highscore_fd, &the_score)) break;
m = 0;
j = 0;
@@ -5102,18 +4916,16 @@ void show_highclass(int building)
while ((m < 9) || (j < MAX_HISCORES))
{
- if (highscore_seek(j)) break;
- if (highscore_read(&the_score)) break;
+ if (highscore_seek(highscore_fd, j)) break;
+ if (highscore_read(highscore_fd, &the_score)) break;
pr = atoi(the_score.p_r);
pc = atoi(the_score.p_c);
clev = atoi(the_score.cur_lev);
- 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)))
+ if (((pc == (building - 10)) && (building != 1)) ||
+ ((building == 1) && (clev >= PY_MAX_LEVEL)))
{
sprintf(out_val, "%3d) %s the %s (Level %2d)",
- (m + 1), the_score.who, rp_name + race_info[pr].title, clev);
+ (m + 1), the_score.who, race_info[pr].title, clev);
prt(out_val, (m + 7), 0);
m++;
}
@@ -5124,27 +4936,21 @@ void show_highclass(int building)
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);
+ player_name, race_info[p_ptr->prace].title, p_ptr->lev);
prt(out_val, (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);
+ player_name, race_info[p_ptr->prace].title, p_ptr->lev);
prt(out_val, (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 +4964,20 @@ void show_highclass(int building)
*/
void race_score(int race_num)
{
- register int i = 0, j, m = 0;
+ int i = 0, j, m = 0;
int pr, clev, lastlev;
high_score the_score;
char buf[1024], out_val[256], 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);
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,11 +4989,11 @@ void race_score(int race_num)
return;
}
- if (highscore_seek(0)) return;
+ if (highscore_seek(highscore_fd, 0)) return;
for (i = 0; i < MAX_HISCORES; i++)
{
- if (highscore_read(&the_score)) break;
+ if (highscore_read(highscore_fd, &the_score)) break;
}
m = 0;
@@ -5194,15 +5001,15 @@ void race_score(int race_num)
while ((m < 10) && (j < i))
{
- if (highscore_seek(j)) break;
- if (highscore_read(&the_score)) break;
+ if (highscore_seek(highscore_fd, j)) break;
+ if (highscore_read(highscore_fd, &the_score)) break;
pr = atoi(the_score.p_r);
clev = atoi(the_score.cur_lev);
if (pr == race_num)
{
sprintf(out_val, "%3d) %s the %s (Level %3d)",
(m + 1), the_score.who,
- rp_name + race_info[pr].title, clev);
+ race_info[pr].title, clev);
prt(out_val, (m + 7), 0);
m++;
lastlev = clev;
@@ -5214,12 +5021,11 @@ void race_score(int race_num)
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);
+ player_name, race_info[p_ptr->prace].title, p_ptr->lev);
prt(out_val, (m + 8), 0);
}
- (void)fd_close(highscore_fd);
- highscore_fd = -1;
+ fd_close(highscore_fd);
}
@@ -5247,8 +5053,6 @@ void race_legends(void)
/*
* Enters a players name on a hi-score table, if "legal", and in any
* case, displays some relevant portion of the high score list.
- *
- * Assumes "signals_ignore_tstp()" has been called.
*/
static errr top_twenty(void)
{
@@ -5258,58 +5062,60 @@ 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);
+ display_scores_aux(highscore_fd, 0, 10, -1, NULL);
+ goto out;
}
-#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);
+ display_scores_aux(highscore_fd, 0, 10, -1, NULL);
+ goto out;
}
-#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 */
@@ -5317,13 +5123,15 @@ static errr top_twenty(void)
{
msg_print("Score not registered due to quitting.");
msg_print(NULL);
- display_scores_aux(0, 10, -1, NULL);
- return (0);
+ display_scores_aux(highscore_fd, 0, 10, -1, NULL);
+ goto out;
}
/* 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,22 +5146,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);
/* 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);
@@ -5366,39 +5168,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);
- /* 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 +5206,33 @@ static errr top_twenty(void)
/*
* Predict the players location, and display it.
*/
-errr predict_score(void)
+static errr predict_score(void)
{
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,7 +5247,7 @@ 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 */
@@ -5446,7 +5257,6 @@ errr predict_score(void)
sprintf(the_score.who, "%-.15s", player_name);
/* Save the player info XXX XXX XXX */
- sprintf(the_score.uid, "%7u", player_uid);
sprintf(the_score.sex, "%c", (p_ptr->psex ? 'm' : 'f'));
sprintf(the_score.p_r, "%2d", p_ptr->prace);
sprintf(the_score.p_s, "%2d", p_ptr->pracem);
@@ -5459,38 +5269,98 @@ 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 */
+ (void)fd_close(highscore_fd);
+
+ /* Forget the fd */
+ highscore_fd = -1;
+
+ /* Restore screen */
+ screen_load();
+
+ /* Hack - Flush it */
+ Term_fresh();
+
+ /* Mega-Hack - We are ready again */
+ *initialized_p = TRUE;
+}
+
/*
* Change the player into a King! -RAK-
@@ -5586,9 +5456,6 @@ void wipe_saved()
*/
void close_game(void)
{
- char buf[1024];
-
-
/* Handle stuff */
handle_stuff();
@@ -5599,30 +5466,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,8 +5494,7 @@ void close_game(void)
/* Show more info */
show_info();
- /* Write a note */
- if (take_notes)
+ /* Make a note */
{
char long_day[30];
char buf[80];
@@ -5670,11 +5524,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 +5533,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;
@@ -5775,7 +5616,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 +5664,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];
@@ -5945,114 +5786,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..e3df5636
--- /dev/null
+++ b/src/files.h
@@ -0,0 +1,17 @@
+#pragma once
+
+#include "h-basic.h"
+
+// C linkage required for these functions since main-* code uses them.
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern bool_ txt_to_html(cptr head, cptr food, cptr base, cptr ext, bool_ force, bool_ recur);
+extern void process_player_name(bool_ sf);
+extern void do_cmd_save_game(void);
+extern 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..52206d12
--- /dev/null
+++ b/src/files.hpp
@@ -0,0 +1,27 @@
+#pragma once
+
+#include "h-basic.h"
+#include "monster_type_fwd.hpp"
+
+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 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 get_name(void);
+extern void do_cmd_suicide(void);
+extern void autosave_checkpoint();
+extern void close_game(void);
+extern errr get_rnd_line(const char * file_name, char * output);
+extern char *get_line(const char* fname, cptr fdir, char *linbuf, int line);
+extern void race_legends(void);
+extern void show_highclass(int building);
+extern errr get_xtra_line(const char * file_name, monster_type *m_ptr, char * output);
diff --git a/src/flags_group.hpp b/src/flags_group.hpp
new file mode 100644
index 00000000..bdf5216b
--- /dev/null
+++ b/src/flags_group.hpp
@@ -0,0 +1,20 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * For level gaining artifacts
+ */
+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 */
+};
diff --git a/src/gen_evol.c b/src/gen_evol.cc
index bfdfbd68..6f3fbcba 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,8 +6,16 @@
* included in all such copies.
*/
-#include "angband.h"
+#include "gen_evol.hpp"
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "feature_type.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
@@ -48,7 +52,7 @@ void evolve_level(bool_ noise)
if (f_info[c_ptr->feat].flags1 & FF1_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;
@@ -82,7 +86,7 @@ void evolve_level(bool_ noise)
if (f_info[c_ptr->feat].flags1 & FF1_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;
diff --git a/src/gen_evol.hpp b/src/gen_evol.hpp
new file mode 100644
index 00000000..65b1320d
--- /dev/null
+++ b/src/gen_evol.hpp
@@ -0,0 +1,6 @@
+#pragma once
+
+#include "h-basic.h"
+
+extern bool_ level_generate_life();
+extern 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..28c092e3
--- /dev/null
+++ b/src/gen_maze.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+extern bool_ level_generate_maze();
diff --git a/src/generate.c b/src/generate.cc
index 6d83c321..b5733682 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,41 @@
* 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 "feature_type.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_type.hpp"
+#include "object2.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 "traps.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
/*
@@ -273,12 +303,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 +313,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;
@@ -586,8 +607,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 +614,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;
@@ -1021,7 +1025,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));
}
}
@@ -2748,8 +2752,7 @@ static bool_ vault_aux_chapel(int r_idx)
if (r_ptr->flags1 & (RF1_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);
}
@@ -3462,7 +3465,7 @@ static void build_type6(int by0, int bx0)
for (i = 0; i < 8; i++)
{
/* Message */
- msg_print(r_name + r_info[what[i]].name);
+ msg_print(r_info[what[i]].name);
}
}
}
@@ -3830,10 +3833,6 @@ static void build_type7(int by0, int bx0)
}
-#ifdef FORCE_V_IDX
- v_ptr = &v_info[FORCE_V_IDX];
-#endif
-
/* Message */
if (cheat_room || p_ptr->precognition) msg_print("Lesser Vault");
@@ -3848,7 +3847,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);
}
@@ -3890,10 +3889,6 @@ static void build_type8(int by0, int bx0)
}
-#ifdef FORCE_V_IDX
- v_ptr = &v_info[FORCE_V_IDX];
-#endif
-
/* Message */
if (cheat_room || p_ptr->precognition) msg_print("Greater Vault");
@@ -3908,7 +3903,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);
}
/*
@@ -4746,7 +4741,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 */
@@ -5313,7 +5308,7 @@ 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;
@@ -5360,22 +5355,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,8 +5377,7 @@ 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");
@@ -5425,16 +5410,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 +5448,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);
}
@@ -6667,7 +6643,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;
@@ -6819,7 +6795,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++)
@@ -6876,10 +6855,7 @@ bool_ level_generate_dungeon()
/* Attempt a very unusual room */ /* test hack */
if (ironman_rooms || (rand_int(DUN_UNUSUAL) < dun_level))
{
-#ifdef FORCE_V_IDX
- if (room_build(y, x, 8)) continue;
-#else
-/* Type 8 -- Greater vault (10%) */
+ /* Type 8 -- Greater vault (10%) */
if (k < 10)
{
if (max_vault_ok > 1)
@@ -6914,7 +6890,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%) */
@@ -7205,34 +7180,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 +7215,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
@@ -7547,6 +7505,87 @@ 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
*
@@ -7554,7 +7593,6 @@ static void fill_level(bool_ use_floor, byte smooth)
*/
static bool_ cave_gen(void)
{
- int i, k, y, x, y1, x1, branch;
dungeon_info_type *d_ptr = &d_info[dungeon_type];
int max_vault_ok = 2;
@@ -7614,7 +7652,7 @@ static bool_ cave_gen(void)
{
if (!strcmp(generator->name, generator_name))
{
- if (!generator->generator(generator->name))
+ if (!generator->generator())
return FALSE;
break;
}
@@ -7622,18 +7660,17 @@ 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);
@@ -7658,21 +7695,20 @@ static bool_ cave_gen(void)
}
}
- 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))
@@ -7700,7 +7736,7 @@ static bool_ cave_gen(void)
}
/* 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;
@@ -7833,8 +7869,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)
{
@@ -7851,8 +7887,7 @@ static bool_ cave_gen(void)
}
}
- /* Only if requested */
- if (generator->default_miscs)
+ /* Place traps and rubble */
{
/* Place some traps in the dungeon */
alloc_object(ALLOC_SET_BOTH, ALLOC_TYP_TRAP, randint(k * 2));
@@ -7861,8 +7896,7 @@ static bool_ cave_gen(void)
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 +7906,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));
@@ -7969,13 +8002,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 +8052,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);
}
}
}
@@ -8038,64 +8067,24 @@ static bool_ cave_gen(void)
/* Now double the generated dungeon */
if (dungeon_flags1 & DF1_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,139 +8099,6 @@ static bool_ cave_gen(void)
}
-/*
- * Builds the arena after it is entered -KMW-
- */
-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;
-
- 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--)
- {
- for (i = y_height; i <= y_depth; i++)
- {
- cave_set_feat(i, j, FEAT_PERM_EXTRA);
- cave[i][j].info |= (CAVE_GLOW | CAVE_MARK);
- }
- }
-
- 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);
-
- 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;
-
- /* Start with solid walls */
- for (y = 0; y < MAX_HGT; y++)
- {
- 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);
- }
- }
-
- /* Then place some floors */
- for (y = qy + 1; y < qy + SCREEN_HGT - 1; y++)
- {
- 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);
- }
- }
- }
-
- 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
@@ -8320,7 +8176,7 @@ static void wipe_special_level(void)
/* No special levels on the surface */
if (!dun_level) return;
- process_hooks(HOOK_LEVEL_REGEN, "()");
+ process_hooks_new(HOOK_LEVEL_REGEN, NULL, NULL);
/* Calculate relative depth */
level = dun_level - d_info[dungeon_type].mindepth;
@@ -8346,7 +8202,7 @@ static void finalise_special_level(void)
/* No special levels on the surface */
if (!dun_level) return;
- process_hooks(HOOK_LEVEL_END_GEN, "()");
+ process_hooks_new(HOOK_LEVEL_END_GEN, NULL, NULL);
/* Calculate relative depth */
level = dun_level - d_info[dungeon_type].mindepth;
@@ -8364,7 +8220,7 @@ static void finalise_special_level(void)
/*
* 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;
@@ -8450,7 +8306,7 @@ void generate_cave(void)
Rand_value = 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 +8322,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;
}
}
@@ -8526,33 +8360,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 +8403,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 +8434,7 @@ void generate_cave(void)
if (!p_ptr->wild_mode)
{
/* Make the wilderness */
- wilderness_gen(0);
+ wilderness_gen();
}
/* Small wilderness mode */
@@ -8842,7 +8647,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..d09907b5
--- /dev/null
+++ b/src/generate.hpp
@@ -0,0 +1,12 @@
+#pragma once
+
+#include "h-basic.h"
+
+extern bool_ new_player_spot(int branch);
+extern void add_level_generator(cptr name, bool_ (*generator)());
+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_cave(void);
+extern 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..1163e9b6 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,19 @@
* not for profit purposes provided that this copyright and statement are
* included in all such copies.
*/
+#include "gods.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,6 +51,30 @@ void abandon_god(int god)
}
/*
+ * Check if god may be followed by player
+ */
+static bool_ may_follow_god(int god)
+{
+ if (god == GOD_MELKOR)
+ {
+ int i;
+
+ /* Check if player has wielded The One Ring */
+ for (i = INVEN_WIELD; i < INVEN_TOTAL; i++)
+ {
+ if (p_ptr->inventory[i].name1 == ART_POWER)
+ {
+ msg_print("The One Ring has corrupted "
+ "you, and you are rejected.");
+ return FALSE;
+ }
+ }
+ }
+ /* Default is to allow */
+ return TRUE;
+}
+
+/*
* Get a religion
*/
void follow_god(int god, bool_ silent)
@@ -56,7 +87,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 +95,18 @@ 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.");
}
-
- /* 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 +153,60 @@ int wisdom_scale(int max)
return (i * max) / 37;
}
+/*
+ * Get deity info for a given god index.
+ * Returns NULL for the "atheist" god.
+ */
+deity_type *god_at(byte god_idx)
+{
+ assert(god_idx >= 0);
+ assert(god_idx < MAX_GODS);
+
+ if (god_idx == 0)
+ {
+ return NULL;
+ }
+
+ return &deity_info[god_idx];
+}
+
+/*
+ * Check if god is enabled for the current module
+ */
+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..7035dd14
--- /dev/null
+++ b/src/gods.hpp
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "h-basic.h"
+
+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);
+extern bool_ god_enabled(struct deity_type *deity);
+extern deity_type *god_at(byte god_idx);
+extern bool_ show_god_info();
+extern bool praying_to(int god);
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..a6d83079
--- /dev/null
+++ b/src/help.cc
@@ -0,0 +1,742 @@
+/*
+ * 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 "options.hpp"
+#include "player_type.hpp"
+#include "skills.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+
+#define DESC_MAX 14
+#define TRIGGERED_HELP_MAX 18
+
+#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_RUNE 5
+#define HELP_GET_ROD 6
+#define HELP_GET_ROD_TIP 7
+#define HELP_GET_TRAP_KIT 8
+#define HELP_GET_DEVICE 9
+#define HELP_WILDERNESS 10
+#define HELP_GAME_TOME 11
+#define HELP_GAME_THEME 12
+#define HELP_1ST_LEVEL 13
+#define HELP_20TH_LEVEL 14
+#define HELP_ID_SPELL_ITM 15
+#define HELP_MELEE_SKILLS 16
+#define HELP_MON_ASK_HELP 17
+
+/**
+ * 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 },
+ { "Runecrafter", "c_runecr.txt", 0 },
+ { "Sorceror", "c_sorcer.txt", 0 },
+ { "Summoner", "c_summon.txt", 0 },
+ { "Swordmaster", "c_swordm.txt", 0 },
+ { "Symbiant", "c_symbia.txt", 0 },
+ { "Thaumaturgist", "c_thaum.txt", 0 },
+ { "Unbeliever", "c_unbel.txt", 0 },
+ { "Warper", "c_warper.txt", 0 },
+ { "Warrior", "c_warrio.txt", 0 },
+ /* Theme */
+ { "Ascetic", "c_ascet.txt", 0 },
+ { "Clairvoyant", "c_clairv.txt", 0 },
+ { "Mercenary", "c_mercen.txt", 0 },
+ { "Pacifist", "c_pacif.txt", 0 },
+ { "Peace-mage", "c_peacemag.txt", 0 },
+ { "Priest(Mandos)", "c_pr_mand.txt", 0 },
+ { "Priest(Ulmo)", "c_pr_ulmo.txt", 0 },
+ { "Priest(Varda)", "c_pr_varda.txt", 0 },
+ { "Sniper", "c_sniper.txt", 0 },
+ { "Stonewright", "c_stonewr.txt", 0 },
+ { "Trapper", "c_trapper.txt", 0 },
+ { "Wainrider", "c_wainrid.txt", 0 },
+ { "War-mage", "c_warmage.txt", 0 },
+ /* End of list */
+ { NULL, NULL, 0 },
+};
+
+/**
+ * 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 },
+ { "Runecraft", "skills.txt", 36 },
+ { "Sling-mastery", "skills.txt", 9 },
+ { "Sneakiness", "skills.txt", 14 },
+ { "Spell-power", "skills.txt", 22 },
+ { "Spirituality", "skills.txt", 38 },
+ { "Sorcery", "skills.txt", 23 },
+ { "Stealing", "skills.txt", 19 },
+ { "Stealth", "skills.txt", 15 },
+ { "Stunning-blows", "skills.txt", 53 },
+ { "Summoning", "skills.txt", 43 },
+ { "Sword-mastery", "skills.txt", 3 },
+ { "Symbiosis", "skills.txt", 46 },
+ { "Temporal", "skills.txt", 32 },
+ { "Thaumaturgy", "skills.txt", 37 },
+ { "Udun", "skills.txt", 48 },
+ { "Weaponmastery", "skills.txt", 2 },
+ { "Water", "skills.txt", 26 },
+ { NULL, NULL, 0 },
+};
+
+/**
+ * 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 },
+ { "Trapping", "ability.txt", 11 },
+ { "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_rune(void *in, void *out) {
+ hook_get_in *g = (hook_get_in *) in;
+ return ((g->o_ptr->tval == TV_RUNE1) ||
+ (g->o_ptr->tval == TV_RUNE2));
+}
+
+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_trap_kit(void *in, void *out) {
+ hook_get_in *g = (hook_get_in *) in;
+ return (g->o_ptr->tval == TV_TRAPKIT);
+}
+
+static bool_ trigger_get_magic_device(void *in, void *out) {
+ hook_get_in *g = (hook_get_in *) in;
+ return ((g->o_ptr->tval == TV_WAND) ||
+ (g->o_ptr->tval == TV_STAFF));
+}
+
+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)
+ {
+ u32b f1, f2, f3, f4, f5, esp;
+ object_flags(in->o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ if (f5 & TR5_SPELL_CONTAIN)
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+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_RUNE,
+ HOOK_GET,
+ trigger_get_rune,
+ { "Ah, a rune! Runes are used with the Runecraft skill to allow you to",
+ "create spells on your own.",
+ NULL
+ }
+ },
+ { 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_TRAP_KIT,
+ HOOK_GET,
+ trigger_get_trap_kit,
+ { "Ooooh, a trapping kit. If you have ability in the trapping skill,",
+ "you can lay this trap (via the 'm' key) to harm unsuspecting foes.",
+ "You'll generally need either some ammo or magic device depending",
+ "on the exact type of trap kit.",
+ NULL
+ }
+ },
+ { 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 ((option_ingame_help) &&
+ (!p_ptr->help.activated[triggered_help->help_index]) &&
+ triggered_help->trigger_func(in,out))
+ {
+ int i;
+
+ /* Triggered */
+ p_ptr->help.activated[triggered_help->help_index] = TRUE;
+
+ /* Show the description */
+ for (i = 0; (i < DESC_MAX) && (triggered_help->desc[i] != NULL); i++)
+ {
+ cmsg_print(TERM_YELLOW, triggered_help->desc[i]);
+ }
+ }
+ /* Don't stop processing */
+ return FALSE;
+}
+
+static 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, 0);
+
+ screen_load();
+}
+
+/*
+ * Find context help
+ */
+static context_help_type *find_context_help(context_help_type table[], cptr key)
+{
+ int i;
+
+ for (i = 0; ; i++)
+ {
+ context_help_type *context_help = &table[i];
+
+ if (context_help->key == NULL)
+ {
+ return NULL; /* End of list */
+ }
+
+ if (streq(key, context_help->key))
+ {
+ return context_help;
+ }
+ }
+}
+
+/*
+ * Racial help
+ */
+void help_race(cptr race)
+{
+ show_context_help(find_context_help(race_table, race));
+}
+
+void help_subrace(cptr subrace)
+{
+ show_context_help(find_context_help(subrace_table, subrace));
+}
+
+void help_class(cptr klass)
+{
+ show_context_help(find_context_help(class_table, klass));
+}
+
+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(cptr skill)
+{
+ show_context_help(find_context_help(skill_table, skill));
+}
+
+void help_ability(cptr ability)
+{
+ show_context_help(find_context_help(ability_table, ability));
+}
diff --git a/src/help.hpp b/src/help.hpp
new file mode 100644
index 00000000..7c057a01
--- /dev/null
+++ b/src/help.hpp
@@ -0,0 +1,11 @@
+#pragma once
+
+#include "h-basic.h"
+
+extern void init_hooks_help();
+extern void help_race(cptr race);
+extern void help_subrace(cptr subrace);
+extern void help_class(cptr klass);
+extern void help_god(cptr god);
+extern void help_skill(cptr skill);
+extern void help_ability(cptr ability);
diff --git a/src/help_info.hpp b/src/help_info.hpp
new file mode 100644
index 00000000..ea440bb9
--- /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; /* ingame help enabled */
+ bool_ activated[HELP_MAX]; /* 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..0b1b713d
--- /dev/null
+++ b/src/hiscore.hpp
@@ -0,0 +1,83 @@
+#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 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 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/hist_type.hpp b/src/hist_type.hpp
new file mode 100644
index 00000000..2da47b7c
--- /dev/null
+++ b/src/hist_type.hpp
@@ -0,0 +1,16 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * Player background descriptor.
+ */
+struct hist_type
+{
+ char *info; /* Textual History */
+
+ byte roll; /* Frequency of this entry */
+ s16b chart; /* Chart index */
+ s16b next; /* Next chart index */
+ byte bonus; /* Social Class Bonus + 50 */
+};
diff --git a/src/hist_type_fwd.hpp b/src/hist_type_fwd.hpp
new file mode 100644
index 00000000..d1cbce91
--- /dev/null
+++ b/src/hist_type_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct hist_type;
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..4fcc39d3
--- /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..b6124e6a
--- /dev/null
+++ b/src/hooks.hpp
@@ -0,0 +1,10 @@
+#pragma once
+
+#include "h-basic.h"
+
+typedef bool_ (*hook_func_t)(void *, void *, void *);
+
+extern void add_hook_new(int h_idx, hook_func_t hook_func, cptr name, void *data);
+extern void del_hook_new(int h_idx, hook_func_t hook_func);
+extern int process_hooks_restart;
+extern 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..8ae1e115
--- /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) {
+ auto i = bimap.left.find(e);
+ assert(i != bimap.left.end() && "Missing mapping for enumerated value");
+ return i->second.c_str();
+ }
+
+ E parse(const char *s) {
+ E e;
+ bool result = parse(s, &e);
+ assert(result && "Missing string->enum mapping");
+ return e;
+ }
+
+ bool parse(const char *s, E *e) {
+ auto i = bimap.right.find(s);
+ if (i == bimap.right.end())
+ {
+ return false;
+ }
+
+ *e = i->second;
+ return true;
+ }
+};
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/squelch/automatizer.hpp b/src/include/tome/squelch/automatizer.hpp
new file mode 100644
index 00000000..786ca1ae
--- /dev/null
+++ b/src/include/tome/squelch/automatizer.hpp
@@ -0,0 +1,156 @@
+#pragma once
+
+#include <boost/noncopyable.hpp>
+#include <memory>
+#include <vector>
+#include <jansson.h>
+
+#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 data structure to represent
+ * all the rules.
+ */
+ std::shared_ptr<json_t> to_json() const;
+
+ /**
+ * Load rules from a JSON data structure.
+ */
+ void load_json(json_t *json);
+
+ /**
+ * Remove currently selected condition or rule.
+ */
+ int remove_current_selection();
+
+ /**
+ * Reset view.
+ */
+ void reset_view();
+
+ /**
+ * Show current rule
+ */
+ void show_current() const;
+
+ /**
+ * Scroll view up
+ */
+ void scroll_up();
+
+ /**
+ * Scroll view down
+ */
+ void scroll_down();
+
+ /**
+ * Scroll view left
+ */
+ void scroll_left();
+
+ /**
+ * Scroll view right
+ */
+ void scroll_right();
+
+ /**
+ * Move selection up
+ */
+ void move_up();
+
+ /**
+ * Move selection down
+ */
+ void move_down();
+
+ /**
+ * Move selection left
+ */
+ void move_left();
+
+ /**
+ * Move selection right
+ */
+ void move_right();
+
+ /**
+ * Add new condition to selected rule
+ */
+ void add_new_condition(std::function<std::shared_ptr<Condition> ()> factory);
+
+ /**
+ * Get rule names. The names are not stable across multiple
+ * calls to methods on this class.
+ */
+ void get_rule_names(std::vector<const char *> *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..5d1240f5
--- /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 <functional>
+#include <memory>
+#include <cstdint>
+#include <jansson.h>
+
+#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:
+ json_t *to_json() const;
+
+ virtual void add_child(ConditionFactory const &factory) {
+ // Default is to not support children.
+ };
+
+ virtual void remove_child(Condition *c) {
+ // Nothing to do by default.
+ }
+
+ virtual std::shared_ptr<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(json_t *);
+
+ /**
+ * Convert an (optional) condition to JSON.
+ */
+ static json_t *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(json_t *) const = 0;
+
+ // What do we want to match?
+ match_type match;
+};
+
+/**
+ * Check for a specific TVAL
+ */
+class TvalCondition : public Condition
+{
+public:
+ TvalCondition(uint8_t tval)
+ : Condition(match_type::TVAL)
+ , m_tval(tval) {
+ }
+
+ bool is_match(object_type *) const override;
+
+ static std::shared_ptr<Condition> from_json(json_t *);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(json_t *) const override;
+
+private:
+ uint8_t m_tval;
+};
+
+/**
+ * Check for object name
+ */
+class NameCondition : public Condition
+{
+public:
+ NameCondition(std::string name) :
+ Condition(match_type::NAME),
+ m_name(name) {
+ }
+
+ bool is_match(object_type *) const override;
+
+ static std::shared_ptr<Condition> from_json(json_t *);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(json_t *) const override;
+
+private:
+ std::string m_name;
+};
+
+/**
+ * Check for infix of object name
+ */
+class ContainCondition : public Condition
+{
+public:
+ ContainCondition(std::string contain) :
+ Condition(match_type::CONTAIN),
+ m_contain(contain) {
+ }
+
+ bool is_match(object_type *) const override;
+
+ static std::shared_ptr<Condition> from_json(json_t *);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(json_t *) const override;
+
+private:
+ std::string m_contain;
+};
+
+/**
+ * Check for specific SVAL
+ */
+class SvalCondition : public Condition
+{
+public:
+ SvalCondition(uint8_t min, uint8_t max)
+ : Condition(match_type::SVAL)
+ , m_min(min)
+ , m_max(max) {
+ }
+
+ bool is_match(object_type *) const override;
+
+ static std::shared_ptr<Condition> from_json(json_t *);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(json_t *) const override;
+
+private:
+ uint8_t m_min;
+ uint8_t m_max;
+};
+
+/**
+ * Groupings of subconditions
+ */
+class GroupingCondition : public Condition
+{
+public:
+ GroupingCondition(match_type match,
+ std::vector< std::shared_ptr<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(json_t *);
+
+protected:
+ void to_json(json_t *) 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(json_t *);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+};
+
+/**
+ * Conditions that are OR'ed together
+ */
+class OrCondition : public GroupingCondition
+{
+public:
+ OrCondition() : GroupingCondition(match_type::OR) {
+ }
+
+ bool is_match(object_type *) const override;
+
+ static std::shared_ptr<Condition> from_json(json_t *);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+};
+
+/**
+ * Check for object status
+ */
+class StatusCondition : public Condition
+{
+public:
+ StatusCondition(status_type status)
+ : Condition(match_type::STATUS)
+ , m_status(status) {
+ }
+
+public:
+ bool is_match(object_type *) const override;
+
+ static std::shared_ptr<Condition> from_json(json_t *);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(json_t *) const override;
+
+private:
+ status_type m_status;
+};
+
+/**
+ * Check for player race
+ */
+class RaceCondition : public Condition
+{
+public:
+ RaceCondition(std::string race)
+ : Condition(match_type::RACE)
+ , m_race(race) {
+ }
+
+ bool is_match(object_type *) const override;
+
+ static std::shared_ptr<Condition> from_json(json_t *);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(json_t *) const override;
+
+private:
+ std::string m_race;
+};
+
+/**
+ * Check player subrace
+ */
+class SubraceCondition : public Condition
+{
+public:
+ SubraceCondition(std::string subrace)
+ : Condition(match_type::SUBRACE)
+ , m_subrace(subrace) {
+ }
+
+ bool is_match(object_type *) const override;
+
+ static std::shared_ptr<Condition> from_json(json_t *);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(json_t *) const override;
+
+private:
+ std::string m_subrace;
+};
+
+/**
+ * Check player class
+ */
+class ClassCondition : public Condition
+{
+public:
+ ClassCondition(std::string klass)
+ : Condition(match_type::CLASS)
+ , m_class(klass) {
+ }
+
+ bool is_match(object_type *) const override;
+
+ static std::shared_ptr<Condition> from_json(json_t *);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(json_t *) const override;
+
+private:
+ std::string m_class;
+};
+
+/**
+ * Check object inscription
+ */
+class InscriptionCondition : public Condition
+{
+public:
+ InscriptionCondition(std::string inscription)
+ : Condition(match_type::INSCRIBED)
+ , m_inscription(inscription) {
+ }
+
+ bool is_match(object_type *) const override;
+
+ static std::shared_ptr<Condition> from_json(json_t *);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(json_t *) const override;
+
+private:
+ std::string m_inscription;
+};
+
+/**
+ * Check object discount
+ */
+class DiscountCondition : public Condition
+{
+public:
+ DiscountCondition(int min, int max)
+ : Condition(match_type::DISCOUNT)
+ , m_min(min)
+ , m_max(max) {
+ }
+
+ bool is_match(object_type *) const override;
+
+ static std::shared_ptr<Condition> from_json(json_t *);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(json_t *) const override;
+
+private:
+ int m_min;
+ int m_max;
+};
+
+/**
+ * Check player level
+ */
+class LevelCondition : public Condition
+{
+public:
+ LevelCondition(int min, int max)
+ : Condition(match_type::LEVEL)
+ , m_min(min)
+ , m_max(max) {
+ }
+
+ bool is_match(object_type *) const override;
+
+ static std::shared_ptr<Condition> from_json(json_t *);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(json_t *) const override;
+
+private:
+ int m_min;
+ int m_max;
+};
+
+/**
+ * Check player's skill level
+ */
+class SkillCondition : public Condition
+{
+public:
+ SkillCondition(uint16_t skill_idx, uint16_t min, uint16_t max)
+ : Condition(match_type::SKILL)
+ , m_skill_idx(skill_idx)
+ , m_min(min)
+ , m_max(max) {
+ }
+
+ bool is_match(object_type *) const override;
+
+ static std::shared_ptr<Condition> from_json(json_t *);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(json_t *) const override;
+
+private:
+ uint16_t m_skill_idx;
+ uint16_t m_min;
+ uint16_t m_max;
+};
+
+/**
+ * Check identification state
+ */
+class StateCondition : public Condition
+{
+public:
+ StateCondition(identification_state state)
+ : Condition(match_type::STATE)
+ , m_state(state) {
+ }
+
+ bool is_match(object_type *) const override;
+
+ static std::shared_ptr<Condition> from_json(json_t *);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(json_t *) const override;
+
+private:
+ identification_state m_state;
+};
+
+/**
+ * Check object symbol
+ */
+class SymbolCondition : public Condition
+{
+public:
+ SymbolCondition(char symbol)
+ : Condition(match_type::SYMBOL)
+ , m_symbol(symbol) {
+ }
+
+ bool is_match(object_type *) const override;
+
+ static std::shared_ptr<Condition> from_json(json_t *);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(json_t *) const override;
+
+private:
+ char m_symbol;
+};
+
+/**
+ * Check if player has a particular ability
+ */
+class AbilityCondition : public Condition
+{
+public:
+ AbilityCondition(uint16_t ability_idx)
+ : Condition(match_type::ABILITY)
+ , m_ability_idx(ability_idx) {
+ }
+
+ bool is_match(object_type *) const override;
+
+ static std::shared_ptr<Condition> from_json(json_t *);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+
+ void to_json(json_t *) const override;
+
+private:
+ uint16_t m_ability_idx;
+};
+
+/**
+ * Condition with a single subcondition
+ */
+class SingleSubconditionCondition : public Condition
+{
+public:
+ SingleSubconditionCondition(match_type match,
+ std::shared_ptr<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(json_t *) const override;
+
+ static std::shared_ptr<Condition> parse_single_subcondition(
+ json_t *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(json_t *);
+
+protected:
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+};
+
+/**
+ * Condition which checks if player inventory contains object(s)
+ * satisfying another condition.
+ */
+class InventoryCondition : public SingleSubconditionCondition
+{
+public:
+ InventoryCondition(std::shared_ptr<Condition> subcondition = nullptr)
+ : SingleSubconditionCondition(match_type::INVENTORY, subcondition) {
+ }
+
+ bool is_match(object_type *) const override;
+
+ static std::shared_ptr<Condition> from_json(json_t *);
+
+protected:
+
+ void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override;
+};
+
+/**
+ * Condition which checks if player equipment contains object(s)
+ * satisfying another condition.
+ */
+class EquipmentCondition : public SingleSubconditionCondition
+{
+public:
+ EquipmentCondition(std::shared_ptr<Condition> subcondition = nullptr)
+ : SingleSubconditionCondition(match_type::EQUIPMENT, subcondition) {
+ }
+
+ bool is_match(object_type *) const override;
+
+ static std::shared_ptr<Condition> from_json(json_t *);
+
+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..63f1b6c0
--- /dev/null
+++ b/src/include/tome/squelch/rule.hpp
@@ -0,0 +1,162 @@
+#pragma once
+
+#include <jansson.h>
+#include <memory>
+
+#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 char *new_name);
+
+ /**
+ * Get the name of the rule
+ */
+ const char *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 json_t *to_json() const;
+
+ /**
+ * Parse rule from JSON
+ */
+ static std::shared_ptr<Rule> parse_rule(json_t *);
+
+protected:
+ virtual bool do_apply_rule(object_type *, int) const = 0;
+ virtual void do_write_tree(TreePrinter *p) const = 0;
+
+protected:
+ // Rule name
+ std::string m_name;
+ // What does the rule do?
+ action_type m_action;
+ // Which module does this rule apply to?
+ int m_module_idx;
+ // Condition to check
+ std::shared_ptr<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) {
+ }
+
+ json_t *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..e8ee1e56
--- /dev/null
+++ b/src/include/tome/squelch/tree_printer.hpp
@@ -0,0 +1,49 @@
+#ifndef H_3d6cc652_c674_4a84_911d_e8ec35cc992a
+#define H_3d6cc652_c674_4a84_911d_e8ec35cc992a
+
+#include <boost/noncopyable.hpp>
+#include <cstdint>
+
+namespace squelch {
+
+/**
+ * Printing trees.
+ */
+class TreePrinter : boost::noncopyable
+{
+public:
+ TreePrinter();
+
+ void indent();
+
+ void dedent();
+
+ void reset();
+
+ void reset_scroll();
+
+ void scroll_up();
+
+ void scroll_down();
+
+ void scroll_left();
+
+ void scroll_right();
+
+ void write(uint8_t color, const char *line);
+
+private:
+ int m_indent;
+ int m_write_out_y;
+ int m_write_out_x;
+ int m_write_out_h;
+ int m_write_out_w;
+ int m_write_y;
+ int m_write_x;
+ int m_write_off_x;
+ int m_write_off_y;
+};
+
+} // namespace
+
+#endif
diff --git a/src/include/tome/squelch/tree_printer_fwd.hpp b/src/include/tome/squelch/tree_printer_fwd.hpp
new file mode 100644
index 00000000..d7d75453
--- /dev/null
+++ b/src/include/tome/squelch/tree_printer_fwd.hpp
@@ -0,0 +1,10 @@
+#ifndef H_4ce68eb3_c475_4fc4_8a70_0590c16dc684
+#define H_4ce68eb3_c475_4fc4_8a70_0590c16dc684
+
+namespace squelch {
+
+class TreePrinter;
+
+} // namespace
+
+#endif
diff --git a/src/init1.c b/src/init1.cc
index 9715831d..7083a5f3 100644
--- a/src/init1.c
+++ b/src/init1.cc
@@ -1,8 +1,55 @@
-/* File: init1.c */
-
-/* Purpose: Initialization (part 1) -BEN- */
-
-#include "angband.h"
+#include "init1.hpp"
+
+#include "ability_type.hpp"
+#include "artifact_type.hpp"
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "dungeon_info_type.hpp"
+#include "ego_item_type.hpp"
+#include "feature_type.hpp"
+#include "files.hpp"
+#include "gods.hpp"
+#include "hist_type.hpp"
+#include "init2.hpp"
+#include "meta_class_type.hpp"
+#include "monster2.hpp"
+#include "monster_ego.hpp"
+#include "monster_race.hpp"
+#include "monster_type.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_kind.hpp"
+#include "owner_type.hpp"
+#include "player_class.hpp"
+#include "player_race.hpp"
+#include "player_race_mod.hpp"
+#include "player_type.hpp"
+#include "randart_gen_type.hpp"
+#include "randart_part_type.hpp"
+#include "set_type.hpp"
+#include "skill_type.hpp"
+#include "skills.hpp"
+#include "spells5.hpp"
+#include "store_action_type.hpp"
+#include "store_info_type.hpp"
+#include "store_type.hpp"
+#include "tables.hpp"
+#include "town_type.hpp"
+#include "trap_type.hpp"
+#include "traps.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 "z-rand.hpp"
+
+#include <boost/algorithm/string/predicate.hpp>
+
+using boost::algorithm::iequals;
+using boost::algorithm::ends_with;
/*
@@ -363,7 +410,7 @@ static cptr r_info_flags7[] =
"AI_PLAYER",
"NO_THEFT",
"SPIRIT",
- "IM_MELEE",
+ "XXX7X20",
"XXX7X21",
"XXX7X22",
"XXX7X23",
@@ -637,9 +684,9 @@ cptr k_info_flags4[] =
"CHEAPNESS",
"FOUNTAIN",
"ANTIMAGIC_50",
- "ANTIMAGIC_30",
- "ANTIMAGIC_20",
- "ANTIMAGIC_10",
+ "XXX5",
+ "XXX5",
+ "XXX5",
"EASY_USE",
"IM_NETHER",
"RECHARGED",
@@ -648,7 +695,7 @@ cptr k_info_flags4[] =
"LITE2",
"LITE3",
"FUEL_LITE",
- "ART_EXP",
+ "XXX5",
"CURSE_NO_DROP",
"NO_RECHARGE"
};
@@ -924,46 +971,6 @@ static cptr t_info_flags[] =
};
/*
- * 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[] =
@@ -1167,30 +1174,6 @@ d_info_dtypes[] =
{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*/
@@ -1394,6 +1377,12 @@ static const char *activation_names[] =
"XXX198",
"XXX199",
"MUSIC", /* 200*/
+ "ETERNAL_FLAME", /* 201 */
+ "MAGGOT", /* 202 */
+ "LEBOHAUM", /* 203 */
+ "DURANDIL", /* 204 */
+ "RADAGAST", /* 205, Theme */
+ "VALAROMA", /* 206, Theme */
""
};
@@ -1488,76 +1477,47 @@ static byte monster_ego_modify(char c)
}
}
-/*
- * Implements fp stacks, for included files
- */
-static FILE *fp_stack[10];
-static int fp_stack_idx = 0;
-
-/*
- * Must be caleld before the main loop
+/**
+ * Version of strdup() which just aborts if an allocation
+ * error occurs.
*/
-static void fp_stack_init(FILE *fp)
-{
- fp_stack[0] = fp;
- fp_stack_idx = 0;
-}
-
-static void fp_stack_push(cptr name)
+static char *my_strdup(const char *s)
{
- if (fp_stack_idx < 9)
+ char *p = strdup(s);
+ if (!p)
{
- 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;
+ abort();
}
+ return p;
}
-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
+/**
+ * Append one string to the end of another, reallocating if
+ * necessary.
*/
-static int my_fgets_dostack(char *buf, int len)
+static void strappend(char **s, const char *t)
{
- // End of a file
- if (0 != my_fgets(fp_stack[fp_stack_idx], buf, len))
+ // Do we need to initialize the destination string?
+ if (*s == nullptr)
{
- // If any left, use them
- if (fp_stack_pop())
- return my_fgets_dostack(buf, len);
- // If not, this is the end
- else
- return 1;
+ // Costs an extra allocation which could be avoided
+ // but this leads to simpler code.
+ *s = my_strdup("");
}
- else
+ // 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)
{
- return 0;
+ abort(); // Cannot handle failure to reallocate
}
-}
+ /* Append 't' to the destination string */
+ strcat(*s, t);
+}
/*** Initialize from ascii template files ***/
@@ -1571,7 +1531,7 @@ static errr grab_one_class_flag(u32b *choice, cptr what)
cptr s;
/* Scan classes flags */
- for (i = 0; i < max_c_idx && (s = class_info[i].title + c_name); i++)
+ for (i = 0; i < max_c_idx && (s = class_info[i].title); i++)
{
if (streq(what, s))
{
@@ -1592,7 +1552,7 @@ static errr grab_one_race_allow_flag(u32b *choice, cptr what)
cptr s;
/* Scan classes flags */
- for (i = 0; i < max_rp_idx && (s = race_info[i].title + rp_name); i++)
+ for (i = 0; i < max_rp_idx && (s = race_info[i].title); i++)
{
if (streq(what, s))
{
@@ -1666,14 +1626,18 @@ static errr grab_one_player_race_flag(u32b *f1, u32b *f2, cptr what)
}
/* Get an activation number (good for artifacts, recipes, egos, and object kinds) */
-int get_activation(char *activation)
+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;
}
@@ -1764,7 +1728,7 @@ static errr grab_one_race_kind_flag(u32b *f1, u32b *f2, u32b *f3, u32b *f4, u32b
/*
* Initialize the "player" arrays, by parsing an ascii "template" file
*/
-errr init_player_info_txt(FILE *fp, char *buf)
+errr init_player_info_txt(FILE *fp)
{
int i = 0, z;
int powers = 0;
@@ -1772,12 +1736,9 @@ errr init_player_info_txt(FILE *fp, char *buf)
int tit_idx = 0;
int spec_idx = 0;
int cur_ab = -1;
-
+ char buf[1024];
char *s, *t;
- /* Not ready yet */
- bool_ okay = FALSE;
-
/* Current entry */
player_race *rp_ptr = NULL;
player_race_mod *rmp_ptr = NULL;
@@ -1792,15 +1753,6 @@ errr init_player_info_txt(FILE *fp, char *buf)
/* 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++)
{
@@ -1811,8 +1763,7 @@ errr init_player_info_txt(FILE *fp, char *buf)
}
/* Parse */
- fp_stack_init(fp);
- while (0 == my_fgets_dostack(buf, 1024))
+ while (0 == my_fgets(fp, buf, 1024))
{
/* Advance the line number */
error_line++;
@@ -1823,32 +1774,6 @@ errr init_player_info_txt(FILE *fp, char *buf)
/* 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')
{
@@ -1871,13 +1796,9 @@ errr init_player_info_txt(FILE *fp, char *buf)
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]);
+ /* Copy text */
+ assert(!bg[idx].info);
+ bg[idx].info = my_strdup(zz[5]);
/* Next... */
continue;
@@ -1925,7 +1846,7 @@ errr init_player_info_txt(FILE *fp, char *buf)
if (i < error_idx) return (4);
/* Verify information */
- if (i >= rp_head->info_num) return (2);
+ if (i >= max_rp_idx) return (2);
/* Save the index */
error_idx = i;
@@ -1933,18 +1854,11 @@ errr init_player_info_txt(FILE *fp, char *buf)
/* 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);
+ /* Copy title */
+ assert(!rp_ptr->title);
+ rp_ptr->title = my_strdup(s);
+ /* Initialize */
rp_ptr->powers[0] = rp_ptr->powers[1] = rp_ptr->powers[2] = rp_ptr->powers[3] = -1;
powers = 0;
lev = 1;
@@ -1962,27 +1876,13 @@ errr init_player_info_txt(FILE *fp, char *buf)
/* 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);
+ rp_ptr->desc = my_strdup(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;
+ strappend(&rp_ptr->desc, format("\n%s", s));
}
/* Next... */
@@ -2047,12 +1947,12 @@ errr init_player_info_txt(FILE *fp, char *buf)
s = buf + 4;
/* Find it in the list */
- for (i = 0; i < power_max; i++)
+ for (i = 0; i < POWER_MAX; i++)
{
- if (!stricmp(s, powers_type[i].name)) break;
+ if (iequals(s, powers_type[i].name)) break;
}
- if (i == power_max) return (6);
+ if (i == POWER_MAX) return (6);
rp_ptr->powers[powers++] = i;
@@ -2299,7 +2199,7 @@ errr init_player_info_txt(FILE *fp, char *buf)
if (i < error_idx) return (4);
/* Verify information */
- if (i >= rmp_head->info_num) return (2);
+ if (i >= max_rmp_idx) return (2);
/* Save the index */
error_idx = i;
@@ -2307,18 +2207,11 @@ errr init_player_info_txt(FILE *fp, char *buf)
/* 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);
+ /* Copy title */
+ assert(!rmp_ptr->title);
+ rmp_ptr->title = my_strdup(s);
+ /* Initialize */
rmp_ptr->powers[0] = rmp_ptr->powers[1] = rmp_ptr->powers[2] = rmp_ptr->powers[3] = -1;
powers = 0;
lev = 1;
@@ -2336,30 +2229,25 @@ errr init_player_info_txt(FILE *fp, char *buf)
/* 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);
+ /* Place */
+ if (buf[4] == 'A')
+ {
+ rmp_ptr->place = TRUE;
+ }
+ else
+ {
+ rmp_ptr->place = FALSE;
+ }
- /* Advance and Save the text index */
+ /* Description */
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);
+ rmp_ptr->desc = my_strdup(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;
+ strappend(&rmp_ptr->desc, format("\n%s", s));
}
/* Next... */
@@ -2425,12 +2313,12 @@ errr init_player_info_txt(FILE *fp, char *buf)
s = buf + 4;
/* Find it in the list */
- for (i = 0; i < power_max; i++)
+ for (i = 0; i < POWER_MAX; i++)
{
- if (!stricmp(s, powers_type[i].name)) break;
+ if (iequals(s, powers_type[i].name)) break;
}
- if (i == power_max) return (6);
+ if (i == POWER_MAX) return (6);
rmp_ptr->powers[powers++] = i;
@@ -2713,7 +2601,7 @@ errr init_player_info_txt(FILE *fp, char *buf)
if (i < error_idx) return (4);
/* Verify information */
- if (i >= c_head->info_num) return (2);
+ if (i >= max_c_idx) return (2);
/* Save the index */
error_idx = i;
@@ -2721,18 +2609,11 @@ errr init_player_info_txt(FILE *fp, char *buf)
/* 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);
+ /* Copy name */
+ assert(!c_ptr->title);
+ c_ptr->title = my_strdup(s);
+ /* Initialize */
c_ptr->powers[0] = c_ptr->powers[1] = c_ptr->powers[2] = c_ptr->powers[3] = -1;
powers = 0;
lev = 1;
@@ -2755,43 +2636,31 @@ errr init_player_info_txt(FILE *fp, char *buf)
/* 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 */
+ case '0': /* Class description */
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);
+ c_ptr->desc = my_strdup(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;
+ strappend(&c_ptr->desc, format("\n%s", s));
}
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);
+ 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++;
- /* Advance the index */
- c_head->text_size += strlen(s);
break;
- default:
+
+ default: /* Unknown */
return (6);
break;
}
@@ -2948,12 +2817,12 @@ errr init_player_info_txt(FILE *fp, char *buf)
s = buf + 4;
/* Find it in the list */
- for (i = 0; i < power_max; i++)
+ for (i = 0; i < POWER_MAX; i++)
{
- if (!stricmp(s, powers_type[i].name)) break;
+ if (iequals(s, powers_type[i].name)) break;
}
- if (i == power_max) return (6);
+ if (i == POWER_MAX) return (6);
c_ptr->powers[powers++] = i;
@@ -3132,18 +3001,11 @@ errr init_player_info_txt(FILE *fp, char *buf)
/* 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);
+ /* Copy title */
+ assert(!s_ptr->title);
+ s_ptr->title = my_strdup(s);
+ /* Initialize */
s_ptr->obj_num = 0;
cur_ab = 0;
for (z = 0; z < 10; z++)
@@ -3159,27 +3021,13 @@ errr init_player_info_txt(FILE *fp, char *buf)
/* 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);
+ s_ptr->desc = my_strdup(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;
+ strappend(&s_ptr->desc, format("\n%s", s));
}
/* Next... */
@@ -3373,7 +3221,10 @@ errr init_player_info_txt(FILE *fp, char *buf)
/* Find it in the list */
for (i = 0; i < max_c_idx; i++)
{
- if (!stricmp(s, class_info[i].title + c_name)) break;
+ if (class_info[i].title && iequals(s, class_info[i].title))
+ {
+ break;
+ }
}
if (i == max_c_idx) return (6);
@@ -3388,16 +3239,6 @@ errr init_player_info_txt(FILE *fp, char *buf)
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);
}
@@ -3406,33 +3247,23 @@ errr init_player_info_txt(FILE *fp, char *buf)
/*
* Initialize the "v_info" array, by parsing an ascii "template" file
*/
-errr init_v_info_txt(FILE *fp, char *buf, bool_ start)
+errr init_v_info_txt(FILE *fp)
{
int i;
+ char buf[1024];
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;
+ /* Just before the first record */
+ error_idx = -1;
- /* Prepare the "fake" stuff */
- v_head->name_size = 0;
- v_head->text_size = 0;
- }
+ /* Just before the first line */
+ error_line = -1;
/* Parse */
- fp_stack_init(fp);
- while (0 == my_fgets_dostack(buf, 1024))
+ while (0 == my_fgets(fp, buf, 1024))
{
/* Advance the line number */
error_line++;
@@ -3444,32 +3275,6 @@ errr init_v_info_txt(FILE *fp, char *buf, bool_ start)
/* 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')
{
@@ -3492,7 +3297,7 @@ errr init_v_info_txt(FILE *fp, char *buf, bool_ start)
if (i <= error_idx) return (4);
/* Verify information */
- if (i >= v_head->info_num) return (2);
+ if (i >= max_v_idx) return (2);
/* Save the index */
error_idx = i;
@@ -3500,17 +3305,9 @@ errr init_v_info_txt(FILE *fp, char *buf, bool_ start)
/* 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);
+ /* Initialize data -- we ignore the name, it's not
+ * used for anything */
+ v_ptr->data = my_strdup("");
/* Next... */
continue;
@@ -3525,17 +3322,8 @@ errr init_v_info_txt(FILE *fp, char *buf, bool_ start)
/* 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);
+ /* Append data */
+ strappend(&v_ptr->data, s);
/* Next... */
continue;
@@ -3602,18 +3390,6 @@ errr init_v_info_txt(FILE *fp, char *buf, bool_ start)
}
- /* 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);
}
@@ -3647,47 +3423,23 @@ static errr grab_one_feature_flag(feature_type *f_ptr, cptr what)
/*
* Initialize the "f_info" array, by parsing an ascii "template" file
*/
-errr init_f_info_txt(FILE *fp, char *buf)
+errr init_f_info_txt(FILE *fp)
{
int i;
-
+ char buf[1024];
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))
+ while (0 == my_fgets(fp, buf, 1024))
{
/* Advance the line number */
error_line++;
@@ -3698,32 +3450,6 @@ errr init_f_info_txt(FILE *fp, char *buf)
/* 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')
{
@@ -3746,7 +3472,7 @@ errr init_f_info_txt(FILE *fp, char *buf)
if (i <= error_idx) return (4);
/* Verify information */
- if (i >= f_head->info_num) return (2);
+ if (i >= max_f_idx) return (2);
/* Save the index */
error_idx = i;
@@ -3754,24 +3480,15 @@ errr init_f_info_txt(FILE *fp, char *buf)
/* 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);
+ /* Copy name */
+ assert(!f_ptr->name);
+ f_ptr->name = my_strdup(s);
- /* Default "mimic" */
+ /* Initialize */
f_ptr->mimic = i;
- f_ptr->text = default_desc;
- f_ptr->block = default_desc;
- f_ptr->tunnel = default_tunnel;
- f_ptr->block = default_block;
+ f_ptr->text = DEFAULT_FEAT_TEXT;
+ f_ptr->tunnel = DEFAULT_FEAT_TUNNEL;
+ f_ptr->block = DEFAULT_FEAT_BLOCK;
/* Next... */
continue;
@@ -3787,34 +3504,24 @@ errr init_f_info_txt(FILE *fp, char *buf)
/* 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;
+ assert(f_ptr->text == DEFAULT_FEAT_TEXT);
+ f_ptr->text = my_strdup(s);
break;
case '1':
- /* Advance and Save the text index */
- f_ptr->tunnel = ++f_head->text_size;
+ assert(f_ptr->tunnel == DEFAULT_FEAT_TUNNEL);
+ f_ptr->tunnel = my_strdup(s);
break;
case '2':
- /* Advance and Save the text index */
- f_ptr->block = ++f_head->text_size;
+ assert(f_ptr->block == DEFAULT_FEAT_BLOCK);
+ f_ptr->block = my_strdup(s);
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;
}
@@ -3971,16 +3678,6 @@ errr init_f_info_txt(FILE *fp, char *buf)
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);
}
@@ -4094,15 +3791,12 @@ static errr grab_one_kind_flag(object_kind *k_ptr, cptr what, bool_ obvious)
/*
* Initialize the "k_info" array, by parsing an ascii "template" file
*/
-errr init_k_info_txt(FILE *fp, char *buf)
+errr init_k_info_txt(FILE *fp)
{
int i;
-
+ char buf[1024];
char *s, *t;
- /* Not ready yet */
- bool_ okay = FALSE;
-
/* Current entry */
object_kind *k_ptr = NULL;
@@ -4114,13 +3808,8 @@ errr init_k_info_txt(FILE *fp, char *buf)
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))
+ while (0 == my_fgets(fp, buf, 1024))
{
/* Advance the line number */
error_line++;
@@ -4132,31 +3821,6 @@ errr init_k_info_txt(FILE *fp, char *buf)
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')
{
@@ -4179,7 +3843,7 @@ errr init_k_info_txt(FILE *fp, char *buf)
if (i <= error_idx) return (4);
/* Verify information */
- if (i >= k_head->info_num) return (2);
+ if (i >= max_k_idx) return (2);
/* Save the index */
error_idx = i;
@@ -4187,17 +3851,12 @@ errr init_k_info_txt(FILE *fp, char *buf)
/* 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);
+ assert(!k_ptr->name);
+ k_ptr->name = my_strdup(s);
- /* Advance the index */
- k_head->name_size += strlen(s);
+ /* Ensure empty description */
+ k_ptr->text = my_strdup("");
/* Needed hack */
k_ptr->esp = 0;
@@ -4216,27 +3875,8 @@ errr init_k_info_txt(FILE *fp, char *buf)
/* 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);
+ /* Append description */
+ strappend(&k_ptr->text, s);
/* Next... */
continue;
@@ -4309,16 +3949,15 @@ errr init_k_info_txt(FILE *fp, char *buf)
/* Process 'W' for "More Info" (one line only) */
if (buf[0] == 'W')
{
- int level, extra, wgt;
+ int level, unused, wgt;
long cost;
/* Scan for the values */
if (4 != sscanf(buf + 2, "%d:%d:%d:%ld",
- &level, &extra, &wgt, &cost)) return (1);
+ &level, &unused, &wgt, &cost)) return (1);
/* Save the values */
k_ptr->level = level;
- k_ptr->extra = extra;
k_ptr->weight = wgt;
k_ptr->cost = cost;
@@ -4352,12 +3991,12 @@ errr init_k_info_txt(FILE *fp, char *buf)
s = buf + 2;
/* Find it in the list */
- for (i = 0; i < power_max; i++)
+ for (i = 0; i < POWER_MAX; i++)
{
- if (!stricmp(s, powers_type[i].name)) break;
+ if (iequals(s, powers_type[i].name)) break;
}
- if (i == power_max) return (6);
+ if (i == POWER_MAX) return (6);
k_ptr->power = i;
@@ -4368,17 +4007,10 @@ errr init_k_info_txt(FILE *fp, char *buf)
/* 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 = get_activation(buf + 2);
+ if (k_ptr->activate == -1)
{
- k_ptr->activate = -find_spell(buf + 8);
- if (k_ptr->activate == -( -1))
- return 1;
+ return 1;
}
/* Next... */
@@ -4393,6 +4025,11 @@ errr init_k_info_txt(FILE *fp, char *buf)
/* 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;
@@ -4409,7 +4046,9 @@ errr init_k_info_txt(FILE *fp, char *buf)
if (t && (!s || t < s))
{
int chance = atoi(t + 1);
- if (chance > 0) k_ptr->chance[i] = chance;
+ if (chance > 0) {
+ k_ptr->chance[i] = chance;
+ }
}
}
@@ -4496,403 +4135,6 @@ errr init_k_info_txt(FILE *fp, char *buf)
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);
}
@@ -5008,15 +4250,12 @@ static errr grab_one_artifact_flag(artifact_type *a_ptr, cptr what, bool_ obviou
/*
* Initialize the "a_info" array, by parsing an ascii "template" file
*/
-errr init_a_info_txt(FILE *fp, char *buf)
+errr init_a_info_txt(FILE *fp)
{
int i;
-
+ char buf[1024];
char *s, *t;
- /* Not ready yet */
- bool_ okay = FALSE;
-
/* Current entry */
artifact_type *a_ptr = NULL;
@@ -5029,8 +4268,7 @@ errr init_a_info_txt(FILE *fp, char *buf)
/* Parse */
- fp_stack_init(fp);
- while (0 == my_fgets_dostack(buf, 1024))
+ while (0 == my_fgets(fp, buf, 1024))
{
/* Advance the line number */
error_line++;
@@ -5041,32 +4279,6 @@ errr init_a_info_txt(FILE *fp, char *buf)
/* 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')
{
@@ -5089,7 +4301,7 @@ errr init_a_info_txt(FILE *fp, char *buf)
if (i < error_idx) return (4);
/* Verify information */
- if (i >= a_head->info_num) return (2);
+ if (i >= max_a_idx) return (2);
/* Save the index */
error_idx = i;
@@ -5097,17 +4309,12 @@ errr init_a_info_txt(FILE *fp, char *buf)
/* 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);
+ /* Copy name */
+ assert(!a_ptr->name);
+ a_ptr->name = my_strdup(s);
- /* Advance the index */
- a_head->name_size += strlen(s);
+ /* Ensure empty description */
+ a_ptr->text = my_strdup("");
/* Ignore everything */
a_ptr->flags3 |= (TR3_IGNORE_ACID);
@@ -5139,27 +4346,13 @@ errr init_a_info_txt(FILE *fp, char *buf)
/* 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;
+ /* Add separator if necessary */
+ if (*a_ptr->text != '\0' && !ends_with(a_ptr->text, " ")) {
+ strappend(&a_ptr->text, " ");
}
- /* Append chars to the name */
- strcpy(a_text + a_head->text_size, s);
-
- /* Advance the index */
- a_head->text_size += strlen(s);
+ /* Append to description */
+ strappend(&a_ptr->text, s);
/* Next... */
continue;
@@ -5238,12 +4431,12 @@ errr init_a_info_txt(FILE *fp, char *buf)
s = buf + 2;
/* Find it in the list */
- for (i = 0; i < power_max; i++)
+ for (i = 0; i < POWER_MAX; i++)
{
- if (!stricmp(s, powers_type[i].name)) break;
+ if (iequals(s, powers_type[i].name)) break;
}
- if (i == power_max) return (6);
+ if (i == POWER_MAX) return (6);
a_ptr->power = i;
@@ -5308,17 +4501,10 @@ errr init_a_info_txt(FILE *fp, char *buf)
/* Read activation type. */
if (buf[0] == 'a')
{
- if (prefix(buf + 2, "HARDCORE="))
+ a_ptr->activate = get_activation(buf + 2);
+ if (a_ptr->activate == -1)
{
- 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;
+ return 1;
}
/* Next... */
@@ -5330,16 +4516,6 @@ errr init_a_info_txt(FILE *fp, char *buf)
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);
}
@@ -5347,16 +4523,14 @@ errr init_a_info_txt(FILE *fp, char *buf)
/*
* Initialize the "set_info" array, by parsing an ascii "template" file
*/
-errr init_set_info_txt(FILE *fp, char *buf)
+errr init_set_info_txt(FILE *fp)
{
int i;
int cur_art = 0, cur_num = 0;
+ char buf[1024];
char *s, *t;
- /* Not ready yet */
- bool_ okay = FALSE;
-
/* Current entry */
set_type *set_ptr = NULL;
@@ -5369,8 +4543,7 @@ errr init_set_info_txt(FILE *fp, char *buf)
/* Parse */
- fp_stack_init(fp);
- while (0 == my_fgets_dostack(buf, 1024))
+ while (0 == my_fgets(fp, buf, 1024))
{
/* Advance the line number */
error_line++;
@@ -5381,32 +4554,6 @@ errr init_set_info_txt(FILE *fp, char *buf)
/* 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')
{
@@ -5431,7 +4578,7 @@ errr init_set_info_txt(FILE *fp, char *buf)
if (i < error_idx) return (4);
/* Verify information */
- if (i >= set_head->info_num) return (2);
+ if (i >= max_set_idx) return (2);
/* Save the index */
error_idx = i;
@@ -5439,19 +4586,11 @@ errr init_set_info_txt(FILE *fp, char *buf)
/* 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);
+ /* Copy name */
+ assert(!set_ptr->name);
+ set_ptr->name = my_strdup(s);
- /* 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 */
+ /* Initialize */
set_ptr->num = 0;
set_ptr->num_use = 0;
for (z = 0; z < 6; z++)
@@ -5483,17 +4622,8 @@ errr init_set_info_txt(FILE *fp, char *buf)
/* 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);
+ /* Append chars to the description */
+ strappend(&set_ptr->desc, s);
/* Next... */
continue;
@@ -5567,16 +4697,6 @@ errr init_set_info_txt(FILE *fp, char *buf)
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);
}
@@ -5585,15 +4705,12 @@ errr init_set_info_txt(FILE *fp, char *buf)
/*
* Initialize the "s_info" array, by parsing an ascii "template" file
*/
-errr init_s_info_txt(FILE *fp, char *buf)
+errr init_s_info_txt(FILE *fp)
{
int i, z, order = 1;
-
+ char buf[1024];
char *s;
- /* Not ready yet */
- bool_ okay = FALSE;
-
/* Current entry */
skill_type *s_ptr = NULL;
@@ -5606,8 +4723,7 @@ errr init_s_info_txt(FILE *fp, char *buf)
/* Parse */
- fp_stack_init(fp);
- while (0 == my_fgets_dostack(buf, 1024))
+ while (0 == my_fgets(fp, buf, 1024))
{
/* Advance the line number */
error_line++;
@@ -5618,32 +4734,6 @@ errr init_s_info_txt(FILE *fp, char *buf)
/* 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')
{
@@ -5780,7 +4870,7 @@ errr init_s_info_txt(FILE *fp, char *buf)
i = atoi(buf + 2);
/* Verify information */
- if (i >= s_head->info_num) return (2);
+ if (i >= max_s_idx) return (2);
/* Save the index */
error_idx = i;
@@ -5788,17 +4878,9 @@ errr init_s_info_txt(FILE *fp, char *buf)
/* 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);
+ /* Copy name */
+ assert(!s_ptr->name);
+ s_ptr->name = my_strdup(s);
/* Init */
s_ptr->action_mkey = 0;
@@ -5822,34 +4904,21 @@ errr init_s_info_txt(FILE *fp, char *buf)
/* 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 */
+ /* Description */
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);
+ s_ptr->desc = my_strdup(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;
+ strappend(&s_ptr->desc, format("\n%s", s));
}
/* Next... */
continue;
}
- /* Process 'A' for "Activation Description" */
+ /* Process 'A' for "Activation Description" (one line only) */
if (buf[0] == 'A')
{
char *txt;
@@ -5861,19 +4930,13 @@ errr init_s_info_txt(FILE *fp, char *buf)
*txt = '\0';
txt++;
- /* Hack -- Verify space */
- if (s_head->text_size + strlen(txt) + 8 > fake_text_size) return (7);
+ /* Copy action description */
+ assert(!s_ptr->action_desc);
+ s_ptr->action_desc = my_strdup(txt);
- /* 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);
+ /* Copy mkey index */
s_ptr->action_mkey = atoi(s);
- /* Advance the index */
- s_head->text_size += strlen(txt);
-
/* Next... */
continue;
}
@@ -5947,16 +5010,6 @@ errr init_s_info_txt(FILE *fp, char *buf)
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);
}
@@ -5964,15 +5017,12 @@ errr init_s_info_txt(FILE *fp, char *buf)
/*
* Initialize the "ab_info" array, by parsing an ascii "template" file
*/
-errr init_ab_info_txt(FILE *fp, char *buf)
+errr init_ab_info_txt(FILE *fp)
{
int i, z;
-
+ char buf[1024];
char *s;
- /* Not ready yet */
- bool_ okay = FALSE;
-
/* Current entry */
ability_type *ab_ptr = NULL;
@@ -5985,8 +5035,7 @@ errr init_ab_info_txt(FILE *fp, char *buf)
/* Parse */
- fp_stack_init(fp);
- while (0 == my_fgets_dostack(buf, 1024))
+ while (0 == my_fgets(fp, buf, 1024))
{
/* Advance the line number */
error_line++;
@@ -5997,32 +5046,6 @@ errr init_ab_info_txt(FILE *fp, char *buf)
/* 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')
{
@@ -6042,7 +5065,7 @@ errr init_ab_info_txt(FILE *fp, char *buf)
i = atoi(buf + 2);
/* Verify information */
- if (i >= ab_head->info_num) return (2);
+ if (i >= max_ab_idx) return (2);
/* Save the index */
error_idx = i;
@@ -6050,17 +5073,9 @@ errr init_ab_info_txt(FILE *fp, char *buf)
/* 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);
+ /* Copy name */
+ assert(!ab_ptr->name);
+ ab_ptr->name = my_strdup(s);
/* Init */
ab_ptr->action_mkey = 0;
@@ -6089,27 +5104,14 @@ errr init_ab_info_txt(FILE *fp, char *buf)
/* 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 */
+ /* Append description */
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);
+ ab_ptr->desc = my_strdup(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;
+ strappend(&ab_ptr->desc, format("\n%s", s));
}
/* Next... */
@@ -6128,19 +5130,13 @@ errr init_ab_info_txt(FILE *fp, char *buf)
*txt = '\0';
txt++;
- /* Hack -- Verify space */
- if (ab_head->text_size + strlen(txt) + 8 > fake_text_size) return (7);
+ /* Copy name */
+ assert(!ab_ptr->action_desc);
+ ab_ptr->action_desc = my_strdup(txt);
- /* 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);
+ /* Set mkey */
ab_ptr->action_mkey = atoi(s);
- /* Advance the index */
- ab_head->text_size += strlen(txt);
-
/* Next... */
continue;
}
@@ -6288,16 +5284,6 @@ errr init_ab_info_txt(FILE *fp, char *buf)
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);
}
@@ -6309,6 +5295,7 @@ errr init_ab_info_txt(FILE *fp, char *buf)
static bool_ grab_one_ego_item_flag(ego_item_type *e_ptr, cptr what, int n, bool_ obvious)
{
int i;
+ assert(n < FLAG_RARITY_MAX);
/* Check flags1 */
for (i = 0; i < 32; i++)
@@ -6526,15 +5513,12 @@ static bool_ grab_one_ego_item_flag_restrict(ego_item_type *e_ptr, cptr what, bo
/*
* Initialize the "e_info" array, by parsing an ascii "template" file
*/
-errr init_e_info_txt(FILE *fp, char *buf)
+errr init_e_info_txt(FILE *fp)
{
int i, cur_r = -1, cur_t = 0, j;
-
+ char buf[1024];
char *s, *t;
- /* Not ready yet */
- bool_ okay = FALSE;
-
/* Current entry */
ego_item_type *e_ptr = NULL;
@@ -6547,8 +5531,7 @@ errr init_e_info_txt(FILE *fp, char *buf)
/* Parse */
- fp_stack_init(fp);
- while (0 == my_fgets_dostack(buf, 1024))
+ while (0 == my_fgets(fp, buf, 1024))
{
/* Advance the line number */
error_line++;
@@ -6559,32 +5542,6 @@ errr init_e_info_txt(FILE *fp, char *buf)
/* 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')
{
@@ -6607,7 +5564,7 @@ errr init_e_info_txt(FILE *fp, char *buf)
if (i < error_idx) return (4);
/* Verify information */
- if (i >= e_head->info_num) return (2);
+ if (i >= max_e_idx) return (2);
/* Save the index */
error_idx = i;
@@ -6615,17 +5572,9 @@ errr init_e_info_txt(FILE *fp, char *buf)
/* 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);
+ /* Copy name */
+ assert(!e_ptr->name);
+ e_ptr->name = my_strdup(s);
/* Needed hack */
e_ptr->power = -1;
@@ -6636,7 +5585,7 @@ errr init_e_info_txt(FILE *fp, char *buf)
{
e_ptr->tval[j] = 255;
}
- for (j = 0; j < 5; j++)
+ for (j = 0; j < FLAG_RARITY_MAX; j++)
{
e_ptr->rar[j] = 0;
e_ptr->flags1[j] = 0;
@@ -6645,6 +5594,13 @@ errr init_e_info_txt(FILE *fp, char *buf)
e_ptr->flags4[j] = 0;
e_ptr->flags5[j] = 0;
e_ptr->esp[j] = 0;
+ e_ptr->oflags1[j] = 0;
+ e_ptr->oflags2[j] = 0;
+ e_ptr->oflags3[j] = 0;
+ e_ptr->oflags4[j] = 0;
+ e_ptr->oflags5[j] = 0;
+ e_ptr->oesp[j] = 0;
+ e_ptr->fego[j] = 0;
}
/* Next... */
@@ -6682,14 +5638,16 @@ errr init_e_info_txt(FILE *fp, char *buf)
{
int rar;
- if (cur_r == 5) return 1;
+ cur_r++;
+
+ if (cur_r >= FLAG_RARITY_MAX) {
+ 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;
@@ -6763,12 +5721,12 @@ errr init_e_info_txt(FILE *fp, char *buf)
s = buf + 2;
/* Find it in the list */
- for (i = 0; i < power_max; i++)
+ for (i = 0; i < POWER_MAX; i++)
{
- if (!stricmp(s, powers_type[i].name)) break;
+ if (iequals(s, powers_type[i].name)) break;
}
- if (i == power_max) return (6);
+ if (i == POWER_MAX) return (6);
e_ptr->power = i;
@@ -6778,16 +5736,9 @@ errr init_e_info_txt(FILE *fp, char *buf)
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 = get_activation(buf + 2);
+ if (e_ptr->activate == -1)
{
- e_ptr->activate = -find_spell(buf + 8);
- if (e_ptr->activate == -( -1))
return 1;
}
@@ -6911,16 +5862,6 @@ errr init_e_info_txt(FILE *fp, char *buf)
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);
}
@@ -7048,15 +5989,12 @@ static bool_ grab_one_randart_item_flag(randart_part_type *ra_ptr, cptr what, ch
/*
* Initialize the "ra_info" array, by parsing an ascii "template" file
*/
-errr init_ra_info_txt(FILE *fp, char *buf)
+errr init_ra_info_txt(FILE *fp)
{
int i, cur_t = 0, j, cur_g = 0;
-
+ char buf[1024];
char *s, *t;
- /* Not ready yet */
- bool_ okay = FALSE;
-
/* Current entry */
randart_part_type *ra_ptr = NULL;
@@ -7069,8 +6007,7 @@ errr init_ra_info_txt(FILE *fp, char *buf)
/* Parse */
- fp_stack_init(fp);
- while (0 == my_fgets_dostack(buf, 1024))
+ while (0 == my_fgets(fp, buf, 1024))
{
/* Advance the line number */
error_line++;
@@ -7081,32 +6018,6 @@ errr init_ra_info_txt(FILE *fp, char *buf)
/* 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')
{
@@ -7137,7 +6048,7 @@ errr init_ra_info_txt(FILE *fp, char *buf)
if (i < error_idx) return (4);
/* Verify information */
- if (i >= ra_head->info_num) return (2);
+ if (i >= max_ra_idx) return (2);
/* Save the index */
error_idx = i;
@@ -7252,12 +6163,12 @@ errr init_ra_info_txt(FILE *fp, char *buf)
s = buf + 2;
/* Find it in the list */
- for (i = 0; i < power_max; i++)
+ for (i = 0; i < POWER_MAX; i++)
{
- if (!stricmp(s, powers_type[i].name)) break;
+ if (iequals(s, powers_type[i].name)) break;
}
- if (i == power_max) return (6);
+ if (i == POWER_MAX) return (6);
ra_ptr->power = i;
@@ -7323,11 +6234,6 @@ errr init_ra_info_txt(FILE *fp, char *buf)
return (6);
}
-
- /* No version yet */
- if (!okay) return (2);
-
-
/* Success */
return (0);
}
@@ -7455,15 +6361,12 @@ static errr grab_one_spell_flag(monster_race *r_ptr, cptr what)
/*
* Initialize the "r_info" array, by parsing an ascii "template" file
*/
-errr init_r_info_txt(FILE *fp, char *buf)
+errr init_r_info_txt(FILE *fp)
{
int i;
-
+ char buf[1024];
char *s, *t;
- /* Not ready yet */
- bool_ okay = FALSE;
-
/* Current entry */
monster_race *r_ptr = NULL;
@@ -7475,13 +6378,8 @@ errr init_r_info_txt(FILE *fp, char *buf)
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))
+ while (0 == my_fgets(fp, buf, 1024))
{
/* Advance the line number */
error_line++;
@@ -7492,32 +6390,6 @@ errr init_r_info_txt(FILE *fp, char *buf)
/* 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')
{
@@ -7540,7 +6412,7 @@ errr init_r_info_txt(FILE *fp, char *buf)
if (i < error_idx) return (4);
/* Verify information */
- if (i >= r_head->info_num) return (2);
+ if (i >= max_r_idx) return (2);
/* Save the index */
error_idx = i;
@@ -7548,17 +6420,12 @@ errr init_r_info_txt(FILE *fp, char *buf)
/* 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);
+ /* Allocate name string. */
+ assert(!r_ptr->name); // Sanity check that we aren't overwriting anything
+ r_ptr->name = my_strdup(s);
- /* Advance the index */
- r_head->name_size += strlen(s);
+ /* Ensure empty description */
+ r_ptr->text = my_strdup("");
/* HACK -- Those ones HAVE to have a set default value */
r_ptr->drops.treasure = OBJ_GENE_TREASURE;
@@ -7581,17 +6448,8 @@ errr init_r_info_txt(FILE *fp, char *buf)
/* 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);
+ /* Append to description */
+ strappend(&r_ptr->text, s);
/* Next... */
continue;
@@ -7843,11 +6701,7 @@ errr init_r_info_txt(FILE *fp, char *buf)
return (6);
}
-
- /* Complete the "name" and "text" sizes */
- ++r_head->name_size;
- ++r_head->text_size;
-
+ /* Postprocessing */
for (i = 1; i < max_r_idx; i++)
{
/* Invert flag WILD_ONLY <-> RF8_DUNGEON */
@@ -7858,9 +6712,6 @@ errr init_r_info_txt(FILE *fp, char *buf)
r_info[i].flags8 = 0x0463;
}
- /* No version yet */
- if (!okay) return (2);
-
/* Success */
return (0);
}
@@ -8095,18 +6946,15 @@ static errr grab_one_ego_flag(monster_ego *re_ptr, cptr what, bool_ must)
/*
* Initialize the "re_info" array, by parsing an ascii "template" file
*/
-errr init_re_info_txt(FILE *fp, char *buf)
+errr init_re_info_txt(FILE *fp)
{
int i, j;
-
+ char buf[1024];
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;
@@ -8117,14 +6965,8 @@ errr init_re_info_txt(FILE *fp, char *buf)
/* 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))
+ while (0 == my_fgets(fp, buf, 1024))
{
/* Advance the line number */
error_line++;
@@ -8135,32 +6977,6 @@ errr init_re_info_txt(FILE *fp, char *buf)
/* 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')
{
@@ -8183,7 +6999,7 @@ errr init_re_info_txt(FILE *fp, char *buf)
if (i < error_idx) return (4);
/* Verify information */
- if (i >= re_head->info_num) return (2);
+ if (i >= max_re_idx) return (2);
/* Save the index */
error_idx = i;
@@ -8191,17 +7007,9 @@ errr init_re_info_txt(FILE *fp, char *buf)
/* 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);
+ /* Copy name */
+ assert(!re_ptr->name);
+ re_ptr->name = my_strdup(s);
/* Some inits */
blow_num = 0;
@@ -8600,13 +7408,6 @@ errr init_re_info_txt(FILE *fp, char *buf)
return (6);
}
-
- /* Complete the "name" and "text" sizes */
- ++re_head->name_size;
-
- /* No version yet */
- if (!okay) return (2);
-
/* Success */
return (0);
}
@@ -8639,33 +7440,23 @@ static errr grab_one_trap_type_flag(trap_type *t_ptr, cptr what)
/*
* Initialize the "tr_info" array, by parsing an ascii "template" file
*/
-errr init_t_info_txt(FILE *fp, char *buf)
+errr init_t_info_txt(FILE *fp)
{
int i;
-
+ char buf[1024];
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))
+ while (0 == my_fgets(fp, buf, 1024))
{
/* Advance the line number */
error_line++;
@@ -8676,32 +7467,6 @@ errr init_t_info_txt(FILE *fp, char *buf)
/* 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')
{
@@ -8724,7 +7489,7 @@ errr init_t_info_txt(FILE *fp, char *buf)
if (i <= error_idx) return (4);
/* Verify information */
- if (i >= t_head->info_num) return (2);
+ if (i >= max_t_idx) return (2);
/* Save the index */
error_idx = i;
@@ -8732,17 +7497,11 @@ errr init_t_info_txt(FILE *fp, char *buf)
/* 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);
+ /* Copy name */
+ t_ptr->name = my_strdup(s);
- /* Advance the index */
- t_head->name_size += strlen(s);
+ /* Initialize */
+ t_ptr->text = my_strdup("");
/* Next... */
continue;
@@ -8786,17 +7545,8 @@ errr init_t_info_txt(FILE *fp, char *buf)
/* 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);
+ strappend(&t_ptr->text, s);
/* Next... */
continue;
@@ -8838,16 +7588,6 @@ errr init_t_info_txt(FILE *fp, char *buf)
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);
}
@@ -9008,9 +7748,10 @@ static errr grab_one_spell_monster_flag(dungeon_info_type *d_ptr, cptr what, byt
/*
* Initialize the "d_info" array, by parsing an ascii "template" file
*/
-errr init_d_info_txt(FILE *fp, char *buf)
+errr init_d_info_txt(FILE *fp)
{
int i, j;
+ char buf[1024];
s16b rule_num = 0;
@@ -9018,9 +7759,6 @@ errr init_d_info_txt(FILE *fp, char *buf)
char *s, *t;
- /* Not ready yet */
- bool_ okay = FALSE;
-
/* Current entry */
dungeon_info_type *d_ptr = NULL;
@@ -9031,14 +7769,8 @@ errr init_d_info_txt(FILE *fp, char *buf)
/* 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))
+ while (0 == my_fgets(fp, buf, 1024))
{
/* Advance the line number */
error_line++;
@@ -9049,32 +7781,6 @@ errr init_d_info_txt(FILE *fp, char *buf)
/* 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')
{
@@ -9097,7 +7803,7 @@ errr init_d_info_txt(FILE *fp, char *buf)
if (i < error_idx) return (4);
/* Verify information */
- if (i >= d_head->info_num) return (2);
+ if (i >= max_d_idx) return (2);
/* Save the index */
error_idx = i;
@@ -9105,17 +7811,12 @@ errr init_d_info_txt(FILE *fp, char *buf)
/* 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);
+ /* Copy name */
+ assert(!d_ptr->name);
+ d_ptr->name = my_strdup(s);
- /* Advance the index */
- d_head->name_size += strlen(s);
+ /* Initialize description */
+ d_ptr->text = my_strdup("");
/* HACK -- Those ones HAVE to have a set default value */
d_ptr->size_x = -1;
@@ -9164,17 +7865,8 @@ errr init_d_info_txt(FILE *fp, char *buf)
/* 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);
+ /* Append to description */
+ strappend(&d_ptr->text, s);
/* Next... */
continue;
@@ -9587,14 +8279,6 @@ errr init_d_info_txt(FILE *fp, char *buf)
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);
}
@@ -9657,15 +8341,12 @@ static errr grab_one_store_flag(store_info_type *st_ptr, cptr what)
/*
* Initialize the "st_info" array, by parsing an ascii "template" file
*/
-errr init_st_info_txt(FILE *fp, char *buf)
+errr init_st_info_txt(FILE *fp)
{
int i = 0, item_idx = 0;
-
+ char buf[1024];
char *s, *t;
- /* Not ready yet */
- bool_ okay = FALSE;
-
/* Current entry */
store_info_type *st_ptr = NULL;
@@ -9676,14 +8357,8 @@ errr init_st_info_txt(FILE *fp, char *buf)
/* 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))
+ while (0 == my_fgets(fp, buf, 1024))
{
/* Advance the line number */
error_line++;
@@ -9694,32 +8369,6 @@ errr init_st_info_txt(FILE *fp, char *buf)
/* 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')
{
@@ -9742,7 +8391,7 @@ errr init_st_info_txt(FILE *fp, char *buf)
if (i < error_idx) return (4);
/* Verify information */
- if (i >= st_head->info_num) return (2);
+ if (i >= max_st_idx) return (2);
/* Save the index */
error_idx = i;
@@ -9750,17 +8399,9 @@ errr init_st_info_txt(FILE *fp, char *buf)
/* 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);
+ /* Copy name */
+ assert(!st_ptr->name);
+ st_ptr->name = my_strdup(s);
/* We are ready for a new set of objects */
item_idx = 0;
@@ -9794,6 +8435,7 @@ errr init_st_info_txt(FILE *fp, char *buf)
st_ptr->table[item_idx++][0] = test_item_name(s);
st_ptr->table_num = item_idx;
+ assert(st_ptr->table_num <= STORE_CHOICES);
/* Next... */
continue;
@@ -9931,14 +8573,6 @@ errr init_st_info_txt(FILE *fp, char *buf)
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);
}
@@ -9946,15 +8580,12 @@ errr init_st_info_txt(FILE *fp, char *buf)
/*
* Initialize the "ba_info" array, by parsing an ascii "template" file
*/
-errr init_ba_info_txt(FILE *fp, char *buf)
+errr init_ba_info_txt(FILE *fp)
{
int i = 0;
-
+ char buf[1024];
char *s;
- /* Not ready yet */
- bool_ okay = FALSE;
-
/* Current entry */
store_action_type *ba_ptr = NULL;
@@ -9965,14 +8596,8 @@ errr init_ba_info_txt(FILE *fp, char *buf)
/* 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))
+ while (0 == my_fgets(fp, buf, 1024))
{
/* Advance the line number */
error_line++;
@@ -9983,32 +8608,6 @@ errr init_ba_info_txt(FILE *fp, char *buf)
/* 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')
{
@@ -10031,7 +8630,7 @@ errr init_ba_info_txt(FILE *fp, char *buf)
if (i < error_idx) return (4);
/* Verify information */
- if (i >= ba_head->info_num) return (2);
+ if (i >= max_ba_idx) return (2);
/* Save the index */
error_idx = i;
@@ -10039,17 +8638,9 @@ errr init_ba_info_txt(FILE *fp, char *buf)
/* 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);
+ /* Copy name */
+ assert(!ba_ptr->name);
+ ba_ptr->name = my_strdup(s);
/* Next... */
continue;
@@ -10101,14 +8692,6 @@ errr init_ba_info_txt(FILE *fp, char *buf)
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);
}
@@ -10116,33 +8699,23 @@ errr init_ba_info_txt(FILE *fp, char *buf)
/*
* Initialize the "ow_info" array, by parsing an ascii "template" file
*/
-errr init_ow_info_txt(FILE *fp, char *buf)
+errr init_ow_info_txt(FILE *fp)
{
int i;
-
+ char buf[1024];
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))
+ while (0 == my_fgets(fp, buf, 1024))
{
/* Advance the line number */
error_line++;
@@ -10153,32 +8726,6 @@ errr init_ow_info_txt(FILE *fp, char *buf)
/* 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')
{
@@ -10201,7 +8748,7 @@ errr init_ow_info_txt(FILE *fp, char *buf)
if (i < error_idx) return (4);
/* Verify information */
- if (i >= ow_head->info_num) return (2);
+ if (i >= max_ow_idx) return (2);
/* Save the index */
error_idx = i;
@@ -10209,17 +8756,9 @@ errr init_ow_info_txt(FILE *fp, char *buf)
/* 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);
+ /* Copy name */
+ assert(!ow_ptr->name);
+ ow_ptr->name = my_strdup(s);
/* Next... */
continue;
@@ -10250,18 +8789,15 @@ errr init_ow_info_txt(FILE *fp, char *buf)
/* Process 'I' for "Info" (multiple lines line only) */
if (buf[0] == 'I')
{
- int cost, max_inf, min_inf, haggle, insult;
+ int cost, inf;
/* Scan for the values */
- if (5 != sscanf(buf + 2, "%d:%d:%d:%d:%d",
- &cost, &max_inf, &min_inf, &haggle, &insult)) return (1);
+ if (2 != sscanf(buf + 2, "%d:%d",
+ &cost, &inf)) return (1);
/* Save the values */
ow_ptr->max_cost = cost;
- ow_ptr->max_inflate = max_inf;
- ow_ptr->min_inflate = min_inf;
- ow_ptr->haggle_per = haggle;
- ow_ptr->insult_max = insult;
+ ow_ptr->inflation = inf;
/* Next... */
continue;
@@ -10324,72 +8860,30 @@ errr init_ow_info_txt(FILE *fp, char *buf)
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)
+errr init_wf_info_txt(FILE *fp)
{
int i;
-
- char *s, *t;
-
- /* Not ready yet */
- bool_ okay = FALSE;
+ char buf[1024];
+ char *s;
/* 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))
+ while (0 == my_fgets(fp, buf, 1024))
{
/* Advance the line number */
error_line++;
@@ -10400,32 +8894,6 @@ errr init_wf_info_txt(FILE *fp, char *buf)
/* 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')
{
@@ -10448,7 +8916,7 @@ errr init_wf_info_txt(FILE *fp, char *buf)
if (i < error_idx) return (4);
/* Verify information */
- if (i >= wf_head->info_num) return (2);
+ if (i >= max_wf_idx) return (2);
/* Save the index */
error_idx = i;
@@ -10456,17 +8924,9 @@ errr init_wf_info_txt(FILE *fp, char *buf)
/* 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);
+ /* Copy the name */
+ assert(!wf_ptr->name);
+ wf_ptr->name = my_strdup(s);
/* Next... */
continue;
@@ -10475,23 +8935,15 @@ errr init_wf_info_txt(FILE *fp, char *buf)
/* There better be a current wf_ptr */
if (!wf_ptr) return (3);
- /* Process 'D' for "Description */
+ /* Process 'D' for "Description (one line only) */
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);
+ /* Copy description */
+ assert(!wf_ptr->text);
+ wf_ptr->text = my_strdup(s);
/* Next... */
continue;
@@ -10546,45 +8998,10 @@ errr init_wf_info_txt(FILE *fp, char *buf)
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);
}
@@ -10812,7 +9229,7 @@ static errr process_dungeon_file_aux(char *buf, int *yval, int *xval, int xvalst
i = strlen(zz[8]) - 1;
if (zz[8][i] == '"') zz[8][i] = '\0';
letter[index].special = 0;
- for (i = 0; i < max_q_idx; i++)
+ for (i = 0; i < MAX_Q_IDX; i++)
{
if (!strcmp(&zz[8][1], quest[i].name))
{
@@ -11277,12 +9694,6 @@ static errr process_dungeon_file_aux(char *buf, int *yval, int *xval, int xvalst
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')
{
@@ -11402,6 +9813,7 @@ static errr process_dungeon_file_aux(char *buf, int *yval, int *xval, int xvalst
*/
static cptr process_dungeon_file_expr(char **sp, char *fp)
{
+ static char pref_tmp_value[8];
cptr v;
char *b;
@@ -11574,28 +9986,22 @@ static cptr process_dungeon_file_expr(char **sp, char *fp)
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;
+ v = rp_ptr->title;
}
/* Race Mod */
else if (streq(b + 1, "RACEMOD"))
{
- v = rmp_ptr->title + rmp_name;
+ v = rmp_ptr->title;
}
/* Class */
else if (streq(b + 1, "CLASS"))
{
- v = cp_ptr->title + c_name;
+ v = cp_ptr->title;
}
/* Player */
@@ -11659,7 +10065,7 @@ static cptr process_dungeon_file_expr(char **sp, char *fp)
for (i = 0; (c[i] != '"') && (c[i] != '\0'); i++);
if (c[i] == '"') c[i] = '\0';
strcpy(pref_tmp_value, "-1");
- for (i = 0; i < max_q_idx; i++)
+ for (i = 0; i < MAX_Q_IDX; i++)
{
if (streq(c, quest[i].name))
{
diff --git a/src/init1.hpp b/src/init1.hpp
new file mode 100644
index 00000000..766e467d
--- /dev/null
+++ b/src/init1.hpp
@@ -0,0 +1,26 @@
+#pragma once
+
+#include "h-basic.h"
+
+extern int color_char_to_attr(char c);
+extern byte conv_color[16];
+extern errr init_player_info_txt(FILE *fp);
+extern errr init_ab_info_txt(FILE *fp);
+extern errr init_s_info_txt(FILE *fp);
+extern errr init_set_info_txt(FILE *fp);
+extern errr init_v_info_txt(FILE *fp);
+extern errr init_f_info_txt(FILE *fp);
+extern errr init_k_info_txt(FILE *fp);
+extern errr init_a_info_txt(FILE *fp);
+extern errr init_ra_info_txt(FILE *fp);
+extern errr init_e_info_txt(FILE *fp);
+extern errr init_r_info_txt(FILE *fp);
+extern errr init_re_info_txt(FILE *fp);
+extern errr init_d_info_txt(FILE *fp);
+extern errr init_t_info_txt(FILE *fp);
+extern errr init_ba_info_txt(FILE *fp);
+extern errr init_st_info_txt(FILE *fp);
+extern errr init_ow_info_txt(FILE *fp);
+extern errr init_wf_info_txt(FILE *fp);
+extern errr grab_one_dungeon_flag(u32b *flags1, u32b *flags2, cptr what);
+extern 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..338ebf10
--- /dev/null
+++ b/src/init2.cc
@@ -0,0 +1,1494 @@
+#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 "generate.hpp"
+#include "gen_evol.hpp"
+#include "gen_maze.hpp"
+#include "hist_type.hpp"
+#include "hooks.hpp"
+#include "init1.hpp"
+#include "lua_bind.hpp"
+#include "messages.hpp"
+#include "meta_class_type.hpp"
+#include "modules.hpp"
+#include "monster_ego.hpp"
+#include "monster_race.hpp"
+#include "monster_type.hpp"
+#include "object_kind.hpp"
+#include "owner_type.hpp"
+#include "player_class.hpp"
+#include "player_race.hpp"
+#include "player_race_mod.hpp"
+#include "quark.hpp"
+#include "randart.hpp"
+#include "randart_part_type.hpp"
+#include "script.h"
+#include "set_type.hpp"
+#include "skill_type.hpp"
+#include "spells3.hpp"
+#include "squeltch.hpp"
+#include "store_action_type.hpp"
+#include "store_info_type.hpp"
+#include "store_type.hpp"
+#include "tables.hpp"
+#include "trap_type.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);
+}
+
+
+
+/*
+ * 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.
+ */
+void init_file_paths_with_env()
+{
+ 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);
+}
+
+
+/*
+ * 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 void allocate()
+ {
+ f_info = make_array<feature_type>(max_f_idx);
+ }
+
+ static errr parse(FILE *fp)
+ {
+ return init_f_info_txt(fp);
+ }
+
+ };
+
+ struct k_info_traits {
+
+ static constexpr char const *name = "k_info.txt";
+
+ static void allocate()
+ {
+ k_info = make_array<object_kind>(max_k_idx);
+ }
+
+ static errr parse(FILE *fp)
+ {
+ return init_k_info_txt(fp);
+ };
+
+ };
+
+ struct set_info_traits {
+
+ static constexpr char const *name = "set_info.txt";
+
+ static void allocate()
+ {
+ set_info = make_array<set_type>(max_set_idx);
+ }
+
+ static errr parse(FILE *fp)
+ {
+ return init_set_info_txt(fp);
+ }
+
+ };
+
+ struct a_info_traits {
+
+ static constexpr char const *name = "a_info.txt";
+
+ static void allocate()
+ {
+ a_info = make_array<artifact_type>(max_a_idx);
+ }
+
+ static errr parse(FILE *fp)
+ {
+ return init_a_info_txt(fp);
+ }
+
+ };
+
+ struct s_info_traits {
+
+ static constexpr char const *name = "s_info.txt";
+
+ static void allocate()
+ {
+ s_info = make_array<skill_type>(max_s_idx);
+ }
+
+ static errr parse(FILE *fp)
+ {
+ return init_s_info_txt(fp);
+ }
+
+ };
+
+ struct ab_info_traits {
+
+ static constexpr char const *name = "ab_info.txt";
+
+ static void allocate()
+ {
+ ab_info = make_array<ability_type>(max_ab_idx);
+ }
+
+ static errr parse(FILE *fp)
+ {
+ return init_ab_info_txt(fp);
+ }
+
+ };
+
+ struct e_info_traits {
+
+ static constexpr char const *name = "e_info.txt";
+
+ static void allocate()
+ {
+ e_info = make_array<ego_item_type>(max_e_idx);
+ }
+
+ static errr parse(FILE *fp)
+ {
+ return init_e_info_txt(fp);
+ }
+
+ };
+
+ struct ra_info_traits {
+
+ static constexpr char const *name = "ra_info.txt";
+
+ static void allocate()
+ {
+ ra_info = make_array<randart_part_type>(max_ra_idx);
+ }
+
+ static errr parse(FILE *fp)
+ {
+ return init_ra_info_txt(fp);
+ }
+
+ };
+
+ struct r_info_traits {
+
+ static constexpr char const *name = "r_info.txt";
+
+ static void allocate()
+ {
+ r_info = make_array<monster_race>(max_r_idx);
+ }
+
+ static errr parse(FILE *fp)
+ {
+ return init_r_info_txt(fp);
+ }
+
+ };
+
+ struct re_info_traits {
+
+ static constexpr char const *name = "re_info.txt";
+
+ static void allocate()
+ {
+ re_info = make_array<monster_ego>(max_re_idx);
+ }
+
+ static errr parse(FILE *fp)
+ {
+ return init_re_info_txt(fp);
+ }
+
+ };
+
+ struct d_info_traits {
+
+ static constexpr char const *name = "d_info.txt";
+
+ static void allocate()
+ {
+ d_info = make_array<dungeon_info_type>(max_d_idx);
+ }
+
+ static errr parse(FILE *fp)
+ {
+ return init_d_info_txt(fp);
+ }
+
+ };
+
+ struct st_info_traits {
+
+ static constexpr char const *name = "st_info.txt";
+
+ static void allocate()
+ {
+ st_info = make_array<store_info_type>(max_st_idx);
+ }
+
+ static errr parse(FILE *fp)
+ {
+ return init_st_info_txt(fp);
+ }
+
+ };
+
+ struct ow_info_traits {
+
+ static constexpr char const *name = "ow_info.txt";
+
+ static void allocate()
+ {
+ ow_info = make_array<owner_type>(max_ow_idx);
+ }
+
+ static errr parse(FILE *fp)
+ {
+ return init_ow_info_txt(fp);
+ }
+
+ };
+
+ struct ba_info_traits {
+
+ static constexpr char const *name = "ba_info.txt";
+
+ static void allocate()
+ {
+ ba_info = make_array<store_action_type>(max_ba_idx);
+ }
+
+ static errr parse(FILE *fp)
+ {
+ return init_ba_info_txt(fp);
+ }
+
+ };
+
+ struct wf_info_traits {
+
+ static constexpr char const *name = "wf_info.txt";
+
+ static void allocate()
+ {
+ wf_info = make_array<wilderness_type_info>(max_wf_idx);
+ }
+
+ static errr parse(FILE *fp)
+ {
+ return init_wf_info_txt(fp);
+ }
+
+ };
+
+ struct tr_info_traits {
+
+ static constexpr char const *name = "tr_info.txt";
+
+ static void allocate()
+ {
+ t_info = make_array<trap_type>(max_t_idx);
+ }
+
+ static errr parse(FILE *fp)
+ {
+ return init_t_info_txt(fp);
+ }
+
+ };
+
+ struct v_info_traits {
+
+ static constexpr char const *name = "v_info.txt";
+
+ static void allocate()
+ {
+ v_info = make_array<vault_type>(max_v_idx);
+ }
+
+ static errr parse(FILE *fp)
+ {
+ return init_v_info_txt(fp);
+ }
+
+ };
+
+ struct p_info_traits {
+
+ static constexpr char const *name = "p_info.txt";
+
+ static void allocate()
+ {
+ race_info = make_array<player_race>(max_rp_idx);
+ race_mod_info = make_array<player_race_mod>(max_rmp_idx);
+ class_info = make_array<player_class>(max_c_idx);
+ bg = make_array<hist_type>(max_bg_idx);
+ meta_class_info = make_array<meta_class_type>(max_mc_idx);
+ for (std::size_t i = 0; i < max_mc_idx; i++)
+ {
+ meta_class_info[i].classes = make_array<s16b>(max_c_idx);
+ }
+ }
+
+ static errr parse(FILE *fp)
+ {
+ return init_player_info_txt(fp);
+ }
+
+ };
+
+}
+
+template<typename T> static errr init_x_info() {
+
+ /* Allocate the data array */
+ T::allocate();
+
+ /* 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);
+}
+
+
+/*
+ * Initialise misc. values
+ */
+static errr init_misc(void)
+{
+ int xstart = 0;
+ int ystart = 0;
+ int i;
+
+ /*** Prepare the various "bizarre" arrays ***/
+
+ /* Initialize quark subsystem */
+ quark_init();
+
+ /* Initialize messages subsystem */
+ message_init();
+
+ /* 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(void)
+{
+ int i = 0, j = 0;
+
+ /*** Prepare the Towns ***/
+
+ /* Allocate the towns */
+ town_info = make_array<town_type>(max_towns);
+
+ for (i = 1; i < max_towns; i++)
+ {
+ if (i <= max_real_towns) town_info[i].flags |= (TOWN_REAL);
+
+ /* Allocate the stores */
+ town_info[i].store = make_array<store_type>(max_st_idx);
+
+ /* 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 */
+ st_ptr->stock = make_array<object_type>(st_ptr->stock_size);
+ }
+ t_ptr->stocked = TRUE;
+}
+
+/*
+ * Initialise wilderness map array
+ */
+static errr init_wilderness(void)
+{
+ int i;
+
+ /* Allocate the wilderness (two-dimension array) */
+ wild_map = make_array<wilderness_map *>(max_wild_y);
+
+ /* Init the other pointers */
+ for (i = 0; i < max_wild_y; i++)
+ {
+ wild_map[i] = make_array<wilderness_map>(max_wild_x);
+ }
+
+ /* No encounter right now */
+ generate_encounter = FALSE;
+
+ return 0;
+}
+
+/*
+ * Initialise some other arrays
+ */
+static errr init_other(void)
+{
+ int i, n;
+
+ /*** Prepare the "dungeon" information ***/
+
+ /* Allocate and Wipe the special gene flags */
+ m_allow_special = make_array<bool_>(max_r_idx);
+ k_allow_special = make_array<bool_>(max_k_idx);
+ a_allow_special = make_array<bool_>(max_a_idx);
+
+
+ /*** Prepare "vinfo" array ***/
+
+ /* Used by "update_view()" */
+ (void)vinfo_init();
+
+
+ /* Allocate and Wipe the object list */
+ o_list = make_array<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>(max_d_idx);
+
+ /* Allocate and Wipe the special levels */
+ for (i = 0; i < MAX_DUNGEON_DEPTH; i++)
+ {
+ special_lvl[i] = make_array<bool_>(max_d_idx);
+ }
+
+ /* Allocate and wipe each line of the cave */
+ cave = new cave_type *[MAX_HGT];
+ for (i = 0; i < MAX_HGT; i++)
+ {
+ /* Allocate one row of the cave */
+ cave[i] = new cave_type[MAX_WID];
+ }
+
+ /*** 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);
+ 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 */
+ (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 */
+ memset(aux, 0, MAX_DEPTH_MONSTER * sizeof(s16b));
+
+ /* Clear the "num" array */
+ memset(num, 0, MAX_DEPTH_MONSTER * sizeof(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 < ALLOCATION_MAX; 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 */
+ alloc_kind_table = make_array<alloc_entry>(alloc_kind_size);
+
+ /* 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 < 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 */
+ 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 */
+ memset(aux, 0, MAX_DEPTH_MONSTER * sizeof(s16b));
+
+ /* Clear the "num" array */
+ memset(num, 0, MAX_DEPTH_MONSTER * sizeof(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 */
+ alloc_race_table = make_array<alloc_entry>(alloc_race_size);
+
+ /* 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 */
+static 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;
+
+ 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 */
+ (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_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 */
+ (void)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)]");
+ init_lua_init();
+
+ /* 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 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_x_info<tr_info_traits>()) 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);
+
+ /* 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..5697e4ef
--- /dev/null
+++ b/src/init2.h
@@ -0,0 +1,14 @@
+#pragma once
+
+// C linkage required for these functions since main-* code uses them.
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void init_file_paths(char *path);
+extern void init_file_paths_with_env();
+extern void init_angband(void);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/src/init2.hpp b/src/init2.hpp
new file mode 100644
index 00000000..707a2706
--- /dev/null
+++ b/src/init2.hpp
@@ -0,0 +1,9 @@
+#pragma once
+
+#include "h-basic.h"
+
+extern void init_corruptions();
+extern void create_stores_stock(int t);
+extern errr init_v_info(void);
+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..6dbb67f1
--- /dev/null
+++ b/src/inscription_info_type.hpp
@@ -0,0 +1,14 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * Inscriptions
+ */
+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 */
+};
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..be272115
--- /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 (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..05ac1843
--- /dev/null
+++ b/src/joke.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+extern 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/levels.c b/src/levels.cc
index 71148fc5..ac3aa3d3 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,21 @@
* included in all such copies.
*/
-#include "angband.h"
+#include "levels.hpp"
+
+#include "dungeon_info_type.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;
diff --git a/src/levels.hpp b/src/levels.hpp
new file mode 100644
index 00000000..187092b1
--- /dev/null
+++ b/src/levels.hpp
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "h-basic.h"
+
+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 int get_branch(void);
+extern int get_fbranch(void);
+extern int get_flevel(void);
+extern bool_ get_dungeon_save(char *buf);
diff --git a/src/loadsave.c b/src/loadsave.cc
index 8cdb9f72..1806d7c8 100644
--- a/src/loadsave.c
+++ b/src/loadsave.cc
@@ -1,44 +1,57 @@
-/* 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);
-
+#include "loadsave.hpp"
+#include "loadsave.h"
+
+#include "ability_type.hpp"
+#include "artifact_type.hpp"
+#include "birth.hpp"
+#include "cave_type.hpp"
+#include "dungeon_info_type.hpp"
+#include "ego_item_type.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 "player_class.hpp"
+#include "player_race.hpp"
+#include "player_race_mod.hpp"
+#include "player_type.hpp"
+#include "quark.hpp"
+#include "hooks.hpp"
+#include "skill_type.hpp"
+#include "store_type.hpp"
+#include "tables.hpp"
+#include "timer_type.hpp"
+#include "town_type.hpp"
+#include "trap_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 <cassert>
+#include <memory>
+
+static u32b vernum; /* Version flag */
static FILE *fff; /* Local savefile ptr */
+/**
+ * Load/save flag
+ */
+enum class ls_flag_t {
+ LOAD = 3,
+ SAVE = 7
+};
+
/*
* Basic byte-level reading from savefile. This provides a single point
* of interface to the pseudoencryption that ToME (and Angband)
@@ -72,37 +85,178 @@ static void sf_put(byte v)
}
/*
+ * 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_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_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);
+}
+
+/*
* Do object memory and similar stuff
*/
-static void do_xtra(int k_idx, int flag)
+static void do_xtra(int k_idx, ls_flag_t flag)
{
byte tmp8u = 0;
object_kind *k_ptr = &k_info[k_idx];
- if (flag == LS_SAVE)
+ switch(flag)
+ {
+ case ls_flag_t::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);
+ return;
}
- if (flag == LS_LOAD)
+ case ls_flag_t::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);
+ return;
+ }
+ }
+}
+
+static void save_string(const char *str)
+{
+ while (*str)
+ {
+ do_byte((byte*)str, ls_flag_t::SAVE);
+ str++;
+ }
+ do_byte((byte*)str, ls_flag_t::SAVE);
+}
+
+static void load_string(char *str, int max)
+{
+ int i;
+
+ /* Read the string */
+ for (i = 0; TRUE; i++)
+ {
+ byte tmp8u;
+
+ /* Read a byte */
+ do_byte(&tmp8u, ls_flag_t::LOAD);
+
+ /* Collect string while legal */
+ if (i < max) str[i] = tmp8u;
+
+ /* End of string */
+ if (!tmp8u) break;
+ }
+ /* Terminate */
+ str[max - 1] = '\0';
+}
+
+static void do_string(char *str, int max, ls_flag_t flag)
+/* Max is ignored for writing */
+{
+ switch(flag) {
+ case ls_flag_t::LOAD:
+ {
+ load_string(str, max);
+ return;
+ }
+ case ls_flag_t::SAVE:
+ {
+ save_string(str);
+ return;
+ }
}
}
/*
* Load/Save quick start data
*/
-void do_quick_start(int flag)
+static void do_quick_start(ls_flag_t flag)
{
+ s16b tmp16s;
+ u32b tmp32u;
int i;
do_s16b(&previous_char.sex, flag);
@@ -122,8 +276,8 @@ void do_quick_start(int 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_s16b(&tmp16s, flag);
+ do_u32b(&tmp32u, flag);
do_byte((byte*)&previous_char.quick_ok, flag);
for (i = 0; i < 4; i++) do_string(previous_char.history[i], 60, flag);
@@ -132,23 +286,33 @@ void do_quick_start(int flag)
/*
* The special saved subrace
*/
-static void do_subrace(int flag)
+static void do_subrace(ls_flag_t 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);
+ buf[80] = '\0'; // Make sure string is always NUL terminated
+
+ if (flag == ls_flag_t::SAVE)
+ {
+ strncpy(buf, sr_ptr->title, 80);
+ }
do_string(buf, 80, flag);
- if (flag == LS_LOAD)
- strncpy(sr_ptr->title + rmp_name, buf, 80);
+ if (flag == ls_flag_t::LOAD)
+ {
+ set_subrace_title(sr_ptr, buf);
+ }
- if (flag == LS_SAVE)
- strncpy(buf, sr_ptr->desc + rmp_text, 80);
+ if (flag == ls_flag_t::SAVE)
+ {
+ strncpy(buf, sr_ptr->desc, 80);
+ }
do_string(buf, 80, flag);
- if (flag == LS_LOAD)
- strncpy(sr_ptr->desc + rmp_text, buf, 80);
+ if (flag == ls_flag_t::LOAD)
+ {
+ set_subrace_description(sr_ptr, buf);
+ }
do_byte((byte*)&sr_ptr->place, flag);
@@ -217,17 +381,78 @@ static void do_subrace(int flag)
}
}
+
+/* Load/Save the random spells info */
+static void do_spells(int i, ls_flag_t 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);
+}
+
+
+/*
+ * 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();
+}
+
+
+static void skip_ver_byte(u32b version, ls_flag_t flag)
+/* Reads and discards a byte if the savefile is as old as/older than version */
+{
+ if ((flag == ls_flag_t::LOAD) && (vernum <= version))
+ {
+ byte forget;
+ do_byte(&forget, flag);
+ }
+ return;
+}
+
+static void do_ver_s16b(s16b *v, u32b version, s16b defval, ls_flag_t flag)
+{
+ if ((flag == ls_flag_t::LOAD) && (vernum < version))
+ {
+ *v = defval;
+ return;
+ }
+ do_s16b(v, flag);
+}
+
/*
* Misc. other data
*/
static char loaded_game_module[80];
-static bool_ do_extra(int flag)
+static bool_ do_extra(ls_flag_t flag)
{
int i, j;
- byte tmp8u;
- s16b tmp16s;
- u32b tmp32u;
- u16b tmp16b;
+ byte tmp8u = 0;
+ s16b tmp16s = 0;
+ u32b tmp32u = 0;
+ s32b tmp32s = 0;
+ u16b tmp16b = 0;
u32b dummy32u = 0;
do_string(player_name, 32, flag);
@@ -240,14 +465,14 @@ static bool_ do_extra(int flag)
}
/* Handle the special levels info */
- if (flag == LS_SAVE)
+ if (flag == ls_flag_t::SAVE)
{
tmp8u = max_d_idx;
tmp16s = MAX_DUNGEON_DEPTH;
}
do_byte(&tmp8u, flag);
- if (flag == LS_LOAD)
+ if (flag == ls_flag_t::LOAD)
{
if (tmp8u > max_d_idx)
{
@@ -257,7 +482,7 @@ static bool_ do_extra(int flag)
do_s16b(&tmp16s, flag);
- if (flag == LS_LOAD)
+ if (flag == ls_flag_t::LOAD)
{
if (tmp16s > MAX_DUNGEON_DEPTH)
{
@@ -293,7 +518,7 @@ static bool_ do_extra(int 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;
+ if (flag == ls_flag_t::SAVE) tmp8u = 0;
do_byte(&p_ptr->hitdie, flag);
do_u16b(&p_ptr->expfact, flag);
@@ -317,12 +542,12 @@ static bool_ do_extra(int flag)
tmp16s = MAX_SKILLS;
do_s16b(&tmp16s, flag);
- if ((flag == LS_LOAD) && (tmp16s > MAX_SKILLS))
+ if ((flag == ls_flag_t::LOAD) && (tmp16s > MAX_SKILLS))
{
quit("Too many skills");
}
- if (flag == LS_SAVE) old_max_s_idx = max_s_idx;
+ if (flag == ls_flag_t::SAVE) old_max_s_idx = max_s_idx;
do_u16b(&old_max_s_idx, flag);
for (i = 0; i < tmp16s; ++i)
{
@@ -347,7 +572,7 @@ static bool_ do_extra(int flag)
tmp16s = max_ab_idx;
do_s16b(&tmp16s, flag);
- if ((flag == LS_LOAD) && (tmp16s > max_ab_idx))
+ if ((flag == ls_flag_t::LOAD) && (tmp16s > max_ab_idx))
{
quit("Too many abilities");
}
@@ -360,24 +585,6 @@ static bool_ do_extra(int 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);
@@ -388,10 +595,10 @@ static bool_ do_extra(int 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(&tmp16s, flag);
+ do_s16b(&tmp16s, flag);
do_s16b(&p_ptr->inside_quest, flag);
- do_byte((byte*)&p_ptr->exit_bldg, flag);
+ do_byte(&tmp8u, flag);
/* Save/load spellbinder */
@@ -403,10 +610,10 @@ static bool_ do_extra(int flag)
do_byte(&tmp8u, flag); /* tmp8u should be 0 at this point */
- if (flag == LS_SAVE) tmp8u = MAX_PLOTS;
+ if (flag == ls_flag_t::SAVE) tmp8u = MAX_PLOTS;
do_byte(&tmp8u, flag);
- if ((flag == LS_LOAD) && (tmp8u > MAX_PLOTS))
+ if ((flag == ls_flag_t::LOAD) && (tmp8u > MAX_PLOTS))
{
quit(format("Too many plots, %d %d", tmp8u, MAX_PLOTS));
}
@@ -416,13 +623,13 @@ static bool_ do_extra(int flag)
do_s16b(&plots[i], flag);
}
- if (flag == LS_SAVE)
+ if (flag == ls_flag_t::SAVE)
{
tmp8u = MAX_RANDOM_QUEST;
}
do_byte(&tmp8u, flag);
- if ((flag == LS_LOAD) &&
+ if ((flag == ls_flag_t::LOAD) &&
(tmp8u > MAX_RANDOM_QUEST)) quit("Too many random quests");
for (i = 0; i < tmp8u; i++)
{
@@ -458,6 +665,7 @@ static bool_ do_extra(int flag)
/* Gods */
do_s32b(&p_ptr->grace, flag);
+ do_s32b(&p_ptr->grace_delay, flag);
do_byte((byte*)&p_ptr->praying, flag);
do_s16b(&p_ptr->melkor_sacrifice, flag);
do_byte(&p_ptr->pgod, flag);
@@ -465,23 +673,26 @@ static bool_ do_extra(int flag)
/* Max Player and Dungeon Levels */
do_s16b(&p_ptr->max_plv, flag);
- if (flag == LS_SAVE)
+ if (flag == ls_flag_t::SAVE)
tmp8u = max_d_idx;
do_byte(&tmp8u, flag);
for (i = 0; i < tmp8u; i++)
{
- if (flag == LS_SAVE)
+ if (flag == ls_flag_t::SAVE)
tmp16s = max_dlv[i];
do_s16b(&tmp16s, flag);
- if ((flag == LS_LOAD) && (i <= max_d_idx))
+ if ((flag == ls_flag_t::LOAD) && (i <= max_d_idx))
max_dlv[i] = tmp16s;
}
/* Repair max player level??? */
- if ((flag == LS_LOAD) && (p_ptr->max_plv < p_ptr->lev))
+ if ((flag == ls_flag_t::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);
+ for (i = 0; i < HELP_MAX; i++)
+ {
+ do_bool(&(p_ptr->help.activated[i]), flag);
+ }
/* More info */
tmp16s = 0;
@@ -512,6 +723,7 @@ static bool_ do_extra(int flag)
do_s16b(&p_ptr->blessed, flag);
do_s16b(&p_ptr->control, flag);
do_byte(&p_ptr->control_dir, flag);
+ do_s16b(&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);
@@ -547,9 +759,9 @@ static bool_ do_extra(int 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_s16b(&tmp16s, flag);
do_ver_s16b(&p_ptr->tim_poison, SAVEFILE_VERSION, 0, flag);
- do_s16b(&p_ptr->resist_magic, flag);
+ do_s16b(&tmp16s, flag);
do_s16b(&p_ptr->tim_invisible, flag);
do_s16b(&p_ptr->tim_inv_pow, flag);
do_s16b(&p_ptr->tim_mimic, flag);
@@ -558,48 +770,55 @@ static bool_ do_extra(int 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(&tmp16s, flag);
+ do_s16b(&tmp16s, flag);
do_s16b(&p_ptr->immov_cntr, flag);
do_s16b(&p_ptr->strike, flag);
- do_s16b(&p_ptr->meditation, flag);
+ do_s16b(&tmp16s, flag);
do_s16b(&p_ptr->tim_reflect, flag);
- do_s16b(&p_ptr->tim_res_time, flag);
+ do_s16b(&tmp16s, 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_s32b(&tmp32s, flag);
+ do_s32b(&tmp32s, flag);
do_s16b(&p_ptr->absorb_soul, flag);
+ do_s32b(&p_ptr->inertia_controlled_spell, flag);
+ do_s16b(&p_ptr->last_rewarded_level, flag);
- do_s16b(&p_ptr->chaos_patron, flag);
+ do_s16b(&tmp16s, flag); /* compat */
- if (flag == LS_SAVE) tmp16s = max_corruptions;
+ if (flag == ls_flag_t::SAVE) { tmp16s = CORRUPTIONS_MAX; }
do_s16b(&tmp16s, flag);
+ if (tmp16s > CORRUPTIONS_MAX) {
+ quit("Too many corruptions");
+ }
for (i = 0; i < tmp16s; i++)
{
- if ((flag == LS_SAVE) && (i < max_corruptions))
+ if (flag == ls_flag_t::SAVE)
tmp8u = p_ptr->corruptions[i];
do_byte(&tmp8u, flag);
- if ((flag == LS_LOAD) && (i < max_corruptions))
+ if (flag == ls_flag_t::LOAD)
p_ptr->corruptions[i] = tmp8u;
}
+ do_byte((byte*)&p_ptr->corrupt_anti_teleport_stopped, flag);
+
do_byte(&p_ptr->confusing, flag);
do_byte((byte*)&p_ptr->black_breath, flag);
do_byte((byte*)&fate_flag, flag);
do_byte(&p_ptr->searching, flag);
- do_byte(&p_ptr->maximize, flag);
+ do_byte(&tmp8u, 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_s16b(&tmp16s, flag);
do_byte(&tmp8u, flag);
@@ -609,21 +828,21 @@ static bool_ do_extra(int 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(&tmp32u, flag);
+ do_u32b(&tmp32u, flag);
+ do_u32b(&tmp32u, flag);
do_u32b(&p_ptr->music_extra, flag);
- do_u32b(&p_ptr->music_extra2, flag);
+ do_u32b(&tmp32u, 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_u32b(&tmp32u, flag);
+ do_u32b(&tmp32u, flag);
+ do_u32b(&tmp32u, flag);
+ do_u32b(&tmp32u, flag);
+ do_u32b(&tmp32u, flag);
+ do_u32b(&tmp32u, flag);
+ do_u32b(&tmp32u, flag);
do_u16b(&p_ptr->body_monster, flag);
do_byte((byte*)&p_ptr->disembodied, flag);
@@ -631,12 +850,11 @@ static bool_ do_extra(int flag)
/* Are we in astral mode? */
do_byte((byte*)&p_ptr->astral, flag);
- if (flag == LS_SAVE) tmp16s = POWER_MAX_INIT;
+ if (flag == ls_flag_t::SAVE) tmp16s = POWER_MAX;
do_s16b(&tmp16s, flag);
- if ((flag == LS_LOAD) && (tmp16s > POWER_MAX_INIT))
+ if ((flag == ls_flag_t::LOAD) && (tmp16s > POWER_MAX))
note(format("Too many (%u) powers!", tmp16s));
- if (flag == LS_SAVE) tmp16s = POWER_MAX_INIT;
- for (i = 0; i < tmp16s; i++)
+ for (i = 0; i < POWER_MAX; i++)
do_byte((byte*)&p_ptr->powers_mod[i], flag);
skip_ver_byte(100, flag);
@@ -653,13 +871,14 @@ static bool_ do_extra(int 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);
+ /* The bounties -- kept only for load-compatibility with old savefiles. */
+ for (i = 0; i < 24; i++) {
+ tmp16s = 0; do_s16b(&tmp16s, flag);
+ tmp16s = 0; do_s16b(&tmp16s, flag);
}
- do_u32b(&total_bounties, flag);
+ tmp32u = 0; do_u32b(&tmp32u, flag);
+
+ /* Spells */
do_s16b(&spell_num, flag);
for (i = 0; i < MAX_SPELLS; i++)
do_spells(i, flag);
@@ -684,16 +903,16 @@ static bool_ do_extra(int flag)
do_u16b(&noscore, flag);
/* Write death */
- if (flag == LS_SAVE) tmp8u = death;
+ if (flag == ls_flag_t::SAVE) tmp8u = death;
do_byte(&tmp8u, flag);
- if (flag == LS_LOAD) death = tmp8u;
+ if (flag == ls_flag_t::LOAD) death = tmp8u;
/* Incompatible module? */
- if (flag == LS_LOAD)
+ if (flag == ls_flag_t::LOAD)
{
s32b ok;
- call_lua("module_savefile_loadable", "(s,d)", "d", loaded_game_module, death, &ok);
+ ok = module_savefile_loadable(loaded_game_module);
/* Argh bad game module! */
if (!ok)
@@ -704,9 +923,9 @@ static bool_ do_extra(int flag)
}
/* Write feeling */
- if (flag == LS_SAVE) tmp8u = feeling;
+ if (flag == ls_flag_t::SAVE) tmp8u = feeling;
do_byte(&tmp8u, flag);
- if (flag == LS_LOAD) feeling = tmp8u;
+ if (flag == ls_flag_t::LOAD) feeling = tmp8u;
/* Turn of last "feeling" */
do_s32b(&old_turn, flag);
@@ -717,503 +936,58 @@ static bool_ do_extra(int 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.
+ * Read a monster
*/
-
-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)
+static void do_monster(monster_type *m_ptr, ls_flag_t 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);
-}
+ int i;
-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);
-}
+ /* Read the monster race */
+ do_s16b(&m_ptr->r_idx, flag);
-static void do_s32b(s32b *ip, int flag)
-{
- if (flag == LS_LOAD)
- {
- do_u32b((u32b *)ip, flag);
- return;
- }
- if (flag == LS_SAVE)
- {
- do_u32b((u32b *)ip, flag);
- return;
- }
- /* Raus! Schnell! */
- printf("FATAL: do_s32b passed %d\n", flag);
- exit(0);
-}
+ do_u16b(&m_ptr->ego, flag);
-static void do_string(char *str, int max, int flag)
-/* Max is ignored for writing */
-{
- if (flag == LS_LOAD)
- {
- int i;
+ /* Read the other information */
+ do_byte(&m_ptr->fy, flag);
+ do_byte(&m_ptr->fx, flag);
- /* Read the string */
- for (i = 0; TRUE; i++)
- {
- byte tmp8u;
+ do_s32b(&m_ptr->hp, flag);
+ do_s32b(&m_ptr->maxhp, flag);
- /* Read a byte */
- do_byte(&tmp8u, LS_LOAD);
+ 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);
- /* Collect string while legal */
- if (i < max) str[i] = tmp8u;
+ do_s16b(&m_ptr->bleeding, flag);
+ do_s16b(&m_ptr->poisoned, flag);
- /* 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);
-}
+ do_s32b(&m_ptr->mflag, flag);
-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;
-}
+ if (flag == ls_flag_t::LOAD) m_ptr->mflag &= PERM_MFLAG_MASK;
-static void do_ver_s16b(s16b *v, u32b version, s16b defval, int flag)
-{
- if ((flag == LS_LOAD) && (vernum < version))
+ /* Attacks */
+ for (i = 0; i < 4; i++)
{
- *v = defval;
- return;
+ 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);
}
- 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();
-}
/*
@@ -1275,7 +1049,7 @@ static bool_ wearable_p(object_type *o_ptr)
* 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)
+static void do_item(object_type *o_ptr, ls_flag_t flag)
{
byte old_dd;
byte old_ds;
@@ -1320,15 +1094,15 @@ static void do_item(object_type *o_ptr, int flag)
do_s16b(&o_ptr->ac, flag);
/* We do special processing of this flag when reading */
- if (flag == LS_LOAD)
+ if (flag == ls_flag_t::LOAD)
{
- do_byte(&old_dd, LS_LOAD);
- do_byte(&old_ds, LS_LOAD);
+ do_byte(&old_dd, ls_flag_t::LOAD);
+ do_byte(&old_ds, ls_flag_t::LOAD);
}
- if (flag == LS_SAVE)
+ if (flag == ls_flag_t::SAVE)
{
- do_byte(&o_ptr->dd, LS_SAVE);
- do_byte(&o_ptr->ds, LS_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);
@@ -1371,42 +1145,47 @@ static void do_item(object_type *o_ptr, int flag)
do_s16b(&o_ptr->found_aux3, flag);
do_s16b(&o_ptr->found_aux4, flag);
- if (flag == LS_LOAD)
+ if (flag == ls_flag_t::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);
+ load_string(buf, 128);
+ if (buf[0])
+ {
+ o_ptr->note = quark_add(buf);
+ }
+ /* Artifact name */
+ load_string(buf, 128);
+ if (buf[0])
+ {
+ o_ptr->art_name = quark_add(buf);
+ }
}
- if (flag == LS_SAVE)
+ if (flag == ls_flag_t::SAVE)
{
/* Save the inscription (if any) */
if (o_ptr->note)
{
- do_string((char *)quark_str(o_ptr->note), 0, LS_SAVE);
+ save_string(quark_str(o_ptr->note));
}
else
{
- do_string("", 0, LS_SAVE);
+ save_string("");
}
if (o_ptr->art_name)
{
- do_string((char *)quark_str(o_ptr->art_name), 0, LS_SAVE);
+ save_string(quark_str(o_ptr->art_name));
}
else
{
- do_string("", 0, LS_SAVE);
+ save_string("");
}
}
- if (flag == LS_SAVE) return ; /* Stick any more shared code before this. The rest
- of this function is reserved for LS_LOAD's
+ if (flag == ls_flag_t::SAVE) return ; /* Stick any more shared code before this. The rest
+ of this function is reserved for ls_flag_t::LOAD's
cleanup functions */
- /*********** END OF LS_SAVE ***************/
+ /*********** END OF ls_flag_t::SAVE ***************/
/* Obtain the "kind" template */
k_ptr = &k_info[o_ptr->k_idx];
@@ -1498,143 +1277,389 @@ static void do_item(object_type *o_ptr, int flag)
}
}
+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->t_idx, 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 void my_sentinel(const char *place, u16b value, ls_flag_t flag)
+/* This function lets us know exactly where a savefile is
+ broken by reading/writing conveniently a sentinel at this
+ spot */
+{
+ if (flag == ls_flag_t::SAVE)
+ {
+ do_u16b(&value, flag);
+ return;
+ }
+ if (flag == ls_flag_t::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);
+}
/*
- * Read a monster
+ * Handle dungeon
+ *
+ * The monsters/objects must be loaded in the same order
+ * that they were stored, since the actual indexes matter.
*/
-static void do_monster(monster_type *m_ptr, int flag)
+static bool_ do_dungeon(ls_flag_t flag, bool_ no_companions)
{
int i;
- bool_ tmp;
- /* Read the monster race */
- do_s16b(&m_ptr->r_idx, flag);
+ cave_type *c_ptr;
- do_u16b(&m_ptr->ego, flag);
+ /* Read specific */
+ u16b tmp16b = 0;
- /* Read the other information */
- do_byte(&m_ptr->fy, flag);
- do_byte(&m_ptr->fx, flag);
+ my_sentinel("Before do_dungeon", 324, flag);
- do_s32b(&m_ptr->hp, flag);
- do_s32b(&m_ptr->maxhp, 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_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_u32b(&dungeon_flags1, flag);
+ do_u32b(&dungeon_flags2, flag);
- do_s16b(&m_ptr->bleeding, flag);
- do_s16b(&m_ptr->poisoned, flag);
+ /* Last teleportation */
+ do_s16b(&last_teleportation_y, flag);
+ do_s16b(&last_teleportation_y, flag);
- do_s32b(&m_ptr->mflag, flag);
+ /* Spell effects */
+ tmp16b = MAX_EFFECTS;
+ do_u16b(&tmp16b, flag);
- if (flag == LS_LOAD) m_ptr->mflag &= PERM_MFLAG_MASK;
+ if ((flag == ls_flag_t::LOAD) && (tmp16b > MAX_EFFECTS))
+ {
+ quit("Too many spell effects");
+ }
- /* Attacks */
- for (i = 0; i < 4; i++)
+ for (i = 0; i < tmp16b; ++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);
+ 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);
}
- /* Mind */
- tmp = (m_ptr->mind) ? TRUE : FALSE;
- do_byte((byte*)&tmp, flag);
- if (tmp)
+ /* TO prevent bugs with evolving dungeons */
+ for (i = 0; i < 100; i++)
{
- if (flag == LS_LOAD)
+ 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 (flag == ls_flag_t::SAVE) compact_objects(0);
+ if (flag == ls_flag_t::SAVE) compact_monsters(0);
+ if (flag == ls_flag_t::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_flag_t::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_flag_t::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_flag_t::SAVE);
+ continue; /* Saving is easy */
+ }
+ /* Until the end of the loop, this is all ls_flag_t::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_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
{
- MAKE(m_ptr->mind, monster_mind);
+ /* Access the item location */
+ c_ptr = &cave[o_ptr->iy][o_ptr->ix];
+
+ /* Place the object */
+ c_ptr->o_idxs.push_back(o_idx);
}
}
- /* Special race */
- tmp = (m_ptr->sr_ptr) ? TRUE : FALSE;
- do_byte((byte*)&tmp, flag);
- if (tmp)
+ /*** Monsters ***/
+
+ if (flag == ls_flag_t::SAVE)
{
- if (flag == LS_LOAD)
+ tmp16b = m_max;
+
+ if (no_companions)
{
- MAKE(m_ptr->sr_ptr, monster_race);
+ for (i = 1; i < m_max; i++)
+ {
+ monster_type *m_ptr = &m_list[i];
+
+ if (m_ptr->status == MSTATUS_COMPANION) tmp16b--;
+ }
}
- 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);
+ /* Write the monster count */
+ do_u16b(&tmp16b, flag);
- do_s16b(&m_ptr->sr_ptr->ac, flag);
+ tmp16b = m_max;
+ }
+ else
+ /* Read the monster count */
+ do_u16b(&tmp16b, 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);
+ /* Validate */
+ if ((flag == ls_flag_t::LOAD) && (tmp16b > max_m_idx))
+ {
+ note(format("Too many (%d) monster entries!", tmp16b));
+ return (FALSE);
+ }
- do_s32b(&m_ptr->sr_ptr->mexp, flag);
+ /* Read the monsters */
+ for (i = 1; i < tmp16b; i++)
+ {
+ int m_idx;
+ monster_type *m_ptr;
+ monster_race *r_ptr;
- do_s32b(&m_ptr->sr_ptr->weight, flag);
+ if (flag == ls_flag_t::SAVE)
+ {
+ m_ptr = &m_list[i];
- do_byte(&m_ptr->sr_ptr->freq_inate, flag);
- do_byte(&m_ptr->sr_ptr->freq_spell, flag);
+ /* Don't save companions when no_companions is set */
+ if (no_companions && m_ptr->status == MSTATUS_COMPANION) continue;
- 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);
+ do_monster(m_ptr, ls_flag_t::SAVE);
+ continue; /* Easy to save a monster */
+ }
+ /* From here on, it's all ls_flag_t::LOAD */
+ /* Get a new record */
+ m_idx = m_pop();
- /* Attacks */
- for (i = 0; i < 4; i++)
+ /* Oops */
+ if (i != m_idx)
{
- 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);
+ note(format("Monster allocation error (%d <> %d)", i, m_idx));
+ return (FALSE);
}
- for (i = 0; i < BODY_MAX; i++)
- do_byte(&m_ptr->sr_ptr->body_parts[i], flag);
+ /* Acquire monster */
+ m_ptr = &m_list[m_idx];
- do_byte(&m_ptr->sr_ptr->level, flag);
- do_byte(&m_ptr->sr_ptr->rarity, flag);
+ /* Read the monster */
+ do_monster(m_ptr, ls_flag_t::LOAD);
- do_byte((byte*)&m_ptr->sr_ptr->d_char, flag);
- do_byte(&m_ptr->sr_ptr->d_attr, flag);
+ /* 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_flag_t::SAVE && !no_companions) ? max_m_idx : 0;
+
+ /* Read the monster count */
+ do_u16b(&tmp16b, flag);
+
+ /* Hack -- verify */
+ if ((flag == ls_flag_t::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;
- do_byte((byte*)&m_ptr->sr_ptr->x_char, flag);
- do_byte(&m_ptr->sr_ptr->x_attr, flag);
+ /* Acquire monster */
+ m_ptr = &km_list[i];
- do_s16b(&m_ptr->sr_ptr->max_num, flag);
- do_byte(&m_ptr->sr_ptr->cur_num, flag);
+ /* Read the monster */
+ do_monster(m_ptr, flag);
}
+
+ /*** 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(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_flag_t::SAVE, TRUE);
+
+ my_fclose(fff);
}
+bool_ file_exist(cptr 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;
+}
/*
* Handle monster lore
*/
-static void do_lore(int r_idx, int flag)
+static void do_lore(int r_idx, ls_flag_t flag)
{
monster_race *r_ptr = &r_info[r_idx];
@@ -1682,7 +1707,7 @@ static void do_lore(int r_idx, int flag)
do_byte((byte*)&r_ptr->on_saved, flag);
- if (flag == LS_LOAD)
+ if (flag == ls_flag_t::LOAD)
{
/* Lore flag repair? */
r_ptr->r_flags1 &= r_ptr->flags1;
@@ -1700,42 +1725,33 @@ static void do_lore(int r_idx, int flag)
/*
* 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? */
+static void do_store(store_type *str, ls_flag_t flag)
{
- 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 */
+ byte num;
+ if (flag == ls_flag_t::SAVE) num = str->stock_num;
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++)
+ for (int j = 0; j < num; j++)
{
- if (flag == LS_LOAD)
+ if (flag == ls_flag_t::LOAD)
/* Can't this be cleaner? */
{
object_type forge;
/* Wipe the object */
object_wipe(&forge);
/* Read the item */
- do_item(&forge, LS_LOAD);
+ do_item(&forge, ls_flag_t::LOAD);
/* Acquire valid items */
if ((str->stock_num < store_inven_max) && (str->stock_num < str->stock_size))
{
@@ -1745,17 +1761,14 @@ static bool_ do_store(store_type *str, int flag)
object_copy(&str->stock[k], &forge);
}
}
- if (flag == LS_SAVE) do_item(&str->stock[j], flag);
+ if (flag == ls_flag_t::SAVE) do_item(&str->stock[j], flag);
}
-
- /* Success */
- return (TRUE);
}
/*
* RNG state
*/
-static void do_randomizer(int flag)
+static void do_randomizer(ls_flag_t flag)
{
int i;
@@ -1774,7 +1787,7 @@ static void do_randomizer(int flag)
}
/* Accept */
- if (flag == LS_LOAD)
+ if (flag == ls_flag_t::LOAD)
{
Rand_quick = FALSE;
}
@@ -1792,7 +1805,7 @@ static void do_randomizer(int flag)
* 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)
+static void do_options(ls_flag_t flag)
{
int i, n;
@@ -1808,10 +1821,10 @@ static void do_options(int flag)
do_byte(&hitpoint_warn, flag);
/*** Cheating options ***/
- if (flag == LS_LOAD) /* There *MUST* be some nice way to unify this! */
+ if (flag == ls_flag_t::LOAD) /* There *MUST* be some nice way to unify this! */
{
u16b c;
- do_u16b(&c, LS_LOAD);
+ do_u16b(&c, ls_flag_t::LOAD);
if (c & 0x0002) wizard = TRUE;
cheat_peek = (c & 0x0100) ? TRUE : FALSE;
cheat_hear = (c & 0x0200) ? TRUE : FALSE;
@@ -1820,7 +1833,7 @@ static void do_options(int flag)
cheat_know = (c & 0x1000) ? TRUE : FALSE;
cheat_live = (c & 0x2000) ? TRUE : FALSE;
}
- if (flag == LS_SAVE)
+ if (flag == ls_flag_t::SAVE)
{
u16b c = 0;
if (wizard) c |= 0x0002;
@@ -1830,14 +1843,14 @@ static void do_options(int flag)
if (cheat_xtra) c |= 0x0800;
if (cheat_know) c |= 0x1000;
if (cheat_live) c |= 0x2000;
- do_u16b(&c, LS_SAVE);
+ do_u16b(&c, ls_flag_t::SAVE);
}
do_byte((byte*)&autosave_l, flag);
do_byte((byte*)&autosave_t, flag);
do_s16b(&autosave_freq, flag);
- if (flag == LS_LOAD)
+ if (flag == ls_flag_t::LOAD)
{
/* Read the option flags */
for (n = 0; n < 8; n++) do_u32b(&oflag[n], flag);
@@ -1914,7 +1927,7 @@ static void do_options(int flag)
}
}
}
- if (flag == LS_SAVE)
+ if (flag == ls_flag_t::SAVE)
{
/* Analyze the options */
for (i = 0; option_info[i].o_desc; i++)
@@ -1961,33 +1974,15 @@ static void do_options(int 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)
+static bool_ do_inventory(ls_flag_t flag)
{
- if (flag == LS_LOAD)
+ if (flag == ls_flag_t::LOAD)
{
int slot = 0;
@@ -2004,7 +1999,7 @@ static bool_ do_inventory(int flag)
u16b n;
/* Get the next item index */
- do_u16b(&n, LS_LOAD);
+ do_u16b(&n, ls_flag_t::LOAD);
/* Nope, we reached the end */
if (n == 0xFFFF) break;
@@ -2016,7 +2011,7 @@ static bool_ do_inventory(int flag)
object_wipe(q_ptr);
/* Read the item */
- do_item(q_ptr, LS_LOAD);
+ do_item(q_ptr, ls_flag_t::LOAD);
/* Hack -- verify item */
if (!q_ptr->k_idx) return (FALSE);
@@ -2061,7 +2056,7 @@ static bool_ do_inventory(int flag)
}
}
}
- if (flag == LS_SAVE)
+ if (flag == ls_flag_t::SAVE)
{
u16b i;
u16b sent = 0xFFFF;
@@ -2072,7 +2067,7 @@ static bool_ do_inventory(int flag)
do_u16b(&i, flag);
do_item(o_ptr, flag);
}
- do_u16b(&sent, LS_SAVE); /* Sentinel */
+ do_u16b(&sent, ls_flag_t::SAVE); /* Sentinel */
}
/* Success */
return (TRUE);
@@ -2083,339 +2078,45 @@ static bool_ do_inventory(int flag)
/*
* Read the saved messages
*/
-static void do_messages(int flag) /* FIXME! We should be able to unify this better */
+static void do_messages(ls_flag_t flag) /* FIXME! We should be able to unify this better */
{
int i;
char buf[128];
- byte color, type;
+ byte color;
s16b num;
- if (flag == LS_SAVE) num = message_num();
-
/* Total */
+ if (flag == ls_flag_t::SAVE) num = message_num();
do_s16b(&num, flag);
/* Read the messages */
- if (flag == LS_LOAD)
+ if (flag == ls_flag_t::LOAD)
{
+ byte tmp8u = 0;
for (i = 0; i < num; i++)
{
/* Read the message */
- do_string(buf, 128, LS_LOAD);
+ do_string(buf, 128, ls_flag_t::LOAD);
do_byte(&color, flag);
- do_byte(&type, flag);
+ do_byte(&tmp8u, flag);
/* Save the message */
- message_add(type, buf, color);
+ message_add(buf, color);
}
}
- if (flag == LS_SAVE)
+ if (flag == ls_flag_t::SAVE)
{
byte holder;
+ byte zero = 0;
for (i = num - 1; i >= 0; i--)
{
- do_string((char *)message_str((s16b)i), 0, LS_SAVE);
+ do_string((char *)message_str((s16b)i), 0, ls_flag_t::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;
+ do_byte(&zero, flag);
}
}
-
- /*** 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 */
@@ -2443,7 +2144,7 @@ bool_ load_dungeon(char *ext)
}
/* Read the dungeon */
- if (!do_dungeon(LS_LOAD, FALSE))
+ if (!do_dungeon(ls_flag_t::LOAD, FALSE))
{
dun_level = old_dun;
dungeon_type = old_dungeon_type;
@@ -2460,26 +2161,9 @@ bool_ load_dungeon(char *ext)
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)
+void do_fate(int i, ls_flag_t flag)
{
- if ((flag == LS_LOAD) && (i >= MAX_FATES)) i = MAX_FATES - 1;
+ if ((flag == ls_flag_t::LOAD) && (i >= MAX_FATES)) i = MAX_FATES - 1;
do_byte(&fates[i].fate, flag);
do_byte(&fates[i].level, flag);
@@ -2495,21 +2179,108 @@ void do_fate(int i, int flag)
}
/*
+ * Load/save timers.
+ */
+static void do_timers(ls_flag_t flag)
+{
+ timer_type *t_ptr;
+
+ for (t_ptr = gl_timers; t_ptr != NULL; t_ptr = t_ptr->next)
+ {
+ do_bool(&t_ptr->enabled, flag);
+ do_s32b(&t_ptr->delay, flag);
+ do_s32b(&t_ptr->countdown, flag);
+ }
+}
+
+/*
+ * Load/save stores.
+ */
+static void do_stores(ls_flag_t flag)
+{
+ u16b tmp16u;
+ u16b real_max = 0;
+
+ /* Note that this forbids max_towns from shrinking, but that is fine */
+ std::unique_ptr<byte[]> reals(new byte[max_towns]);
+
+ /* Find the real towns */
+ if (flag == ls_flag_t::SAVE)
+ {
+ for (int i = 1; i < max_towns; i++)
+ {
+ if (!(town_info[i].flags & (TOWN_REAL))) continue;
+ reals[real_max++] = i;
+ }
+ }
+ do_u16b(&real_max, flag);
+ for (int i = 0; i < real_max; i++)
+ {
+ do_byte((byte*)&reals[i], flag);
+ }
+
+ /* Read the stores */
+ if (flag == ls_flag_t::SAVE) tmp16u = max_st_idx;
+ do_u16b(&tmp16u, flag);
+ assert(tmp16u <= max_st_idx);
+
+ /* Ok now read the real towns */
+ for (int i = 0; i < real_max; i++)
+ {
+ int z = reals[i];
+
+ /* Ultra paranoia */
+ if (!town_info[z].stocked) create_stores_stock(z);
+
+ for (int j = 0; j < tmp16u; j++)
+ {
+ do_store(&town_info[z].store[j], flag);
+ }
+ }
+}
+
+/*
+ * 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->inside_quest = 0;
+ 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];
+}
+
+
+/*
* Actually read the savefile
*/
-static bool_ do_savefile_aux(int flag)
+static bool_ do_savefile_aux(ls_flag_t 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 (flag == ls_flag_t::LOAD)
{
if (vernum < 100)
{
@@ -2521,15 +2292,14 @@ static bool_ do_savefile_aux(int flag)
note(format("Loading version %lu savefile... ", vernum));
}
}
- if (flag == LS_SAVE)
+ if (flag == ls_flag_t::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)
+ if (flag == ls_flag_t::LOAD)
{
u32b mt32b;
byte mtbyte;
@@ -2538,7 +2308,7 @@ static bool_ do_savefile_aux(int flag)
do_u32b(&mt32b, flag);
do_byte(&mtbyte, flag);
}
- if (flag == LS_SAVE)
+ if (flag == ls_flag_t::SAVE)
{
u32b saver;
saver = SAVEFILE_VERSION;
@@ -2547,8 +2317,11 @@ static bool_ do_savefile_aux(int flag)
do_byte(&tmp8u, flag); /* 'encryption' */
}
- /* Operating system info? Not really. This is just set to 0L */
- do_u32b(&sf_xtra, flag);
+ /* Kept only for compatibility; always set to 0 */
+ {
+ u32b tmp32u = 0;
+ do_u32b(&tmp32u, flag);
+ }
/* Time of last save */
do_u32b(&sf_when, flag);
@@ -2560,31 +2333,31 @@ static bool_ do_savefile_aux(int flag)
do_u16b(&sf_saves, flag);
/* Game module */
- if (flag == LS_SAVE)
+ if (flag == ls_flag_t::SAVE)
strcpy(loaded_game_module, game_module);
do_string(loaded_game_module, 80, flag);
+ /* Timers */
+ do_timers(flag);
+
/* Read RNG state */
do_randomizer(flag);
- if ((flag == LS_LOAD) && (arg_fiddle)) note("Loaded Randomizer Info");
/* 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;
+ if (flag == ls_flag_t::SAVE) tmp16u = max_r_idx;
do_u16b(&tmp16u, flag);
/* Incompatible save files */
- if ((flag == LS_LOAD) && (tmp16u > max_r_idx))
+ if ((flag == ls_flag_t::LOAD) && (tmp16u > max_r_idx))
{
note(format("Too many (%u) monster races!", tmp16u));
return (FALSE);
@@ -2597,13 +2370,12 @@ static bool_ do_savefile_aux(int flag)
do_lore(i, flag);
}
- if ((flag == LS_LOAD) && (arg_fiddle)) note("Loaded Monster Memory");
/* Object Memory */
- if (flag == LS_SAVE) tmp16u = max_k_idx;
+ if (flag == ls_flag_t::SAVE) tmp16u = max_k_idx;
do_u16b(&tmp16u, flag);
/* Incompatible save files */
- if ((flag == LS_LOAD) && (tmp16u > max_k_idx))
+ if ((flag == ls_flag_t::LOAD) && (tmp16u > max_k_idx))
{
note(format("Too many (%u) object kinds!", tmp16u));
return (FALSE);
@@ -2611,26 +2383,25 @@ static bool_ do_savefile_aux(int flag)
/* Read the object memory */
for (i = 0; i < tmp16u; i++) do_xtra(i, flag);
- if ((flag == LS_LOAD) && (arg_fiddle)) note("Loaded Object Memory");
- if (flag == LS_LOAD) junkinit();
+ if (flag == ls_flag_t::LOAD) junkinit();
{
u16b max_towns_ldsv;
u16b max_quests_ldsv;
- if (flag == LS_SAVE) max_towns_ldsv = max_towns;
+ if (flag == ls_flag_t::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))
+ if ((flag == ls_flag_t::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;
+ if (flag == ls_flag_t::SAVE) max_towns_ldsv = TOWN_RANDOM;
do_u16b(&max_towns_ldsv, flag);
/* Incompatible save files */
- if ((flag == LS_LOAD) && (max_towns_ldsv != TOWN_RANDOM))
+ if ((flag == ls_flag_t::LOAD) && (max_towns_ldsv != TOWN_RANDOM))
{
note(format("Different random towns base (%u)!", max_towns_ldsv));
return (FALSE);
@@ -2647,7 +2418,7 @@ static bool_ do_savefile_aux(int 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))
+ if ((town_info[i].flags & (TOWN_REAL)) && (flag == ls_flag_t::LOAD))
{
create_stores_stock(i);
}
@@ -2655,21 +2426,21 @@ static bool_ do_savefile_aux(int flag)
}
/* Number of dungeon */
- if (flag == LS_SAVE) max_towns_ldsv = max_d_idx;
+ if (flag == ls_flag_t::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))
+ if ((flag == ls_flag_t::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;
+ if (flag == ls_flag_t::SAVE) max_quests_ldsv = TOWN_DUNGEON;
do_u16b(&max_quests_ldsv, flag);
/* Incompatible save files */
- if ((flag == LS_LOAD) && (max_quests_ldsv > TOWN_DUNGEON))
+ if ((flag == ls_flag_t::LOAD) && (max_quests_ldsv > TOWN_DUNGEON))
{
note(format("Too many town per dungeons (%u)!", max_quests_ldsv));
return (FALSE);
@@ -2685,27 +2456,30 @@ static bool_ do_savefile_aux(int flag)
do_s16b(&(d_info[i].t_num), flag);
}
- if (flag == LS_SAVE) max_quests_ldsv = MAX_Q_IDX_INIT;
- /* Number of quests */
+ /* Sanity check number of quests */
+ if (flag == ls_flag_t::SAVE) max_quests_ldsv = MAX_Q_IDX;
do_u16b(&max_quests_ldsv, flag);
/* Incompatible save files */
- if ((flag == LS_LOAD) && (max_quests_ldsv > MAX_Q_IDX_INIT))
+ if ((flag == ls_flag_t::LOAD) && (max_quests_ldsv != MAX_Q_IDX))
{
- note(format("Too many (%u) quests!", max_quests_ldsv));
+ note(format("Invalid number of quests (%u)!", max_quests_ldsv));
return (FALSE);
}
- for (i = 0; i < max_quests_ldsv; i++)
+ for (i = 0; i < MAX_Q_IDX; i++)
{
do_s16b(&quest[i].status, flag);
- for (j = 0; j < 4; j++)
+ for (auto &quest_data : quest[i].data)
{
- do_s32b(&(quest[i].data[j]), flag);
+ do_s32b(&quest_data, flag);
}
/* Init the hooks */
- if ((flag == LS_LOAD) && (quest[i].type == HOOK_TYPE_C)) quest[i].init(i);
+ if ((flag == ls_flag_t::LOAD) && (quest[i].init != NULL))
+ {
+ quest[i].init(i);
+ }
}
/* Position in the wilderness */
@@ -2716,7 +2490,7 @@ static bool_ do_savefile_aux(int flag)
{
s32b wild_x_size, wild_y_size;
- if (flag == LS_SAVE)
+ if (flag == ls_flag_t::SAVE)
{
wild_x_size = max_wild_x;
wild_y_size = max_wild_y;
@@ -2725,11 +2499,11 @@ static bool_ do_savefile_aux(int flag)
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)))
+ if ((flag == ls_flag_t::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));
+ wild_x_size, wild_y_size));
return (FALSE);
}
/* Wilderness seeds */
@@ -2744,12 +2518,11 @@ static bool_ do_savefile_aux(int flag)
}
}
}
- if ((flag == LS_LOAD) && (arg_fiddle)) note("Loaded Quests");
/* Load the random artifacts. */
- if (flag == LS_SAVE) tmp16u = MAX_RANDARTS;
+ if (flag == ls_flag_t::SAVE) tmp16u = MAX_RANDARTS;
do_u16b(&tmp16u, flag);
- if ((flag == LS_LOAD) && (tmp16u > MAX_RANDARTS))
+ if ((flag == ls_flag_t::LOAD) && (tmp16u > MAX_RANDARTS))
{
note(format("Too many (%u) random artifacts!", tmp16u));
return (FALSE);
@@ -2768,10 +2541,10 @@ static bool_ do_savefile_aux(int flag)
}
/* Load the Artifacts */
- if (flag == LS_SAVE) tmp16u = max_a_idx;
+ if (flag == ls_flag_t::SAVE) tmp16u = max_a_idx;
do_u16b(&tmp16u, flag);
/* Incompatible save files */
- if ((flag == LS_LOAD) && (tmp16u > max_a_idx))
+ if ((flag == ls_flag_t::LOAD) && (tmp16u > max_a_idx))
{
note(format("Too many (%u) artifacts!", tmp16u));
return (FALSE);
@@ -2782,14 +2555,13 @@ static bool_ do_savefile_aux(int flag)
{
do_byte(&(&a_info[i])->cur_num, flag);
}
- if ((flag == LS_LOAD) && arg_fiddle) note("Loaded Artifacts");
/* Fates */
- if (flag == LS_SAVE) tmp16u = MAX_FATES;
+ if (flag == ls_flag_t::SAVE) tmp16u = MAX_FATES;
do_u16b(&tmp16u, flag);
/* Incompatible save files */
- if ((flag == LS_LOAD) && (tmp16u > MAX_FATES))
+ if ((flag == ls_flag_t::LOAD) && (tmp16u > MAX_FATES))
{
note(format("Too many (%u) fates!", tmp16u));
return (FALSE);
@@ -2800,14 +2572,13 @@ static bool_ do_savefile_aux(int flag)
{
do_fate(i, flag);
}
- if ((flag == LS_LOAD) && arg_fiddle) note("Loaded Fates");
/* Load the Traps */
- if (flag == LS_SAVE) tmp16u = max_t_idx;
+ if (flag == ls_flag_t::SAVE) tmp16u = max_t_idx;
do_u16b(&tmp16u, flag);
/* Incompatible save files */
- if ((flag == LS_LOAD) && (tmp16u > max_t_idx))
+ if ((flag == ls_flag_t::LOAD) && (tmp16u > max_t_idx))
{
note(format("Too many (%u) traps!", tmp16u));
return (FALSE);
@@ -2818,14 +2589,13 @@ static bool_ do_savefile_aux(int flag)
{
do_byte((byte*)&t_info[i].ident, flag);
}
- if ((flag == LS_LOAD) && (arg_fiddle)) note("Loaded Traps");
/* inscription knowledge */
- if (flag == LS_SAVE) tmp16u = MAX_INSCRIPTIONS;
+ if (flag == ls_flag_t::SAVE) tmp16u = MAX_INSCRIPTIONS;
do_u16b(&tmp16u, flag);
/* Incompatible save files */
- if ((flag == LS_LOAD) && (tmp16u > MAX_INSCRIPTIONS))
+ if ((flag == ls_flag_t::LOAD) && (tmp16u > MAX_INSCRIPTIONS))
{
note(format("Too many (%u) inscriptions!", tmp16u));
return (FALSE);
@@ -2834,20 +2604,18 @@ static bool_ do_savefile_aux(int flag)
/* Read the inscription flag */
for (i = 0; i < tmp16u; i++)
do_byte((byte*)&inscription_info[i].know, flag);
- if ((flag == LS_LOAD) && arg_fiddle) note("Loaded Inscriptions");
/* Read the extra stuff */
if (!do_extra(flag))
return FALSE;
- if ((flag == LS_LOAD) && arg_fiddle) note("Loaded extra information");
/* player_hp array */
- if (flag == LS_SAVE) tmp16u = PY_MAX_LEVEL;
+ if (flag == ls_flag_t::SAVE) tmp16u = PY_MAX_LEVEL;
do_u16b(&tmp16u, flag);
/* Incompatible save files */
- if ((flag == LS_LOAD) && (tmp16u > PY_MAX_LEVEL))
+ if ((flag == ls_flag_t::LOAD) && (tmp16u > PY_MAX_LEVEL))
{
note(format("Too many (%u) hitpoint entries!", tmp16u));
return (FALSE);
@@ -2859,99 +2627,44 @@ static bool_ do_savefile_aux(int flag)
do_s16b(&player_hp[i], flag);
}
- if (flag == LS_LOAD) morejunk();
+ if (flag == ls_flag_t::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);
+ /* Dripping Tread */
+ do_s16b(&p_ptr->dripping_tread, flag);
+
/* Read the inventory */
- if (!do_inventory(flag) && (flag == LS_LOAD)) /* do NOT reverse this ordering */
+ if (!do_inventory(flag) && (flag == ls_flag_t::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--;
- }
- }
+ /* Stores */
+ do_stores(flag);
/* 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)))
+ 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_SAVE) do_dungeon(LS_SAVE, FALSE);
+ if (flag == ls_flag_t::SAVE) do_dungeon(ls_flag_t::SAVE, FALSE);
my_sentinel("Before ghost data", 435, flag);
my_sentinel("After ghost data", 320, flag);
}
{
byte foo = 0;
- if (flag == LS_SAVE)
+ if (flag == ls_flag_t::SAVE)
{
/*
* Safety Padding. It's there
@@ -2961,7 +2674,7 @@ static bool_ do_savefile_aux(int flag)
* read it. Insert any new stuff before
* this position.
*/
- do_byte(&foo, LS_SAVE);
+ do_byte(&foo, ls_flag_t::SAVE);
}
}
@@ -2970,21 +2683,22 @@ static bool_ do_savefile_aux(int flag)
}
+
/*
* Actually read the savefile
*/
-errr rd_savefile(void)
+static 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);
+ err = !do_savefile_aux(ls_flag_t::LOAD);
/* Check for errors */
if (ferror(fff)) err = -1;
@@ -2996,293 +2710,266 @@ errr rd_savefile(void)
return (err);
}
+
/*
- * Note that this function may not be needed at all.
- * It was taken out of load_player_aux(). Do we need it?
+ * 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.
*/
-static void junkinit(void)
+bool_ load_player(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);
- }
- }
-}
+ int fd = -1;
-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];
-}
+ errr err = 0;
-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;
+ cptr what = "generic";
- int part; /* Which section of the grid we're on */
+ /* Paranoia */
+ turn = 0;
- 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;
+ /* Paranoia */
+ death = FALSE;
- case 1:
- tmp8u = c_ptr->feat;
- break;
- case 2:
- tmp8u = c_ptr->mimic;
- break;
+ /* Allow empty savefile name */
+ if (!savefile[0]) return (TRUE);
- case 3:
- tmp16s = c_ptr->special;
- break;
- case 4:
- tmp16s = c_ptr->special2;
- break;
+ /* XXX XXX XXX Fix this */
- case 5:
- tmp16s = c_ptr->t_idx;
- break;
+ /* Verify the existance of the savefile */
+ if (!file_exist(savefile))
+ {
+ /* Give a message */
+ msg_format("Savefile does not exist: %s", savefile);
+ msg_print(NULL);
- case 6:
- tmp16s = c_ptr->inscription;
- break;
+ /* Allow this */
+ return (TRUE);
+ }
- case 7:
- tmp8u = c_ptr->mana;
- break;
+ /* Okay */
+ if (!err)
+ {
+ /* Open the savefile */
+ fd = fd_open(savefile, O_RDONLY);
- 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;
+ /* No file */
+ if (fd < 0) err = -1;
- case 1:
- c_ptr->feat = tmp8u;
- break;
+ /* Message (below) */
+ if (err) what = "Cannot open savefile";
+ }
- case 2:
- c_ptr->mimic = tmp8u;
- break;
+ /* Process file */
+ if (!err)
+ {
+ byte tmp8u = 0;
- case 3:
- c_ptr->special = tmp16s;
- break;
+ /* Open the file XXX XXX XXX XXX Should use Angband file interface */
+ fff = my_fopen(savefile, "rb");
+/* fff = fdopen(fd, "r"); */
- case 4:
- c_ptr->special2 = tmp16s;
- break;
+ /* Read the first four bytes */
+ do_u32b(&vernum, ls_flag_t::LOAD);
+ do_byte(&tmp8u, ls_flag_t::LOAD); // For comatibility with old savefiles
- case 5:
- c_ptr->t_idx = tmp16s;
- break;
+ /* XXX XXX XXX XXX Should use Angband file interface */
+ my_fclose(fff);
+ /* fclose(fff) */
- case 6:
- c_ptr->inscription = tmp16s;
- break;
+ /* Close the file */
+ fd_close(fd);
+ }
- case 7:
- c_ptr->mana = tmp8u;
- break;
+ /* Process file */
+ if (!err)
+ {
- case 8:
- c_ptr->effect = tmp16s;
- break;
- }
- if (++x >= xmax)
- {
- /* Wrap */
- x = 0;
- if ((++y) >= ymax) break;
- }
- }
- }
- }
+ /* Extract version */
+ sf_major = VERSION_MAJOR;
+ sf_minor = VERSION_MINOR;
+ sf_patch = VERSION_PATCH;
+
+ /* Clear screen */
+ Term_clear();
+
+ /* Attempt to load */
+ err = rd_savefile();
+
+ /* Message (below) */
+ if (err) what = "Cannot parse savefile";
}
-}
-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)
+ /* Paranoia */
+ if (!err)
{
- do_u16b(&value, flag);
- return;
+ /* Invalid turn */
+ if (!turn) err = -1;
+
+ /* Message (below) */
+ if (err) what = "Broken savefile";
}
- if (flag == LS_LOAD)
+
+
+ /* Okay */
+ if (!err)
{
- u16b found;
- do_u16b(&found, flag);
- if (found == value) /* All is good */
- return;
- /* All is bad */
- note(format("Savefile broken %s", place));
- return;
+ /* 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);
}
- note(format("Impossible has occurred")); /* Programmer error */
- exit(0);
+
+
+ /* Message */
+ msg_format("Error (%s) reading %d.%d.%d savefile.",
+ what, sf_major, sf_minor, sf_patch);
+ msg_print(NULL);
+
+ /* Oops */
+ return (FALSE);
}
-/********** Variable savefile stuff **************/
+
/*
- * Add num slots to the savefile
+ * Medium level player saver
*/
-void register_savefile(int num)
+static bool_ save_player_aux(char *name)
{
- extra_savefile_parts += (num > 0) ? num : 0;
-}
+ bool_ ok = FALSE;
+ int fd = -1;
+ int mode = 0644;
-void save_number_key(char *key, u32b val)
-{
- byte len = strlen(key);
+ /* No file yet */
+ fff = NULL;
- do_byte(&len, LS_SAVE);
- while (*key)
+ /* Create the savefile */
+ fd = fd_make(name, mode);
+
+ /* File is okay */
+ if (fd >= 0)
{
- do_byte((byte*)key, LS_SAVE);
- key++;
+ /* 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_flag_t::SAVE)) ok = TRUE;
+
+ /* Attempt to close it */
+ if (my_fclose(fff)) ok = FALSE;
+ }
+
+ /* "broken" savefile */
+ if (!ok)
+ {
+ /* Remove "broken" files */
+ (void)fd_kill(name);
+ }
}
- do_u32b(&val, LS_SAVE);
+
+ /* Failure */
+ if (!ok) return (FALSE);
+
+ /* Success */
+ return (TRUE);
}
-void load_number_key(char *key, u32b *val)
+/*
+ * Attempt to save the player in a savefile
+ */
+bool_ save_player(void)
{
- byte len, i = 0;
+ int result = FALSE;
+ char safe[1024];
- do_byte(&len, LS_LOAD);
- while (i < len)
+ /* New savefile */
+ strcpy(safe, savefile);
+ strcat(safe, ".new");
+
+ /* Remove it */
+ fd_kill(safe);
+
+ /* Attempt to save the player */
+ if (save_player_aux(safe))
{
- do_byte((byte*)&key[i], LS_LOAD);
- i++;
+ 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;
}
- key[i] = '\0';
- do_u32b(val, LS_LOAD);
+
+ save_savefile_names();
+
+ /* Return the result */
+ return (result);
}
diff --git a/src/loadsave.h b/src/loadsave.h
new file mode 100644
index 00000000..61bfced7
--- /dev/null
+++ b/src/loadsave.h
@@ -0,0 +1,16 @@
+#pragma once
+
+#include "h-basic.h"
+
+// C linkage required for these functions since main-* code uses them.
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* loadsave.c */
+extern void save_dungeon(void);
+extern bool_ save_player(void);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/src/loadsave.hpp b/src/loadsave.hpp
new file mode 100644
index 00000000..a9eb9dc8
--- /dev/null
+++ b/src/loadsave.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "h-basic.h"
+
+extern bool_ file_exist(cptr buf);
+extern bool_ load_dungeon(char *ext);
+extern bool_ load_player(void);
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 39a1e0df..00000000
--- a/src/lua/llimits.h
+++ /dev/null
@@ -1,205 +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>
-#include <stdint.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 int32_t
-#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 int_least32_t 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..aa2c3a2a
--- /dev/null
+++ b/src/lua_bind.cc
@@ -0,0 +1,277 @@
+/*
+ * 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 "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)
+{
+ // 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 (!(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);
+}
+
+s32b get_level(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);
+ }
+}
+
+/* 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);
+}
+
+/*
+ * 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 buf;
+ return buf;
+}
+
+char lua_msg_box(cptr title)
+{
+ int wid, hgt;
+
+ Term_get_size(&wid, &hgt);
+ return msg_box(title, hgt / 2, wid / 2);
+}
+
+
+
+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->enabled = TRUE;
+}
+
+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..b2a6c9a7
--- /dev/null
+++ b/src/lua_bind.hpp
@@ -0,0 +1,34 @@
+#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. */
+extern s32b spell_chance_device(spell_type *spell_ptr);
+
+/** Calculate spell failure rate for a spell book. */
+extern s32b spell_chance_book(s32b s);
+
+
+extern s32b lua_get_level(struct spell_type *spell, s32b lvl, s32b max, s32b min, s32b bonus);
+extern int get_mana(s32b s);
+extern s32b get_power(s32b s);
+extern s32b get_level(s32b s, s32b max, s32b min);
+extern 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;
+
+extern void get_map_size(const char *name, int *ysize, int *xsize);
+extern void load_map(const char *name, int *y, int *x);
+
+extern char *lua_input_box(cptr title, int max);
+extern char lua_msg_box(cptr title);
+
+extern 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..c253daf2 100644
--- a/src/main-gcu.c
+++ b/src/main-gcu.c
@@ -38,8 +38,8 @@
* Consider the use of "savetty()" and "resetty()". XXX XXX XXX
*/
-
-#include "angband.h"
+#include "util.h"
+#include "variable.h"
#ifdef USE_GCU
@@ -82,7 +82,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 +122,6 @@
#include <unistd.h>
#include <dirent.h>
-/* /me pffts Solaris */
-#ifndef NAME_MAX
-#define NAME_MAX _POSIX_NAME_MAX
-#endif
-
/*
@@ -451,7 +446,7 @@ static errr Term_xtra_gcu_alive(int v)
keymap_norm();
/* Restore modes */
- nocbreak();
+ noraw();
echo();
nl();
@@ -482,7 +477,7 @@ static errr Term_xtra_gcu_alive(int v)
/* (void)wrefresh(curscr); */
/* Restore the settings */
- cbreak();
+ raw();
noecho();
nonl();
@@ -561,60 +556,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 +604,6 @@ static errr Term_xtra_gcu_event(int v)
return (0);
}
-#endif /* USE_GETCH */
/*
* React to changes
@@ -721,14 +661,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 +675,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 +702,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 +721,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 +756,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;
@@ -995,7 +812,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 +820,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 +833,6 @@ errr init_gcu(int argc, char **argv)
}
-#ifdef USE_GRAPHICS
-
- /* Set graphics flag */
- use_graphics = arg_graphics;
-
-#endif
#ifdef A_COLOR
@@ -1106,15 +911,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();
diff --git a/src/main-gtk2.c b/src/main-gtk2.c
index 4830638a..ca3eff60 100644
--- a/src/main-gtk2.c
+++ b/src/main-gtk2.c
@@ -30,60 +30,14 @@
* and reorganised the file a bit.
*/
-#include "angband.h"
+#include "files.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
@@ -99,19 +53,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 +76,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 +102,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 +126,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 +163,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 +193,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 +251,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 +267,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 +284,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 +407,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 +425,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 +514,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 +523,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 +679,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 +786,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 +812,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 +878,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 +905,6 @@ static gboolean keypress_event_handler(
GdkEventKey *event,
gpointer user_data)
{
-#if 1
int i, mc, ms, mo, mx;
char msg[128];
@@ -3703,123 +1021,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 +1262,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 +1271,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 +1307,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 +1358,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 +1413,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 +1465,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 +1555,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 +1570,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 +1633,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 +1741,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,38 +1888,12 @@ 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
*/
@@ -4852,10 +1906,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 +1927,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,52 +1964,12 @@ errr init_gtk2(int argc, char **argv)
/* Activate the "Angband" window screen */
Term_activate(&data[0].t);
-#ifndef SAVEFILE_SCREEN
-
- /* Set the system suffix */
- ANGBAND_SYS = "gtk";
-
- /* Catch nasty signals */
- signals_init();
-
- /* Initialize */
- init_angband();
-
-#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);
}
diff --git a/src/main-sdl.c b/src/main-sdl.c
index 1b53cfc7..9a177cbb 100644
--- a/src/main-sdl.c
+++ b/src/main-sdl.c
@@ -25,23 +25,33 @@
#ifdef USE_SDL
-#include "angband.h"
+#include "loadsave.h"
+#include "util.h"
+#include "variable.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 +68,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 +84,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 +100,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 +493,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 +566,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 +575,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 +604,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 +669,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 +970,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 +1034,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 +1077,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 +1268,6 @@ void moveTerminal(int x, int y)
void bringToTop(int current)
{
term_data *td;
- term_data *tc;
int n = 0;
int i;
@@ -1551,8 +1442,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 +1734,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 */
@@ -1946,7 +1826,7 @@ This routine processes arguments, opens the SDL
window, loads fonts, etc. */
errr 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 +1929,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 +1994,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 +2012,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. */
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..a2daffbe 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,7 +68,11 @@
#include "angband.h"
-
+#include "dungeon.h"
+#include "files.h"
+#include "init2.h"
+#include "util.h"
+#include "variable.h"
#ifdef WINDOWS
@@ -101,11 +99,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 +165,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 +240,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 +430,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 +454,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 +499,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 +524,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 +848,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 +879,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 +904,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 +954,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 +995,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 +1040,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 +1104,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 +1129,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 +1245,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 +1300,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 +1428,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 +1485,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 +1521,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 +1550,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 +1561,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 +1652,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 +1669,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 +1699,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 +1716,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 +1874,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 +1899,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 +1906,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 +2011,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" */
@@ -2915,102 +2192,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 +2384,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 +2425,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 +2710,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 +2915,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 +2940,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 +3075,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 +3118,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 +3151,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 +3176,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 +3241,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();
diff --git a/src/main-x11.c b/src/main-x11.c
index e32e2617..b4b242e5 100644
--- a/src/main-x11.c
+++ b/src/main-x11.c
@@ -92,7 +92,9 @@
*
*/
-#include "angband.h"
+#include "loadsave.h"
+#include "util.h"
+#include "variable.h"
#ifdef USE_X11
@@ -112,20 +114,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.
*/
-#include "maid-x11.c"
+
+#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 -- 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 +474,9 @@ Infowin_init_dad(D,X,Y,W,H,B,Metadpy->fg,Metadpy->bg)
#define Infoclr_init_ppo(F,B,O,M) \
Infoclr_init_data(F,B,O,M)
-#define Infoclr_init_cco(F,B,O,M) \
-Infoclr_init_ppo(Infoclr_Pixell(F),Infoclr_Pixell(B),O,M)
-
#define Infoclr_init_ppn(F,B,O,M) \
Infoclr_init_ppo(F,B,Infoclr_Opcode(O),M)
-#define Infoclr_init_ccn(F,B,O,M) \
-Infoclr_init_cco(F,B,Infoclr_Opcode(O),M)
-
/* Set the current infofnt */
#define Infofnt_set(I) \
@@ -615,36 +677,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 +722,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 +762,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 +780,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 +853,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 +866,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 +879,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 +892,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 +954,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 +1015,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 +1063,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 +1082,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 +1115,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 +1128,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 +1283,6 @@ struct term_data
infowin *win;
-#ifdef USE_GRAPHICS
-
- XImage *tiles;
-
- /* Tempory storage for overlaying tiles. */
- XImage *TmpImage;
-
-#endif
};
@@ -2433,56 +2165,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 +2187,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 +2214,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 +2352,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 +2368,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 +2457,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 +2484,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 +2495,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 +2504,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 +2513,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 +2527,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,102 +2578,6 @@ 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 */
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
index 48ab3f04..680e5c5a 100644
--- a/src/main.c
+++ b/src/main.c
@@ -8,7 +8,14 @@
* are included in all such copies.
*/
-#include "angband.h"
+#include "birth.h"
+#include "dungeon.h"
+#include "files.h"
+#include "init2.h"
+#include "modules.h"
+#include "script.h"
+#include "util.h"
+#include "variable.h"
@@ -18,7 +25,7 @@
*/
-#if !defined(MACINTOSH) && !defined(WINDOWS)
+#if !defined(WINDOWS)
/*
@@ -44,51 +51,11 @@ static void quit_hook(cptr s)
/*
- * 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)
+static void init_save_dir(void)
{
char dirpath[1024];
char versionpath[1024];
@@ -101,139 +68,34 @@ static bool_ check_create_user_dir(void)
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);
+ if (!private_check_user_directory(dirpath))
+ {
+ quit_fmt("Cannot create directory '%s'", dirpath);
+ }
- /* Hack -- Add a path separator (only if needed) */
- if (!suffix(path, PATH_SEP)) strcat(path, PATH_SEP);
+ if (!private_check_user_directory(versionpath))
+ {
+ quit_fmt("Cannot create directory '%s'", versionpath);
+ }
- /* Initialize */
- init_file_paths(path);
+ if (!private_check_user_directory(savepath))
+ {
+ quit_fmt("Cannot create directory '%s'", savepath);
+ }
}
-
-/*
- * 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)
+static void init_player_name()
{
- 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;
- }
+ /* Get the user id (?) */
+ int player_uid = getuid();
- default:
- {
- quit_fmt("Bad semantics in '-d%s'", info);
- }
- }
+ /* Acquire the "user name" as a default player name */
+ user_name(player_name, player_uid);
}
+
/*
* Simple "main" function for multiple platforms.
*
@@ -249,51 +111,18 @@ int main(int argc, char *argv[])
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);
- }
+ init_file_paths_with_env();
+ /* Initialize the player name */
+ init_player_name();
+ /* Make sure save directory exists */
+ init_save_dir();
/* Process the command line arguments */
@@ -312,13 +141,6 @@ int main(int argc, char *argv[])
break;
}
- case 'F':
- case 'f':
- {
- arg_fiddle = TRUE;
- break;
- }
-
case 'W':
case 'w':
{
@@ -326,20 +148,6 @@ int main(int argc, char *argv[])
break;
}
- case 'V':
- case 'v':
- {
- arg_sound = TRUE;
- break;
- }
-
- case 'G':
- case 'g':
- {
- arg_graphics = TRUE;
- break;
- }
-
case 'R':
case 'r':
{
@@ -354,14 +162,6 @@ int main(int argc, char *argv[])
break;
}
- case 'S':
- case 's':
- {
- show_score = atoi(&argv[i][2]);
- if (show_score <= 0) show_score = 10;
- break;
- }
-
case 'u':
case 'U':
{
@@ -382,7 +182,7 @@ int main(int argc, char *argv[])
case 'M':
{
if (!argv[i][2]) goto usage;
- force_module = string_make(&argv[i][2]);
+ force_module = &argv[i][2];
break;
}
@@ -397,7 +197,8 @@ int main(int argc, char *argv[])
char *s;
int j;
- init_lua();
+ init_lua_init();
+
for (j = i + 1; j < argc; j++)
{
s = argv[j];
@@ -411,13 +212,6 @@ int main(int argc, char *argv[])
return 0;
}
- case 'd':
- case 'D':
- {
- change_path(&argv[i][2]);
- break;
- }
-
case '-':
{
if (argv[i][2] == 'h' && !strcmp((argv[i] + 2), "help"))
@@ -443,53 +237,26 @@ usage:
puts("Usage: tome [options] [-- subopts]");
puts(" -h This help");
puts(" -n Start a new character");
- puts(" -f Request fiddle mode");
puts(" -w Request wizard mode");
- puts(" -v Request sound mode");
- puts(" -g Request graphics mode");
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
@@ -498,17 +265,10 @@ usage:
puts(" -- -b Requests big screen");
#endif /* USE_GCU */
-#ifdef USE_SLA
- puts(" -msla To use SLang");
-#endif /* USE_SLA */
-
#ifdef USE_SDL
puts(" -msdl To use SDL");
puts(" -- Sub options");
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");
@@ -539,19 +299,6 @@ usage:
quit_aux = quit_hook;
-#ifdef USE_GLU
- /* Attempt to use the "main-glu.c" support */
- if (!done && (!mstr || (streq(mstr, "glu"))))
- {
- extern errr init_glu(int, char**);
- if (0 == init_glu(argc, argv))
- {
- ANGBAND_SYS = "glu";
- done = TRUE;
- }
- }
-#endif
-
#ifdef USE_GTK2
/* Attempt to use the "main-gtk2.c" support */
if (!done && (!mstr || (streq(mstr, "gtk2"))))
@@ -565,32 +312,6 @@ usage:
}
#endif
-#ifdef USE_GTK
- /* Attempt to use the "main-gtk.c" support */
- if (!done && (!mstr || (streq(mstr, "gtk"))))
- {
- extern errr init_gtk(int, char**);
- if (0 == init_gtk(argc, argv))
- {
- ANGBAND_SYS = "gtk";
- done = TRUE;
- }
- }
-#endif
-
-#ifdef USE_XAW
- /* Attempt to use the "main-xaw.c" support */
- if (!done && (!mstr || (streq(mstr, "xaw"))))
- {
- 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"))))
@@ -617,34 +338,6 @@ usage:
}
#endif
-#ifdef USE_GLU
- /* Attempt to use the "main-glu.c" support */
- if (!done && (!mstr || (streq(mstr, "glu"))))
- {
- extern errr init_glu(int, char**);
- if (0 == init_glu(argc, argv))
- {
- ANGBAND_SYS = "glu";
- done = TRUE;
- }
- }
-#endif
-
-
-#ifdef USE_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"))))
@@ -662,25 +355,15 @@ usage:
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);
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..bb4c06d1 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,34 @@
* included in all such copies.
*/
-#include "angband.h"
-
-
+#include "melee1.hpp"
+
+#include "cave.hpp"
+#include "cmd5.hpp"
+#include "gods.hpp"
+#include "mimic.hpp"
+#include "monster2.hpp"
+#include "monster3.hpp"
+#include "monster_race.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,
@@ -261,7 +282,7 @@ bool_ carried_make_attack_normal(int r_idx)
if (!effect || check_hit(power, rlev))
{
/* Always disturbing */
- disturb(1, 0);
+ disturb(1);
/* Hack -- Apply "protection from evil" */
if ((p_ptr->protevil > 0) &&
@@ -783,7 +804,7 @@ bool_ carried_make_attack_normal(int r_idx)
}
else
{
- if (set_paralyzed(p_ptr->paralyzed + 3 + randint(rlev)))
+ if (set_paralyzed(3 + randint(rlev)))
{
obvious = TRUE;
}
@@ -1280,7 +1301,7 @@ bool_ carried_make_attack_normal(int r_idx)
case RBM_CHARGE:
/* Disturbing */
- disturb(1, 0);
+ disturb(1);
/* Message */
msg_format("%s misses you.", sym_name);
@@ -1329,8 +1350,6 @@ 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;
@@ -1350,7 +1369,8 @@ bool_ make_attack_normal(int m_idx, byte divis)
bool_ touched = FALSE, fear = FALSE, alive = TRUE;
bool_ explode = FALSE;
- /* Not allowed to attack */
+ /* Not allowed to attack? */
+ auto r_ptr = m_ptr->race();
if (r_ptr->flags1 & (RF1_NEVER_BLOW)) return (FALSE);
/* ...nor if friendly */
@@ -1525,7 +1545,7 @@ bool_ make_attack_normal(int m_idx, byte divis)
int chance = p_ptr->dodge_chance - ((rlev * 5) / 6);
/* Always disturbing */
- disturb(1, 0);
+ disturb(1);
if ((chance > 0) && magik(chance))
{
@@ -1536,7 +1556,7 @@ 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;
@@ -1648,7 +1668,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")))
+ if (magik(5) && iequals(r_ptr->name, "vampire"))
do_vampire = TRUE;
touched = TRUE;
sound(SOUND_BITE);
@@ -1774,7 +1794,7 @@ bool_ make_attack_normal(int m_idx, byte divis)
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)];
@@ -1955,7 +1975,7 @@ bool_ make_attack_normal(int m_idx, byte divis)
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;
@@ -2036,7 +2056,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);
@@ -2094,8 +2114,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,43 +2152,7 @@ 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);
}
}
@@ -2418,7 +2401,7 @@ bool_ make_attack_normal(int m_idx, byte divis)
}
else
{
- if (set_paralyzed(p_ptr->paralyzed + 3 + randint(rlev)))
+ if (set_paralyzed(3 + randint(rlev)))
{
obvious = TRUE;
}
@@ -2877,7 +2860,7 @@ bool_ make_attack_normal(int m_idx, byte divis)
{
/* Change to resist(but never total protection) */
/* if (magik(3) || (magik(m_ptr->level - (p_ptr->lev / 2))))
- call_lua("gain_corruption", "(s)", "", "Vampire");*/
+ gain_corruption("Vampire");*/
}
if (explode)
@@ -3011,7 +2994,7 @@ bool_ make_attack_normal(int m_idx, byte divis)
if (m_ptr->ml)
{
/* Disturbing */
- disturb(1, 0);
+ disturb(1);
/* Message */
msg_format("%^s misses you.", m_name);
diff --git a/src/melee1.hpp b/src/melee1.hpp
new file mode 100644
index 00000000..e84c8f03
--- /dev/null
+++ b/src/melee1.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "h-basic.h"
+
+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);
diff --git a/src/melee2.c b/src/melee2.cc
index 6ada6bd0..b3aa5c61 100644
--- a/src/melee2.c
+++ b/src/melee2.cc
@@ -1,27 +1,58 @@
-/* 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 "feature_type.hpp"
+#include "files.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_type.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "options.hpp"
+#include "player_type.hpp"
+#include "quark.hpp"
+#include "skills.hpp"
+#include "spells1.hpp"
+#include "spells2.hpp"
+#include "stats.hpp"
+#include "tables.hpp"
+#include "traps.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
+static void cmonster_msg(char a, cptr fmt, ...);
+
/*
* Based on mon_take_hit... all monster attacks on
* other monsters should use
@@ -30,14 +61,11 @@ 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;
-
/* 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 */
+ /* Some monsters are immune to death */
+ auto const r_ptr = m_ptr->race();
if (r_ptr->flags7 & RF7_NO_DEATH) return FALSE;
/* Wake it up */
@@ -112,13 +140,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 */
@@ -163,7 +191,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,6 +227,7 @@ bool_ mon_take_hit_mon(int s_idx, int m_idx, int dam, bool_ *fear, cptr note)
}
/* Sometimes a monster gets scared by damage */
+ auto const r_ptr = m_ptr->race();
if (!m_ptr->monfear && !(r_ptr->flags3 & (RF3_NO_FEAR)))
{
int percentage;
@@ -197,9 +236,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 +251,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 +278,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,7 +286,7 @@ 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;
@@ -275,7 +303,6 @@ static bool_ int_outof(monster_race *r_ptr, int prob)
static void remove_bad_spells(int m_idx, u32b *f4p, u32b *f5p, u32b *f6p)
{
monster_type *m_ptr = &m_list[m_idx];
- monster_race *r_ptr = race_inf(m_ptr);
u32b f4 = (*f4p);
u32b f5 = (*f5p);
@@ -284,66 +311,26 @@ static void remove_bad_spells(int m_idx, u32b *f4p, u32b *f5p, u32b *f6p)
u32b smart = 0L;
- /* Too stupid to know anything */
+ /* Too stupid to know anything? */
+ auto const r_ptr = m_ptr->race();
if (r_ptr->flags2 & (RF2_STUPID)) return;
/* Must be cheating or learning */
- if (!smart_cheat && !smart_learn) return;
+ if (!smart_learn) return;
/* Update acquired knowledge */
if (smart_learn)
{
/* Hack -- Occasionally forget player status */
- if (m_ptr->smart && (rand_int(100) < 1)) m_ptr->smart = 0L;
+ if (m_ptr->smart && magik(1)) m_ptr->smart = 0L;
/* Use the memorized flags */
smart = m_ptr->smart;
}
- /* Cheat if requested */
- if (smart_cheat)
- {
- /* 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);
- }
-
-
/* Nothing known */
if (!smart) return;
@@ -771,7 +758,6 @@ static bool_ spell_heal(byte spell)
static int choose_attack_spell(int m_idx, byte spells[], byte num)
{
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;
@@ -781,9 +767,8 @@ static int choose_attack_spell(int m_idx, byte spells[], byte num)
byte haste[96], haste_num = 0;
byte heal[96], heal_num = 0;
- int i;
-
/* Stupid monsters choose randomly */
+ auto const r_ptr = m_ptr->race();
if (r_ptr->flags2 & (RF2_STUPID))
{
/* Pick at random */
@@ -791,7 +776,7 @@ static int choose_attack_spell(int m_idx, byte spells[], byte num)
}
/* Categorize spells */
- for (i = 0; i < num; i++)
+ for (int i = 0; i < num; i++)
{
/* Escape spell? */
if (spell_escape(spells[i])) escape[escape_num++] = spells[i];
@@ -895,7 +880,7 @@ 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;
@@ -915,7 +900,7 @@ 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;
@@ -937,7 +922,7 @@ static void monst_bolt_monst(int m_idx, int y, int x, int typ, int dam_hp)
}
-void monster_msg(cptr fmt, ...)
+static void monster_msg(cptr fmt, ...)
{
va_list vp;
@@ -952,12 +937,20 @@ void monster_msg(cptr fmt, ...)
/* End the Varargs Stuff */
va_end(vp);
+ /* Print */
+ monster_msg_simple(buf);
+}
+
+void monster_msg_simple(cptr s)
+{
/* Display */
if (disturb_other)
- msg_print(buf);
+ {
+ msg_print(s);
+ }
else
{
- message_add(MESSAGE_MSG, buf, TERM_WHITE);
+ message_add(s, TERM_WHITE);
p_ptr->window |= PW_MESSAGE;
}
}
@@ -982,7 +975,7 @@ void cmonster_msg(char a, cptr fmt, ...)
cmsg_print(a, buf);
else
{
- message_add(MESSAGE_MSG, buf, a);
+ message_add(buf, a);
p_ptr->window |= PW_MESSAGE;
}
}
@@ -996,17 +989,13 @@ int monst_spell_monst_spell = -1;
static bool_ monst_spell_monst(int m_idx)
{
int y = 0, x = 0;
- int i = 1, k, t_idx;
- int chance, thrown_spell, count = 0;
+ int i = 1;
+ int thrown_spell;
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,7 +1019,8 @@ 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);
@@ -1050,9 +1040,10 @@ static bool_ monst_spell_monst(int m_idx)
{
- t_idx = i;
- t_ptr = &m_list[t_idx];
- tr_ptr = race_inf(t_ptr);
+ int t_idx = i;
+
+ 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,7 +1056,7 @@ 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;
@@ -1087,19 +1078,19 @@ static bool_ monst_spell_monst(int m_idx)
}
/* Extract the "inate" spells */
- for (k = 0; k < 32; k++)
+ for (int k = 0; k < 32; k++)
{
if (f4 & (1L << k)) spell[num++] = k + 32 * 3;
}
/* Extract the "normal" spells */
- for (k = 0; k < 32; k++)
+ for (int k = 0; k < 32; k++)
{
if (f5 & (1L << k)) spell[num++] = k + 32 * 4;
}
/* Extract the "bizarre" spells */
- for (k = 0; k < 32; k++)
+ for (int k = 0; k < 32; k++)
{
if (f6 & (1L << k)) spell[num++] = k + 32 * 5;
}
@@ -1140,13 +1131,14 @@ static bool_ monst_spell_monst(int m_idx)
see_either = (see_m || see_t);
see_both = (see_m && see_t);
+ int count = 0;
switch (thrown_spell)
{
/* RF4_SHRIEK */
case 96 + 0:
{
if (!direct) break;
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!see_m) monster_msg("You hear a shriek.");
else monster_msg("%^s shrieks at %s.", m_name, t_name);
wake_up = TRUE;
@@ -1162,10 +1154,10 @@ static bool_ monst_spell_monst(int m_idx)
/* RF4_S_ANIMAL */
case 96 + 2:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s magically summons an animal!", m_name);
- for (k = 0; k < 1; k++)
+ for (int k = 0; k < 1; k++)
{
if (friendly)
count += summon_specific_friendly(y, x, rlev, SUMMON_ANIMAL, TRUE);
@@ -1179,7 +1171,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF4_ROCKET */
case 96 + 3:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!see_either) monster_msg("You hear an explosion!");
else if (blind) monster_msg("%^s shoots something.", m_name);
else monster_msg("%^s fires a rocket at %s.", m_name, t_name);
@@ -1191,7 +1183,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF4_ARROW_1 */
case 96 + 4:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!see_either) monster_msg("You hear a strange noise.");
else if (blind) monster_msg("%^s makes a strange noise.", m_name);
else monster_msg("%^s fires an arrow at %s.", m_name, t_name);
@@ -1203,7 +1195,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF4_ARROW_2 */
case 96 + 5:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!see_either) monster_msg("You hear a strange noise.");
else if (blind) monster_msg("%^s makes a strange noise.", m_name);
else monster_msg("%^s fires an arrow at %s.", m_name, t_name);
@@ -1215,7 +1207,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF4_ARROW_3 */
case 96 + 6:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!see_either) monster_msg("You hear a strange noise.");
else if (blind) monster_msg("%^s makes a strange noise.", m_name);
@@ -1229,7 +1221,7 @@ static bool_ monst_spell_monst(int m_idx)
case 96 + 7:
{
if (!see_either) monster_msg("You hear a strange noise.");
- else if (disturb_other) disturb(1, 0);
+ else if (disturb_other) disturb(1);
if (blind) monster_msg("%^s makes a strange noise.", m_name);
else monster_msg("%^s fires a missile at %s.", m_name, t_name);
sound(SOUND_SHOOT);
@@ -1240,7 +1232,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF4_BR_ACID */
case 96 + 8:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!see_either) monster_msg("You hear breathing noise.");
else if (blind) monster_msg("%^s breathes.", m_name);
else monster_msg("%^s breathes acid at %s.", m_name, t_name);
@@ -1253,7 +1245,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF4_BR_ELEC */
case 96 + 9:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!see_either) monster_msg("You hear breathing noise.");
else if (blind) monster_msg("%^s breathes.", m_name);
else monster_msg("%^s breathes lightning at %s.", m_name, t_name);
@@ -1266,7 +1258,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF4_BR_FIRE */
case 96 + 10:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!see_either) monster_msg("You hear breathing noise.");
else if (blind) monster_msg("%^s breathes.", m_name);
else monster_msg("%^s breathes fire at %s.", m_name, t_name);
@@ -1279,7 +1271,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF4_BR_COLD */
case 96 + 11:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!see_either) monster_msg("You hear breathing noise.");
else if (blind) monster_msg("%^s breathes.", m_name);
else monster_msg("%^s breathes frost at %s.", m_name, t_name);
@@ -1292,7 +1284,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF4_BR_POIS */
case 96 + 12:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!see_either) monster_msg("You hear breathing noise.");
else if (blind) monster_msg("%^s breathes.", m_name);
else monster_msg("%^s breathes gas at %s.", m_name, t_name);
@@ -1305,7 +1297,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF4_BR_NETH */
case 96 + 13:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!see_either) monster_msg("You hear breathing noise.");
else if (blind) monster_msg("%^s breathes.", m_name);
else monster_msg("%^s breathes nether at %s.", m_name, t_name);
@@ -1318,7 +1310,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF4_BR_LITE */
case 96 + 14:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!see_either) monster_msg("You hear breathing noise.");
else if (blind) monster_msg("%^s breathes.", m_name);
else monster_msg("%^s breathes light at %s.", m_name, t_name);
@@ -1331,7 +1323,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF4_BR_DARK */
case 96 + 15:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!see_either) monster_msg("You hear breathing noise.");
else if (blind) monster_msg("%^s breathes.", m_name);
else monster_msg("%^s breathes darkness at %s.", m_name, t_name);
@@ -1344,7 +1336,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF4_BR_CONF */
case 96 + 16:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!see_either) monster_msg("You hear breathing noise.");
else if (blind) monster_msg("%^s breathes.", m_name);
else monster_msg("%^s breathes confusion at %s.", m_name, t_name);
@@ -1357,7 +1349,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF4_BR_SOUN */
case 96 + 17:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!see_either) monster_msg("You hear breathing noise.");
else if (blind) monster_msg("%^s breathes.", m_name);
else monster_msg("%^s breathes sound at %s.", m_name, t_name);
@@ -1370,7 +1362,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF4_BR_CHAO */
case 96 + 18:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!see_either) monster_msg("You hear breathing noise.");
else if (blind) monster_msg("%^s breathes.", m_name);
else monster_msg("%^s breathes chaos at %s.", m_name, t_name);
@@ -1383,7 +1375,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF4_BR_DISE */
case 96 + 19:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!see_either) monster_msg("You hear breathing noise.");
else if (blind) monster_msg("%^s breathes.", m_name);
else monster_msg("%^s breathes disenchantment at %s.", m_name, t_name);
@@ -1396,7 +1388,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF4_BR_NEXU */
case 96 + 20:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!see_either) monster_msg("You hear breathing noise.");
else if (blind) monster_msg("%^s breathes.", m_name);
else monster_msg("%^s breathes nexus at %s.", m_name, t_name);
@@ -1409,7 +1401,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF4_BR_TIME */
case 96 + 21:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!see_either) monster_msg("You hear breathing noise.");
else if (blind) monster_msg("%^s breathes.", m_name);
else monster_msg("%^s breathes time at %s.", m_name, t_name);
@@ -1422,7 +1414,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF4_BR_INER */
case 96 + 22:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!see_either) monster_msg("You hear breathing noise.");
else if (blind) monster_msg("%^s breathes.", m_name);
else monster_msg("%^s breathes inertia at %s.", m_name, t_name);
@@ -1435,7 +1427,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF4_BR_GRAV */
case 96 + 23:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!see_either) monster_msg("You hear breathing noise.");
else if (blind) monster_msg("%^s breathes.", m_name);
else monster_msg("%^s breathes gravity at %s.", m_name, t_name);
@@ -1448,7 +1440,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF4_BR_SHAR */
case 96 + 24:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!see_either) monster_msg("You hear breathing noise.");
else if (blind) monster_msg("%^s breathes.", m_name);
else monster_msg("%^s breathes shards at %s.", m_name, t_name);
@@ -1461,7 +1453,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF4_BR_PLAS */
case 96 + 25:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!see_either) monster_msg("You hear breathing noise.");
else if (blind) monster_msg("%^s breathes.", m_name);
else monster_msg("%^s breathes plasma at %s.", m_name, t_name);
@@ -1474,7 +1466,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF4_BR_WALL */
case 96 + 26:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!see_either) monster_msg("You hear breathing noise.");
else if (blind) monster_msg("%^s breathes.", m_name);
else monster_msg("%^s breathes force at %s.", m_name, t_name);
@@ -1487,7 +1479,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF4_BR_MANA */
case 96 + 27:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!see_either) monster_msg("You hear breathing noise.");
else if (blind) monster_msg("%^s breathes.", m_name);
else monster_msg("%^s breathes magical energy at %s.", m_name, t_name);
@@ -1500,7 +1492,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF4_BA_NUKE */
case 96 + 28:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!see_either) monster_msg("You hear someone mumble.");
else if (blind) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s casts a ball of radiation at %s.", m_name, t_name);
@@ -1513,7 +1505,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF4_BR_NUKE */
case 96 + 29:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!see_either) monster_msg("You hear breathing noise.");
else if (blind) monster_msg("%^s breathes.", m_name);
else monster_msg("%^s breathes toxic waste at %s.", m_name, t_name);
@@ -1526,7 +1518,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF4_BA_CHAO */
case 96 + 30:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!see_either) monster_msg("You hear someone mumble frighteningly.");
else if (blind) monster_msg("%^s mumbles frighteningly.", m_name);
else monster_msg("%^s invokes a raw Chaos upon %s.", m_name, t_name);
@@ -1539,7 +1531,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF4_BR_DISI -> Breathe Disintegration */
case 96 + 31:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!see_either) monster_msg("You hear breathing noise.");
else if (blind) monster_msg("%^s breathes.", m_name);
else monster_msg("%^s breathes disintegration at %s.", m_name, t_name);
@@ -1552,7 +1544,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF5_BA_ACID */
case 128 + 0:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!see_either) monster_msg ("You hear someone mumble.");
else if (blind) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s casts an acid ball at %s.", m_name, t_name);
@@ -1563,7 +1555,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF5_BA_ELEC */
case 128 + 1:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!see_either) monster_msg ("You hear someone mumble.");
else
if (blind) monster_msg("%^s mumbles.", m_name);
@@ -1575,7 +1567,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF5_BA_FIRE */
case 128 + 2:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!see_either) monster_msg ("You hear someone mumble.");
else
if (blind) monster_msg("%^s mumbles.", m_name);
@@ -1587,7 +1579,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF5_BA_COLD */
case 128 + 3:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!see_either) monster_msg ("You hear someone mumble.");
else
if (blind) monster_msg("%^s mumbles.", m_name);
@@ -1599,7 +1591,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF5_BA_POIS */
case 128 + 4:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!see_either) monster_msg ("You hear someone mumble.");
else
if (blind) monster_msg("%^s mumbles.", m_name);
@@ -1611,7 +1603,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF5_BA_NETH */
case 128 + 5:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!see_either) monster_msg ("You hear someone mumble.");
else
if (blind) monster_msg("%^s mumbles.", m_name);
@@ -1623,7 +1615,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF5_BA_WATE */
case 128 + 6:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!see_either) monster_msg ("You hear someone mumble.");
else
if (blind) monster_msg("%^s mumbles.", m_name);
@@ -1636,7 +1628,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF5_BA_MANA */
case 128 + 7:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!see_either) monster_msg ("You hear someone mumble powerfully.");
else
if (blind) monster_msg("%^s mumbles powerfully.", m_name);
@@ -1648,7 +1640,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF5_BA_DARK */
case 128 + 8:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!see_either) monster_msg ("You hear someone mumble powerfully.");
else
if (blind) monster_msg("%^s mumbles powerfully.", m_name);
@@ -1684,7 +1676,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)
@@ -1703,7 +1695,7 @@ static bool_ monst_spell_monst(int m_idx)
{
if (!direct) break;
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!seen)
{
@@ -1748,7 +1740,7 @@ static bool_ monst_spell_monst(int m_idx)
case 128 + 11:
{
if (!direct) break;
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!seen)
{
/* */
@@ -1794,7 +1786,7 @@ static bool_ monst_spell_monst(int m_idx)
case 128 + 12:
{
if (!direct) break;
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s points at %s and curses.", m_name, t_name);
if (t_ptr->level > randint((rlev - 10) < 1 ? 1 : (rlev - 10)) + 10)
@@ -1815,7 +1807,7 @@ static bool_ monst_spell_monst(int m_idx)
case 128 + 13:
{
if (!direct) break;
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s points at %s and curses horribly.", m_name, t_name);
if (t_ptr->level > randint((rlev - 10) < 1 ? 1 : (rlev - 10)) + 10)
@@ -1835,7 +1827,7 @@ static bool_ monst_spell_monst(int m_idx)
case 128 + 14:
{
if (!direct) break;
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s points at %s, incanting terribly!", m_name, t_name);
if (t_ptr->level > randint((rlev - 10) < 1 ? 1 : (rlev - 10)) + 10)
@@ -1855,7 +1847,7 @@ static bool_ monst_spell_monst(int m_idx)
case 128 + 15:
{
if (!direct) break;
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s points at %s, screaming the word 'DIE!'", m_name, t_name);
if (t_ptr->level > randint((rlev - 10) < 1 ? 1 : (rlev - 10)) + 10)
@@ -1874,7 +1866,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF5_BO_ACID */
case 128 + 16:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s casts an acid bolt at %s.", m_name, t_name);
monst_bolt_monst(m_idx, y, x, GF_ACID,
@@ -1885,7 +1877,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF5_BO_ELEC */
case 128 + 17:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s casts a lightning bolt at %s.", m_name, t_name);
monst_bolt_monst(m_idx, y, x, GF_ELEC,
@@ -1896,7 +1888,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF5_BO_FIRE */
case 128 + 18:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s casts a fire bolt at %s.", m_name, t_name);
monst_bolt_monst(m_idx, y, x, GF_FIRE,
@@ -1907,7 +1899,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF5_BO_COLD */
case 128 + 19:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s casts a frost bolt at %s.", m_name, t_name);
monst_bolt_monst(m_idx, y, x, GF_COLD,
@@ -1925,7 +1917,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF5_BO_NETH */
case 128 + 21:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s casts a nether bolt at %s.", m_name, t_name);
monst_bolt_monst(m_idx, y, x, GF_NETHER,
@@ -1936,7 +1928,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF5_BO_WATE */
case 128 + 22:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s casts a water bolt at %s.", m_name, t_name);
monst_bolt_monst(m_idx, y, x, GF_WATER,
@@ -1947,7 +1939,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF5_BO_MANA */
case 128 + 23:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s casts a mana bolt at %s.", m_name, t_name);
monst_bolt_monst(m_idx, y, x, GF_MANA,
@@ -1958,7 +1950,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF5_BO_PLAS */
case 128 + 24:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s casts a plasma bolt at %s.", m_name, t_name);
monst_bolt_monst(m_idx, y, x, GF_PLASMA,
@@ -1969,7 +1961,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF5_BO_ICEE */
case 128 + 25:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s casts an ice bolt at %s.", m_name, t_name);
monst_bolt_monst(m_idx, y, x, GF_ICE,
@@ -1980,7 +1972,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF5_MISSILE */
case 128 + 26:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s casts a magic missile at %s.", m_name, t_name);
monst_bolt_monst(m_idx, y, x, GF_MISSILE,
@@ -1992,7 +1984,7 @@ static bool_ monst_spell_monst(int m_idx)
case 128 + 27:
{
if (!direct) break;
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles, and you hear scary noises.", m_name);
else monster_msg("%^s casts a fearful illusion at %s.", m_name, t_name);
if (tr_ptr->flags3 & RF3_NO_FEAR)
@@ -2016,7 +2008,7 @@ static bool_ monst_spell_monst(int m_idx)
case 128 + 28:
{
if (!direct) break;
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s casts a spell, burning %s%s eyes.", m_name, t_name,
(!strcmp(t_name, "it") ? "s" : "'s"));
@@ -2042,7 +2034,7 @@ static bool_ monst_spell_monst(int m_idx)
case 128 + 29:
{
if (!direct) break;
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles, and you hear puzzling noises.", m_name);
else monster_msg("%^s creates a mesmerising illusion in front of %s.", m_name, t_name);
if (tr_ptr->flags3 & RF3_NO_CONF)
@@ -2066,7 +2058,7 @@ static bool_ monst_spell_monst(int m_idx)
case 128 + 30:
{
if (!direct) break;
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!blind && see_either) monster_msg("%^s drains power from %s%s muscles.", m_name, t_name,
(!strcmp(t_name, "it") ? "s" : "'s"));
if (tr_ptr->flags1 & RF1_UNIQUE)
@@ -2090,7 +2082,7 @@ static bool_ monst_spell_monst(int m_idx)
case 128 + 31:
{
if (!direct) break;
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!blind && see_m) monster_msg("%^s stares intently at %s.", m_name, t_name);
if ((tr_ptr->flags1 & RF1_UNIQUE) ||
(tr_ptr->flags3 & RF3_NO_STUN))
@@ -2114,7 +2106,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_HASTE */
case 160 + 0:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m)
{
monster_msg("%^s mumbles.", m_name);
@@ -2145,7 +2137,7 @@ static bool_ monst_spell_monst(int m_idx)
case 160 + 1:
{
if (!direct) break;
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (!see_m) monster_msg("You hear someone invoke the Hand of Doom!");
else if (!blind) monster_msg("%^s invokes the Hand of Doom on %s.", m_name, t_name);
else
@@ -2176,7 +2168,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_HEAL */
case 160 + 2:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
/* Message */
if (blind || !see_m)
@@ -2223,7 +2215,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)
@@ -2241,10 +2233,10 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_S_ANIMALS */
case 160 + 3:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s magically summons some animals!", m_name);
- for (k = 0; k < 4; k++)
+ for (int k = 0; k < 4; k++)
{
if (friendly)
count += summon_specific_friendly(y, x, rlev, SUMMON_ANIMAL, TRUE);
@@ -2258,7 +2250,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_BLINK */
case 160 + 4:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (see_m) monster_msg("%^s blinks away.", m_name);
teleport_away(m_idx, 10);
break;
@@ -2270,7 +2262,7 @@ static bool_ monst_spell_monst(int m_idx)
if (dungeon_flags2 & DF2_NO_TELEPORT) break; /* No teleport on special levels */
else
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (see_m) monster_msg("%^s teleports away.", m_name);
teleport_away(m_idx, MAX_SIGHT * 2 + 5);
break;
@@ -2293,7 +2285,7 @@ static bool_ monst_spell_monst(int m_idx)
else
{
bool_ resists_tele = FALSE;
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
monster_msg("%^s teleports %s away.", m_name, t_name);
@@ -2339,7 +2331,7 @@ static bool_ monst_spell_monst(int m_idx)
case 160 + 9:
{
if (!direct) break;
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s gestures in shadow.", m_name);
if (seen)
@@ -2373,10 +2365,10 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_S_BUG */
case 160 + 13:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s magically codes some software bugs.", m_name);
- for (k = 0; k < 6; k++)
+ for (int k = 0; k < 6; k++)
{
if (friendly)
count += summon_specific_friendly(y, x, rlev, SUMMON_BUG, TRUE);
@@ -2390,10 +2382,10 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_S_RNG */
case 160 + 14:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s magically codes some RNGs.", m_name);
- for (k = 0; k < 6; k++)
+ for (int k = 0; k < 6; k++)
{
if (friendly)
count += summon_specific_friendly(y, x, rlev, SUMMON_RNG, TRUE);
@@ -2408,10 +2400,10 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_S_THUNDERLORD */
case 160 + 15:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s magically summons a Thunderlord!", m_name);
- for (k = 0; k < 1; k++)
+ for (int k = 0; k < 1; k++)
{
if (friendly)
count += summon_specific_friendly(y, x, rlev, SUMMON_THUNDERLORD, TRUE);
@@ -2425,14 +2417,14 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_SUMMON_KIN */
case 160 + 16:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s magically summons %s %s.",
m_name, m_poss,
((r_ptr->flags1) & RF1_UNIQUE ?
"minions" : "kin"));
summon_kin_type = r_ptr->d_char; /* Big hack */
- for (k = 0; k < 6; k++)
+ for (int k = 0; k < 6; k++)
{
if (friendly)
count += summon_specific_friendly(y, x, rlev, SUMMON_KIN, TRUE);
@@ -2448,7 +2440,7 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_S_HI_DEMON */
case 160 + 17:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s magically summons greater demons!", m_name);
if (blind && count) monster_msg("You hear heavy steps nearby.");
@@ -2462,10 +2454,10 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_S_MONSTER */
case 160 + 18:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s magically summons help!", m_name);
- for (k = 0; k < 1; k++)
+ for (int k = 0; k < 1; k++)
{
if (friendly)
count += summon_specific_friendly(y, x, rlev, SUMMON_NO_UNIQUES, TRUE);
@@ -2479,10 +2471,10 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_S_MONSTERS */
case 160 + 19:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s magically summons monsters!", m_name);
- for (k = 0; k < 8; k++)
+ for (int k = 0; k < 8; k++)
{
if (friendly)
count += summon_specific_friendly(y, x, rlev, SUMMON_NO_UNIQUES, TRUE);
@@ -2496,10 +2488,10 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_S_ANT */
case 160 + 20:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s magically summons ants.", m_name);
- for (k = 0; k < 6; k++)
+ for (int k = 0; k < 6; k++)
{
if (friendly)
count += summon_specific_friendly(y, x, rlev, SUMMON_ANT, TRUE);
@@ -2513,10 +2505,10 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_S_SPIDER */
case 160 + 21:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s magically summons spiders.", m_name);
- for (k = 0; k < 6; k++)
+ for (int k = 0; k < 6; k++)
{
if (friendly)
count += summon_specific_friendly(y, x, rlev, SUMMON_SPIDER, TRUE);
@@ -2530,10 +2522,10 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_S_HOUND */
case 160 + 22:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s magically summons hounds.", m_name);
- for (k = 0; k < 6; k++)
+ for (int k = 0; k < 6; k++)
{
if (friendly)
count += summon_specific_friendly(y, x, rlev, SUMMON_HOUND, TRUE);
@@ -2547,10 +2539,10 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_S_HYDRA */
case 160 + 23:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s magically summons hydras.", m_name);
- for (k = 0; k < 6; k++)
+ for (int k = 0; k < 6; k++)
{
if (friendly)
count += summon_specific_friendly(y, x, rlev, SUMMON_HYDRA, TRUE);
@@ -2564,10 +2556,10 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_S_ANGEL */
case 160 + 24:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s magically summons an angel!", m_name);
- for (k = 0; k < 1; k++)
+ for (int k = 0; k < 1; k++)
{
if (friendly)
count += summon_specific_friendly(y, x, rlev, SUMMON_ANGEL, TRUE);
@@ -2581,10 +2573,10 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_S_DEMON */
case 160 + 25:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s magically summons a demon!", m_name);
- for (k = 0; k < 1; k++)
+ for (int k = 0; k < 1; k++)
{
if (friendly)
count += summon_specific_friendly(y, x, rlev, SUMMON_DEMON, TRUE);
@@ -2598,10 +2590,10 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_S_UNDEAD */
case 160 + 26:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s magically summons an undead adversary!", m_name);
- for (k = 0; k < 1; k++)
+ for (int k = 0; k < 1; k++)
{
if (friendly)
count += summon_specific_friendly(y, x, rlev, SUMMON_UNDEAD, TRUE);
@@ -2615,10 +2607,10 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_S_DRAGON */
case 160 + 27:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s magically summons a dragon!", m_name);
- for (k = 0; k < 1; k++)
+ for (int k = 0; k < 1; k++)
{
if (friendly)
count += summon_specific_friendly(y, x, rlev, SUMMON_DRAGON, TRUE);
@@ -2632,10 +2624,10 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_S_HI_UNDEAD */
case 160 + 28:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s magically summons greater undead!", m_name);
- for (k = 0; k < 8; k++)
+ for (int k = 0; k < 8; k++)
{
if (friendly)
count += summon_specific_friendly(y, x, rlev, SUMMON_HI_UNDEAD_NO_UNIQUES, TRUE);
@@ -2652,10 +2644,10 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_S_HI_DRAGON */
case 160 + 29:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s magically summons ancient dragons!", m_name);
- for (k = 0; k < 8; k++)
+ for (int k = 0; k < 8; k++)
{
if (friendly)
count += summon_specific_friendly(y, x, rlev, SUMMON_HI_DRAGON_NO_UNIQUES, TRUE);
@@ -2672,12 +2664,12 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_S_WRAITH */
case 160 + 30:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s magically summons a wraith!", m_name);
- for (k = 0; k < 8; k++)
+ for (int k = 0; k < 8; k++)
{
count += summon_specific(y, x, rlev, SUMMON_WRAITH);
}
@@ -2692,15 +2684,15 @@ static bool_ monst_spell_monst(int m_idx)
/* RF6_S_UNIQUE */
case 160 + 31:
{
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
if (blind || !see_m) monster_msg("%^s mumbles.", m_name);
else monster_msg("%^s magically summons special opponents!", m_name);
- for (k = 0; k < 8; k++)
+ for (int k = 0; k < 8; k++)
{
if (!friendly)
count += summon_specific(y, x, 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);
@@ -2896,14 +2888,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 +2901,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,13 +2909,11 @@ 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);
char m_name[80];
bool_ no_inate = FALSE;
int x, y;
@@ -2948,15 +2924,15 @@ bool_ make_attack_spell(int m_idx)
/* 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)
{
@@ -2980,6 +2956,7 @@ 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 ... */
+ auto const r_ptr = m_ptr->race();
if ((r_ptr->flags7 & RF7_MORTAL) && (p_ptr->no_mortal)) return (FALSE);
/* Hack -- Extract the spell probability */
@@ -2988,21 +2965,11 @@ bool_ make_attack_spell(int m_idx)
/* Not allowed to cast spells */
if (!chance) return (FALSE);
- if (stupid_monsters)
- {
- /* Only do spells occasionally */
- if (rand_int(100) >= chance) return (FALSE);
- }
- else
- {
- if (rand_int(100) >= chance) return (FALSE);
-
- /* Sometimes forbid inate attacks (breaths) */
- if (rand_int(100) >= (chance * 2)) no_inate = TRUE;
- }
-
- /* XXX XXX XXX Handle "track_target" option (?) */
+ /* Only do spells occasionally */
+ if (rand_int(100) >= chance) return (FALSE);
+ /* Sometimes forbid inate attacks (breaths) */
+ if (rand_int(100) >= (chance * 2)) no_inate = TRUE;
/* Hack -- require projectable player */
if (normal)
@@ -3022,11 +2989,8 @@ bool_ make_attack_spell(int m_idx)
f5 = r_ptr->flags5;
f6 = r_ptr->flags6;
- if (!stupid_monsters)
- {
- /* Forbid inate attacks sometimes */
- if (no_inate) f4 = 0L;
- }
+ /* Forbid inate attacks sometimes */
+ if (no_inate) f4 = 0L;
/* Hack -- allow "desperate" spells */
if ((r_ptr->flags2 & (RF2_SMART)) &&
@@ -3048,36 +3012,33 @@ bool_ make_attack_spell(int m_idx)
/* No spells left */
if (!f4 && !f5 && !f6) return (FALSE);
- if (!stupid_monsters)
+ /* Check for a clean bolt shot */
+ if ((f4&(RF4_BOLT_MASK) || f5 & (RF5_BOLT_MASK) ||
+ f6&(RF6_BOLT_MASK)) &&
+ !(r_ptr->flags2 & (RF2_STUPID)) &&
+ !clean_shot(m_ptr->fy, m_ptr->fx, y, x))
{
- /* Check for a clean bolt shot */
- if ((f4&(RF4_BOLT_MASK) || f5 & (RF5_BOLT_MASK) ||
- f6&(RF6_BOLT_MASK)) &&
- !(r_ptr->flags2 & (RF2_STUPID)) &&
- !clean_shot(m_ptr->fy, m_ptr->fx, y, x))
- {
- /* Remove spells that will only hurt friends */
- f4 &= ~(RF4_BOLT_MASK);
- f5 &= ~(RF5_BOLT_MASK);
- f6 &= ~(RF6_BOLT_MASK);
- }
-
- /* Check for a possible summon */
- if ((f4 & (RF4_SUMMON_MASK) || f5 & (RF5_SUMMON_MASK) ||
- f6 & (RF6_SUMMON_MASK)) &&
- !(r_ptr->flags2 & (RF2_STUPID)) &&
- !(summon_possible(y, x)))
- {
- /* Remove summoning spells */
- f4 &= ~(RF4_SUMMON_MASK);
- f5 &= ~(RF5_SUMMON_MASK);
- f6 &= ~(RF6_SUMMON_MASK);
- }
+ /* Remove spells that will only hurt friends */
+ f4 &= ~(RF4_BOLT_MASK);
+ f5 &= ~(RF5_BOLT_MASK);
+ f6 &= ~(RF6_BOLT_MASK);
+ }
- /* No spells left */
- if (!f4 && !f5 && !f6) return (FALSE);
+ /* Check for a possible summon */
+ if ((f4 & (RF4_SUMMON_MASK) || f5 & (RF5_SUMMON_MASK) ||
+ f6 & (RF6_SUMMON_MASK)) &&
+ !(r_ptr->flags2 & (RF2_STUPID)) &&
+ !(summon_possible(y, x)))
+ {
+ /* Remove summoning spells */
+ f4 &= ~(RF4_SUMMON_MASK);
+ f5 &= ~(RF5_SUMMON_MASK);
+ f6 &= ~(RF6_SUMMON_MASK);
}
+ /* No spells left */
+ if (!f4 && !f5 && !f6) return (FALSE);
+
/* Extract the "inate" spells */
for (k = 0; k < 32; k++)
{
@@ -3108,32 +3069,25 @@ bool_ make_attack_spell(int m_idx)
/* Get the monster name (or "it") */
monster_desc(m_name, m_ptr, 0x00);
- if (stupid_monsters)
- {
- /* Choose a spell to cast */
- thrown_spell = spell[rand_int(num)];
- }
- else
- {
- thrown_spell = choose_attack_spell(m_idx, spell, num);
+ /* Choose a spell to cast */
+ thrown_spell = choose_attack_spell(m_idx, spell, num);
- /* Abort if no spell was chosen */
- if (!thrown_spell) return (FALSE);
+ /* Abort if no spell was chosen */
+ if (!thrown_spell) return (FALSE);
- /* Calculate spell failure rate */
- failrate = 25 - (rlev + 3) / 4;
+ /* Calculate spell failure rate */
+ failrate = 25 - (rlev + 3) / 4;
- /* Hack -- Stupid monsters will never fail (for jellies and such) */
- if (r_ptr->flags2 & (RF2_STUPID)) failrate = 0;
+ /* Hack -- Stupid monsters will never fail (for jellies and such) */
+ if (r_ptr->flags2 & (RF2_STUPID)) failrate = 0;
- /* Check for spell failure (inate attacks never fail) */
- if ((thrown_spell >= 128) && (rand_int(100) < failrate))
- {
- /* Message */
- msg_format("%^s tries to cast a spell, but fails.", m_name);
+ /* Check for spell failure (inate attacks never fail) */
+ if ((thrown_spell >= 128) && (rand_int(100) < failrate))
+ {
+ /* Message */
+ msg_format("%^s tries to cast a spell, but fails.", m_name);
- return (TRUE);
- }
+ return (TRUE);
}
/* Can the player disrupt its puny attempts? */
@@ -3163,8 +3117,7 @@ bool_ make_attack_spell(int m_idx)
/* RF4_SHRIEK */
case 96 + 0:
{
- if (!direct) break;
- disturb(1, 0);
+ disturb(1);
msg_format("%^s makes a high pitched shriek.", m_name);
aggravate_monsters(m_idx);
break;
@@ -3179,7 +3132,7 @@ bool_ make_attack_spell(int m_idx)
/* RF4_S_ANIMAL */
case 96 + 2:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s magically summons an animal!", m_name);
for (k = 0; k < 1; k++)
@@ -3193,7 +3146,7 @@ bool_ make_attack_spell(int m_idx)
/* RF4_ROCKET */
case 96 + 3:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s shoots something.", m_name);
else msg_format("%^s fires a rocket.", m_name);
breath(m_idx, GF_ROCKET,
@@ -3205,7 +3158,7 @@ bool_ make_attack_spell(int m_idx)
/* RF4_ARROW_1 */
case 96 + 4:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s makes a strange noise.", m_name);
else msg_format("%^s fires an arrow.", m_name);
bolt(m_idx, GF_ARROW, damroll(1, 6));
@@ -3216,7 +3169,7 @@ bool_ make_attack_spell(int m_idx)
/* RF4_ARROW_2 */
case 96 + 5:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s makes a strange noise.", m_name);
else msg_format("%^s fires an arrow!", m_name);
bolt(m_idx, GF_ARROW, damroll(3, 6));
@@ -3227,7 +3180,7 @@ bool_ make_attack_spell(int m_idx)
/* RF4_ARROW_3 */
case 96 + 6:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s makes a strange noise.", m_name);
else msg_format("%^s fires a missile.", m_name);
bolt(m_idx, GF_ARROW, damroll(5, 6));
@@ -3238,7 +3191,7 @@ bool_ make_attack_spell(int m_idx)
/* RF4_ARROW_4 */
case 96 + 7:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s makes a strange noise.", m_name);
else msg_format("%^s fires a missile!", m_name);
bolt(m_idx, GF_ARROW, damroll(7, 6));
@@ -3249,7 +3202,7 @@ bool_ make_attack_spell(int m_idx)
/* RF4_BR_ACID */
case 96 + 8:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s breathes.", m_name);
else msg_format("%^s breathes acid.", m_name);
breath(m_idx, GF_ACID,
@@ -3261,7 +3214,7 @@ bool_ make_attack_spell(int m_idx)
/* RF4_BR_ELEC */
case 96 + 9:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s breathes.", m_name);
else msg_format("%^s breathes lightning.", m_name);
breath(m_idx, GF_ELEC,
@@ -3273,7 +3226,7 @@ bool_ make_attack_spell(int m_idx)
/* RF4_BR_FIRE */
case 96 + 10:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s breathes.", m_name);
else msg_format("%^s breathes fire.", m_name);
breath(m_idx, GF_FIRE,
@@ -3285,7 +3238,7 @@ bool_ make_attack_spell(int m_idx)
/* RF4_BR_COLD */
case 96 + 11:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s breathes.", m_name);
else msg_format("%^s breathes frost.", m_name);
breath(m_idx, GF_COLD,
@@ -3297,7 +3250,7 @@ bool_ make_attack_spell(int m_idx)
/* RF4_BR_POIS */
case 96 + 12:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s breathes.", m_name);
else msg_format("%^s breathes gas.", m_name);
breath(m_idx, GF_POIS,
@@ -3310,7 +3263,7 @@ bool_ make_attack_spell(int m_idx)
/* RF4_BR_NETH */
case 96 + 13:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s breathes.", m_name);
else msg_format("%^s breathes nether.", m_name);
breath(m_idx, GF_NETHER,
@@ -3322,7 +3275,7 @@ bool_ make_attack_spell(int m_idx)
/* RF4_BR_LITE */
case 96 + 14:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s breathes.", m_name);
else msg_format("%^s breathes light.", m_name);
breath(m_idx, GF_LITE,
@@ -3334,7 +3287,7 @@ bool_ make_attack_spell(int m_idx)
/* RF4_BR_DARK */
case 96 + 15:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s breathes.", m_name);
else msg_format("%^s breathes darkness.", m_name);
breath(m_idx, GF_DARK,
@@ -3346,7 +3299,7 @@ bool_ make_attack_spell(int m_idx)
/* RF4_BR_CONF */
case 96 + 16:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s breathes.", m_name);
else msg_format("%^s breathes confusion.", m_name);
breath(m_idx, GF_CONFUSION,
@@ -3358,7 +3311,7 @@ bool_ make_attack_spell(int m_idx)
/* RF4_BR_SOUN */
case 96 + 17:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s breathes.", m_name);
else msg_format("%^s breathes sound.", m_name);
breath(m_idx, GF_SOUND,
@@ -3370,7 +3323,7 @@ bool_ make_attack_spell(int m_idx)
/* RF4_BR_CHAO */
case 96 + 18:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s breathes.", m_name);
else msg_format("%^s breathes chaos.", m_name);
breath(m_idx, GF_CHAOS,
@@ -3382,7 +3335,7 @@ bool_ make_attack_spell(int m_idx)
/* RF4_BR_DISE */
case 96 + 19:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s breathes.", m_name);
else msg_format("%^s breathes disenchantment.", m_name);
breath(m_idx, GF_DISENCHANT,
@@ -3394,7 +3347,7 @@ bool_ make_attack_spell(int m_idx)
/* RF4_BR_NEXU */
case 96 + 20:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s breathes.", m_name);
else msg_format("%^s breathes nexus.", m_name);
breath(m_idx, GF_NEXUS,
@@ -3406,7 +3359,7 @@ bool_ make_attack_spell(int m_idx)
/* RF4_BR_TIME */
case 96 + 21:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s breathes.", m_name);
else msg_format("%^s breathes time.", m_name);
breath(m_idx, GF_TIME,
@@ -3417,7 +3370,7 @@ bool_ make_attack_spell(int m_idx)
/* RF4_BR_INER */
case 96 + 22:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s breathes.", m_name);
else msg_format("%^s breathes inertia.", m_name);
breath(m_idx, GF_INERTIA,
@@ -3428,7 +3381,7 @@ bool_ make_attack_spell(int m_idx)
/* RF4_BR_GRAV */
case 96 + 23:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s breathes.", m_name);
else msg_format("%^s breathes gravity.", m_name);
breath(m_idx, GF_GRAVITY,
@@ -3439,7 +3392,7 @@ bool_ make_attack_spell(int m_idx)
/* RF4_BR_SHAR */
case 96 + 24:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s breathes.", m_name);
else msg_format("%^s breathes shards.", m_name);
breath(m_idx, GF_SHARDS,
@@ -3451,7 +3404,7 @@ bool_ make_attack_spell(int m_idx)
/* RF4_BR_PLAS */
case 96 + 25:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s breathes.", m_name);
else msg_format("%^s breathes plasma.", m_name);
breath(m_idx, GF_PLASMA,
@@ -3462,7 +3415,7 @@ bool_ make_attack_spell(int m_idx)
/* RF4_BR_WALL */
case 96 + 26:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s breathes.", m_name);
else msg_format("%^s breathes force.", m_name);
breath(m_idx, GF_FORCE,
@@ -3473,7 +3426,7 @@ bool_ make_attack_spell(int m_idx)
/* RF4_BR_MANA */
case 96 + 27:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s breathes.", m_name);
else msg_format("%^s breathes magical energy.", m_name);
breath(m_idx, GF_MANA,
@@ -3484,7 +3437,7 @@ bool_ make_attack_spell(int m_idx)
/* RF4_BA_NUKE */
case 96 + 28:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s casts a ball of radiation.", m_name);
breath(m_idx, GF_NUKE, (rlev + damroll(10, 6)), 2);
@@ -3495,7 +3448,7 @@ bool_ make_attack_spell(int m_idx)
/* RF4_BR_NUKE */
case 96 + 29:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s breathes.", m_name);
else msg_format("%^s breathes toxic waste.", m_name);
breath(m_idx, GF_NUKE,
@@ -3507,7 +3460,7 @@ bool_ make_attack_spell(int m_idx)
/* RF4_BA_CHAO */
case 96 + 30:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles frighteningly.", m_name);
else msg_format("%^s invokes a raw chaos.", m_name);
breath(m_idx, GF_CHAOS, (rlev * 2) + damroll(10, 10), 4);
@@ -3518,7 +3471,7 @@ bool_ make_attack_spell(int m_idx)
/* RF4_BR_DISI -> Disintegration breath! */
case 96 + 31:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s breathes.", m_name);
else msg_format("%^s breathes disintegration.", m_name);
breath(m_idx, GF_DISINTEGRATE,
@@ -3531,7 +3484,7 @@ bool_ make_attack_spell(int m_idx)
/* RF5_BA_ACID */
case 128 + 0:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s casts an acid ball.", m_name);
breath(m_idx, GF_ACID,
@@ -3543,7 +3496,7 @@ bool_ make_attack_spell(int m_idx)
/* RF5_BA_ELEC */
case 128 + 1:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s casts a lightning ball.", m_name);
breath(m_idx, GF_ELEC,
@@ -3555,7 +3508,7 @@ bool_ make_attack_spell(int m_idx)
/* RF5_BA_FIRE */
case 128 + 2:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s casts a fire ball.", m_name);
breath(m_idx, GF_FIRE,
@@ -3567,7 +3520,7 @@ bool_ make_attack_spell(int m_idx)
/* RF5_BA_COLD */
case 128 + 3:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s casts a frost ball.", m_name);
breath(m_idx, GF_COLD,
@@ -3579,7 +3532,7 @@ bool_ make_attack_spell(int m_idx)
/* RF5_BA_POIS */
case 128 + 4:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s casts a stinking cloud.", m_name);
breath(m_idx, GF_POIS,
@@ -3591,7 +3544,7 @@ bool_ make_attack_spell(int m_idx)
/* RF5_BA_NETH */
case 128 + 5:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s casts a nether ball.", m_name);
breath(m_idx, GF_NETHER,
@@ -3603,7 +3556,7 @@ bool_ make_attack_spell(int m_idx)
/* RF5_BA_WATE */
case 128 + 6:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s gestures fluidly.", m_name);
msg_print("You are engulfed in a whirlpool.");
@@ -3615,7 +3568,7 @@ bool_ make_attack_spell(int m_idx)
/* RF5_BA_MANA */
case 128 + 7:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles powerfully.", m_name);
else msg_format("%^s invokes a mana storm.", m_name);
breath(m_idx, GF_MANA,
@@ -3626,7 +3579,7 @@ bool_ make_attack_spell(int m_idx)
/* RF5_BA_DARK */
case 128 + 8:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles powerfully.", m_name);
else msg_format("%^s invokes a darkness storm.", m_name);
breath(m_idx, GF_DARK,
@@ -3638,13 +3591,12 @@ bool_ make_attack_spell(int m_idx)
/* RF5_DRAIN_MANA */
case 128 + 9:
{
- if (!direct) break;
if (p_ptr->csp)
{
int r1;
/* Disturb if legal */
- disturb(1, 0);
+ disturb(1);
/* Basic message */
msg_format("%^s draws psychic energy from you!", m_name);
@@ -3667,7 +3619,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 +3632,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)
@@ -3696,8 +3648,7 @@ bool_ make_attack_spell(int m_idx)
/* RF5_MIND_BLAST */
case 128 + 10:
{
- if (!direct) break;
- disturb(1, 0);
+ disturb(1);
if (!seen)
{
msg_print("You feel something focusing on your mind.");
@@ -3733,8 +3684,7 @@ bool_ make_attack_spell(int m_idx)
/* RF5_BRAIN_SMASH */
case 128 + 11:
{
- if (!direct) break;
- disturb(1, 0);
+ disturb(1);
if (!seen)
{
msg_print("You feel something focusing on your mind.");
@@ -3762,7 +3712,7 @@ bool_ make_attack_spell(int m_idx)
}
if (!p_ptr->free_act)
{
- (void)set_paralyzed(p_ptr->paralyzed + rand_int(4) + 4);
+ (void)set_paralyzed(rand_int(4) + 4);
}
(void)set_slow(p_ptr->slow + rand_int(4) + 4);
@@ -3782,8 +3732,7 @@ bool_ make_attack_spell(int m_idx)
/* RF5_CAUSE_1 */
case 128 + 12:
{
- if (!direct) break;
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s points at you and curses.", m_name);
if (rand_int(100) < p_ptr->skill_sav)
@@ -3801,8 +3750,7 @@ bool_ make_attack_spell(int m_idx)
/* RF5_CAUSE_2 */
case 128 + 13:
{
- if (!direct) break;
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s points at you and curses horribly.", m_name);
if (rand_int(100) < p_ptr->skill_sav)
@@ -3820,8 +3768,7 @@ bool_ make_attack_spell(int m_idx)
/* RF5_CAUSE_3 */
case 128 + 14:
{
- if (!direct) break;
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles loudly.", m_name);
else msg_format("%^s points at you, incanting terribly!", m_name);
if (rand_int(100) < p_ptr->skill_sav)
@@ -3839,8 +3786,7 @@ bool_ make_attack_spell(int m_idx)
/* RF5_CAUSE_4 */
case 128 + 15:
{
- if (!direct) break;
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s screams the word 'DIE!'", m_name);
else msg_format("%^s points at you, screaming the word DIE!", m_name);
if (rand_int(100) < p_ptr->skill_sav)
@@ -3858,7 +3804,7 @@ bool_ make_attack_spell(int m_idx)
/* RF5_BO_ACID */
case 128 + 16:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s casts a acid bolt.", m_name);
bolt(m_idx, GF_ACID, damroll(7, 8) + (rlev / 3));
@@ -3870,7 +3816,7 @@ bool_ make_attack_spell(int m_idx)
/* RF5_BO_ELEC */
case 128 + 17:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s casts a lightning bolt.", m_name);
bolt(m_idx, GF_ELEC, damroll(4, 8) + (rlev / 3));
@@ -3882,7 +3828,7 @@ bool_ make_attack_spell(int m_idx)
/* RF5_BO_FIRE */
case 128 + 18:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s casts a fire bolt.", m_name);
bolt(m_idx, GF_FIRE, damroll(9, 8) + (rlev / 3));
@@ -3894,7 +3840,7 @@ bool_ make_attack_spell(int m_idx)
/* RF5_BO_COLD */
case 128 + 19:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s casts a frost bolt.", m_name);
bolt(m_idx, GF_COLD, damroll(6, 8) + (rlev / 3));
@@ -3913,7 +3859,7 @@ bool_ make_attack_spell(int m_idx)
/* RF5_BO_NETH */
case 128 + 21:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s casts a nether bolt.", m_name);
bolt(m_idx, GF_NETHER, 30 + damroll(5, 5) + (rlev * 3) / 2);
@@ -3925,7 +3871,7 @@ bool_ make_attack_spell(int m_idx)
/* RF5_BO_WATE */
case 128 + 22:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s casts a water bolt.", m_name);
bolt(m_idx, GF_WATER, damroll(10, 10) + (rlev));
@@ -3936,7 +3882,7 @@ bool_ make_attack_spell(int m_idx)
/* RF5_BO_MANA */
case 128 + 23:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s casts a mana bolt.", m_name);
bolt(m_idx, GF_MANA, randint(rlev * 7 / 2) + 50);
@@ -3947,7 +3893,7 @@ bool_ make_attack_spell(int m_idx)
/* RF5_BO_PLAS */
case 128 + 24:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s casts a plasma bolt.", m_name);
bolt(m_idx, GF_PLASMA, 10 + damroll(8, 7) + (rlev));
@@ -3958,7 +3904,7 @@ bool_ make_attack_spell(int m_idx)
/* RF5_BO_ICEE */
case 128 + 25:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s casts an ice bolt.", m_name);
bolt(m_idx, GF_ICE, damroll(6, 6) + (rlev));
@@ -3970,7 +3916,7 @@ bool_ make_attack_spell(int m_idx)
/* RF5_MISSILE */
case 128 + 26:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s casts a magic missile.", m_name);
bolt(m_idx, GF_MISSILE, damroll(2, 6) + (rlev / 3));
@@ -3981,8 +3927,7 @@ bool_ make_attack_spell(int m_idx)
/* RF5_SCARE */
case 128 + 27:
{
- if (!direct) break;
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles, and you hear scary noises.", m_name);
else msg_format("%^s casts a fearful illusion.", m_name);
if (p_ptr->resist_fear)
@@ -4004,8 +3949,7 @@ bool_ make_attack_spell(int m_idx)
/* RF5_BLIND */
case 128 + 28:
{
- if (!direct) break;
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s casts a spell, burning your eyes!", m_name);
if (p_ptr->resist_blind)
@@ -4027,8 +3971,7 @@ bool_ make_attack_spell(int m_idx)
/* RF5_CONF */
case 128 + 29:
{
- if (!direct) break;
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles, and you hear puzzling noises.", m_name);
else msg_format("%^s creates a mesmerizing illusion.", m_name);
if (p_ptr->resist_conf)
@@ -4050,8 +3993,7 @@ bool_ make_attack_spell(int m_idx)
/* RF5_SLOW */
case 128 + 30:
{
- if (!direct) break;
- disturb(1, 0);
+ disturb(1);
msg_format("%^s drains power from your muscles!", m_name);
if (p_ptr->free_act)
{
@@ -4072,8 +4014,7 @@ bool_ make_attack_spell(int m_idx)
/* RF5_HOLD */
case 128 + 31:
{
- if (!direct) break;
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s stares deep into your eyes!", m_name);
if (p_ptr->free_act)
@@ -4086,7 +4027,7 @@ bool_ make_attack_spell(int m_idx)
}
else
{
- (void)set_paralyzed(p_ptr->paralyzed + rand_int(4) + 4);
+ (void)set_paralyzed(rand_int(4) + 4);
}
update_smart_learn(m_idx, DRS_FREE);
break;
@@ -4097,7 +4038,7 @@ bool_ make_attack_spell(int m_idx)
/* RF6_HASTE */
case 160 + 0:
{
- disturb(1, 0);
+ disturb(1);
if (blind)
{
msg_format("%^s mumbles.", m_name);
@@ -4127,7 +4068,7 @@ bool_ make_attack_spell(int m_idx)
/* RF6_HAND_DOOM */
case 160 + 1:
{
- disturb(1, 0);
+ disturb(1);
msg_format("%^s invokes the Hand of Doom!", m_name);
if (rand_int(100) < p_ptr->skill_sav)
{
@@ -4148,7 +4089,7 @@ bool_ make_attack_spell(int m_idx)
/* RF6_HEAL */
case 160 + 2:
{
- disturb(1, 0);
+ disturb(1);
/* Message */
if (blind)
@@ -4195,7 +4136,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)
@@ -4212,7 +4153,7 @@ bool_ make_attack_spell(int m_idx)
/* RF6_S_ANIMALS */
case 160 + 3:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s magically summons some animals!", m_name);
for (k = 0; k < 4; k++)
@@ -4226,7 +4167,7 @@ bool_ make_attack_spell(int m_idx)
/* RF6_BLINK */
case 160 + 4:
{
- disturb(1, 0);
+ disturb(1);
msg_format("%^s blinks away.", m_name);
teleport_away(m_idx, 10);
break;
@@ -4235,7 +4176,7 @@ bool_ make_attack_spell(int m_idx)
/* RF6_TPORT */
case 160 + 5:
{
- disturb(1, 0);
+ disturb(1);
msg_format("%^s teleports away.", m_name);
teleport_away(m_idx, MAX_SIGHT * 2 + 5);
break;
@@ -4244,8 +4185,7 @@ bool_ make_attack_spell(int m_idx)
/* RF6_TELE_TO */
case 160 + 6:
{
- if (!direct) break;
- disturb(1, 0);
+ disturb(1);
msg_format("%^s commands you to return.", m_name);
teleport_player_to(m_ptr->fy, m_ptr->fx);
break;
@@ -4254,8 +4194,7 @@ bool_ make_attack_spell(int m_idx)
/* RF6_TELE_AWAY */
case 160 + 7:
{
- if (!direct) break;
- disturb(1, 0);
+ disturb(1);
msg_format("%^s teleports you away.", m_name);
teleport_player(100);
break;
@@ -4264,8 +4203,7 @@ bool_ make_attack_spell(int m_idx)
/* RF6_TELE_LEVEL */
case 160 + 8:
{
- if (!direct) break;
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles strangely.", m_name);
else msg_format("%^s gestures at your feet.", m_name);
if (p_ptr->resist_nexus)
@@ -4287,8 +4225,7 @@ bool_ make_attack_spell(int m_idx)
/* RF6_DARKNESS */
case 160 + 9:
{
- if (!direct) break;
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s gestures in shadow.", m_name);
(void)unlite_area(0, 3);
@@ -4298,8 +4235,7 @@ bool_ make_attack_spell(int m_idx)
/* RF6_TRAPS */
case 160 + 10:
{
- if (!direct) break;
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles, and then cackles evilly.", m_name);
else msg_format("%^s casts a spell and cackles evilly.", m_name);
(void)trap_creation();
@@ -4309,8 +4245,7 @@ bool_ make_attack_spell(int m_idx)
/* RF6_FORGET */
case 160 + 11:
{
- if (!direct) break;
- disturb(1, 0);
+ disturb(1);
msg_format("%^s tries to blank your mind.", m_name);
if (rand_int(100) < p_ptr->skill_sav)
@@ -4331,7 +4266,7 @@ bool_ make_attack_spell(int m_idx)
/* RF6_S_BUG */
case 160 + 13:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s magically codes some software bugs.", m_name);
for (k = 0; k < 6; k++)
@@ -4345,7 +4280,7 @@ bool_ make_attack_spell(int m_idx)
/* RF6_S_RNG */
case 160 + 14:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s magically codes some RNGs.", m_name);
for (k = 0; k < 6; k++)
@@ -4359,7 +4294,7 @@ bool_ make_attack_spell(int m_idx)
/* RF6_S_THUNDERLORD */
case 160 + 15:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s magically summons a Thunderlord!", m_name);
for (k = 0; k < 1; k++)
@@ -4373,7 +4308,7 @@ bool_ make_attack_spell(int m_idx)
/* RF6_SUMMON_KIN */
case 160 + 16:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s magically summons %s %s.",
m_name, m_poss,
@@ -4393,7 +4328,7 @@ bool_ make_attack_spell(int m_idx)
/* RF6_S_HI_DEMON */
case 160 + 17:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s magically summons greater demons!", m_name);
if (blind && count) msg_print("You hear heavy steps nearby.");
@@ -4404,7 +4339,7 @@ bool_ make_attack_spell(int m_idx)
/* RF6_S_MONSTER */
case 160 + 18:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s magically summons help!", m_name);
for (k = 0; k < 1; k++)
@@ -4418,7 +4353,7 @@ bool_ make_attack_spell(int m_idx)
/* RF6_S_MONSTERS */
case 160 + 19:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s magically summons monsters!", m_name);
for (k = 0; k < 8; k++)
@@ -4432,7 +4367,7 @@ bool_ make_attack_spell(int m_idx)
/* RF6_S_ANT */
case 160 + 20:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s magically summons ants.", m_name);
for (k = 0; k < 6; k++)
@@ -4446,7 +4381,7 @@ bool_ make_attack_spell(int m_idx)
/* RF6_S_SPIDER */
case 160 + 21:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s magically summons spiders.", m_name);
for (k = 0; k < 6; k++)
@@ -4460,7 +4395,7 @@ bool_ make_attack_spell(int m_idx)
/* RF6_S_HOUND */
case 160 + 22:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s magically summons hounds.", m_name);
for (k = 0; k < 6; k++)
@@ -4474,7 +4409,7 @@ bool_ make_attack_spell(int m_idx)
/* RF6_S_HYDRA */
case 160 + 23:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s magically summons hydras.", m_name);
for (k = 0; k < 6; k++)
@@ -4488,7 +4423,7 @@ bool_ make_attack_spell(int m_idx)
/* RF6_S_ANGEL */
case 160 + 24:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s magically summons an angel!", m_name);
for (k = 0; k < 1; k++)
@@ -4502,7 +4437,7 @@ bool_ make_attack_spell(int m_idx)
/* RF6_S_DEMON */
case 160 + 25:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s magically summons a demon!", m_name);
for (k = 0; k < 1; k++)
@@ -4516,7 +4451,7 @@ bool_ make_attack_spell(int m_idx)
/* RF6_S_UNDEAD */
case 160 + 26:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s magically summons an undead adversary!", m_name);
for (k = 0; k < 1; k++)
@@ -4530,7 +4465,7 @@ bool_ make_attack_spell(int m_idx)
/* RF6_S_DRAGON */
case 160 + 27:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s magically summons a dragon!", m_name);
for (k = 0; k < 1; k++)
@@ -4544,7 +4479,7 @@ bool_ make_attack_spell(int m_idx)
/* RF6_S_HI_UNDEAD */
case 160 + 28:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s magically summons greater undead!", m_name);
for (k = 0; k < 8; k++)
@@ -4561,7 +4496,7 @@ bool_ make_attack_spell(int m_idx)
/* RF6_S_HI_DRAGON */
case 160 + 29:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s magically summons ancient dragons!", m_name);
for (k = 0; k < 8; k++)
@@ -4578,7 +4513,7 @@ bool_ make_attack_spell(int m_idx)
/* RF6_S_WRAITH */
case 160 + 30:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s magically summons Wraith!", m_name);
@@ -4598,7 +4533,7 @@ bool_ make_attack_spell(int m_idx)
/* RF6_S_UNIQUE */
case 160 + 31:
{
- disturb(1, 0);
+ disturb(1);
if (blind) msg_format("%^s mumbles.", m_name);
else msg_format("%^s magically summons special opponents!", m_name);
for (k = 0; k < 8; k++)
@@ -4671,16 +4606,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 +4620,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 +4648,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 +4687,17 @@ 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);
/* 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 +4707,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;
@@ -5081,9 +5008,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,6 +5043,9 @@ 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)
{
@@ -5128,10 +5055,12 @@ static bool_ get_moves(int m_idx, int *mm)
/* Let quests redefine AI */
if (r_ptr->flags7 & RF7_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;
}
}
@@ -5148,8 +5077,8 @@ 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)
@@ -5170,7 +5099,7 @@ static bool_ get_moves(int m_idx, int *mm)
}
}
- if (!stupid_monsters && (is_friend(m_ptr) < 0))
+ if (is_friend(m_ptr) < 0)
{
int tx = x2, ty = y2;
@@ -5243,7 +5172,7 @@ static bool_ get_moves(int m_idx, int *mm)
}
/* Apply fear if possible and necessary */
- if ((stupid_monsters) || (is_friend(m_ptr) > 0))
+ if (is_friend(m_ptr) > 0)
{
if (mon_will_run(m_idx))
{
@@ -5275,15 +5204,12 @@ static bool_ get_moves(int m_idx, int *mm)
}
- if (!stupid_monsters)
- {
- /* Check for no move */
- if (!x && !y) return (FALSE);
- }
+ /* Check for no move */
+ if (!x && !y) return (FALSE);
/* Extract the "absolute distances" */
- ax = ABS(x);
- ay = ABS(y);
+ int ay = ABS(y);
+ int ax = ABS(x);
/* Do something weird */
if (y < 0) move_val += 8;
@@ -5476,37 +5402,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;
/* 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,7 +5446,7 @@ 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;
@@ -5564,7 +5492,7 @@ static bool_ monst_attack_monst(int m_idx, int t_idx)
if (!effect || check_hit2(power, rlev, ac))
{
/* Always disturbing */
- if (disturb_other) disturb(1, 0);
+ if (disturb_other) disturb(1);
/* Describe the attack method */
switch (method)
@@ -5745,7 +5673,7 @@ 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);
@@ -5760,7 +5688,7 @@ static bool_ monst_attack_monst(int m_idx, int t_idx)
/* Hack need more punch against monsters */
damage *= 3;
- pt = GF_MISSILE;
+ int pt = GF_MISSILE;
/* Apply appropriate damage */
switch (effect)
@@ -5969,7 +5897,7 @@ static bool_ monst_attack_monst(int m_idx, int t_idx)
if (m_ptr->ml)
{
/* Disturbing */
- disturb(1, 0);
+ disturb(1);
/* Message */
monster_msg("%^s misses %s.", m_name, t_name);
@@ -6032,12 +5960,9 @@ 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);
-
- inv = p_ptr->invis;
-
- mlv = (s16b) m_ptr->level;
+ const auto r_ptr = m_ptr->race();
+ s16b inv = p_ptr->invis;
+ s16b mlv = m_ptr->level;
if (r_ptr->flags3 & RF3_NO_SLEEP)
mlv += 10;
@@ -6096,34 +6021,14 @@ 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];
-
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);
+ auto const r_ptr = m_ptr->race();
if (r_ptr->flags9 & RF9_DOPPLEGANGER) doppleganger = m_idx;
/* Handle "bleeding" */
@@ -6133,6 +6038,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 +6066,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 +6078,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 +6106,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);
}
}
}
@@ -6348,6 +6255,9 @@ 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))
gets_angry = TRUE;
@@ -6415,41 +6325,39 @@ static void process_monster(int m_idx, bool_ is_frien)
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->flags2 & RF2_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[80];
- /* 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 */
+ /* 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);
+ 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);
}
}
}
@@ -6523,36 +6431,28 @@ 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;
+ bool_ did_take_item = FALSE;
+ bool_ did_kill_item = FALSE;
+ bool_ did_move_body = FALSE;
+ bool_ did_kill_body = FALSE;
+ bool_ did_pass_wall = FALSE;
+ bool_ did_kill_wall = FALSE;
/* Take a zero-terminated array of "directions" */
for (i = 0; mm[i]; i++)
@@ -6571,7 +6471,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? */
@@ -6772,7 +6672,7 @@ static void process_monster(int m_idx, bool_ is_frien)
msg_print("You hear a door burst open!");
/* Disturb (sometimes) */
- if (disturb_minor) disturb(0, 0);
+ if (disturb_minor) disturb(0);
/* The door was bashed open */
did_bash_door = TRUE;
@@ -6921,7 +6821,7 @@ 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 */
@@ -7013,8 +6913,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;
@@ -7074,7 +6972,7 @@ static void process_monster(int m_idx, bool_ is_frien)
{
/* Disturb */
if ((is_friend(m_ptr) < 0) || disturb_pets)
- disturb(0, 0);
+ disturb(0);
}
/* Check for monster trap */
@@ -7084,16 +6982,14 @@ static void process_monster(int m_idx, bool_ is_frien)
}
else
{
+ /* Copy list of objects; we need a copy because we're mutating 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;
-
/* 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;
@@ -7173,8 +7069,7 @@ static void process_monster(int m_idx, bool_ is_frien)
msg_format("%^s picks up %s.", m_name, o_name);
}
- /* Option */
- if (testing_carry)
+ /* Put into inventory of monster */
{
/* Excise the object */
excise_object_idx(this_o_idx);
@@ -7188,18 +7083,8 @@ static void process_monster(int m_idx, bool_ is_frien)
/* Memorize monster */
o_ptr->held_m_idx = m_idx;
- /* Build a stack */
- o_ptr->next_o_idx = m_ptr->hold_o_idx;
-
/* Carry object */
- m_ptr->hold_o_idx = this_o_idx;
- }
-
- /* Nope */
- else
- {
- /* Delete the object */
- delete_object_idx(this_o_idx);
+ m_ptr->hold_o_idxs.push_back(this_o_idx);
}
}
@@ -7233,7 +7118,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 */
@@ -7383,7 +7268,6 @@ void process_monsters(void)
bool_ is_frien = FALSE;
monster_type *m_ptr;
- monster_race *r_ptr;
int old_monster_race_idx;
@@ -7413,7 +7297,7 @@ void process_monsters(void)
if (monster_race_idx)
{
/* Acquire current monster */
- r_ptr = &r_info[monster_race_idx];
+ monster_race *r_ptr = &r_info[monster_race_idx];
/* Memorize flags */
old_r_flags1 = r_ptr->r_flags1;
@@ -7489,7 +7373,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;
@@ -7568,7 +7452,7 @@ void process_monsters(void)
if (monster_race_idx && (monster_race_idx == old_monster_race_idx))
{
/* Acquire monster race */
- r_ptr = &r_info[monster_race_idx];
+ monster_race *r_ptr = &r_info[monster_race_idx];
/* Check for knowledge change */
if ((old_r_flags1 != r_ptr->r_flags1) ||
diff --git a/src/melee2.hpp b/src/melee2.hpp
new file mode 100644
index 00000000..fece0564
--- /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;
+extern bool_ mon_take_hit_mon(int s_idx, int m_idx, int dam, bool_ *fear, cptr note);
+extern void mon_handle_fear(monster_type *m_ptr, int dam, bool_ *fear);
+extern int check_hit2(int power, int level, int ac);
+extern void process_monsters(void);
+extern void curse_equipment(int chance, int heavy_chance);
+extern void curse_equipment_dg(int chance, int heavy_chance);
diff --git a/src/messages.cc b/src/messages.cc
new file mode 100644
index 00000000..a4ce949d
--- /dev/null
+++ b/src/messages.cc
@@ -0,0 +1,368 @@
+#include "messages.hpp"
+
+#include "tome/make_array.hpp"
+
+#include "z-term.h"
+#include "z-form.h"
+#include "z-util.h"
+
+/*
+ * OPTION: Maximum number of messages to remember (see "io.c")
+ * Default: assume maximal memorization of 2048 total messages
+ */
+#define MESSAGE_MAX 2048
+
+/*
+ * OPTION: Maximum space for the message text buffer (see "io.c")
+ * Default: assume that each of the 2048 messages is repeated an
+ * average of three times, and has an average length of 48
+ */
+#define MESSAGE_BUF 32768
+
+
+
+
+/*
+ * The next "free" index to use
+ */
+static u16b message__next;
+
+/*
+ * The index of the oldest message (none yet)
+ */
+static u16b message__last;
+
+/*
+ * The next "free" offset
+ */
+static u16b message__head;
+
+/*
+ * The offset to the oldest used char (none yet)
+ */
+static u16b message__tail;
+
+/*
+ * The array of offsets, by index [MESSAGE_MAX]
+ */
+static u16b *message__ptr;
+
+/*
+ * The array of colors, by index [MESSAGE_MAX]
+ */
+static byte *message__color;
+
+/*
+ * The array of message counts, by index [MESSAGE_MAX]
+ */
+static u16b *message__count;
+
+/*
+ * The array of chars, by offset [MESSAGE_BUF]
+ */
+static char *message__buf;
+
+
+/*
+* Second try for the "message" handling routines.
+*
+* Each call to "message_add(s)" will add a new "most recent" message
+* to the "message recall list", using the contents of the string "s".
+*
+* The messages will be stored in such a way as to maximize "efficiency",
+* that is, we attempt to maximize the number of sequential messages that
+* can be retrieved, given a limited amount of storage space.
+*
+* We keep a buffer of chars to hold the "text" of the messages, not
+* necessarily in "order", and an array of offsets into that buffer,
+* representing the actual messages. This is made more complicated
+* by the fact that both the array of indexes, and the buffer itself,
+* are both treated as "circular arrays" for efficiency purposes, but
+* the strings may not be "broken" across the ends of the array.
+*
+* The "message_add()" function is rather "complex", because it must be
+* extremely efficient, both in space and time, for use with the Borg.
+*/
+
+void message_init()
+{
+ /* Message variables */
+ message__ptr = make_array<u16b>(MESSAGE_MAX);
+ message__color = make_array<byte>(MESSAGE_MAX);
+ message__count = make_array<u16b>(MESSAGE_MAX);
+ message__buf = make_array<char>(MESSAGE_BUF);
+
+ /* Hack -- No messages yet */
+ message__tail = MESSAGE_BUF;
+}
+
+/*
+* How many messages are "available"?
+*/
+s16b message_num(void)
+{
+ int last, next, n;
+
+ /* Extract the indexes */
+ last = message__last;
+ next = message__next;
+
+ /* Handle "wrap" */
+ if (next < last) next += MESSAGE_MAX;
+
+ /* Extract the space */
+ n = (next - last);
+
+ /* Return the result */
+ return (n);
+}
+
+
+
+/*
+* Recall the "text" of a saved message
+*/
+cptr message_str(int age)
+{
+ static char buf[1024];
+ s16b x;
+ s16b o;
+ cptr s;
+
+ /* Forgotten messages have no text */
+ if ((age < 0) || (age >= message_num())) return ("");
+
+ /* Acquire the "logical" index */
+ x = (message__next + MESSAGE_MAX - (age + 1)) % MESSAGE_MAX;
+
+ /* Get the "offset" for the message */
+ o = message__ptr[x];
+
+ /* Access the message text */
+ s = &message__buf[o];
+
+ /* Hack -- Handle repeated messages */
+ if (message__count[x] > 1)
+ {
+ strnfmt(buf, 1024, "%s <%dx>", s, message__count[x]);
+ s = buf;
+ }
+
+ /* Return the message text */
+ return (s);
+}
+
+/*
+* Recall the color of a saved message
+*/
+byte message_color(int age)
+{
+ s16b x;
+ byte color = TERM_WHITE;
+
+ /* Forgotten messages have no text */
+ if ((age < 0) || (age >= message_num())) return (TERM_WHITE);
+
+ /* Acquire the "logical" index */
+ x = (message__next + MESSAGE_MAX - (age + 1)) % MESSAGE_MAX;
+
+ /* Get the "offset" for the message */
+ color = message__color[x];
+
+ /* Return the message text */
+ return (color);
+}
+
+
+/*
+* Add a new message, with great efficiency
+*/
+void message_add(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__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__count[x] = 1;
+
+ /* Append the new part of the message */
+ for (i = 0; i < n; i++)
+ {
+ /* Copy the message */
+ message__buf[message__head + i] = str[i];
+ }
+
+ /* Terminate */
+ message__buf[message__head + i] = '\0';
+
+ /* Advance the "head" pointer */
+ message__head += n + 1;
+}
diff --git a/src/messages.hpp b/src/messages.hpp
new file mode 100644
index 00000000..22943ab9
--- /dev/null
+++ b/src/messages.hpp
@@ -0,0 +1,9 @@
+#pragma once
+
+#include "h-basic.h"
+
+void message_init();
+s16b message_num();
+cptr message_str(int age);
+byte message_color(int age);
+void message_add(cptr msg, byte color);
diff --git a/src/meta_class_type.hpp b/src/meta_class_type.hpp
new file mode 100644
index 00000000..e74e75b3
--- /dev/null
+++ b/src/meta_class_type.hpp
@@ -0,0 +1,10 @@
+#pragma once
+
+#include "h-basic.h"
+
+struct meta_class_type
+{
+ char name[80]; /* Name */
+ byte color;
+ s16b *classes; /* list of classes */
+};
diff --git a/src/meta_class_type_fwd.hpp b/src/meta_class_type_fwd.hpp
new file mode 100644
index 00000000..2d0e482a
--- /dev/null
+++ b/src/meta_class_type_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct meta_class_type;
diff --git a/src/mimic.cc b/src/mimic.cc
new file mode 100644
index 00000000..edf79f4b
--- /dev/null
+++ b/src/mimic.cc
@@ -0,0 +1,728 @@
+#include "mimic.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(TR1_SPEED + TR1_STR + TR1_INT + TR1_WIS + TR1_DEX + TR1_CON + TR1_CHR, 0, 0, 0, 0, 0, -10, 0, 0, 0, 0);
+ p_ptr->xtra_f3 |= TR3_AGGRAVATE;
+
+ return 0;
+}
+
+static s32b mouse_calc()
+{
+ /* Mice run! */
+ p_ptr->pspeed += 5 + (p_ptr->mimic_level / 7);
+
+ /* They can crawl under your armor to hit you ;) */
+ p_ptr->to_h = p_ptr->to_h + 10 + (p_ptr->mimic_level / 5);
+ p_ptr->dis_to_h = p_ptr->dis_to_h + 10 + (p_ptr->mimic_level / 5);
+
+ /* But they are not very powerfull */
+ p_ptr->to_d = p_ptr->to_d / 5;
+ p_ptr->dis_to_d = p_ptr->dis_to_d / 5;
+
+ /* But they are stealthy */
+ p_ptr->skill_stl = p_ptr->skill_stl + 10 + (p_ptr->mimic_level / 5);
+
+ /* Stat mods */
+ p_ptr->stat_add[A_STR] += -5;
+ p_ptr->stat_add[A_DEX] += 3;
+ p_ptr->stat_add[A_CON] += 1;
+
+ return 0;
+}
+
+static void mouse_power()
+{
+ if (p_ptr->mimic_level >= 30)
+ {
+ p_ptr->powers[POWER_INVISIBILITY] = TRUE;
+ }
+}
+
+static s32b eagle_calc()
+{
+ p_ptr->ffall = TRUE;
+ p_ptr->pspeed = p_ptr->pspeed + 2 + (p_ptr->mimic_level / 6);
+
+ p_ptr->stat_add[A_STR] += -3;
+ p_ptr->stat_add[A_DEX] += 2 + (p_ptr->mimic_level / 15);
+ p_ptr->stat_add[A_CON] += 4 + (p_ptr->mimic_level / 20);
+ p_ptr->stat_add[A_INT] += -1;
+ p_ptr->stat_add[A_WIS] += 1;
+ p_ptr->stat_add[A_CHR] += -1;
+
+ if (p_ptr->mimic_level >= 20)
+ {
+ p_ptr->xtra_f4 |= TR4_FLY;
+ p_ptr->xtra_f3 |= TR3_SEE_INVIS;
+ }
+
+ if (p_ptr->mimic_level >= 25)
+ {
+ p_ptr->xtra_f2 |= TR2_FREE_ACT;
+ }
+
+ if (p_ptr->mimic_level >= 30)
+ {
+ p_ptr->xtra_f2 |= TR2_RES_ELEC;
+ }
+
+ if (p_ptr->mimic_level >= 35)
+ {
+ p_ptr->xtra_f3 |= TR3_SH_ELEC;
+ }
+
+ return 0;
+}
+
+static s32b wolf_calc()
+{
+ p_ptr->stat_add[A_STR] += 2 + (p_ptr->mimic_level / 20);
+ p_ptr->stat_add[A_DEX] += 3 + (p_ptr->mimic_level / 20);
+ p_ptr->stat_add[A_INT] += -3;
+ p_ptr->stat_add[A_CHR] += -2;
+
+ p_ptr->pspeed = p_ptr->pspeed + 10 + (p_ptr->mimic_level / 5);
+
+ p_ptr->xtra_f2 |= TR2_FREE_ACT;
+ p_ptr->xtra_f2 |= TR2_RES_FEAR;
+
+ if (p_ptr->mimic_level >= 10)
+ {
+ p_ptr->xtra_f2 |= TR2_RES_COLD;
+ }
+
+ if (p_ptr->mimic_level >= 15)
+ {
+ p_ptr->xtra_f3 |= TR3_SEE_INVIS;
+ }
+
+ if (p_ptr->mimic_level >= 30)
+ {
+ p_ptr->xtra_f2 |= TR2_RES_DARK;
+ }
+
+ if (p_ptr->mimic_level >= 35)
+ {
+ p_ptr->xtra_f2 |= TR2_RES_CONF;
+ }
+
+ return 0;
+}
+
+static s32b spider_calc()
+{
+ p_ptr->stat_add[A_STR] += -4;
+ p_ptr->stat_add[A_DEX] += 1 + (p_ptr->mimic_level / 8);
+ p_ptr->stat_add[A_INT] += 1 + (p_ptr->mimic_level / 5);
+ p_ptr->stat_add[A_WIS] += 1 + (p_ptr->mimic_level / 5);
+ p_ptr->stat_add[A_CON] += -5;
+ p_ptr->stat_add[A_CHR] += -10;
+
+ p_ptr->pspeed = p_ptr->pspeed + 5;
+
+ p_ptr->xtra_f2 |= TR2_RES_POIS;
+ p_ptr->xtra_f2 |= TR2_RES_FEAR;
+ p_ptr->xtra_f2 |= TR2_RES_DARK;
+
+ if (p_ptr->mimic_level >= 40)
+ {
+ p_ptr->xtra_f4 |= TR4_CLIMB;
+ }
+
+ return 0;
+}
+
+static void spider_power()
+{
+ if (p_ptr->mimic_level >= 25)
+ {
+ p_ptr->powers[POWER_WEB] = TRUE;
+ }
+}
+
+static s32b ent_calc()
+{
+ p_ptr->pspeed = p_ptr->pspeed - 5 - (p_ptr->mimic_level / 10);
+
+ p_ptr->to_a = p_ptr->to_a + 10 + p_ptr->mimic_level;
+ p_ptr->dis_to_a = p_ptr->dis_to_a + 10 + p_ptr->mimic_level;
+
+ p_ptr->stat_add[A_STR] += p_ptr->mimic_level / 5;
+ p_ptr->stat_add[A_INT] += - (p_ptr->mimic_level / 7);
+ p_ptr->stat_add[A_WIS] += - (p_ptr->mimic_level / 7);
+ p_ptr->stat_add[A_DEX] += -4;
+ p_ptr->stat_add[A_CON] += p_ptr->mimic_level / 5;
+ p_ptr->stat_add[A_CHR] += -7;
+
+ p_ptr->xtra_f2 |= TR2_RES_POIS;
+ p_ptr->xtra_f2 |= TR2_RES_COLD;
+ p_ptr->xtra_f2 |= TR2_FREE_ACT;
+ p_ptr->xtra_f3 |= TR3_REGEN;
+ p_ptr->xtra_f3 |= TR3_SEE_INVIS;
+ p_ptr->xtra_f2 |= TR2_SENS_FIRE;
+
+ return 0;
+}
+
+static void ent_power()
+{
+ p_ptr->powers[PWR_GROW_TREE] = TRUE;
+}
+
+static s32b vapour_calc()
+{
+ p_ptr->pspeed = p_ptr->pspeed + 5;
+
+ /* Try to hit a cloud! */
+ p_ptr->to_a = p_ptr->to_a + 40 + p_ptr->mimic_level;
+ p_ptr->dis_to_a = p_ptr->dis_to_a + 40 + p_ptr->mimic_level;
+
+ /* Try to hit WITH a cloud! */
+ p_ptr->to_h = p_ptr->to_h - 40;
+ p_ptr->dis_to_h = p_ptr->dis_to_h - 40;
+
+ /* Stat mods */
+ p_ptr->stat_add[A_STR] += -4;
+ p_ptr->stat_add[A_DEX] += 5;
+ p_ptr->stat_add[A_CON] += -4;
+ p_ptr->stat_add[A_CHR] += -10;
+
+ /* But they are stealthy */
+ p_ptr->skill_stl = p_ptr->skill_stl + 10 + (p_ptr->mimic_level / 5);
+ p_ptr->xtra_f2 |= TR2_RES_POIS;
+ p_ptr->xtra_f2 |= TR2_RES_SHARDS;
+ p_ptr->xtra_f2 |= TR2_IM_COLD;
+ p_ptr->xtra_f2 |= TR2_FREE_ACT;
+ p_ptr->xtra_f3 |= TR3_REGEN;
+ p_ptr->xtra_f3 |= TR3_SEE_INVIS;
+ p_ptr->xtra_f2 |= TR2_SENS_FIRE;
+ p_ptr->xtra_f3 |= TR3_FEATHER;
+
+ return 0;
+}
+
+static s32b serpent_calc()
+{
+ p_ptr->pspeed = p_ptr->pspeed + 10 + (p_ptr->mimic_level / 6);
+
+ p_ptr->to_a = p_ptr->to_a + 3 + (p_ptr->mimic_level / 8);
+ p_ptr->dis_to_a = p_ptr->dis_to_a + 3 + (p_ptr->mimic_level / 8);
+
+ p_ptr->stat_add[A_STR] += p_ptr->mimic_level / 8;
+ p_ptr->stat_add[A_INT] += -6;
+ p_ptr->stat_add[A_WIS] += -6;
+ p_ptr->stat_add[A_DEX] += -4;
+ p_ptr->stat_add[A_CON] += p_ptr->mimic_level / 7;
+ p_ptr->stat_add[A_CHR] += -6;
+
+ p_ptr->xtra_f2 |= TR2_RES_POIS;
+ if (p_ptr->mimic_level >= 25)
+ {
+ p_ptr->xtra_f2 |= TR2_FREE_ACT;
+ }
+
+ return 0;
+}
+
+static s32b mumak_calc()
+{
+ p_ptr->pspeed = p_ptr->pspeed - 5 - (p_ptr->mimic_level / 10);
+
+ p_ptr->to_a = p_ptr->to_a + 10 + (p_ptr->mimic_level / 6);
+ p_ptr->dis_to_a = p_ptr->dis_to_a + 10 + (p_ptr->mimic_level / 6);
+ p_ptr->to_d = p_ptr->to_d + 5 + ((p_ptr->mimic_level * 2) / 3);
+ p_ptr->dis_to_d = p_ptr->dis_to_d + 5 + ((p_ptr->mimic_level * 2) / 3);
+
+ p_ptr->stat_add[A_STR] += p_ptr->mimic_level / 4;
+ p_ptr->stat_add[A_INT] += -8;
+ p_ptr->stat_add[A_WIS] += -4;
+ p_ptr->stat_add[A_DEX] += -5;
+ p_ptr->stat_add[A_CON] += p_ptr->mimic_level / 3;
+ p_ptr->stat_add[A_CHR] += -10;
+
+ if (p_ptr->mimic_level >= 10)
+ {
+ p_ptr->xtra_f2 |= TR2_RES_FEAR;
+ }
+
+ if (p_ptr->mimic_level >= 25)
+ {
+ p_ptr->xtra_f2 |= TR2_RES_CONF;
+ }
+
+ if (p_ptr->mimic_level >= 30)
+ {
+ p_ptr->xtra_f2 |= TR2_FREE_ACT;
+ }
+
+ if (p_ptr->mimic_level >= 35)
+ {
+ p_ptr->xtra_f2 |= TR2_RES_NEXUS;
+ }
+
+ return 0;
+}
+
+static s32b bear_calc()
+{
+ p_ptr->pspeed = p_ptr->pspeed - 5 + (p_ptr->mimic_level / 5);
+
+ p_ptr->to_a = p_ptr->to_a + 5 + ((p_ptr->mimic_level * 2) / 3);
+ p_ptr->dis_to_a = p_ptr->dis_to_a + 5 + ((p_ptr->mimic_level * 2) / 3);
+
+ p_ptr->stat_add[A_STR] += p_ptr->mimic_level / 11;
+ p_ptr->stat_add[A_INT] += p_ptr->mimic_level / 11;
+ p_ptr->stat_add[A_WIS] += p_ptr->mimic_level / 11;
+ p_ptr->stat_add[A_DEX] += -1;
+ p_ptr->stat_add[A_CON] += p_ptr->mimic_level / 11;
+ p_ptr->stat_add[A_CHR] += -10;
+
+ if (p_ptr->mimic_level >= 10)
+ {
+ p_ptr->xtra_f2 |= TR2_FREE_ACT;
+ }
+
+ if (p_ptr->mimic_level >= 20)
+ {
+ p_ptr->xtra_f3 |= TR3_REGEN;
+ }
+
+ if (p_ptr->mimic_level >= 30)
+ {
+ p_ptr->xtra_f2 |= TR2_RES_CONF;
+ }
+
+ if (p_ptr->mimic_level >= 35)
+ {
+ p_ptr->xtra_f2 |= TR2_RES_NEXUS;
+ }
+
+ /* activate the skill */
+ s_info[SKILL_BEAR].hidden = FALSE;
+
+ return 0;
+}
+
+static s32b balrog_calc()
+{
+ p_ptr->stat_add[A_STR] += 5 + p_ptr->mimic_level / 5;
+ p_ptr->stat_add[A_INT] += p_ptr->mimic_level / 10;
+ p_ptr->stat_add[A_WIS] += - ( 5 + p_ptr->mimic_level / 10);
+ p_ptr->stat_add[A_DEX] += p_ptr->mimic_level / 10;
+ p_ptr->stat_add[A_CON] += 5 + p_ptr->mimic_level / 5;
+ p_ptr->stat_add[A_CHR] += - ( 5 + p_ptr->mimic_level / 10);
+
+ p_ptr->xtra_f2 |= TR2_IM_ACID;
+ p_ptr->xtra_f2 |= TR2_IM_FIRE;
+ p_ptr->xtra_f2 |= TR2_IM_ELEC;
+ p_ptr->xtra_f2 |= TR2_RES_DARK;
+ p_ptr->xtra_f2 |= TR2_RES_CHAOS;
+ p_ptr->xtra_f2 |= TR2_RES_POIS;
+ p_ptr->xtra_f2 |= TR2_HOLD_LIFE;
+ p_ptr->xtra_f3 |= TR3_FEATHER;
+ p_ptr->xtra_f3 |= TR3_REGEN;
+ p_ptr->xtra_f3 |= TR3_SH_FIRE;
+ p_ptr->xtra_f3 |= TR3_LITE1;
+
+ return 1; /* Adds a blow */
+}
+
+static s32b maia_calc()
+{
+ p_ptr->stat_add[A_STR] += 5 + p_ptr->mimic_level / 5;
+ p_ptr->stat_add[A_INT] += 5 + p_ptr->mimic_level / 5;
+ p_ptr->stat_add[A_WIS] += 5 + p_ptr->mimic_level / 5;
+ p_ptr->stat_add[A_DEX] += 5 + p_ptr->mimic_level / 5;
+ p_ptr->stat_add[A_CON] += 5 + p_ptr->mimic_level / 5;
+ p_ptr->stat_add[A_CHR] += 5 + p_ptr->mimic_level / 5;
+
+ p_ptr->xtra_f2 |= TR2_IM_FIRE;
+ p_ptr->xtra_f2 |= TR2_IM_ELEC;
+ p_ptr->xtra_f2 |= TR2_IM_ACID;
+ p_ptr->xtra_f2 |= TR2_IM_COLD;
+ p_ptr->xtra_f2 |= TR2_RES_POIS;
+ p_ptr->xtra_f2 |= TR2_RES_LITE;
+ p_ptr->xtra_f2 |= TR2_RES_DARK;
+ p_ptr->xtra_f2 |= TR2_RES_CHAOS;
+ p_ptr->xtra_f2 |= TR2_HOLD_LIFE;
+ p_ptr->xtra_f3 |= TR3_FEATHER;
+ p_ptr->xtra_f3 |= TR3_REGEN;
+
+ return 2; /* Add two blows */
+}
+
+static s32b fire_elemental_calc()
+{
+ p_ptr->stat_add[A_STR] += 5 + (p_ptr->mimic_level / 5);
+ p_ptr->stat_add[A_DEX] += 5 + (p_ptr->mimic_level / 5);
+ p_ptr->stat_add[A_WIS] += -5 - (p_ptr->mimic_level / 5);
+
+ p_ptr->xtra_f2 |= TR2_IM_FIRE;
+ p_ptr->xtra_f2 |= TR2_RES_POIS;
+ p_ptr->xtra_f3 |= TR3_SH_FIRE;
+ p_ptr->xtra_f3 |= TR3_LITE1;
+
+ return 0;
+}
+
+/*
+ * Mimicry forms
+ */
+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 *f)
+{
+ int i;
+
+ for (i = 0; f->modules[i] >= 0; i++)
+ {
+ if (f->modules[i] == game_module_idx)
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/*
+ * Get a mimic form by index
+ */
+static mimic_form_type *get_mimic_form(int mf_idx)
+{
+ assert(mf_idx >= 0);
+ assert(mf_idx < MIMIC_FORMS_MAX);
+ return &mimic_forms[mf_idx];
+}
+
+/*
+ * Find a mimic by name
+ */
+s16b resolve_mimic_name(cptr name)
+{
+ s16b i;
+
+ for (i = 0; i < MIMIC_FORMS_MAX; i++)
+ {
+ mimic_form_type *mf_ptr = get_mimic_form(i);
+ if (mimic_form_enabled(mf_ptr) && streq(mf_ptr->name, name))
+ {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+/*
+ * Find a random mimic form
+ */
+s16b find_random_mimic_shape(byte level, bool_ limit)
+{
+ int tries = 1000;
+
+ while (tries > 0)
+ {
+ int mf_idx = 0;
+ mimic_form_type *mf_ptr = NULL;
+
+ tries = tries - 1;
+
+ mf_idx = rand_int(MIMIC_FORMS_MAX);
+ mf_ptr = get_mimic_form(mf_idx);
+
+ if (mimic_form_enabled(mf_ptr))
+ {
+ if (limit >= mf_ptr->limit)
+ {
+ if ((rand_int(mf_ptr->level * 3) < level) &&
+ (mf_ptr->rarity < 100) &&
+ (magik(100 - mf_ptr->rarity)))
+ {
+ return mf_idx;
+ }
+ }
+ }
+ }
+ /* Abomination */
+ return 0;
+}
+
+/*
+ * Get mimic name
+ */
+cptr get_mimic_name(s16b mf_idx)
+{
+ return get_mimic_form(mf_idx)->name;
+}
+
+/*
+ * Get mimic object name
+ */
+cptr get_mimic_object_name(s16b mf_idx)
+{
+ return get_mimic_form(mf_idx)->obj_name;
+}
+
+/*
+ * Get mimic object level
+ */
+byte get_mimic_level(s16b mf_idx)
+{
+ return get_mimic_form(mf_idx)->level;
+}
+
+/*
+ * Get a random duration for the given mimic form
+ */
+s32b get_mimic_random_duration(s16b mf_idx)
+{
+ mimic_form_type *mf_ptr = get_mimic_form(mf_idx);
+ return rand_range(mf_ptr->duration.min, mf_ptr->duration.max);
+}
+
+/*
+ * Calculate bonuses for player's current mimic form
+ */
+byte calc_mimic()
+{
+ mimic_form_type *mf_ptr = get_mimic_form(p_ptr->mimic_form);
+ 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..d9c8f3bd
--- /dev/null
+++ b/src/mimic.hpp
@@ -0,0 +1,10 @@
+#include "h-basic.h"
+
+extern s16b resolve_mimic_name(cptr name);
+extern s16b find_random_mimic_shape(byte level, bool_ limit);
+extern cptr get_mimic_name(s16b mf_idx);
+extern cptr get_mimic_object_name(s16b mf_idx);
+extern byte get_mimic_level(s16b mf_idx);
+extern s32b get_mimic_random_duration(s16b mf_idx);
+extern byte calc_mimic();
+extern void calc_mimic_power();
diff --git a/src/module_type.hpp b/src/module_type.hpp
new file mode 100644
index 00000000..96938856
--- /dev/null
+++ b/src/module_type.hpp
@@ -0,0 +1,64 @@
+#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;
+
+ /* Max player level. */
+ int max_plev;
+
+ /* Skills */
+ struct {
+ /* Skill points per level */
+ s32b skill_per_level;
+ /* Maximum "overage" for skill points, i.e. how many skill
+ points you can go above your current level. */
+ s32b max_skill_overage;
+ } skills;
+
+ /* 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..c5d065f4
--- /dev/null
+++ b/src/modules.cc
@@ -0,0 +1,1279 @@
+/*
+ * 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 "modules.h"
+
+#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_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 */
+ max_plev = module_ptr->max_plev;
+
+ 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;
+ 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();
+}
+
+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(cptr savefile_mod)
+{
+ return (strcmp(savefile_mod, modules[game_module_idx].meta.save_file_tag) == 0);
+}
+
+/* Did the player force a module on command line */
+cptr force_module = NULL;
+
+/* 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 *data, void *in_, void *out)
+{
+ hook_give_in *in = (hook_give_in *) in_;
+ monster_type *m_ptr = &m_list[in->m_idx];
+ object_type *o_ptr = get_object(in->item);
+
+ if ((m_ptr->r_idx == test_monster_name("Singing, happy drunk")) &&
+ (o_ptr->tval == TV_FOOD) &&
+ ((o_ptr->sval == 38) ||
+ (o_ptr->sval == 39)))
+ {
+ cmsg_print(TERM_YELLOW, "'Hic!'");
+
+ /* Destroy item */
+ inc_stack_size_ex(in->item, -1, OPTIMIZE, NO_DESCRIBE);
+
+ /* Create empty bottle */
+ {
+ object_type forge;
+ object_prep(&forge, lookup_kind(TV_BOTTLE,1));
+ drop_near(&forge, 50, p_ptr->py, p_ptr->px);
+ return TRUE;
+ }
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+static bool_ hobbit_food(void *data, void *in_, void *out)
+{
+ hook_give_in *in = (hook_give_in *) in_;
+ monster_type *m_ptr = &m_list[in->m_idx];
+ object_type *o_ptr = get_object(in->item);
+
+ if ((m_ptr->r_idx == test_monster_name("Scruffy-looking hobbit")) &&
+ (o_ptr->tval == TV_FOOD))
+ {
+ cmsg_print(TERM_YELLOW, "'Yum!'");
+
+ inc_stack_size_ex(in->item, -1, OPTIMIZE, NO_DESCRIBE);
+
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+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 *data, void *in_, void *out_)
+{
+ hook_eat_in *in = (hook_eat_in *) in_;
+
+ if ((in->o_ptr->tval == TV_FOOD) &&
+ (in->o_ptr->sval == 45))
+ {
+ msg_print("What a stress reliever!");
+ heal_insanity(1000);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static bool_ food_vessel(void *data, void *in_, void *out)
+{
+ hook_eat_in *in = (hook_eat_in *) in_;
+
+ if (((in->o_ptr->tval == TV_FOOD) && (in->o_ptr->sval == 43)) ||
+ ((in->o_ptr->tval == TV_FOOD) && (in->o_ptr->sval == 44)))
+ {
+ object_type forge;
+
+ object_prep(&forge, lookup_kind(TV_JUNK, 3));
+
+ forge.ident |= IDENT_MENTAL | IDENT_KNOWN;
+ inven_carry(&forge, FALSE);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/*
+ * Player must have appropriate keys to enter Erebor.
+ */
+static bool_ erebor_stair(void *data, void *in_, void *out_)
+{
+ hook_stair_in *in = (hook_stair_in *) in_;
+ hook_stair_out *out = (hook_stair_out *) out_;
+
+ if ((dungeon_type == 20) &&
+ (dun_level == 60) &&
+ (in->direction == STAIRS_DOWN))
+ {
+ int i, keys;
+
+ keys = 0;
+ for (i = 0; i < INVEN_TOTAL - 1; i++)
+ {
+ if ((p_ptr->inventory[i].name1 == 209) ||
+ (p_ptr->inventory[i].name1 == 210))
+ {
+ keys += 1;
+ }
+ }
+
+ if (keys >= 2)
+ {
+ msg_print("The moon-letters on the map show you "
+ "the keyhole! You use the key to enter.");
+ out->allow = TRUE;
+ }
+ else
+ {
+ msg_print("You have found a door, but you cannot "
+ "find a way to enter. Ask in Dale, perhaps?");
+ out->allow = FALSE;
+ }
+ }
+
+ return FALSE;
+}
+
+/*
+ * Orthanc requires a key.
+ */
+static bool_ orthanc_stair(void *data, void *in_, void *out_)
+{
+ hook_stair_in *in = (hook_stair_in *) in_;
+ hook_stair_out *out = (hook_stair_out *) out_;
+
+ if ((dungeon_type == 36) &&
+ (dun_level == 39) &&
+ (in->direction == STAIRS_DOWN))
+ {
+ int i, keys;
+
+ keys = 0;
+ for (i = 0; i < INVEN_TOTAL - 1; i++)
+ {
+ if (p_ptr->inventory[i].name1 == 15)
+ {
+ keys += 1;
+ }
+ }
+
+ if (keys >= 1)
+ {
+ msg_print("#BYou have the key to the tower of Orthanc! You may proceed.#w");
+ out->allow = TRUE;
+ }
+ else
+ {
+ msg_print("#yYou may not enter Orthanc without the key to the gates!#w Rumours say the key was lost in the Mines of Moria...");
+ out->allow = FALSE;
+ }
+ }
+
+ return FALSE;
+}
+
+/*
+ * 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->flags2 == RF2_PASS_WALL))
+ {
+ char buf[128];
+
+ monster_desc(buf, m_ptr, 0);
+ msg_print(format("You push past %s.", buf));
+
+ m_ptr->fy = p_ptr->py;
+ m_ptr->fx = p_ptr->px;
+ cave[p_ptr->py][p_ptr->px].m_idx = c_ptr->m_idx;
+ c_ptr->m_idx = 0;
+ }
+ else
+ {
+ char buf[128];
+
+ monster_desc(buf, m_ptr, 0);
+ msg_print(format("%s is in your way!", buf));
+ energy_use = 0;
+
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+/*
+ * 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 *data, void *in, void *out)
+{
+ int i = 0;
+
+ for (i = 0; i < m_max; i++)
+ {
+ monster_type *m_ptr = &m_list[i];
+ int r_idx = m_ptr->r_idx;
+ s16b *status = theme_race_status(r_idx);
+ if (status)
+ {
+ m_ptr->status = *status;
+ }
+ }
+
+ return FALSE;
+}
+
+static bool_ theme_new_monster_end(void *data, void *in_, void *out)
+{
+ hook_new_monster_end_in *in = (hook_new_monster_end_in *) in_;
+ s16b *status = 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.h b/src/modules.h
new file mode 100644
index 00000000..8a3b88b0
--- /dev/null
+++ b/src/modules.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
+
+extern bool_ private_check_user_directory(cptr dirpath);
+extern cptr force_module;
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/src/modules.hpp b/src/modules.hpp
new file mode 100644
index 00000000..d83e3e2e
--- /dev/null
+++ b/src/modules.hpp
@@ -0,0 +1,11 @@
+#pragma once
+
+#include "h-basic.h"
+
+extern bool_ select_module(void);
+extern bool_ module_savefile_loadable(cptr savefile_mod);
+extern void tome_intro();
+extern void theme_intro();
+extern s16b *theme_race_status(int r_idx);
+extern void init_hooks_module();
+extern int find_module(cptr name);
diff --git a/src/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.cc
index 196272ce..4e3e2c42 100644
--- a/src/monster1.c
+++ b/src/monster1.cc
@@ -1,7 +1,3 @@
-/* File: monster1.c */
-
-/* Purpose: describe monsters (using monster memory) */
-
/*
* Copyright (c) 1989 James E. Wilson, Christopher J. Stuart
*
@@ -10,8 +6,17 @@
* included in all such copies.
*/
-#include "angband.h"
+#include "monster1.hpp"
+#include "cave_type.hpp"
+#include "monster2.hpp"
+#include "monster_ego.hpp"
+#include "monster_race.hpp"
+#include "player_type.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+#include "wilderness_map.hpp"
+#include "wilderness_type_info.hpp"
/*
* Pronoun arrays, by gender.
@@ -35,10 +40,8 @@ static cptr wd_his[3] = { "its", "his", "her" };
* Determine if the "armor" is known
* The higher the level, the fewer kills needed.
*/
-static bool_ know_armour(int r_idx)
+static bool_ know_armour(std::shared_ptr<monster_race const> r_ptr)
{
- monster_race *r_ptr = &r_info[r_idx];
-
s32b level = r_ptr->level;
s32b kills = r_ptr->r_tkills;
@@ -62,10 +65,8 @@ static bool_ know_armour(int r_idx)
* 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)
+static bool_ know_damage(std::shared_ptr<monster_race const> r_ptr, int i)
{
- monster_race *r_ptr = &r_info[r_idx];
-
s32b level = r_ptr->level;
s32b a = r_ptr->r_blows[i];
@@ -101,10 +102,8 @@ static bool_ know_damage(int r_idx, int i)
* 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)
+static void roff_aux(std::shared_ptr<monster_race> r_ptr, int remem)
{
- monster_race *r_ptr;
-
bool_ old = FALSE;
bool_ sin = FALSE;
@@ -132,12 +131,6 @@ static void roff_aux(int r_idx, int ego, int remem)
monster_race save_mem;
-
-
- /* Access the race and lore */
- r_ptr = race_info_idx(r_idx, ego);
-
-
/* Cheat -- Know everything */
if (cheat_know)
{
@@ -242,14 +235,8 @@ static void roff_aux(int r_idx, int ego, int remem)
}
- /* Require a flag to show kills */
- if (!(show_details))
- {
- /* nothing */
- }
-
/* Treat uniques differently */
- else if (flags1 & (RF1_UNIQUE))
+ if (flags1 & (RF1_UNIQUE))
{
/* Hack -- Determine if the unique is "dead" */
bool_ dead = (r_ptr->max_num == 0) ? TRUE : FALSE;
@@ -339,12 +326,11 @@ static void roff_aux(int r_idx, int ego, int remem)
/* Descriptions */
- if (show_details)
{
char buf[2048];
/* Simple method */
- strcpy(buf, r_text + r_ptr->text);
+ strcpy(buf, r_ptr->text);
/* Dump it */
text_out(buf);
@@ -380,31 +366,17 @@ static void roff_aux(int r_idx, int ego, int remem)
text_out(", ");
else
text_out(format("%^s ", wd_he[msex]));
- if (depth_in_feet)
+
+ text_out(format("is normally found on level ", wd_he[msex]));
+ if (dun_level < r_ptr->level) /* out of depth monster */
{
- 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");
+ text_out_c(TERM_L_RED, format("%d", r_ptr->level));
}
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));
- }
+ text_out_c(TERM_L_GREEN, format("%d", r_ptr->level));
}
+
old = TRUE;
}
@@ -530,16 +502,16 @@ static void roff_aux(int r_idx, int ego, int remem)
long i, j;
/* calculate the integer exp part */
- i = (long)r_ptr->mexp * r_ptr->level / p_ptr->lev;
+ 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 = ((((long)r_ptr->mexp * r_ptr->level % p_ptr->lev) *
- (long)1000 / p_ptr->lev + 5) / 10);
+ 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", (long)i, (long)j));
+ text_out_c(TERM_ORANGE, format("%ld.%02ld", i, j));
text_out(" point");
text_out(((i == 1) && (j == 0)) ? "" : "s");
@@ -558,7 +530,7 @@ static void roff_aux(int r_idx, int ego, int remem)
/* Mention the dependance on the player's level */
text_out(format(" for a%s %lu%s level character. ",
- q, (long)i, p));
+ q, i, p));
}
}
@@ -824,7 +796,7 @@ static void roff_aux(int r_idx, int ego, int remem)
/* Describe monster "toughness" */
- if (know_armour(r_idx))
+ if (know_armour(r_ptr))
{
/* Armor */
text_out(format("%^s has an armor rating of ", wd_he[msex]));
@@ -1094,9 +1066,9 @@ static void roff_aux(int r_idx, int ego, int remem)
/* 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)))
+ if (((static_cast<int>(r_ptr->r_wake) * static_cast<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;
@@ -1485,7 +1457,7 @@ static void roff_aux(int r_idx, int ego, int remem)
text_out_c(TERM_YELLOW, q);
/* Describe damage (if known) */
- if (d1 && d2 && know_damage(r_idx, m))
+ if (d1 && d2 && know_damage(r_ptr, m))
{
/* Display the damage */
text_out(" with damage");
@@ -1524,7 +1496,7 @@ static void roff_aux(int r_idx, int ego, int remem)
if ((cheat_know) && (remem == 0))
{
/* Hack -- restore memory */
- COPY(r_ptr, &save_mem, monster_race);
+ *r_ptr = save_mem;
}
}
@@ -1533,18 +1505,15 @@ static void roff_aux(int r_idx, int ego, int remem)
*/
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;
+ const auto r_ptr = race_info_idx(r_idx, ego);
/* Access the chars */
- c1 = r_ptr->d_char;
- c2 = r_ptr->x_char;
+ const char c1 = r_ptr->d_char;
+ const char c2 = r_ptr->x_char;
/* Access the attrs */
- a1 = r_ptr->d_attr;
- a2 = r_ptr->x_attr;
+ const byte a1 = r_ptr->d_attr;
+ const byte a2 = r_ptr->x_attr;
/* A title (use "The" for non-uniques) */
if (!(r_ptr->flags1 & (RF1_UNIQUE)))
@@ -1555,24 +1524,28 @@ static void roff_name(int r_idx, int ego)
/* 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));
+ 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_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, "'):");
}
@@ -1595,6 +1568,8 @@ static void roff_top(int r_idx, int ego)
*/
void screen_roff(int r_idx, int ego, int remember)
{
+ auto r_ptr = race_info_idx(r_idx, ego);
+
/* Flush messages */
msg_print(NULL);
@@ -1602,19 +1577,20 @@ void screen_roff(int r_idx, int ego, int remember)
Term_erase(0, 1, 255);
/* Recall monster */
- roff_aux(r_idx, ego, remember);
+ roff_aux(r_ptr, remember);
/* Describe monster */
roff_top(r_idx, ego);
}
/*
- * Ddescribe the given monster race at the current pos of the "term" window
+ * 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_idx, ego, 0);
+ roff_aux(r_ptr, 0);
}
/*
@@ -1623,9 +1599,11 @@ void monster_description_out(int r_idx, int ego)
void display_roff(int r_idx, int ego)
{
int y;
+ int hgt;
+ Term_get_size(nullptr, &hgt);
/* Erase the window */
- for (y = 0; y < Term->hgt; y++)
+ for (y = 0; y < hgt; y++)
{
/* Erase the line */
Term_erase(0, y, 255);
@@ -1635,7 +1613,8 @@ void display_roff(int r_idx, int ego)
Term_gotoxy(0, 1);
/* Recall monster */
- roff_aux(r_idx, ego, 0);
+ auto r_ptr = race_info_idx(r_idx, ego);
+ roff_aux(r_ptr, 0);
/* Describe monster */
roff_top(r_idx, ego);
@@ -1670,7 +1649,7 @@ bool_ monster_dungeon(int r_idx)
}
-bool_ monster_ocean(int r_idx)
+static bool_ monster_ocean(int r_idx)
{
monster_race *r_ptr = &r_info[r_idx];
@@ -1681,7 +1660,7 @@ bool_ monster_ocean(int r_idx)
}
-bool_ monster_shore(int r_idx)
+static bool_ monster_shore(int r_idx)
{
monster_race *r_ptr = &r_info[r_idx];
@@ -1692,7 +1671,7 @@ bool_ monster_shore(int r_idx)
}
-bool_ monster_waste(int r_idx)
+static bool_ monster_waste(int r_idx)
{
monster_race *r_ptr = &r_info[r_idx];
@@ -1703,7 +1682,7 @@ bool_ monster_waste(int r_idx)
}
-bool_ monster_town(int r_idx)
+static bool_ monster_town(int r_idx)
{
monster_race *r_ptr = &r_info[r_idx];
@@ -1714,7 +1693,7 @@ bool_ monster_town(int r_idx)
}
-bool_ monster_wood(int r_idx)
+static bool_ monster_wood(int r_idx)
{
monster_race *r_ptr = &r_info[r_idx];
@@ -1725,7 +1704,7 @@ bool_ monster_wood(int r_idx)
}
-bool_ monster_volcano(int r_idx)
+static bool_ monster_volcano(int r_idx)
{
monster_race *r_ptr = &r_info[r_idx];
@@ -1736,7 +1715,7 @@ bool_ monster_volcano(int r_idx)
}
-bool_ monster_mountain(int r_idx)
+static bool_ monster_mountain(int r_idx)
{
monster_race *r_ptr = &r_info[r_idx];
@@ -1747,7 +1726,7 @@ bool_ monster_mountain(int r_idx)
}
-bool_ monster_grass(int r_idx)
+static bool_ monster_grass(int r_idx)
{
monster_race *r_ptr = &r_info[r_idx];
@@ -1758,7 +1737,7 @@ bool_ monster_grass(int r_idx)
}
-bool_ monster_deep_water(int r_idx)
+static bool_ monster_deep_water(int r_idx)
{
monster_race *r_ptr = &r_info[r_idx];
@@ -1771,7 +1750,7 @@ bool_ monster_deep_water(int r_idx)
}
-bool_ monster_shallow_water(int r_idx)
+static bool_ monster_shallow_water(int r_idx)
{
monster_race *r_ptr = &r_info[r_idx];
@@ -1784,7 +1763,7 @@ bool_ monster_shallow_water(int r_idx)
}
-bool_ monster_lava(int r_idx)
+static bool_ monster_lava(int r_idx)
{
monster_race *r_ptr = &r_info[r_idx];
@@ -1845,7 +1824,7 @@ void set_mon_num_hook(void)
/*
* Check if monster can cross terrain
*/
-bool_ monster_can_cross_terrain(byte feat, monster_race *r_ptr)
+bool_ monster_can_cross_terrain(byte feat, std::shared_ptr<monster_race> r_ptr)
{
/* Deep water */
if (feat == FEAT_DEEP_WATER)
diff --git a/src/monster1.hpp b/src/monster1.hpp
new file mode 100644
index 00000000..1d71fef1
--- /dev/null
+++ b/src/monster1.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+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);
diff --git a/src/monster2.c b/src/monster2.cc
index b0753244..3debb27a 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,13 +5,57 @@
* 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_info_type.hpp"
+#include "files.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_type.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_kind.hpp"
+#include "object_type.hpp"
+#include "options.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)
{
@@ -28,7 +68,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 +135,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,10 +164,9 @@ 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];
bool_ ok = FALSE;
int i;
@@ -169,7 +208,7 @@ 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)
{
/* Assume no ego */
int ego = 0, lvl;
@@ -179,7 +218,7 @@ int pick_ego_monster(int r_idx)
if ((!(dungeon_flags2 & DF2_ELVEN)) && (!(dungeon_flags2 & DF2_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;
@@ -192,10 +231,10 @@ int pick_ego_monster(int r_idx)
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;
@@ -216,7 +255,7 @@ int pick_ego_monster(int r_idx)
else if (dungeon_flags2 & DF2_DWARVEN)
ego = test_mego_name("Dwarven");
- if (mego_ok(r_idx, ego))
+ if (mego_ok(r_ptr, ego))
return ego;
}
@@ -228,34 +267,45 @@ 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;
+ monster_race *r_ptr = &r_info[r_idx];
- /* No work needed */
- if (!ego) return r_ptr;
+ /* 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.
+ });
+ }
- /* Copy the base monster */
- COPY(nr_ptr, r_ptr, monster_race);
+ /* We allocate a copy of the "base" monster race to refer to. */
+ auto nr_ptr = std::make_shared<monster_race>();
+ *nr_ptr = *r_ptr;
+
+ /* Get a reference to the ego monster modifiers */
+ monster_ego *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);
@@ -383,18 +433,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,23 +440,13 @@ 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;
- ;
-
-
/* 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;
@@ -426,6 +454,7 @@ void delete_monster_idx(int i)
if (r_ptr->flags4 & (RF4_MULTIPLY)) num_repro--;
/* XXX XXX XXX remove monster light source */
+ bool_ had_lite = FALSE;
if (r_ptr->flags9 & (RF9_HAS_LITE)) had_lite = TRUE;
@@ -438,7 +467,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,17 +482,15 @@ 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;
@@ -487,18 +515,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 +571,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 +609,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 +621,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 +663,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;
@@ -726,28 +727,20 @@ 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" */
@@ -1224,21 +1217,25 @@ 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 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);
+ if (re_info[m_ptr->ego].before)
+ {
+ sprintf(name, "%s %s", re_info[m_ptr->ego].name, r_ptr->name);
+ }
+ else
+ {
+ sprintf(name, "%s %s", r_ptr->name, re_info[m_ptr->ego].name);
+ }
}
else
{
- sprintf(name, "%s", b_name);
+ sprintf(name, "%s", r_ptr->name);
}
/*
@@ -1257,7 +1254,7 @@ void monster_desc(char *desc, monster_type *m_ptr, int mode)
}
while (hallu_race->flags1 & RF1_UNIQUE);
- strcpy(silly_name, (r_name + hallu_race->name));
+ strcpy(silly_name, hallu_race->name);
}
else
{
@@ -1273,7 +1270,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)
{
@@ -1289,7 +1285,7 @@ void monster_desc(char *desc, monster_type *m_ptr, int mode)
/* Assume simple result */
- res = "it";
+ cptr res = "it";
/* Brute force: split on the possibilities */
switch (kind | (mode & 0x07))
@@ -1434,17 +1430,22 @@ void monster_desc(char *desc, monster_type *m_ptr, int mode)
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);
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);
+ if (re_info[ego].before)
+ {
+ sprintf(name, "%s %s", re_info[ego].name, r_ptr->name);
+ }
+ else
+ {
+ sprintf(name, "%s %s", r_ptr->name, re_info[ego].name);
+ }
}
else
{
- sprintf(name, "%s", b_name);
+ sprintf(name, "%s", r_ptr->name);
}
/* It could be a Unique */
@@ -1526,23 +1527,24 @@ void lore_treasure(int m_idx, int num_item, int num_gold)
-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))
@@ -1595,7 +1597,7 @@ void sanity_blast(monster_type * m_ptr, bool_ necro)
}
/* Undead characters are 50% likely to be unaffected */
- if ((PRACE_FLAG(PR1_UNDEAD)) || (p_ptr->mimic_form == resolve_mimic_name("Vampire")))
+ if ((race_flags1_p(PR1_UNDEAD)) || (p_ptr->mimic_form == resolve_mimic_name("Vampire")))
{
if (randint(100) < (25 + (p_ptr->lev))) return;
}
@@ -1604,6 +1606,7 @@ 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)
@@ -1633,7 +1636,7 @@ void sanity_blast(monster_type * m_ptr, bool_ necro)
}
if (!p_ptr->free_act)
{
- (void)set_paralyzed(p_ptr->paralyzed + rand_int(4) + 4);
+ (void)set_paralyzed(rand_int(4) + 4);
}
while (rand_int(100) > p_ptr->skill_sav)
(void)do_dec_stat(A_INT, STAT_DEC_NORMAL);
@@ -1726,13 +1729,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;
@@ -1749,18 +1750,17 @@ void update_mon(int m_idx, bool_ full)
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 +1777,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))
{
@@ -1878,7 +1877,7 @@ 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);
@@ -1889,7 +1888,7 @@ void update_mon(int m_idx, bool_ full)
/* Disturb on appearance */
if (disturb_move)
{
- if (disturb_pets || (is_friend(m_ptr) <= 0)) disturb(1, 0);
+ if (disturb_pets || (is_friend(m_ptr) <= 0)) disturb(1);
}
}
@@ -1921,7 +1920,7 @@ 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);
@@ -1929,7 +1928,7 @@ void update_mon(int m_idx, bool_ full)
/* Disturb on disappearance*/
if (disturb_move)
{
- if (disturb_pets || (is_friend(m_ptr) <= 0)) disturb(1, 0);
+ if (disturb_pets || (is_friend(m_ptr) <= 0)) disturb(1);
}
}
}
@@ -1956,7 +1955,7 @@ void update_mon(int m_idx, bool_ full)
/* Disturb on appearance */
if (disturb_near)
{
- if (disturb_pets || (is_friend(m_ptr) <= 0)) disturb(1, 0);
+ if (disturb_pets || (is_friend(m_ptr) <= 0)) disturb(1);
}
}
@@ -1977,7 +1976,7 @@ void update_mon(int m_idx, bool_ full)
/* Disturb on disappearance */
if (disturb_near)
{
- if (disturb_pets || (is_friend(m_ptr) <= 0)) disturb(1, 0);
+ if (disturb_pets || (is_friend(m_ptr) <= 0)) disturb(1);
}
}
}
@@ -2023,13 +2022,11 @@ void monster_carry(monster_type *m_ptr, int m_idx, object_type *q_ptr)
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
@@ -2109,9 +2106,9 @@ 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)
{
int i;
@@ -2119,31 +2116,15 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status)
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 +2132,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 +2139,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 +2162,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,53 +2169,48 @@ 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;
- }
+ monster_race *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->flags1 & RF1_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;
}
@@ -2248,7 +2218,6 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status)
if ((r_ptr->flags9 & RF9_SPECIAL_GENE) && (!m_allow_special[r_idx]))
{
if (wizard) cmsg_format(TERM_L_RED, "WARNING: Refused monster(%d): SPECIAL_GENE", r_idx);
- if (place_monster_one_race) KILL(place_monster_one_race, monster_race);
return 0;
}
@@ -2256,7 +2225,6 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status)
if ((r_ptr->flags7 & RF7_SPIRIT) && (dungeon_type != DUNGEON_VOID))
{
if (wizard) cmsg_format(TERM_L_RED, "WARNING: Refused monster(%d): SPIRIT in non VOID", r_idx);
- if (place_monster_one_race) KILL(place_monster_one_race, monster_race);
return 0;
}
@@ -2264,7 +2232,6 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status)
if (r_ptr->flags9 & RF9_NEVER_GENE)
{
if (wizard) cmsg_print(TERM_L_RED, "WARNING: Refused monster: NEVER_GENE");
- if (place_monster_one_race) KILL(place_monster_one_race, monster_race);
return 0;
}
@@ -2273,7 +2240,6 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status)
{
/* Cannot create */
if (wizard) cmsg_format(TERM_L_RED, "WARNING: Refused monster %d: unique not unique", r_idx);
- if (place_monster_one_race) KILL(place_monster_one_race, monster_race);
return 0;
}
@@ -2281,7 +2247,6 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status)
if (r_ptr->on_saved)
{
if (wizard) cmsg_print(TERM_L_RED, "WARNING: Refused monster: unique already on saved level");
- if (place_monster_one_race) KILL(place_monster_one_race, monster_race);
return 0;
}
@@ -2290,7 +2255,6 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status)
{
/* Cannot create */
if (wizard) cmsg_format(TERM_L_RED, "WARNING: Refused monster %d: cur_num >= max_num", r_idx);
- if (place_monster_one_race) KILL(place_monster_one_race, monster_race);
return 0;
}
@@ -2299,7 +2263,6 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status)
{
/* Cannot create */
if (wizard) cmsg_print(TERM_L_RED, "WARNING: FORCE_DEPTH");
- if (place_monster_one_race) KILL(place_monster_one_race, monster_race);
return 0;
}
@@ -2310,7 +2273,7 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status)
if (r_ptr->flags1 & (RF1_UNIQUE))
{
/* Message for cheaters */
- if ((cheat_hear) || (p_ptr->precognition)) msg_format("Deep Unique (%s).", name);
+ if ((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 +2283,7 @@ 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 ((cheat_hear) || (p_ptr->precognition)) msg_format("Deep Monster (%s).", r_ptr->name);
/* Boost rating by delta-depth */
rating += (r_ptr->level - dun_level);
@@ -2331,12 +2294,12 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status)
else if (r_ptr->flags1 & (RF1_UNIQUE))
{
/* Unique monsters induce message */
- if ((cheat_hear) || (p_ptr->precognition)) msg_format("Unique (%s).", name);
+ if ((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 +2308,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,7 +2341,7 @@ 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;
@@ -2411,15 +2369,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->flags1 & (RF1_DROP_GOOD)) ? TRUE : FALSE;
+ const bool_ great = (r_ptr->flags1 & (RF1_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;
+ const bool_ do_gold = (!(r_ptr->flags1 & (RF1_ONLY_ITEM)));
+ const bool_ do_item = (!(r_ptr->flags1 & (RF1_ONLY_GOLD)));
+ const bool_ do_mimic = (r_ptr->flags9 & (RF9_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;
@@ -2447,7 +2404,6 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status)
{
int tries = 1000;
obj_theme theme;
- int i;
/* Get local object */
q_ptr = &forge;
@@ -2465,7 +2421,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--;
@@ -2494,7 +2450,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;
@@ -2578,7 +2534,7 @@ 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;
@@ -2643,11 +2599,14 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status)
/* Hack -- Notice new multi-hued monsters */
if (r_ptr->flags1 & (RF1_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 */
+ monster_race *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))
@@ -2655,7 +2614,11 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status)
r_ptr->on_saved = TRUE;
}
- place_monster_one_race = NULL;
+ /* Processs hooks */
+ {
+ hook_new_monster_end_in in = { m_ptr };
+ process_hooks_new(HOOK_NEW_MONSTER_END, &in, NULL);
+ }
/* Success */
place_monster_result = c_ptr->m_idx;
@@ -2739,7 +2702,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;
@@ -2818,7 +2781,7 @@ bool_ place_monster_aux(int y, int x, int r_idx, bool_ slp, bool_ grp, int statu
/* 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 */
@@ -2876,7 +2839,7 @@ 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)) ||
@@ -2934,8 +2897,6 @@ bool_ place_monster(int y, int x, bool_ slp, bool_ grp)
}
-#ifdef MONSTER_HORDES
-
bool_ alloc_horde(int y, int x)
{
int r_idx = 0;
@@ -2993,8 +2954,6 @@ bool_ alloc_horde(int y, int x)
return TRUE;
}
-#endif /* MONSTER_HORDES */
-
/*
* Attempt to allocate a random monster in the dungeon.
*
@@ -3034,7 +2993,6 @@ bool_ alloc_monster(int dis, bool_ slp)
}
-#ifdef MONSTER_HORDES
if (randint(5000) <= dun_level)
{
if (alloc_horde(y, x))
@@ -3045,14 +3003,11 @@ bool_ alloc_monster(int dis, bool_ slp)
}
else
{
-#endif /* MONSTER_HORDES */
/* Attempt to place the monster, allow groups */
if (place_monster(y, x, slp, TRUE)) return (TRUE);
-#ifdef MONSTER_HORDES
}
-#endif /* MONSTER_HORDES */
/* Nope */
return (FALSE);
@@ -3070,7 +3025,7 @@ 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];
@@ -3235,7 +3190,7 @@ bool_ summon_specific_okay(int r_idx)
case SUMMON_DAWN:
{
- okay = ((strstr((r_name + r_ptr->name), "the Dawn")) &&
+ okay = ((strstr(r_ptr->name, "the Dawn")) &&
!(r_ptr->flags1 & (RF1_UNIQUE)));
break;
}
@@ -3284,14 +3239,14 @@ bool_ summon_specific_okay(int r_idx)
case SUMMON_PHANTOM:
{
- okay = ((strstr((r_name + r_ptr->name), "Phantom")) &&
+ okay = ((strstr(r_ptr->name, "Phantom")) &&
!(r_ptr->flags1 & (RF1_UNIQUE)));
break;
}
case SUMMON_ELEMENTAL:
{
- okay = ((strstr((r_name + r_ptr->name), "lemental")) &&
+ okay = ((strstr(r_ptr->name, "lemental")) &&
!(r_ptr->flags1 & (RF1_UNIQUE)));
break;
}
@@ -3304,21 +3259,21 @@ bool_ summon_specific_okay(int r_idx)
case SUMMON_BLUE_HORROR:
{
- okay = ((strstr((r_name + r_ptr->name), "lue horror")) &&
+ okay = ((strstr(r_ptr->name, "lue horror")) &&
!(r_ptr->flags1 & (RF1_UNIQUE)));
break;
}
case SUMMON_BUG:
{
- okay = ((strstr((r_name + r_ptr->name), "Software bug")) &&
+ okay = ((strstr(r_ptr->name, "Software bug")) &&
!(r_ptr->flags1 & (RF1_UNIQUE)));
break;
}
case SUMMON_RNG:
{
- okay = ((strstr((r_name + r_ptr->name), "Random Number Generator")) &&
+ okay = ((strstr(r_ptr->name, "Random Number Generator")) &&
!(r_ptr->flags1 & (RF1_UNIQUE)));
break;
}
@@ -3349,11 +3304,6 @@ bool_ summon_specific_okay(int r_idx)
break;
}
- case SUMMON_LUA:
- {
- okay = summon_lua_okay(r_idx);
- break;
- }
}
/* Result */
@@ -3441,10 +3391,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 +3471,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;
@@ -3681,10 +3623,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 +3635,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 +3696,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);
}
}
@@ -3889,17 +3824,17 @@ 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 (!smart_learn) return;
+ /* Get racial flags */
+ auto const r_ptr = m_ptr->race();
+
/* Too stupid to learn anything */
if (r_ptr->flags2 & (RF2_STUPID)) return;
/* Not intelligent, only learn sometimes */
- if (!(r_ptr->flags2 & (RF2_SMART)) && (rand_int(100) < 50)) return;
+ if (!(r_ptr->flags2 & (RF2_SMART)) && magik(50)) return;
/* XXX XXX XXX */
@@ -4018,26 +3953,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 +3981,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..84f79e36
--- /dev/null
+++ b/src/monster2.hpp
@@ -0,0 +1,52 @@
+#pragma once
+
+#include "h-basic.h"
+#include "monster_race_fwd.hpp"
+#include "monster_type_fwd.hpp"
+#include "object_type_fwd.hpp"
+#include <memory>
+
+extern s32b monster_exp(s16b level);
+extern void monster_set_level(int m_idx, int level);
+extern s32b modify_aux(s32b a, s32b b, char mod);
+extern void monster_msg_simple(cptr s);
+extern bool_ mego_ok(monster_race const *r_ptr, 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 std::shared_ptr<monster_race> race_info_idx(int r_idx, int ego);
+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 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 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 void set_mon_num_hook(void);
+extern void set_mon_num2_hook(int y, int x);
+extern 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..0d26538c 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,25 @@
* included in all such copies.
*/
-#include "angband.h"
+#include "monster3.hpp"
+
+#include "cave_type.hpp"
+#include "cmd2.hpp"
+#include "gods.hpp"
+#include "melee2.hpp"
+#include "monster2.hpp"
+#include "monster_race.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, ..)
@@ -59,7 +73,7 @@ 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)
@@ -189,7 +203,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;
@@ -264,7 +278,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;
@@ -332,12 +346,10 @@ bool_ do_control_walk(void)
bool_ do_control_inven(void)
{
- 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);
+ (void) show_monster_inven(p_ptr->control);
inkey();
screen_load();
return TRUE;
@@ -345,24 +357,23 @@ bool_ do_control_inven(void)
bool_ do_control_pickup(void)
{
- 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,14 +390,19 @@ 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;
}
- if (done) msg_print("You pick up all objects on the floor.");
+
+ /* Feedback */
+ if (done)
+ {
+ msg_print("You pick up all objects on the floor.");
+ }
+
return TRUE;
}
diff --git a/src/monster3.hpp b/src/monster3.hpp
new file mode 100644
index 00000000..7cf8ccd0
--- /dev/null
+++ b/src/monster3.hpp
@@ -0,0 +1,20 @@
+#pragma once
+
+#include "h-basic.h"
+#include "monster_type_fwd.hpp"
+
+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);
diff --git a/src/monster_blow.hpp b/src/monster_blow.hpp
new file mode 100644
index 00000000..0f19f64c
--- /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;
+ byte effect;
+ byte d_dice;
+ byte d_side;
+};
diff --git a/src/monster_ego.hpp b/src/monster_ego.hpp
new file mode 100644
index 00000000..00464c2e
--- /dev/null
+++ b/src/monster_ego.hpp
@@ -0,0 +1,81 @@
+#pragma once
+
+#include "h-basic.h"
+#include "monster_blow.hpp"
+
+/**
+ * Monster ego descriptors.
+ */
+struct monster_ego
+{
+ const char *name; /* Name */
+ 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 */
+};
diff --git a/src/monster_ego_fwd.hpp b/src/monster_ego_fwd.hpp
new file mode 100644
index 00000000..5b47f3e9
--- /dev/null
+++ b/src/monster_ego_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct monster_ego;
diff --git a/src/monster_power.hpp b/src/monster_power.hpp
new file mode 100644
index 00000000..03d0f8a9
--- /dev/null
+++ b/src/monster_power.hpp
@@ -0,0 +1,14 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * Monster powers that players can use via e.g. Symbiosis.
+ */
+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 */
+};
diff --git a/src/monster_race.hpp b/src/monster_race.hpp
new file mode 100644
index 00000000..7e5d5082
--- /dev/null
+++ b/src/monster_race.hpp
@@ -0,0 +1,116 @@
+#pragma once
+
+#include "body.hpp"
+#include "h-basic.h"
+#include "monster_blow.hpp"
+#include "obj_theme.hpp"
+
+/**
+ * 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; /* Name */
+ char *text; /* Text */
+
+ 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 */
+};
+
+
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_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..8353f228
--- /dev/null
+++ b/src/monster_type.hpp
@@ -0,0 +1,98 @@
+#pragma once
+
+#include "h-basic.h"
+#include "monster_blow.hpp"
+#include "monster_race_fwd.hpp"
+
+#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 */
+
+ monster_blow blow[4] = { /* Up to four blows per round */
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ };
+
+ 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..326381c9 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,7 +7,15 @@
* included in all such copies.
*/
-#include "angband.h"
+#include "notes.hpp"
+
+#include "files.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
@@ -49,9 +53,6 @@ void output_note(char *final_note)
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);
basename[sizeof(basename) - 1] = '\0';
@@ -66,7 +67,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 +86,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 +113,13 @@ void add_note(char *note, char code)
*/
void add_note_type(int note_number)
{
- char long_day[50], true_long_day[50];
+ 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 +129,10 @@ 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);
+ 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);
/* Add in "character start" information */
sprintf(buf,
@@ -155,7 +152,7 @@ void add_note_type(int note_number)
"%s slew Morgoth on %s\n"
"Long live %s!\n"
"================================================",
- player_name, long_day, player_name);
+ player_name, true_long_day, player_name);
break;
}
diff --git a/src/notes.hpp b/src/notes.hpp
new file mode 100644
index 00000000..e8c22bb7
--- /dev/null
+++ b/src/notes.hpp
@@ -0,0 +1,6 @@
+#pragma once
+
+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);
diff --git a/src/obj_theme.hpp b/src/obj_theme.hpp
new file mode 100644
index 00000000..13f185e8
--- /dev/null
+++ b/src/obj_theme.hpp
@@ -0,0 +1,15 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * Object theme. Probability in percent for each class of
+ * objects to be dropped.
+ */
+struct obj_theme
+{
+ byte treasure;
+ byte combat;
+ byte magic;
+ byte tools;
+};
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..6bbf23e9 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,56 @@
* 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 "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_type.hpp"
+#include "object2.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 "quark.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 "trap_type.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 <cassert>
+
+static bool_ apply_flags_set(s16b a_idx, s16b set_idx,
+ u32b *f1, u32b *f2, u32b *f3, u32b *f4, u32b *f5, u32b *esp);
/*
* Hack -- note that "TERM_MULTI" is now just "TERM_VIOLET".
@@ -24,6 +68,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
*/
@@ -276,7 +326,7 @@ 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(int k_idx)
{
object_kind *k_ptr = &k_info[k_idx];
@@ -335,39 +385,6 @@ static bool_ object_flavor(int k_idx)
}
-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;
-}
-
-
/*
* Certain items, if aware, are known instantly
* This function is used only by "flavor_init()"
@@ -409,7 +426,6 @@ 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)
return ( FALSE );
@@ -678,7 +694,7 @@ 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
*/
@@ -757,72 +773,15 @@ void reset_visuals(void)
}
- 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;
- }
- }
-
/* 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, u32b *f2, u32b *f3, u32b *esp)
{
switch (o_ptr->xtra1)
{
@@ -939,7 +898,7 @@ void object_flags_xtra(object_type *o_ptr, u32b *f2, u32b *f3, u32b *esp)
* 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)
+void object_flags(object_type const *o_ptr, u32b *f1, u32b *f2, u32b *f3, u32b *f4, u32b *f5, u32b *esp)
{
object_kind *k_ptr = &k_info[o_ptr->k_idx];
@@ -1025,10 +984,8 @@ 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)
+void object_flags_known(object_type const *o_ptr, u32b *f1, u32b *f2, u32b *f3, u32b *f4, u32b *f5, u32b *esp)
{
- bool_ spoil = FALSE;
-
object_kind *k_ptr = &k_info[o_ptr->k_idx];
/* Clear */
@@ -1052,23 +1009,13 @@ void object_flags_known(object_type *o_ptr, u32b *f1, u32b *f2, u32b *f3, u32b *
(*f5) |= k_ptr->oflags5;
(*esp) |= k_ptr->oesp;
-#ifdef SPOIL_ARTIFACTS
- /* Full knowledge for some artifacts */
- if (artifact_p(o_ptr) || o_ptr->art_name) spoil = TRUE;
-#endif /* SPOIL_ARTIFACTS */
-
-#ifdef SPOIL_EGO_ITEMS
- /* Full knowledge for some ego-items */
- if (ego_item_p(o_ptr)) spoil = TRUE;
-#endif /* SPOIL_EGO_ITEMS */
-
/* Artifact */
if (o_ptr->name1)
{
artifact_type *a_ptr = &a_info[o_ptr->name1];
/* Need full knowledge or spoilers */
- if (spoil || (o_ptr->ident & IDENT_MENTAL))
+ if ((o_ptr->ident & IDENT_MENTAL))
{
(*f1) = a_ptr->flags1;
(*f2) = a_ptr->flags2;
@@ -1097,7 +1044,7 @@ void object_flags_known(object_type *o_ptr, u32b *f1, u32b *f2, u32b *f3, u32b *
if (o_ptr->art_flags1 || o_ptr->art_flags2 || o_ptr->art_flags3 || o_ptr->art_flags4 || o_ptr->art_flags5 || o_ptr->art_esp)
{
/* Need full knowledge or spoilers */
- if (spoil || (o_ptr->ident & IDENT_MENTAL))
+ if ((o_ptr->ident & IDENT_MENTAL))
{
(*f1) |= o_ptr->art_flags1;
(*f2) |= o_ptr->art_flags2;
@@ -1332,7 +1279,7 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
indexx = o_ptr->sval;
/* Extract default "base" string */
- basenm = (k_name + k_ptr->name);
+ basenm = k_ptr->name;
/* Assume no "modifier" string */
modstr = "";
@@ -1407,12 +1354,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->art_name && artifact_p(o_ptr))
+ {
+ basenm = k_ptr->name;
+ }
break;
}
@@ -1424,7 +1374,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 +1382,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->art_name && artifact_p(o_ptr))
+ {
+ basenm = k_ptr->name;
+ }
break;
}
@@ -1442,7 +1395,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 +1407,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 +1419,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 +1433,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 +1442,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 +1460,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 +1477,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 +1491,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 +1519,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;
@@ -1595,9 +1539,9 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
monster_race* r_ptr = &r_info[o_ptr->pval2];
modstr = basenm;
if (r_ptr->flags1 & RF1_UNIQUE)
- basenm = format("& %s's #~", r_name + r_ptr->name);
+ basenm = format("& %s's #~", r_ptr->name);
else
- basenm = format("& %s #~", r_name + r_ptr->name);
+ basenm = format("& %s #~", r_ptr->name);
break;
}
@@ -1606,7 +1550,7 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
monster_race* r_ptr = &r_info[o_ptr->pval2];
modstr = basenm;
- basenm = format("& %s #~", r_name + r_ptr->name);
+ basenm = format("& %s #~", r_ptr->name);
break;
}
@@ -1615,7 +1559,7 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
/* We print hit points further down. --dsb */
monster_race* r_ptr = &r_info[o_ptr->pval];
modstr = basenm;
- basenm = format("& %s~", r_name + r_ptr->name);
+ basenm = format("& %s~", r_ptr->name);
break;
}
@@ -1624,7 +1568,6 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
char name[80];
monster_type monster;
- monster.sr_ptr = 0;
monster.r_idx = o_ptr->pval;
monster.ego = o_ptr->pval2;
monster.ml = TRUE;
@@ -1672,31 +1615,27 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
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;
- }
+ strcpy(buf, "(nothing)");
+ return;
}
}
/* Mega Hack */
- if ((!hack_name) && known && (k_ptr->flags5 & TR5_FULL_NAME)) basenm = (k_name + k_ptr->name);
+ if ((!hack_name) && known && (k_ptr->flags5 & TR5_FULL_NAME))
+ {
+ basenm = k_ptr->name;
+ }
/* Start dumping the result */
@@ -1719,11 +1658,11 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
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;
}
}
@@ -1800,12 +1739,12 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
if (e_ptr->before)
{
- t = object_desc_str(t, (e_name + e_ptr->name));
+ t = object_desc_str(t, e_ptr->name);
t = object_desc_chr(t, ' ');
}
if (e2_ptr->before)
{
- t = object_desc_str(t, (e_name + e2_ptr->name));
+ t = object_desc_str(t, e2_ptr->name);
t = object_desc_chr(t, ' ');
}
}
@@ -1878,12 +1817,12 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
if (e_ptr->before)
{
- t = object_desc_str(t, (e_name + e_ptr->name));
+ t = object_desc_str(t, e_ptr->name);
t = object_desc_chr(t, ' ');
}
if (e2_ptr->before)
{
- t = object_desc_str(t, (e_name + e2_ptr->name));
+ t = object_desc_str(t, e2_ptr->name);
t = object_desc_chr(t, ' ');
}
}
@@ -1924,8 +1863,7 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
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));
+ t = object_desc_str(t, e_ptr->name);
}
}
@@ -1952,7 +1890,7 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
if (((o_ptr->tval == TV_WAND) || (o_ptr->tval == TV_STAFF)))
{
- t = object_desc_str(t, school_spells[o_ptr->pval2].name);
+ t = object_desc_str(t, spell_type_name(spell_at(o_ptr->pval2)));
if (mode >= 1)
{
s32b bonus = o_ptr->pval3 & 0xFFFF;
@@ -1966,7 +1904,9 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
}
}
else
- t = object_desc_str(t, (k_name + k_ptr->name));
+ {
+ t = object_desc_str(t, k_ptr->name);
+ }
}
/* Hack -- Append "Artifact" or "Special" names */
@@ -2006,7 +1946,7 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
if (o_ptr->tval != TV_CORPSE)
{
t = object_desc_chr(t, ' ');
- t = object_desc_str(t, (a_name + a_ptr->name));
+ t = object_desc_str(t, a_ptr->name);
}
}
@@ -2019,12 +1959,12 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
if (o_ptr->name2 && !e_ptr->before)
{
t = object_desc_chr(t, ' ');
- t = object_desc_str(t, (e_name + e_ptr->name));
+ t = object_desc_str(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 = object_desc_str(t, e2_ptr->name);
}
}
}
@@ -2032,7 +1972,7 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
/* It contains a spell */
if ((known) && (f5 & TR5_SPELL_CONTAIN) && (o_ptr->pval2 != -1))
{
- t = object_desc_str(t, format(" [%s]", school_spells[o_ptr->pval2].name));
+ t = object_desc_str(t, format(" [%s]", spell_type_name(spell_at(o_ptr->pval2))));
}
/* Add symbiote hp here, after the "fake-artifact" name. --dsb */
@@ -2050,27 +1990,20 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
if ((f4 & TR4_LEVELS) && known)
{
t = object_desc_str(t, " (E:");
- if (exp_need)
+ if (o_ptr->elevel < PY_MAX_LEVEL)
{
- s32b need;
/* Formula from check_experience_obj(). */
- need = player_exp[o_ptr->elevel - 1] * 5 / 2;
+ s32b 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, "*****");
}
t = object_desc_str(t, ", L:");
t = object_desc_num(t, o_ptr->elevel);
t = object_desc_chr(t, ')');
}
- if ((f4 & TR4_ART_EXP) && known)
- {
- t = object_desc_str(t, " (Exp:");
- t = object_desc_num(t, o_ptr->exp);
- t = object_desc_chr(t, ')');
- }
/* Hack -- Chests must be described in detail */
if (o_ptr->tval == TV_CHEST)
@@ -2099,9 +2032,13 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
/* 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);
+ {
+ t = object_desc_str(t, t_info[o_ptr->pval].name);
+ }
else
+ {
t = object_desc_str(t, "trapped");
+ }
t = object_desc_str(t, ")");
}
}
@@ -2245,28 +2182,14 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode)
if ((f1 & TR1_MANA) && (known) && (o_ptr->pval > 0))
{
t = object_desc_chr(t, '(');
- if (munchkin_multipliers)
- {
- t = object_desc_num(t, 100 * o_ptr->pval / 5);
- }
- else
- {
- t = object_desc_num(t, 100 * o_ptr->pval / 10);
- }
+ t = object_desc_num(t, 100 * o_ptr->pval / 5);
t = object_desc_str(t, "%)");
}
if ((known) && (f2 & TR2_LIFE) ) /* Can disp neg now -- Improv */
{
t = object_desc_chr(t, '(');
- if (munchkin_multipliers)
- {
- t = object_desc_num(t, 100 * o_ptr->pval / 5);
- }
- else
- {
- t = object_desc_num(t, 100 * o_ptr->pval / 10);
- }
+ t = object_desc_num(t, 100 * o_ptr->pval / 5);
t = object_desc_str(t, "%)");
}
@@ -2578,8 +2501,8 @@ cptr item_activation(object_type *o_ptr, byte num)
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,
+ k_info[lookup_kind(TV_RUNE1, gf)].name,
+ k_info[lookup_kind(TV_RUNE2, mod)].name,
mana, mana * 5);
return rspell[num];
}
@@ -2602,14 +2525,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;
@@ -2826,28 +2746,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, 0));
+ text_out_c(TERM_L_BLUE, buf);
text_out("\nMinimum Magic Device level to increase spell level: ");
- text_out_c(TERM_L_BLUE, format("%d", school_spells[o_ptr->pval2].skill_level));
+ text_out_c(TERM_L_BLUE, format("%d", spell_type_skill_level(spell)));
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();
@@ -2868,15 +2799,25 @@ static cptr object_out_desc_where_found(s16b level, s16b dungeon)
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);
+ }
return str;
}
@@ -2888,7 +2829,7 @@ bool_ object_out_desc(object_type *o_ptr, FILE *fff, bool_ trim_down, bool_ wait
{
u32b f1, f2, f3, f4, f5, esp;
- char *txt;
+ const char *txt;
cptr vp[64];
byte vc[64];
@@ -2940,7 +2881,7 @@ bool_ object_out_desc(object_type *o_ptr, FILE *fff, bool_ trim_down, bool_ wait
{
object_kind *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");
}
@@ -2948,14 +2889,12 @@ bool_ object_out_desc(object_type *o_ptr, FILE *fff, bool_ trim_down, bool_ wait
{
artifact_type *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);
text_out("\n");
}
}
@@ -3047,7 +2986,7 @@ 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 (f4 & TR4_ANTIMAGIC_50)
{
text_out("It generates an antimagic field. ");
}
@@ -3135,7 +3074,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)
@@ -3864,12 +3803,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));
}
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));
}
else if (o_ptr->found == OBJ_FOUND_SELFMADE)
{
@@ -3929,7 +3868,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 +3890,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 +3911,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,11 +3941,25 @@ 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;
+ /* Theme has restrictions for winged races. */
+ if (game_module_idx == MODULE_THEME)
+ {
+ cptr race_name = rp_ptr->title;
+
+ if (streq(race_name, "Dragon") ||
+ streq(race_name, "Eagle"))
+ {
+ switch (o_ptr->tval)
+ {
+ case TV_CLOAK:
+ case TV_HARD_ARMOR:
+ case TV_DRAG_ARMOR:
+ return -1;
+ }
+ }
+ }
/* Slot for equipment */
switch (o_ptr->tval)
@@ -4145,6 +4098,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 +4127,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 +4135,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 +4240,7 @@ cptr mention_use(int i)
*/
cptr describe_use(int i)
{
- cptr p;
+ cptr p = nullptr;
switch (i)
{
@@ -4366,45 +4338,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, bool_ everything, object_filter_t const &filter);
+static void show_inven_aux(bool_ mirror, bool_ everything, object_filter_t const &filter);
/*
* Choice window "shadow" of the "show_inven()" function
*/
void display_inven(void)
{
- show_inven_aux(TRUE, inventory_no_move);
+ show_inven_aux(TRUE, inventory_no_move, object_filter::True());
}
@@ -4414,7 +4383,7 @@ void display_inven(void)
*/
void display_equip(void)
{
- show_equip_aux(TRUE, inventory_no_move);
+ show_equip_aux(TRUE, inventory_no_move, object_filter::True());
}
@@ -4441,7 +4410,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, bool_ everything, const object_filter_t &filter)
{
int i, j, k, l, z = 0;
int row, col, len, lim;
@@ -4469,11 +4438,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,7 +4462,7 @@ 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;
@@ -4519,10 +4488,10 @@ void show_inven_aux(bool_ mirror, bool_ everything)
l = strlen(out_desc[k]) + 5;
/* Be sure to account for the weight */
- if (show_weights) l += 9;
+ l += 9;
- /* Account for icon if displayed */
- if (show_inven_graph) l += 2;
+ /* Account for icon */
+ l += 2;
/* Maintain the maximum length */
if (l > len) len = l;
@@ -4557,8 +4526,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 +4536,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 +4551,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 +4570,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, FALSE, filter);
+}
+
+void show_inven_full()
+{
+ item_tester_full = true;
+ show_inven(object_filter::True());
+ item_tester_full = false;
+}
+
+static void show_equip(object_filter_t const &filter)
{
- show_inven_aux(FALSE, FALSE);
+ show_equip_aux(FALSE, FALSE, filter);
}
-void show_equip()
+void show_equip_full()
{
- show_equip_aux(FALSE, FALSE);
+ 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, bool_ everything, object_filter_t const &filter)
{
int i, j, k, l;
int row, col, len, lim, idx;
@@ -4644,13 +4626,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;
@@ -4701,7 +4684,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;
@@ -4725,7 +4708,7 @@ 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;
@@ -4746,12 +4729,13 @@ void show_equip_aux(bool_ mirror, bool_ everything)
l = strlen(out_desc[k]) + (2 + 3);
/* Increase length for labels (if needed) */
- if (show_labels) l += (14 + 2);
+ l += (14 + 2);
- /* Increase length for weight (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 +4771,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 +4782,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);
-
- /* Display the entry itself */
- c_put_str(out_color[j], out_desc[j], row + j, show_equip_graph ? col + 21 : col + 19);
- }
+ put_str(tmp_val, row + j, col + 5);
- /* 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);
+ c_put_str(out_color[j], out_desc[j], row + j, col + 21);
}
- /* 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 +4803,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);
@@ -4956,16 +4933,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);
}
@@ -5035,61 +5012,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 +5065,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 +5102,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 +5137,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 +5152,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 +5165,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 +5176,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 +5195,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 +5215,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 +5237,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 +5249,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 +5267,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,7 +5314,6 @@ bool_ get_item_floor(int *cp, cptr pmt, cptr str, int mode)
while (!done)
{
/* Show choices */
- if (show_choices)
{
int ni = 0;
int ne = 0;
@@ -5416,7 +5357,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 +5368,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 +5382,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 +5448,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 +5602,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 +5661,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 +5683,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 +5748,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 +5780,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 +5794,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 +5867,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 +5948,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 +5962,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 +5982,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 +5992,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 +6051,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 +6097,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);
- }
- }
-
- /* Squeltch the floor */
- squeltch_grid();
+ /* Copy list of objects since we're going to manipulate the list itself */
+ auto const object_idxs(c_ptr->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)
+ /* 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(0);
/* Pick up gold */
if (o_ptr->tval == TV_GOLD)
@@ -6234,139 +6118,174 @@ 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);
}
+ }
+
+ /* Sense floor tile */
+ sense_objects(floor_object_idxs);
+}
- /* Count non-gold */
- floor_num++;
+void py_pickup_floor(int pickup)
+{
+ /* Get the tile */
+ auto c_ptr = &cave[p_ptr->py][p_ptr->px];
- /* Remember this index */
- floor_o_idx = this_o_idx;
+ /* Hack -- ignore monster traps */
+ if (c_ptr->feat == FEAT_MON_TRAP)
+ {
+ return;
}
- /* There were no non-gold items */
- if (!floor_num) return;
+ /* Try to grab ammo */
+ pickup_ammo();
+
+ /* Auto-ID and pseudo-ID */
+ sense_floor(c_ptr);
+
+ /* Squeltch the floor */
+ squeltch_grid();
+
+ /* 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())
{
- /* One item */
- if (floor_num == 1)
+ /* Nothing to do */
+ }
+ else if (c_ptr->o_idxs.size() == 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 (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;
@@ -6391,7 +6310,7 @@ void gain_flag_group(object_type *o_ptr, bool_ silent)
o_ptr->pval2 -= flags_groups[grp].price;
o_ptr->pval3 |= BIT(grp);
- if (!silent)
+ /* Message */
{
char o_name[80];
@@ -6400,7 +6319,7 @@ void gain_flag_group(object_type *o_ptr, bool_ silent)
}
}
-u32b get_flag(object_type *o_ptr, int grp, int k)
+static u32b get_flag(object_type *o_ptr, int grp, int k)
{
u32b f = 0, flag_set = 0;
int tries = 1000;
@@ -6461,7 +6380,7 @@ u32b get_flag(object_type *o_ptr, int grp, int k)
}
/* 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;
@@ -6508,7 +6427,7 @@ void gain_flag_group_flag(object_type *o_ptr, bool_ silent)
break;
}
- if (!silent)
+ /* Message */
{
char o_name[80];
@@ -6545,13 +6464,13 @@ 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);
+ if (!o_ptr->pval3) gain_flag_group(o_ptr);
- gain_flag_group_flag(o_ptr, FALSE);
+ gain_flag_group_flag(o_ptr);
if (!o_ptr->pval) o_ptr->pval = 1;
else
@@ -6580,8 +6499,14 @@ bool_ wield_set(s16b a_idx, s16b set_idx, bool_ silent)
{
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);
+ }
return (TRUE);
}
return (FALSE);
@@ -6599,10 +6524,15 @@ bool_ takeoff_set(s16b a_idx, s16b set_idx)
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);
+ }
+
return (TRUE);
}
return (FALSE);
@@ -6634,7 +6564,7 @@ bool_ apply_set(s16b a_idx, s16b set_idx)
return (FALSE);
}
-bool_ apply_flags_set(s16b a_idx, s16b set_idx,
+static bool_ apply_flags_set(s16b a_idx, s16b set_idx,
u32b *f1, u32b *f2, u32b *f3, u32b *f4, u32b *f5, u32b *esp)
{
set_type *s_ptr = &set_info[set_idx];
@@ -6663,7 +6593,106 @@ bool_ apply_flags_set(s16b a_idx, s16b set_idx,
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)
+{
+ 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)
+{
+ 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)
+{
+ 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)
+{
+ 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)
+{
+ return
+ (o_ptr->tval == TV_RANDART) ||
+ (o_ptr->name1 ? true : false) ||
+ (o_ptr->art_name ? true : false) ||
+ ((k_info[o_ptr->k_idx].flags3 & TR3_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..ec8f9367
--- /dev/null
+++ b/src/object1.hpp
@@ -0,0 +1,46 @@
+#pragma once
+
+#include "h-basic.h"
+#include "object_filter.hpp"
+
+#include <boost/optional.hpp>
+#include <functional>
+
+typedef std::function<boost::optional<int>(object_filter_t const &filter)> select_by_name_t;
+
+extern byte get_item_letter_color(object_type *o_ptr);
+extern void object_pickup(int this_o_idx);
+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 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 const *o_ptr, u32b *f1, u32b *f2, u32b *f3, u32b *f4, u32b *f5, u32b *esp);
+extern void object_flags_known(object_type const *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 wield_slot_ideal(object_type const *o_ptr, bool_ ideal);
+extern s16b wield_slot(object_type const *o_ptr);
+extern cptr describe_use(int i);
+extern void display_inven(void);
+extern void display_equip(void);
+extern void show_inven_full();
+extern void show_equip_full();
+extern void toggle_inven_equip(void);
+extern 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());
+extern cptr item_activation(object_type *o_ptr,byte num);
+extern void py_pickup_floor(int pickup);
+extern void object_gain_level(object_type *o_ptr);
+extern byte object_attr(object_type const *o_ptr);
+extern byte object_attr_default(object_type *o_ptr);
+extern char object_char(object_type const *o_ptr);
+extern char object_char_default(object_type const *o_ptr);
+extern bool artifact_p(object_type const *o_ptr);
+extern bool ego_item_p(object_type const *o_ptr);
+extern bool is_ego_p(object_type const *o_ptr, s16b ego);
+extern bool cursed_p(object_type const *o_ptr);
diff --git a/src/object2.c b/src/object2.cc
index 98afb815..620037a3 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,7 +6,45 @@
* 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_item_type.hpp"
+#include "feature_type.hpp"
+#include "hooks.hpp"
+#include "mimic.hpp"
+#include "monster2.hpp"
+#include "monster_race.hpp"
+#include "monster_type.hpp"
+#include "object1.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 "traps.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.
@@ -33,123 +67,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;
- }
-
- /* Forget next pointer */
- o_ptr->next_o_idx = 0;
-
- /* Done */
- break;
- }
+ monster_type *m_ptr = &m_list[o_ptr->held_m_idx];
- /* 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;
- }
+ cave_type *c_ptr = &cave[o_ptr->iy][o_ptr->ix];
- /* 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 objects in the grid, if present. */
+ remove_it(&c_ptr->o_idxs);
}
}
@@ -195,28 +142,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 +162,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 +174,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];
@@ -502,13 +406,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 +426,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" */
@@ -805,6 +707,17 @@ 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)
+{
+ return ((o_ptr->ident & (IDENT_KNOWN)) ||
+ (k_info[o_ptr->k_idx].easy_know && k_info[o_ptr->k_idx].aware));
+}
+
/*
@@ -816,6 +729,13 @@ void object_aware(object_type *o_ptr)
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)
+{
+ return k_info[o_ptr->k_idx].aware;
+}
/*
@@ -828,12 +748,20 @@ void object_tried(object_type *o_ptr)
}
+/**
+ * Has the given object been "tried"?
+ */
+bool object_tried_p(object_type const *o_ptr)
+{
+ 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];
@@ -897,7 +825,7 @@ 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;
@@ -1133,7 +1061,7 @@ 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;
@@ -1200,7 +1128,7 @@ s32b object_value_real(object_type *o_ptr)
if (f5 & TR5_SPELL_CONTAIN)
{
if (o_ptr->pval2 != -1)
- value += 5000 + 500 * school_spells[o_ptr->pval2].skill_level;
+ value += 5000 + 500 * spell_type_skill_level(spell_at(o_ptr->pval2));
else
value += 5000;
}
@@ -1282,7 +1210,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 +1225,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 +1242,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;
@@ -1447,7 +1375,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,7 +1431,7 @@ 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;
@@ -1708,9 +1636,6 @@ bool_ object_similar(object_type *o_ptr, object_type *j_ptr)
case TV_TRAPKIT:
case TV_DAEMON_BOOK:
{
- /* Require permission */
- if (!stack_allow_items) return (0);
-
/* Fall through */
}
@@ -1785,13 +1710,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:
{
@@ -1816,13 +1734,6 @@ bool_ object_similar(object_type *o_ptr, object_type *j_ptr)
/* 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);
-
-
/* Maximal "stacking" limit */
if (total >= MAX_STACK_SIZE) return (0);
@@ -1902,7 +1813,8 @@ s16b lookup_kind(int tval, int sval)
void object_wipe(object_type *o_ptr)
{
/* Wipe the structure */
- o_ptr = WIPE(o_ptr, object_type);
+ static_assert(std::is_pod<object_type>::value, "object_type must be POD type for memset to work");
+ memset(o_ptr, 0, sizeof(object_type));
}
@@ -1912,7 +1824,7 @@ 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;
}
@@ -1924,7 +1836,7 @@ void object_prep(object_type *o_ptr, int k_idx)
object_kind *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;
@@ -2381,17 +2293,15 @@ 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;
bool_ ret = FALSE;
object_kind *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 < max_e_idx; i++)
{
ego_item_type *e_ptr = &e_info[i];
bool_ ok = FALSE;
@@ -2400,7 +2310,7 @@ static bool_ make_ego_item(object_type *o_ptr, bool_ good)
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)
{
@@ -2436,16 +2346,14 @@ static bool_ make_ego_item(object_type *o_ptr, bool_ good)
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())];
+ ego_item_type *e_ptr = &e_info[j];
/* XXX XXX Enforce minimum "depth" (loosely) */
if (e_ptr->level > dun_level)
@@ -2481,12 +2389,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
+ ego_item_type *e_ptr = &e_info[j];
/* Cannot be a double ego of the same ego type */
if (j == o_ptr->name2) continue;
@@ -2523,8 +2429,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 +2439,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);
}
/*
@@ -2604,8 +2509,6 @@ 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:
@@ -2751,8 +2654,6 @@ 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:
@@ -2761,9 +2662,7 @@ static void a_m_aux_2(object_type *o_ptr, int level, int power)
o_ptr->pval = randint(4); /* No cursed elven cloaks...? */
else if (o_ptr->sval == SV_MIMIC_CLOAK)
{
- s32b mimic;
-
- call_lua("find_random_mimic_shape", "(d,d)", "d", level, TRUE, &mimic);
+ s32b mimic = find_random_mimic_shape(level, TRUE);
o_ptr->pval2 = mimic;
}
break;
@@ -2836,8 +2735,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:
@@ -3226,6 +3123,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"
@@ -3252,8 +3192,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 +3203,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)
@@ -3361,9 +3303,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 +3318,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 +3333,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 +3349,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 */
@@ -3437,9 +3384,7 @@ static void a_m_aux_4(object_type *o_ptr, int level, int power)
case TV_POTION2:
if (o_ptr->sval == SV_POTION2_MIMIC)
{
- s32b mimic;
-
- call_lua("find_random_mimic_shape", "(d,d)", "d", level, FALSE, &mimic);
+ s32b mimic = find_random_mimic_shape(level, FALSE);
o_ptr->pval2 = mimic;
}
break;
@@ -3933,8 +3878,7 @@ 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];
@@ -3979,8 +3923,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 */
@@ -4035,15 +3979,11 @@ void apply_magic(object_type *o_ptr, int lev, bool_ okay, bool_ good, bool_ grea
if (magik(f2)) power = -2;
}
- /* Mega hack */
- if (hack_apply_magic_power)
+ /* Override power with parameter? */
+ if (auto power_override = force_power)
{
- if (hack_apply_magic_power == -99)
- power = 0;
- else
- power = hack_apply_magic_power;
+ power = *power_override;
}
- hack_apply_magic_power = 0;
/* Assume no rolls */
rolls = 0;
@@ -4209,7 +4149,7 @@ try_an_other_ego:
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]))
@@ -4342,7 +4282,7 @@ static obj_theme match_theme;
* 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)
+void init_match_theme(obj_theme const &theme)
{
/* Save the theme */
match_theme = theme;
@@ -4367,7 +4307,7 @@ static bool_ theme_changed(obj_theme theme)
/*
* Maga-Hack -- match certain types of object only.
*/
-bool_ kind_is_theme(int k_idx)
+static bool kind_is_theme(int k_idx)
{
object_kind *k_ptr = &k_info[k_idx];
@@ -4436,6 +4376,7 @@ bool_ kind_is_theme(int k_idx)
prob = match_theme.combat;
break;
case TV_HAFTED:
+ // FIXME: These cases can be shortened drastically
prob = match_theme.combat;
break;
case TV_POLEARM:
@@ -4490,9 +4431,6 @@ bool_ kind_is_theme(int k_idx)
case TV_POTION2:
prob = match_theme.magic;
break;
- case TV_BATERIE:
- prob = match_theme.magic;
- break;
case TV_RANDART:
prob = match_theme.magic;
break;
@@ -4560,7 +4498,6 @@ 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];
@@ -4597,9 +4534,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,7 +4542,7 @@ 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];
@@ -4748,7 +4682,7 @@ 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)
{
int invprob, base;
@@ -4918,10 +4852,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 +4865,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);
@@ -5007,6 +4936,10 @@ 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 (no_selling)
+ j_ptr->pval *= 5;
/* Success */
return (TRUE);
@@ -5066,11 +4999,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);
@@ -5106,10 +5036,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];
@@ -5189,15 +5115,10 @@ s16b drop_near(object_type *j_ptr, int chance, int y, int x)
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 +5130,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;
@@ -5298,15 +5216,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 +5236,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 */
@@ -5369,11 +5283,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;
@@ -5740,7 +5651,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 +5824,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 */
@@ -6297,72 +6207,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 +6225,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 +6255,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);
@@ -6602,13 +6452,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..26d07b25
--- /dev/null
+++ b/src/object2.hpp
@@ -0,0 +1,69 @@
+#pragma once
+
+#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;
+
+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 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 void init_match_theme(obj_theme const &theme);
+extern bool_ kind_is_artifactable(int k_idx);
+extern bool_ kind_is_legal(int k_idx);
+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 const *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 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 bool object_known_p(object_type const *o_ptr);
+extern void object_aware(object_type *o_ptr);
+extern bool object_aware_p(object_type const *o_ptr);
+extern void object_tried(object_type *o_ptr);
+extern bool object_tried_p(object_type const *o_ptr);
+extern s32b object_value(object_type const *o_ptr);
+extern s32b object_value_real(object_type const *o_ptr);
+extern bool_ object_similar(object_type const *o_ptr, object_type const *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 void apply_magic(object_type *o_ptr, int lev, bool_ okay, bool_ good, bool_ great, boost::optional<int> force_power = boost::none);
+extern bool_ make_object(object_type *j_ptr, bool_ good, bool_ great, obj_theme const &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 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 void combine_pack(void);
+extern void reorder_pack(void);
+extern void random_artifact_resistance (object_type * o_ptr);
+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 s16b m_bonus(int max, int level);
+extern 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..39961146
--- /dev/null
+++ b/src/object_filter.cc
@@ -0,0 +1,98 @@
+#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 HasFlag3(u32b mask) {
+ return [=](object_type const *o_ptr) -> bool {
+ // Extract the flags
+ u32b f1, f2, f3, f4, f5, esp;
+ object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ // Does the item have the flag?
+ return (f3 & mask);
+ };
+}
+
+object_filter_t HasFlag4(u32b mask) {
+ return [=](object_type const *o_ptr) -> bool {
+ // Extract the flags
+ u32b f1, f2, f3, f4, f5, esp;
+ object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ // Does the item have the flag?
+ return (f4 & mask);
+ };
+}
+
+object_filter_t HasFlag5(u32b mask) {
+ return [=](object_type const *o_ptr) -> bool {
+ // Extract the flags
+ u32b f1, f2, f3, f4, f5, esp;
+ object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+ // Does the item have the flag?
+ return (f5 & 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..9a22090b
--- /dev/null
+++ b/src/object_filter.hpp
@@ -0,0 +1,99 @@
+#pragma once
+
+#include "h-basic.h"
+#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 bit mask in flag3 value.
+ */
+object_filter_t HasFlag3(u32b mask);
+
+/**
+ * Has given bit mask in flag4 value.
+ */
+object_filter_t HasFlag4(u32b mask);
+
+/**
+ * Has given bit mask in flag5 value.
+ */
+object_filter_t HasFlag5(u32b mask);
+
+/**
+ * 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_kind.hpp b/src/object_kind.hpp
new file mode 100644
index 00000000..505f54d9
--- /dev/null
+++ b/src/object_kind.hpp
@@ -0,0 +1,83 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * 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; /* Name */
+ char *text; /* Text */
+
+ 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[ALLOCATION_MAX]; /* Allocation level(s) */
+ byte chance[ALLOCATION_MAX]; /* Allocation chance(s) */
+
+ byte level; /* Level */
+
+
+ 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 */
+
+ 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) */
+};
diff --git a/src/object_kind_fwd.hpp b/src/object_kind_fwd.hpp
new file mode 100644
index 00000000..6d26db9f
--- /dev/null
+++ b/src/object_kind_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct object_kind;
diff --git a/src/object_type.hpp b/src/object_type.hpp
new file mode 100644
index 00000000..d7f003e6
--- /dev/null
+++ b/src/object_type.hpp
@@ -0,0 +1,104 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * 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; /* 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 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 */
+};
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..58834b79
--- /dev/null
+++ b/src/option_type.hpp
@@ -0,0 +1,40 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * Option descriptor.
+ */
+struct option_type
+{
+ /**
+ * Address of actual option variable. NULL signals the
+ * end of the table.
+ */
+ bool_ *o_var;
+
+ /**
+ * Default value.
+ */
+ byte o_norm;
+
+ /**
+ * 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..5501ab52
--- /dev/null
+++ b/src/options.cc
@@ -0,0 +1,89 @@
+#include "options.hpp"
+
+//
+// Option Set 1 -- User Interface
+//
+bool_ rogue_like_commands; /* Rogue-like commands */
+bool_ quick_messages; /* Activate quick messages */
+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_ always_repeat; /* Repeat obvious commands */
+bool_ ring_bell; /* Ring the bell (on errors, etc) */
+
+//
+// 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_ small_levels; /* Allow unusually small dungeon levels */
+bool_ empty_levels; /* Allow empty 'arena' levels */
+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_scum; /* Auto-scum for good levels */
+bool_ view_perma_grids; /* Map remembers all perma-lit grids */
+bool_ view_torch_grids; /* Map remembers all torch-lit grids */
+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_ smart_learn; /* Monsters learn from their mistakes */
+
+//
+// Option Set 4 -- Efficiency
+//
+bool_ view_reduce_lite; /* Reduce lite-radius when running */
+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) */
+bool_ center_player; /* Center view on player */
+
+//
+// Option Set 5 - ToME options
+//
+bool_ linear_stats;
+bool_ player_char_health; /* Display the player as a special symbol when in bad health ? */
+bool_ option_ingame_help; /* Ingame contextual help */
+bool_ auto_more; /* Auto more */
+bool_ inventory_no_move; /* In inventory option window, just erase the letters,
+ * rather that displaying the list without the invalid
+ * selections */
+
+//
+// Option Set 6 - Birth options
+//
+bool_ always_small_level;
+bool_ autoroll;
+bool_ fate_option;
+bool_ ironman_rooms;
+bool_ joke_monsters;
+bool_ point_based;
+bool_ preserve;
+bool_ no_selling;
diff --git a/src/options.hpp b/src/options.hpp
new file mode 100644
index 00000000..45e19cf7
--- /dev/null
+++ b/src/options.hpp
@@ -0,0 +1,89 @@
+#pragma once
+
+#include "h-basic.h"
+
+//
+// Option Set 1 -- User Interface.
+//
+extern bool_ rogue_like_commands;
+extern bool_ quick_messages;
+extern bool_ carry_query_flag;
+extern bool_ use_old_target;
+extern bool_ always_pickup;
+extern bool_ always_repeat;
+extern bool_ ring_bell;
+
+//
+// Option Set 2 -- Disturbance
+//
+extern bool_ find_ignore_stairs;
+extern bool_ find_ignore_doors;
+extern bool_ find_cut;
+extern bool_ find_examine;
+extern bool_ disturb_move;
+extern bool_ disturb_near;
+extern bool_ disturb_panel;
+extern bool_ disturb_detect;
+extern bool_ disturb_state;
+extern bool_ disturb_minor;
+extern bool_ disturb_other;
+extern bool_ alert_hitpoint;
+extern bool_ alert_failure;
+extern bool_ last_words;
+extern bool_ small_levels;
+extern bool_ empty_levels;
+extern bool_ confirm_stairs;
+extern bool_ wear_confirm;
+extern bool_ disturb_pets;
+
+//
+// Option Set 3 -- Game-Play
+//
+extern bool_ auto_scum;
+extern bool_ view_perma_grids;
+extern bool_ view_torch_grids;
+extern bool_ dungeon_align;
+extern bool_ dungeon_stair;
+extern bool_ flow_by_sound;
+extern bool_ smart_learn;
+
+//
+// Option Set 4 -- Efficiency
+//
+extern bool_ view_reduce_lite;
+extern bool_ avoid_abort;
+extern bool_ avoid_shimmer;
+extern bool_ avoid_other;
+extern bool_ flush_failure;
+extern bool_ flush_disturb;
+extern bool_ flush_command;
+extern bool_ fresh_before;
+extern bool_ fresh_after;
+extern bool_ fresh_message;
+extern bool_ hilite_player;
+extern bool_ view_yellow_lite;
+extern bool_ view_bright_lite;
+extern bool_ view_granite_lite;
+extern bool_ view_special_lite;
+extern bool_ center_player;
+
+//
+// Option Set 5 - ToME options
+//
+extern bool_ linear_stats;
+extern bool_ player_char_health;
+extern bool_ option_ingame_help;
+extern bool_ auto_more;
+extern bool_ inventory_no_move;
+
+//
+// Option Set 6 - Birth options
+//
+extern bool_ always_small_level;
+extern bool_ autoroll;
+extern bool_ fate_option;
+extern bool_ ironman_rooms;
+extern bool_ joke_monsters;
+extern bool_ point_based;
+extern bool_ preserve;
+extern bool_ no_selling;
diff --git a/src/owner_type.hpp b/src/owner_type.hpp
new file mode 100644
index 00000000..703d3159
--- /dev/null
+++ b/src/owner_type.hpp
@@ -0,0 +1,39 @@
+#pragma once
+
+#include "h-basic.h"
+
+/*
+ * Store owner descriptor.
+ */
+struct owner_type
+{
+ /**
+ * Name
+ */
+ const char *name;
+
+ /**
+ * Purse limit
+ */
+ s16b max_cost;
+
+ /**
+ * Inflation
+ */
+ s16b inflation;
+
+ /**
+ * 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/owner_type_fwd.hpp b/src/owner_type_fwd.hpp
new file mode 100644
index 00000000..20c25802
--- /dev/null
+++ b/src/owner_type_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct owner_type;
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..d67d1d73
--- /dev/null
+++ b/src/player_class.hpp
@@ -0,0 +1,105 @@
+#pragma once
+
+#include "body.hpp"
+#include "h-basic.h"
+#include "player_defs.hpp"
+#include "player_spec.hpp"
+
+/**
+ * Maximum number of specialties.
+ */
+constexpr int MAX_SPEC = 20;
+
+/**
+ * Player descriptor and runtime data.
+ */
+struct player_class
+{
+ const char *title; /* Type of class */
+ char *desc; /* Small desc of the class */
+ const char *titles[PY_MAX_LEVEL / 5];
+ /* Titles */
+
+ 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) */
+};
+
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_race.hpp b/src/player_race.hpp
new file mode 100644
index 00000000..edb304f2
--- /dev/null
+++ b/src/player_race.hpp
@@ -0,0 +1,83 @@
+#pragma once
+
+#include "h-basic.h"
+#include "body.hpp"
+#include "player_defs.hpp"
+#include "skills_defs.hpp"
+
+/**
+ * Player racial descriptior.
+ */
+struct player_race
+{
+ const char *title; /* Type of race */
+ char *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) */
+};
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..72f975ce
--- /dev/null
+++ b/src/player_race_mod.hpp
@@ -0,0 +1,87 @@
+#pragma once
+
+#include "body.hpp"
+#include "h-basic.h"
+#include "skills_defs.hpp"
+
+struct player_race_mod
+{
+ char *title; /* Type of race mod */
+ char *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) */
+};
+
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_sex.hpp b/src/player_sex.hpp
new file mode 100644
index 00000000..5722f1a4
--- /dev/null
+++ b/src/player_sex.hpp
@@ -0,0 +1,17 @@
+#pragma once
+
+/**
+ * Player sex descriptor.
+ */
+struct player_sex
+{
+ /**
+ * Type of sex.
+ */
+ char const *title;
+
+ /**
+ * Winner title.
+ */
+ char const *winner;
+};
diff --git a/src/player_sex_fwd.hpp b/src/player_sex_fwd.hpp
new file mode 100644
index 00000000..eabea488
--- /dev/null
+++ b/src/player_sex_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct player_sex;
diff --git a/src/player_spec.hpp b/src/player_spec.hpp
new file mode 100644
index 00000000..28b32830
--- /dev/null
+++ b/src/player_spec.hpp
@@ -0,0 +1,38 @@
+#pragma once
+
+#include "h-basic.h"
+#include "skills_defs.hpp"
+
+/**
+ * Player class descriptor.
+ */
+struct player_spec
+{
+ const char *title; /* Type of class spec */
+ char *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) */
+};
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.hpp b/src/player_type.hpp
new file mode 100644
index 00000000..d9410dcb
--- /dev/null
+++ b/src/player_type.hpp
@@ -0,0 +1,423 @@
+#pragma once
+
+#include "corrupt.hpp"
+#include "h-basic.h"
+#include "help_info.hpp"
+#include "inventory.hpp"
+#include "object_type.hpp"
+#include "powers.hpp"
+
+/*
+ * 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; /* 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 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 inside_quest; /* Inside quest level */
+
+ 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. */
+ s32b grace_delay; /* Delay factor for granting piety. */
+ byte pgod; /* Your God. */
+ bool_ praying; /* Praying to your god. */
+ s16b melkor_sacrifice; /* How much hp has been sacrified for damage */
+
+ 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 tim_esp; /* Timed ESP */
+ s16b tim_wraith; /* Timed wraithform */
+ s16b tim_ffall; /* Timed Levitation */
+ s16b tim_fly; /* Timed Levitation */
+ 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 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 strike; /* True Strike(+25 hit) */
+ s16b tim_reflect; /* Timed Reflection */
+ 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 */
+ s16b absorb_soul; /* Timed soul absordtion */
+ s16b tim_magic_breath; /* Magical breathing -- can breath anywhere */
+ s16b tim_water_breath; /* Water breathing -- can breath underwater */
+ s16b tim_precognition; /* Timed precognition */
+
+ s16b immov_cntr; /* Timed -- Last ``immovable'' command. */
+
+ 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 */
+
+ 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_ammo; /* Correct ammo tval */
+
+ s16b pspeed; /* Current speed */
+
+ u32b mimic_extra; /* Mimicry powers use that */
+ u32b antimagic_extra; /* Antimagic powers */
+ u32b music_extra; /* Music songs */
+ u32b necro_extra; /* Necro powers */
+ u32b necro_extra2; /* Necro powers */
+
+ 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[CORRUPTIONS_MAX];
+ bool_ corrupt_anti_teleport_stopped;
+
+ /*** 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[POWER_MAX]; /* Actual powers */
+ bool_ powers_mod[POWER_MAX]; /* 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 */
+
+ /* Dripping Tread spell timer */
+ s16b dripping_tread;
+
+ /* Help */
+ help_info help;
+
+ /* Inertia control */
+ s32b inertia_controlled_spell;
+
+ /* For automatic stat-gain */
+ s16b last_rewarded_level;
+
+ /*** Temporary fields ***/
+
+ bool_ did_nothing; /* True if the last action wasnt a real action */
+ bool_ leaving; /* True if player is leaving */
+};
+
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/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..a7db2968 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,43 @@
* 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 "feature_type.hpp"
+#include "files.hpp"
+#include "hooks.hpp"
+#include "mimic.hpp"
+#include "monster2.hpp"
+#include "monster3.hpp"
+#include "monster_race.hpp"
+#include "monster_type.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_kind.hpp"
+#include "options.hpp"
+#include "player_type.hpp"
+#include "quark.hpp"
+#include "spells1.hpp"
+#include "spells2.hpp"
+#include "stats.hpp"
+#include "tables.hpp"
+#include "traps.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 +107,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);
@@ -168,199 +195,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();
@@ -713,7 +547,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,7 +558,7 @@ 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)))
{
@@ -760,13 +593,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];
@@ -1051,12 +881,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);
@@ -1159,23 +987,18 @@ 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)
{
@@ -1221,29 +1044,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 +1097,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 +1114,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 +1139,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 +1148,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 +1185,6 @@ static power_type* select_power(int *x_idx)
character_icky = FALSE;
}
- C_FREE(p, power_max, int);
-
return ret;
}
@@ -1365,7 +1198,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 +1206,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..35d317b0
--- /dev/null
+++ b/src/powers.hpp
@@ -0,0 +1,74 @@
+#pragma once
+
+extern 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_LAY_TRAP 56
+#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..2bebe452 100644
--- a/src/q_betwen.c
+++ b/src/q_betwen.cc
@@ -1,14 +1,30 @@
-#undef cquest
+#include "q_betwen.hpp"
+
+#include "cave.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;
@@ -49,7 +65,8 @@ bool_ quest_between_move_hook(char *fmt)
return FALSE;
}
-bool_ quest_between_gen_hook(char *fmt)
+
+static bool_ quest_between_gen_hook(void *, void *, void *)
{
int x, y;
int xstart = 2;
@@ -83,13 +100,13 @@ bool_ quest_between_gen_hook(char *fmt)
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;
c_put_str(TERM_YELLOW, "Ah you finally arrived, I hope your travel wasn't too hard.", 8, 0);
@@ -116,12 +133,13 @@ bool_ quest_between_finish_hook(char *fmt)
/* 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;
}
-bool_ quest_between_death_hook(char *fmt)
+
+static bool_ quest_between_death_hook(void *, void *, void *)
{
int i, mcnt = 0;
@@ -150,19 +168,24 @@ bool_ quest_between_death_hook(char *fmt)
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);
}
-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);
@@ -173,16 +196,17 @@ bool_ quest_between_forbid_hook(char *fmt)
}
return (FALSE);
}
+
bool_ quest_between_init_hook(int q)
{
if ((cquest.status >= QUEST_STATUS_TAKEN) && (cquest.status < QUEST_STATUS_FINISHED))
{
- 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");
+ 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);
return (FALSE);
}
diff --git a/src/q_betwen.hpp b/src/q_betwen.hpp
new file mode 100644
index 00000000..d2fc08f0
--- /dev/null
+++ b/src/q_betwen.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+bool_ quest_between_init_hook(int q_idx);
diff --git a/src/q_bounty.cc b/src/q_bounty.cc
new file mode 100644
index 00000000..bb84d48d
--- /dev/null
+++ b/src/q_bounty.cc
@@ -0,0 +1,170 @@
+#include "q_bounty.hpp"
+
+#include "monster2.hpp"
+#include "monster_race.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"
+
+#define cquest (quest[QUEST_BOUNTY])
+
+#define bounty_quest_monster (cquest.data[0])
+
+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);
+}
+
+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));
+}
+
+bool_ quest_bounty_init_hook(int dummy)
+{
+ return FALSE;
+}
+
+bool_ quest_bounty_drop_item()
+{
+ char mdesc[512];
+ char msg[512];
+
+ if (cquest.status == QUEST_STATUS_UNTAKEN)
+ {
+ cquest.status = QUEST_STATUS_TAKEN;
+ bounty_quest_monster = get_new_bounty_monster(3 + (p_ptr->lev * 3) / 2);
+
+ monster_race_desc(mdesc, bounty_quest_monster, 0);
+ snprintf(msg, sizeof(msg), "You must bring me back %s corpse.", mdesc);
+ msg_print(msg);
+ }
+ else
+ {
+ monster_race_desc(mdesc, bounty_quest_monster, 0);
+ snprintf(msg, sizeof(msg), "You still must bring me back %s corpse.", mdesc);
+ msg_print(msg);
+ }
+ return FALSE;
+}
+
+bool_ quest_bounty_get_item()
+{
+ if (cquest.status != QUEST_STATUS_TAKEN)
+ {
+ msg_print("You do not have any bounty quest yet.");
+ return FALSE;
+ }
+
+ // Get the corpse.
+ 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;
+}
+
+bool_ quest_bounty_describe(FILE *fff)
+{
+ char mdesc[512];
+
+ if (cquest.status == QUEST_STATUS_TAKEN)
+ {
+ monster_race_desc(mdesc, bounty_quest_monster, 0);
+
+ fprintf(fff, "#####yBounty quest!\n");
+ fprintf(fff, "You must bring back %s corpse to the beastmaster.\n", mdesc);
+ fprintf(fff, "\n");
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
diff --git a/src/q_bounty.hpp b/src/q_bounty.hpp
new file mode 100644
index 00000000..234c036d
--- /dev/null
+++ b/src/q_bounty.hpp
@@ -0,0 +1,8 @@
+#pragma once
+
+#include "h-basic.h"
+
+extern bool_ quest_bounty_init_hook(int q_idx);
+extern bool_ quest_bounty_drop_item();
+extern bool_ quest_bounty_get_item();
+extern bool_ quest_bounty_describe(FILE *fff);
diff --git a/src/q_dragons.c b/src/q_dragons.cc
index 025e8ecd..6c6084d1 100644
--- a/src/q_dragons.c
+++ b/src/q_dragons.cc
@@ -1,7 +1,22 @@
-#undef cquest
+#include "q_dragons.hpp"
+
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "feature_type.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 *)
{
int x, y, i;
int xstart = 2;
@@ -89,7 +104,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;
@@ -111,8 +126,8 @@ bool_ quest_dragons_death_hook(char *fmt)
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.");
@@ -121,11 +136,10 @@ bool_ quest_dragons_death_hook(char *fmt)
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;
@@ -142,9 +156,9 @@ bool_ quest_dragons_init_hook(int q_idx)
{
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..f0aa50f2
--- /dev/null
+++ b/src/q_dragons.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+bool_ quest_dragons_init_hook(int q_idx);
diff --git a/src/q_eol.c b/src/q_eol.cc
index 5b1cf78e..f27ce9df 100644
--- a/src/q_eol.c
+++ b/src/q_eol.cc
@@ -1,7 +1,31 @@
-#undef cquest
+#include "q_eol.hpp"
+
+#include "cave.hpp"
+#include "cave_type.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 "traps.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+#include "z-rand.hpp"
+
+#include <cassert>
+
#define cquest (quest[QUEST_EOL])
-bool_ quest_eol_gen_hook(char *fmt)
+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;
@@ -61,9 +85,13 @@ bool_ quest_eol_gen_hook(char *fmt)
/* 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;
+ // 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;
}
@@ -81,12 +109,12 @@ bool_ quest_eol_gen_hook(char *fmt)
return TRUE;
}
-bool_ quest_eol_finish_hook(char *fmt)
+
+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;
- s32b q_idx;
-
- q_idx = get_next_arg(fmt);
if (q_idx != QUEST_EOL) return FALSE;
@@ -108,16 +136,16 @@ bool_ quest_eol_finish_hook(char *fmt)
*(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);
+ del_hook_new(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);
+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;
@@ -126,37 +154,38 @@ bool_ quest_eol_fail_hook(char *fmt)
/* Continue the plot */
*(quest[q_idx].plot) = QUEST_NULL;
- del_hook(HOOK_QUEST_FAIL, quest_eol_fail_hook);
+ del_hook_new(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;
+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 == test_monster_name("Eol, the Dark Elf"))
+ if (r_idx == get_eol())
{
cmsg_print(TERM_YELLOW, "Such a sad end...");
cquest.status = QUEST_STATUS_COMPLETED;
- del_hook(HOOK_MONSTER_DEATH, quest_eol_death_hook);
+
+ del_hook_new(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);
+static bool_ quest_eol_stair_hook(void *, void *in_, void *)
+{
+ struct hook_stair_in *in = static_cast<struct hook_stair_in *>(in_);
+ monster_race *r_ptr = &r_info[get_eol()];
if (p_ptr->inside_quest != QUEST_EOL) return FALSE;
@@ -164,7 +193,7 @@ bool_ quest_eol_stair_hook(char *fmt)
if (r_ptr->max_num)
{
- if (!strcmp(down, "up"))
+ if (in->direction == STAIRS_UP)
{
/* Flush input */
flush();
@@ -173,7 +202,8 @@ bool_ quest_eol_stair_hook(char *fmt)
cmsg_print(TERM_YELLOW, "You flee away from Eol...");
cquest.status = QUEST_STATUS_FAILED;
- del_hook(HOOK_STAIR, quest_eol_stair_hook);
+
+ del_hook_new(HOOK_STAIR, quest_eol_stair_hook);
process_hooks_restart = TRUE;
return (FALSE);
}
@@ -181,15 +211,16 @@ bool_ quest_eol_stair_hook(char *fmt)
return FALSE;
}
+
bool_ quest_eol_init_hook(int q)
{
if ((cquest.status >= QUEST_STATUS_TAKEN) && (cquest.status < QUEST_STATUS_FINISHED))
{
- 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");
+ 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);
}
return (FALSE);
}
diff --git a/src/q_eol.hpp b/src/q_eol.hpp
new file mode 100644
index 00000000..ab7f1274
--- /dev/null
+++ b/src/q_eol.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+bool_ quest_eol_init_hook(int q_idx);
diff --git a/src/q_evil.c b/src/q_evil.cc
index a143f65c..3bc953cd 100644
--- a/src/q_evil.c
+++ b/src/q_evil.cc
@@ -1,7 +1,22 @@
-#undef cquest
+#include "q_evil.hpp"
+
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "feature_type.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 *)
{
int x, y, i;
int xstart = 2;
@@ -54,7 +69,7 @@ bool_ quest_evil_gen_hook(char *fmt)
return TRUE;
}
-bool_ quest_evil_death_hook(char *fmt)
+static bool_ quest_evil_death_hook(void *, void *, void *)
{
int i, mcnt = 0;
@@ -78,8 +93,9 @@ 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.");
@@ -88,11 +104,10 @@ bool_ quest_evil_death_hook(char *fmt)
return FALSE;
}
-bool_ quest_evil_finish_hook(char *fmt)
+static bool_ quest_evil_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_EVIL) return FALSE;
@@ -109,9 +124,9 @@ bool_ quest_evil_init_hook(int q_idx)
{
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..06fb17e1
--- /dev/null
+++ b/src/q_evil.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+bool_ quest_evil_init_hook(int q_idx);
diff --git a/src/q_fireprof.cc b/src/q_fireprof.cc
new file mode 100644
index 00000000..021cf2fb
--- /dev/null
+++ b/src/q_fireprof.cc
@@ -0,0 +1,577 @@
+#include "q_fireprof.hpp"
+
+#include "cave_type.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_type.hpp"
+#include "player_type.hpp"
+#include "quark.hpp"
+#include "tables.hpp"
+#include "traps.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+#include "z-rand.hpp"
+
+#include <cassert>
+
+#define cquest (quest[QUEST_FIREPROOF])
+
+#define print_hook(fmt,...) do { fprintf(hook_file, fmt, ##__VA_ARGS__); } while (0)
+
+/*
+ * Per-module "settings"
+ */
+typedef struct fireproof_settings fireproof_settings;
+struct fireproof_settings
+{
+ byte tval; /* tval of object to use. */
+ cptr tval_name; /* descriptive name of tval */
+ cptr tval_name_plural; /* descriptive name of tval (plural) */
+ byte sval_max; /* max sval of object to use; sval will be 1<=X<=sval_max. */
+ s32b total_points; /* total number of points awarded */
+};
+
+static fireproof_settings const *fireproof_get_settings()
+{
+ static fireproof_settings fireproof_settings =
+ { TV_RUNE2, "rune", "runes", 5, 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 void fireproof_set_sval(int sval_max)
+{
+ cquest.data[1] = sval_max;
+}
+
+static int fireproof_get_sval()
+{
+ return cquest.data[1];
+}
+
+static bool item_tester_hook_eligible(object_type const *o_ptr)
+{
+ /* check it's the 'marked' item */
+ return ((o_ptr->tval == fireproof_get_settings()->tval) &&
+ (o_ptr->sval == fireproof_get_sval()) &&
+ (o_ptr->pval2 == fireproof_get_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(
+ HasFlag3(TR3_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_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;
+ }
+ }
+}
+
+bool_ quest_fireproof_describe(FILE *hook_file)
+{
+ fireproof_settings const *settings = fireproof_get_settings();
+ int num_books, num_staff, num_scroll;
+ int status = cquest.status;
+
+ num_books = get_item_points_remaining() / FIREPROOF_BOOK_POINTS;
+ num_staff = get_item_points_remaining() / FIREPROOF_STAFF_POINTS;
+ num_scroll = get_item_points_remaining() / FIREPROOF_SCROLL_POINTS;
+
+ if (status == QUEST_STATUS_TAKEN)
+ {
+ /* Quest taken */
+ print_hook("#####yAn Old Mages Quest!\n");
+ print_hook("Retrieve the strange %s for the old mage "
+ "in Lothlorien.\n", settings->tval_name);
+ print_hook("\n");
+ }
+ else if (status == QUEST_STATUS_COMPLETED)
+ {
+ /* essence retrieved, not taken to mage */
+ print_hook("#####yAn Old Mages Quest!\n");
+ print_hook("You have retrieved the %s for the old "
+ "mage in Lothlorien. Perhaps you \n", settings->tval_name);
+ print_hook("should see about a reward.\n");
+ print_hook("\n");
+ }
+ else if ((status == QUEST_STATUS_FINISHED) &&
+ (get_item_points_remaining() > 0))
+ {
+ /* essence returned, not all books fireproofed */
+ print_hook("#####yAn Old Mages Quest!\n");
+ print_hook("You have retrieved the %s for the old "
+ "mage in Lothlorien. He will still \n", settings->tval_name);
+ print_hook("fireproof %d book(s) or %d staff/staves "
+ "or %d scroll(s) for you.\n",
+ num_books, num_staff, num_scroll);
+ print_hook("\n");
+ }
+
+ return TRUE;
+}
+
+static bool_ fireproof_gen_hook(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 */
+ {
+ int traps, trap_y, trap_x;
+
+ /* load the map */
+ {
+ int x0 = 2;
+ int y0 = 2;
+ load_map("fireprof.map", &y0, &x0);
+ }
+
+ /* no teleport */
+ dungeon_flags2 = DF2_NO_TELEPORT;
+
+ /* determine type of item */
+ fireproof_set_sval(randint(settings->sval_max));
+
+ /* create essence */
+ {
+ int x, y;
+ object_type forge;
+
+ object_prep(&forge, lookup_kind(settings->tval, fireproof_get_sval()));
+
+ /* mark item */
+ forge.pval2 = fireproof_get_sval();
+ forge.note = quark_add("quest");
+
+ /* roll for co-ordinates in top half of map */
+ y = randint(3) + 2;
+ x = randint(45) + 2;
+
+ /* drop it */
+ drop_near(&forge, -1, y, x);
+ }
+
+ /* how many traps to generate */
+ traps = rand_range(10, 30);
+
+ /* generate the traps */
+ while (traps > 0)
+ {
+ int tries = 0, trap_level = 0;
+
+ /* make sure it's a safe place */
+ while (tries == 0)
+ {
+ /* get grid coordinates */
+ trap_y = randint(19) + 2;
+ trap_x = randint(45) + 2;
+ cave_type *c_ptr = &cave[trap_y][trap_x];
+
+ /* are the coordinates on a stair, or a wall? */
+ if (((f_info[c_ptr->feat].flags1 & FF1_PERMANENT) != 0) ||
+ ((f_info[c_ptr->feat].flags1 & FF1_FLOOR) == 0))
+ {
+ /* try again */
+ tries = 0;
+ }
+ else
+ {
+ /* not a stair, then stop this 'while' */
+ tries = 1;
+ }
+ }
+
+ /* randomise level of trap */
+ trap_level = rand_range(20, 40);
+
+ /* put the trap there */
+ place_trap_leveled(trap_y, trap_x, trap_level);
+
+ /* that's one less trap to place */
+ traps = traps - 1;
+ }
+
+ return TRUE;
+ }
+}
+
+bool_ quest_fireproof_init_hook(int q)
+{
+ /* Only need hooks if the quest is unfinished. */
+ if ((cquest.status >= QUEST_STATUS_UNTAKEN) &&
+ (cquest.status < QUEST_STATUS_FINISHED))
+ {
+ add_hook_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);
+ }
+
+ return FALSE;
+}
+
+#undef print_hook
diff --git a/src/q_fireprof.hpp b/src/q_fireprof.hpp
new file mode 100644
index 00000000..53d368b0
--- /dev/null
+++ b/src/q_fireprof.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "h-basic.h"
+
+extern void quest_fireproof_building(bool_ *paid, bool_ *recreate);
+extern bool_ quest_fireproof_init_hook(int q);
+extern bool_ quest_fireproof_describe(FILE *fff);
diff --git a/src/q_god.cc b/src/q_god.cc
new file mode 100644
index 00000000..0a3b07e7
--- /dev/null
+++ b/src/q_god.cc
@@ -0,0 +1,1212 @@
+#include "q_god.hpp"
+
+#include "cave_type.hpp"
+#include "dungeon_info_type.hpp"
+#include "feature_type.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 "object2.hpp"
+#include "player_type.hpp"
+#include "quark.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>
+
+#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.
+ *
+ * The returned string is allocated with strdup().
+ */
+static char *compass(int y, int x, int y2, int x2)
+{
+ char compass_dir[64];
+
+ // is it close to the north/south meridian?
+ int y_diff = y2 - y;
+
+ // determine if y2, x2 is to the north or south of y, x
+ const char *y_axis;
+ if ((y_diff > -3) && (y_diff < 3))
+ {
+ y_axis = 0;
+ }
+ else if (y2 > y)
+ {
+ y_axis = "south";
+ }
+ else
+ {
+ y_axis = "north";
+ }
+
+ // is it close to the east/west meridian?
+ int x_diff = x2 - x;
+
+ // determine if y2, x2 is to the east or west of y, x
+ const char *x_axis;
+ if ((x_diff > -3) && (x_diff < 3))
+ {
+ x_axis = 0;
+ }
+ else if (x2 > x)
+ {
+ x_axis = "east";
+ }
+ else
+ {
+ x_axis = "west";
+ }
+
+ // Maybe it is very close
+ if ((!x_axis) && (!y_axis)) { strcpy(compass_dir, "close"); }
+ // Maybe it is (almost) due N/S
+ else if (!x_axis) { strcpy(compass_dir, y_axis); }
+ // Maybe it is (almost) due E/W
+ else if (!y_axis) { strcpy(compass_dir, x_axis); }
+ // or if it is neither
+ else { sprintf(compass_dir, "%s-%s", y_axis, x_axis); }
+
+ /* Return a copy */
+ return strdup(compass_dir);
+}
+
+/* Returns a relative approximation of the 'distance' of y2, x2 from y, x. */
+static cptr approximate_distance(int y, int x, int y2, int x2)
+{
+ // how far to away to the north/south?
+ int y_diff = abs(y2 - y);
+ // how far to away to the east/west?
+ int x_diff = abs(x2 - x);
+ // find which one is the larger distance
+ int most_dist = x_diff;
+ if (y_diff > most_dist) {
+ most_dist = y_diff;
+ }
+
+ // how far away then?
+ if (most_dist >= 41) {
+ return "a very long way";
+ } else if (most_dist >= 25) {
+ return "a long way";
+ } else if (most_dist >= 8) {
+ return "quite some way";
+ } else {
+ return "not very far";
+ }
+}
+
+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 */
+ }
+}
+
+/* Print using cmsg_print. */
+static void print_using_cmsg(cptr line, void *dummy)
+{
+ cmsg_print(TERM_YELLOW, line);
+}
+
+/* Print using print_hook. */
+static void print_using_print_hook(cptr line, void *f_)
+{
+ FILE *f = (FILE *) f_;
+ fprintf(f, "%s\n", line);
+}
+
+/* Show directions */
+static void print_directions(bool_ feel_it, void (*pfunc)(cptr, void *), void *pfdata)
+{
+ int home1_y, home1_x;
+ int home2_y, home2_x;
+ const char *home1 = NULL;
+ const char *home2 = NULL;
+ char *home1_axis = NULL;
+ char *home2_axis = NULL;
+ cptr home1_distance = NULL;
+ cptr home2_distance = NULL;
+ cptr feel_it_str = feel_it ? ", I can feel it.'" : ".";
+ char buf[256];
+
+ get_home_coordinates(
+ &home1_y, &home1_x, &home1,
+ &home2_y, &home2_x, &home2);
+
+ home1_axis = compass(home1_y, home1_x, cquest_dung_y, cquest_dung_x);
+ home2_axis = compass(home2_y, home2_x, cquest_dung_y, cquest_dung_x);
+
+ home1_distance = approximate_distance(home1_y, home1_x, cquest_dung_y, cquest_dung_x);
+ home2_distance = approximate_distance(home2_y, home2_x, cquest_dung_y, cquest_dung_x);
+
+ /* Build the message */
+ if (!streq(home1_axis, "close"))
+ {
+ snprintf(buf, sizeof(buf),
+ "The temple lies %s to the %s of %s, ",
+ home1_distance,
+ home1_axis,
+ home1);
+ pfunc(buf, pfdata);
+ }
+ else
+ {
+ snprintf(buf, sizeof(buf),
+ "The temple lies very close to %s, ",
+ home1);
+ pfunc(buf, pfdata);
+ }
+
+ if (!streq(home2_axis, "close"))
+ {
+ snprintf(buf, sizeof(buf),
+ "and %s to the %s of %s%s",
+ home2_distance,
+ home2_axis,
+ home2,
+ feel_it_str);
+ pfunc(buf, pfdata);
+ }
+ else
+ {
+ snprintf(buf, sizeof(buf),
+ "and very close to %s%s",
+ home2,
+ feel_it_str);
+ pfunc(buf, pfdata);
+ }
+
+ /* Free dyanmically allocated strings */
+ free(home1_axis);
+ free(home2_axis);
+}
+
+bool_ quest_god_describe(FILE *fff)
+{
+ if (cquest.status == QUEST_STATUS_TAKEN)
+ {
+ fprintf(fff, "#####yGod quest " FMTs32b "!\n", cquest_quests_given);
+ fprintf(fff, "Thou art to find the lost temple of thy God and\n");
+ fprintf(fff, "to retrieve the lost part of the relic for thy God! \n");
+ print_directions(FALSE, print_using_print_hook, fff);
+ fprintf(fff, "\n");
+ }
+
+ return TRUE;
+}
+
+static void quest_god_place_rand_dung()
+{
+ int x = -1, y = -1, tries;
+
+ /* erase old dungeon */
+ if (cquest_quests_given > 0)
+ {
+ wild_map[cquest_dung_y][cquest_dung_x].entrance = 0;
+
+ /* erase old recall level */
+ max_dlv[DUNGEON_GOD] = 0;
+ }
+
+ /* initialise tries variable */
+ tries = 1000;
+ while (tries > 0)
+ {
+ wilderness_map *w_ptr = NULL;
+ wilderness_type_info *wf_ptr = NULL;
+ tries = tries - 1;
+
+ /* get grid coordinates, within a range which prevents
+ * dungeon being generated at the very edge of the
+ * wilderness (would crash the game). */
+ x = rand_range(1, max_wild_x-2);
+ y = rand_range(1, max_wild_y-2);
+
+ /* Is there a town/dungeon/potentially impassable feature there, ? */
+ w_ptr = &wild_map[y][x];
+ wf_ptr = &wf_info[w_ptr->feat];
+
+ if ((w_ptr->entrance != 0) ||
+ (wf_ptr->entrance != 0) ||
+ (wf_ptr->terrain_idx == TERRAIN_EDGE) ||
+ (wf_ptr->terrain_idx == TERRAIN_DEEP_WATER) ||
+ (wf_ptr->terrain_idx == TERRAIN_TREES) ||
+ (wf_ptr->terrain_idx == TERRAIN_SHALLOW_LAVA) ||
+ (wf_ptr->terrain_idx == TERRAIN_DEEP_LAVA) ||
+ (wf_ptr->terrain_idx == TERRAIN_MOUNTAIN))
+ {
+ /* try again */
+ }
+ else
+ {
+ /* either player, nor wall, then stop this 'while' */
+ break;
+ }
+ }
+
+ assert(x >= 0);
+ assert(y >= 0);
+
+ if (tries == 0)
+ {
+ /* Use Bree as last resort */
+ x = 32;
+ y = 19;
+ }
+
+ /* create god dungeon in that place */
+ wild_map[y][x].entrance = 1000 + DUNGEON_GOD;
+
+ /* set quest variables */
+ cquest_dung_x = x;
+ cquest_dung_y = y;
+}
+
+static void quest_god_generate_relic()
+{
+ int tries = 1000, x = -1, y = -1;
+ object_type relic;
+
+ tries = 1000;
+
+ while (tries > 0)
+ {
+ cave_type *c_ptr;
+ tries = tries - 1;
+ /* get grid coordinates from current height/width,
+ * minus one to prevent relic being generated in
+ * outside wall. (would crash the game) */
+ y = randint(cur_hgt-1);
+ x = randint(cur_wid-1);
+ c_ptr = &cave[y][x];
+
+ /* are the coordinates on a floor, not on a permanent feature (eg stairs), and not on a trap ? */
+ if ((f_info[c_ptr->feat].flags1 & FF1_FLOOR) &&
+ (!(f_info[c_ptr->feat].flags1 & FF1_PERMANENT)) &&
+ (c_ptr->t_idx == 0))
+ {
+ break;
+ }
+ }
+
+ /* create relic */
+ object_prep(&relic, lookup_kind(TV_JUNK, get_relic_num()));
+
+ /* inscribe it to prevent automatizer 'accidents' */
+ relic.note = quark_add("quest");
+
+ /* If no safe co-ords were found, put it in the players backpack */
+ if (tries == 0)
+ {
+ /* explain it */
+ cmsg_print(TERM_L_BLUE, "You luckily stumble across the relic on the stairs!");
+
+ if (inven_carry_okay(&relic))
+ {
+ inven_carry(&relic, FALSE);
+ }
+ else
+ {
+ /* no place found, drop it on the stairs */
+ drop_near(&relic, -1, p_ptr->py, p_ptr->px);
+ }
+ }
+ else
+ {
+ /* drop it */
+ drop_near(&relic, -1, y, x);
+ }
+
+ /* Only generate once! */
+ cquest_relic_generated = TRUE;
+
+ /* Reset some variables */
+ cquest_relic_gen_tries = 0;
+}
+
+static void quest_god_set_god_dungeon_attributes_eru()
+{
+ /* The Eru temple is based on Meneltarma. */
+
+ /* W: Not too many monsters (they'll be tough though, with big
+ * levels) */
+ d_info[DUNGEON_GOD].min_m_alloc_level = 14;
+ d_info[DUNGEON_GOD].max_m_alloc_chance = 200;
+
+ /* L: Dirt and grass. More dirt at bottom, more grass at
+ * top. rocky ground would be nice */
+ d_info[DUNGEON_GOD].floor1 = 88;
+ d_info[DUNGEON_GOD].floor2 = 89;
+ d_info[DUNGEON_GOD].floor_percent1[0] = 70;
+ d_info[DUNGEON_GOD].floor_percent2[0] = 30;
+ d_info[DUNGEON_GOD].floor_percent1[1] = 10;
+ d_info[DUNGEON_GOD].floor_percent2[1] = 90;
+
+ /* A: Outer wall mountain chain. other walls granite */
+ d_info[DUNGEON_GOD].fill_type1 = 97;
+ d_info[DUNGEON_GOD].fill_percent1[0] = 100;
+ d_info[DUNGEON_GOD].outer_wall = 57;
+ d_info[DUNGEON_GOD].inner_wall = 97;
+ d_info[DUNGEON_GOD].fill_method = 2;
+
+ /* O: "At Meneltarma no weapon or tool had ever been borne"
+ * (but invaders would have left a small number) */
+ d_info[DUNGEON_GOD].objs.treasure = 45;
+ d_info[DUNGEON_GOD].objs.combat = 5;
+ d_info[DUNGEON_GOD].objs.magic = 45;
+ d_info[DUNGEON_GOD].objs.tools = 5;
+
+ /* F: A large pillar, with stairs created at edges. (You can't
+ * climb a rock through the middle, can you?) */
+ d_info[DUNGEON_GOD].flags1 =
+ DF1_BIG | DF1_NO_DOORS | DF1_CIRCULAR_ROOMS |
+ DF1_EMPTY | DF1_TOWER | DF1_FLAT | DF1_ADJUST_LEVEL_2;
+ d_info[DUNGEON_GOD].flags2 =
+ DF2_ADJUST_LEVEL_1_2 |
+ DF2_NO_SHAFT |
+ DF2_ADJUST_LEVEL_PLAYER;
+
+ /* R: */
+ d_info[DUNGEON_GOD].rules[0].mode = 3;
+ d_info[DUNGEON_GOD].rules[0].percent = 50;
+
+ /* M: We want evil or flying characters */
+ d_info[DUNGEON_GOD].rules[0].mflags3 = RF3_EVIL;
+
+ d_info[DUNGEON_GOD].rules[1].mode = 3;
+ d_info[DUNGEON_GOD].rules[1].percent = 50;
+
+ /* M: We want evil or flying characters */
+ d_info[DUNGEON_GOD].rules[1].mflags7 = RF7_CAN_FLY;
+}
+
+static void quest_god_set_god_dungeon_attributes_manwe()
+{
+ /* Manwe's lost temple is high in the clouds */
+
+ /* W: Has average number of monsters. */
+ d_info[DUNGEON_GOD].min_m_alloc_level = 18;
+ d_info[DUNGEON_GOD].max_m_alloc_chance = 160;
+
+ /* L: floor will be 'cloud-like vapour' and pools of
+ * 'condensing water' */
+ d_info[DUNGEON_GOD].floor1 = 208;
+ d_info[DUNGEON_GOD].floor2 = 209;
+ d_info[DUNGEON_GOD].floor_percent1[0] = 85;
+ d_info[DUNGEON_GOD].floor_percent2[0] = 15;
+
+ /* A: Outer wall is 'hail stone wall', inner wall 'dense
+ * fog'. FIlled at max smoothing, like islands. */
+ d_info[DUNGEON_GOD].fill_type1 = 211;
+ d_info[DUNGEON_GOD].fill_percent1[0] = 100;
+ d_info[DUNGEON_GOD].outer_wall = 210;
+ d_info[DUNGEON_GOD].inner_wall = 211;
+ d_info[DUNGEON_GOD].fill_method = 4;
+
+ /* O: Can't imagine Manwe having much treasure. Little need
+ * for tools in a cloud temple. lots of magical stuff
+ * though... */
+ d_info[DUNGEON_GOD].objs.treasure = 15;
+ d_info[DUNGEON_GOD].objs.combat = 25;
+ d_info[DUNGEON_GOD].objs.magic = 55;
+ d_info[DUNGEON_GOD].objs.tools = 5;
+
+ /* F: It's open, goes up like a tower, give it a few
+ * interesting rooms, make the monsters hard(ish). */
+ d_info[DUNGEON_GOD].flags1 =
+ DF1_NO_DOORS | DF1_TOWER |
+ DF1_CAVERN | DF1_ADJUST_LEVEL_2;
+ d_info[DUNGEON_GOD].flags2 =
+ DF2_NO_SHAFT | DF2_ADJUST_LEVEL_PLAYER;
+
+ /* R: */
+ d_info[DUNGEON_GOD].rules[0].mode = 3;
+ d_info[DUNGEON_GOD].rules[0].percent = 20;
+ d_info[DUNGEON_GOD].rules[1].mode = 3;
+ d_info[DUNGEON_GOD].rules[1].percent = 20;
+ d_info[DUNGEON_GOD].rules[2].mode = 3;
+ d_info[DUNGEON_GOD].rules[2].percent = 20;
+ d_info[DUNGEON_GOD].rules[3].mode = 3;
+ d_info[DUNGEON_GOD].rules[3].percent = 20;
+ d_info[DUNGEON_GOD].rules[4].mode = 3;
+ d_info[DUNGEON_GOD].rules[4].percent = 20;
+
+ /* M: We want air(poison-type) or flying characters. Orcs
+ * too. They would have ransacked his elf-loving temple :) */
+ d_info[DUNGEON_GOD].rules[0].mflags2 = RF2_INVISIBLE;
+ d_info[DUNGEON_GOD].rules[1].mflags3 = RF3_ORC | RF3_IM_POIS;
+ d_info[DUNGEON_GOD].rules[2].mflags4 = RF4_BR_POIS | RF4_BR_GRAV;
+ d_info[DUNGEON_GOD].rules[3].mflags5 = RF5_BA_POIS;
+ d_info[DUNGEON_GOD].rules[4].mflags7 = RF7_CAN_FLY;
+}
+
+static void quest_god_set_god_dungeon_attributes_tulkas()
+{
+ /* Tulkas dungeon is quite normal, possibly a bit boring to be
+ * honest. Maybe I should add something radical to it. 'The
+ * house of Tulkas in the midmost of Valmar was a house of
+ * mirth and revelry. It sprang into the air with many
+ * storeys, and had a tower of bronze and pillars of copper in
+ * a wide arcade'
+ */
+
+ /* W: but with lots of monsters */
+ d_info[DUNGEON_GOD].min_m_alloc_level = 20;
+ d_info[DUNGEON_GOD].max_m_alloc_chance = 120;
+
+ /* L: floor is normal */
+ d_info[DUNGEON_GOD].floor1 = 1;
+ d_info[DUNGEON_GOD].floor_percent1[0] = 100;
+
+ /* A: Granite walls */
+ d_info[DUNGEON_GOD].fill_type1 = 56;
+ d_info[DUNGEON_GOD].fill_percent1[0] = 100;
+ d_info[DUNGEON_GOD].outer_wall = 58;
+ d_info[DUNGEON_GOD].inner_wall = 57;
+ d_info[DUNGEON_GOD].fill_method = 0;
+
+ /* O: Loads of combat drops */
+ d_info[DUNGEON_GOD].objs.treasure = 10;
+ d_info[DUNGEON_GOD].objs.combat = 70;
+ d_info[DUNGEON_GOD].objs.magic = 5;
+ d_info[DUNGEON_GOD].objs.tools = 15;
+
+ /* F: fairly standard */
+ d_info[DUNGEON_GOD].flags1 = DF1_NO_DESTROY | DF1_ADJUST_LEVEL_2;
+ d_info[DUNGEON_GOD].flags2 = DF2_ADJUST_LEVEL_PLAYER;
+
+ /* R: */
+ d_info[DUNGEON_GOD].rules[0].mode = 3;
+ d_info[DUNGEON_GOD].rules[0].percent = 100;
+
+ /* M: plenty demons please */
+ d_info[DUNGEON_GOD].rules[0].mflags3 = RF3_DEMON | RF3_EVIL;
+}
+
+static void quest_god_set_god_dungeon_attributes_melkor()
+{
+ /* Melkors dungeon will be dark, fiery and stuff */
+
+ /* Many many monsters! (but prob ADJUST_LEVEL_1_2) */
+ d_info[DUNGEON_GOD].min_m_alloc_level = 24;
+ d_info[DUNGEON_GOD].max_m_alloc_chance = 80;
+
+ /* L: floor is dirt/mud/nether */
+ d_info[DUNGEON_GOD].floor1 = 88;
+ d_info[DUNGEON_GOD].floor2 = 94;
+ d_info[DUNGEON_GOD].floor3 = 102;
+ d_info[DUNGEON_GOD].floor_percent1[0] = 45;
+ d_info[DUNGEON_GOD].floor_percent2[0] = 45;
+ d_info[DUNGEON_GOD].floor_percent3[0] = 10;
+ d_info[DUNGEON_GOD].floor_percent1[1] = 35;
+ d_info[DUNGEON_GOD].floor_percent2[1] = 35;
+ d_info[DUNGEON_GOD].floor_percent3[1] = 30;
+
+ /* A: Granite walls to fill but glass walls for room
+ * perimeters (you can see the nasty monsters coming) */
+ d_info[DUNGEON_GOD].fill_type1 = 188;
+ d_info[DUNGEON_GOD].fill_percent1[0] = 100;
+ d_info[DUNGEON_GOD].outer_wall = 188;
+ d_info[DUNGEON_GOD].inner_wall = 57;
+ d_info[DUNGEON_GOD].fill_method = 1;
+
+ /* O: Even drops */
+ d_info[DUNGEON_GOD].objs.treasure = 25;
+ d_info[DUNGEON_GOD].objs.combat = 25;
+ d_info[DUNGEON_GOD].objs.magic = 25;
+ d_info[DUNGEON_GOD].objs.tools = 25;
+
+ /* F: Small, lava rivers, nasty monsters hehehehehe */
+ d_info[DUNGEON_GOD].flags1 = DF1_SMALL | DF1_LAVA_RIVERS | DF1_ADJUST_LEVEL_1;
+ d_info[DUNGEON_GOD].flags2 = DF2_ADJUST_LEVEL_1_2 | DF2_ADJUST_LEVEL_PLAYER;
+
+ /* R: No restrictions on monsters here */
+ d_info[DUNGEON_GOD].rules[0].mode = 0;
+ d_info[DUNGEON_GOD].rules[0].percent = 80;
+
+ /* R: Apart from making sure we have some GOOD ones */
+ d_info[DUNGEON_GOD].rules[1].mode = 3;
+ d_info[DUNGEON_GOD].rules[1].percent = 20;
+
+ /* M: */
+ d_info[DUNGEON_GOD].rules[1].mflags3 = RF3_GOOD;
+}
+
+static void quest_god_set_god_dungeon_attributes_yavanna()
+{
+ /* Yavannas dungeon will be very natural, tress and stuff. */
+
+ d_info[DUNGEON_GOD].min_m_alloc_level = 22;
+ d_info[DUNGEON_GOD].max_m_alloc_chance = 100;
+
+ /* L: floor is grass/flowers, plus dirt so not always
+ * regenerating quick! */
+ d_info[DUNGEON_GOD].floor1 = 89;
+ d_info[DUNGEON_GOD].floor2 = 199;
+ d_info[DUNGEON_GOD].floor3 = 88;
+ d_info[DUNGEON_GOD].floor_percent1[0] = 40;
+ d_info[DUNGEON_GOD].floor_percent2[0] = 15;
+ d_info[DUNGEON_GOD].floor_percent3[0] = 45;
+
+ /* A: Tree walls to fill, small trees for inner walls */
+ d_info[DUNGEON_GOD].fill_type1 = 96;
+ d_info[DUNGEON_GOD].fill_percent1[0] = 100;
+ d_info[DUNGEON_GOD].outer_wall = 202;
+ d_info[DUNGEON_GOD].inner_wall = 96;
+ d_info[DUNGEON_GOD].fill_method = 1;
+
+ /* O: not much combat.. tools where ransackers have tried to
+ * chop trees down. */
+ d_info[DUNGEON_GOD].objs.treasure = 20;
+ d_info[DUNGEON_GOD].objs.combat = 10;
+ d_info[DUNGEON_GOD].objs.magic = 30;
+ d_info[DUNGEON_GOD].objs.tools = 40;
+
+ /* F: Natural looking */
+ d_info[DUNGEON_GOD].flags1 =
+ DF1_NO_DOORS | DF1_WATER_RIVERS |
+ DF1_NO_DESTROY | DF1_ADJUST_LEVEL_1 |
+ DF1_NO_RECALL;
+ d_info[DUNGEON_GOD].flags2 =
+ DF2_ADJUST_LEVEL_1_2 | DF2_NO_SHAFT |
+ DF2_NO_GENO | DF2_ADJUST_LEVEL_PLAYER;
+
+ /* R: Demons, Undead, non-living */
+ d_info[DUNGEON_GOD].rules[0].mode = 3;
+ d_info[DUNGEON_GOD].rules[0].percent = 100;
+
+ /* M: */
+ d_info[DUNGEON_GOD].rules[0].mflags3 =
+ RF3_DEMON | RF3_UNDEAD | RF3_NONLIVING;
+}
+
+static void quest_god_set_god_dungeon_attributes_aule()
+{
+ d_info[DUNGEON_GOD].min_m_alloc_level = 24;
+ d_info[DUNGEON_GOD].max_m_alloc_chance = 80;
+
+ /* L: floor is dirt/mud/shallow water */
+ d_info[DUNGEON_GOD].floor1 = 88;
+ d_info[DUNGEON_GOD].floor2 = 94;
+ d_info[DUNGEON_GOD].floor3 = 84;
+ d_info[DUNGEON_GOD].floor_percent1[0] = 45;
+ d_info[DUNGEON_GOD].floor_percent2[0] = 45;
+ d_info[DUNGEON_GOD].floor_percent3[0] = 10;
+ d_info[DUNGEON_GOD].floor_percent1[1] = 35;
+ d_info[DUNGEON_GOD].floor_percent2[1] = 35;
+ d_info[DUNGEON_GOD].floor_percent3[1] = 30;
+
+ /* A: Grey mountains, inner walls are low hills */
+ d_info[DUNGEON_GOD].fill_type1 = 216;
+ d_info[DUNGEON_GOD].fill_percent1[0] = 100;
+ d_info[DUNGEON_GOD].outer_wall = 216;
+ d_info[DUNGEON_GOD].inner_wall = 213;
+ d_info[DUNGEON_GOD].fill_method = 1;
+
+ /* O: Weapons and tools only */
+ d_info[DUNGEON_GOD].objs.treasure = 0;
+ d_info[DUNGEON_GOD].objs.combat = 50;
+ d_info[DUNGEON_GOD].objs.magic = 0;
+ d_info[DUNGEON_GOD].objs.tools = 50;
+
+ /* F: Small, no destroyed levels, min monster level = dungeon
+ * level */
+ d_info[DUNGEON_GOD].flags1 =
+ DF1_SMALL | DF1_NO_DESTROY |
+ DF1_ADJUST_LEVEL_1 | DF1_NO_STREAMERS;
+
+ /* R: No restrictions on monsters here */
+ d_info[DUNGEON_GOD].rules[0].mode = 0;
+ d_info[DUNGEON_GOD].rules[0].percent = 80;
+}
+
+static void quest_god_set_god_dungeon_attributes_varda()
+{
+ /* Varda lives with Manwe, so high in the clouds */
+
+ /* W: Has average number of monsters. */
+ d_info[DUNGEON_GOD].min_m_alloc_level = 18;
+ d_info[DUNGEON_GOD].max_m_alloc_chance = 160;
+
+ /* L: floor will be grass and flowers */
+ d_info[DUNGEON_GOD].floor1 = 89;
+ d_info[DUNGEON_GOD].floor2 = 82;
+ d_info[DUNGEON_GOD].floor_percent1[0] = 85;
+ d_info[DUNGEON_GOD].floor_percent2[0] = 15;
+
+ /* A: Outer wall is 'hail stone wall', inner wall 'dense
+ * fog'. Filled at max smoothing, like islands. */
+ d_info[DUNGEON_GOD].fill_type1 = 211;
+ d_info[DUNGEON_GOD].fill_percent1[0] = 100;
+ d_info[DUNGEON_GOD].outer_wall = 210;
+ d_info[DUNGEON_GOD].inner_wall = 211;
+ d_info[DUNGEON_GOD].fill_method = 4;
+
+ /* O: Varda likes magical items and tools, not much treasure
+ * or weapons */
+ d_info[DUNGEON_GOD].objs.treasure = 15;
+ d_info[DUNGEON_GOD].objs.combat = 5;
+ d_info[DUNGEON_GOD].objs.magic = 55;
+ d_info[DUNGEON_GOD].objs.tools = 25;
+
+ /* F: It's open, goes up like a tower, give it a few
+ * interesting rooms, make the monsters hard(ish). */
+ d_info[DUNGEON_GOD].flags1 =
+ DF1_NO_DOORS | DF1_TOWER |
+ DF1_CAVERN | DF1_ADJUST_LEVEL_1;
+ d_info[DUNGEON_GOD].flags2 =
+ DF2_NO_SHAFT | DF2_ADJUST_LEVEL_PLAYER;
+
+ /* R: */
+ d_info[DUNGEON_GOD].rules[0].mode = 3;
+ d_info[DUNGEON_GOD].rules[0].percent = 20;
+ d_info[DUNGEON_GOD].rules[1].mode = 3;
+ d_info[DUNGEON_GOD].rules[1].percent = 20;
+ d_info[DUNGEON_GOD].rules[2].mode = 3;
+ d_info[DUNGEON_GOD].rules[2].percent = 20;
+ d_info[DUNGEON_GOD].rules[3].mode = 3;
+ d_info[DUNGEON_GOD].rules[3].percent = 20;
+ d_info[DUNGEON_GOD].rules[4].mode = 3;
+ d_info[DUNGEON_GOD].rules[4].percent = 20;
+
+ /* M: We want air(poison-type) or flying characters. Orcs too. */
+ d_info[DUNGEON_GOD].rules[0].mflags2 = RF2_INVISIBLE;
+ d_info[DUNGEON_GOD].rules[1].mflags3 = RF3_ORC | RF3_IM_POIS;
+ d_info[DUNGEON_GOD].rules[2].mflags4 = RF4_BR_POIS | RF4_BR_GRAV;
+ d_info[DUNGEON_GOD].rules[3].mflags5 = RF5_BA_POIS;
+ d_info[DUNGEON_GOD].rules[4].mflags7 = RF7_CAN_FLY;
+}
+
+static void quest_god_set_god_dungeon_attributes_ulmo()
+{
+ /* Ulmo dungeon is basically Tulkas, except with acquatic creatures. */
+
+ /* W: but with lots of monsters */
+ d_info[DUNGEON_GOD].min_m_alloc_level = 20;
+ d_info[DUNGEON_GOD].max_m_alloc_chance = 120;
+
+ /* L: floor is dirt */
+ d_info[DUNGEON_GOD].floor1 = 88;
+ d_info[DUNGEON_GOD].floor_percent1[0] = 100;
+
+ /* A: Cheat: walls are water. */
+ d_info[DUNGEON_GOD].fill_type1 = 187;
+ d_info[DUNGEON_GOD].fill_percent1[0] = 100;
+ d_info[DUNGEON_GOD].outer_wall = 238;
+ d_info[DUNGEON_GOD].inner_wall = 84;
+ d_info[DUNGEON_GOD].fill_method = 0;
+
+ /* O: Lots of treasure, not much else. */
+ d_info[DUNGEON_GOD].objs.treasure = 90;
+ d_info[DUNGEON_GOD].objs.combat = 0;
+ d_info[DUNGEON_GOD].objs.magic = 5;
+ d_info[DUNGEON_GOD].objs.tools = 5;
+
+ /* F: fairly standard */
+ d_info[DUNGEON_GOD].flags1 = DF1_NO_DESTROY | DF1_ADJUST_LEVEL_2;
+ d_info[DUNGEON_GOD].flags2 = DF2_ADJUST_LEVEL_PLAYER;
+
+ /* R: */
+ d_info[DUNGEON_GOD].rules[0].mode = 3;
+ d_info[DUNGEON_GOD].rules[0].percent = 35;
+ d_info[DUNGEON_GOD].rules[1].mode = 3;
+ d_info[DUNGEON_GOD].rules[1].percent = 30;
+ d_info[DUNGEON_GOD].rules[2].mode = 3;
+ d_info[DUNGEON_GOD].rules[2].percent = 30;
+
+ /* M: Aquatic creatures only. */
+ d_info[DUNGEON_GOD].rules[0].mflags3 = RF7_CAN_FLY;
+ d_info[DUNGEON_GOD].rules[1].mflags3 = RF7_AQUATIC;
+ d_info[DUNGEON_GOD].rules[2].mflags3 = RF3_RES_WATE;
+}
+
+static void quest_god_set_god_dungeon_attributes_mandos()
+{
+ /* Mandos dungeon is basically Tulkas, except with undead. */
+
+ /* W: but with lots of monsters */
+ d_info[DUNGEON_GOD].min_m_alloc_level = 20;
+ d_info[DUNGEON_GOD].max_m_alloc_chance = 120;
+
+ /* L: floor is normal */
+ d_info[DUNGEON_GOD].floor1 = 1;
+ d_info[DUNGEON_GOD].floor_percent1[0] = 100;
+
+ /* A: Granite walls */
+ d_info[DUNGEON_GOD].fill_type1 = 56;
+ d_info[DUNGEON_GOD].fill_percent1[0] = 100;
+ d_info[DUNGEON_GOD].outer_wall = 58;
+ d_info[DUNGEON_GOD].inner_wall = 57;
+ d_info[DUNGEON_GOD].fill_method = 0;
+
+ /* O: Loads of combat drops */
+ d_info[DUNGEON_GOD].objs.treasure = 10;
+ d_info[DUNGEON_GOD].objs.combat = 70;
+ d_info[DUNGEON_GOD].objs.magic = 5;
+ d_info[DUNGEON_GOD].objs.tools = 15;
+
+ /* F: fairly standard */
+ d_info[DUNGEON_GOD].flags1 = DF1_NO_DESTROY | DF1_ADJUST_LEVEL_2;
+ d_info[DUNGEON_GOD].flags2 = DF2_ADJUST_LEVEL_PLAYER;
+
+ /* R: */
+ d_info[DUNGEON_GOD].rules[0].mode = 3;
+ d_info[DUNGEON_GOD].rules[0].percent = 100;
+
+ /* M: vampires! */
+ d_info[DUNGEON_GOD].rules[0].r_char[0] = 'V';
+ d_info[DUNGEON_GOD].rules[0].r_char[1] = '\0';
+ d_info[DUNGEON_GOD].rules[0].r_char[2] = '\0';
+ d_info[DUNGEON_GOD].rules[0].r_char[3] = '\0';
+ d_info[DUNGEON_GOD].rules[0].r_char[4] = '\0';
+ d_info[DUNGEON_GOD].rules[0].mflags3 = RF3_UNDEAD | RF3_EVIL;
+}
+
+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 */
+ 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!");
+
+ print_directions(TRUE, print_using_cmsg, NULL);
+
+ /* Prepare depth of dungeon. If this was
+ * generated in set_god_dungeon_attributes(),
+ * then we'd have trouble if someone levelled
+ * up in the dungeon! */
+ 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 *)
+{
+ 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()
+{
+ /* 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 */
+ {
+ dungeon_info_type *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;
+}
+
+bool_ quest_god_init_hook(int q)
+{
+ /* Only need hooks if the quest is unfinished. */
+ if ((cquest.status >= QUEST_STATUS_UNTAKEN) &&
+ (cquest.status < QUEST_STATUS_FINISHED))
+ {
+ add_hook_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);
+
+ return FALSE;
+}
diff --git a/src/q_god.hpp b/src/q_god.hpp
new file mode 100644
index 00000000..d9513bdb
--- /dev/null
+++ b/src/q_god.hpp
@@ -0,0 +1,6 @@
+#pragma once
+
+#include "h-basic.h"
+
+bool_ quest_god_describe(FILE *);
+bool_ quest_god_init_hook(int q);
diff --git a/src/q_haunted.c b/src/q_haunted.cc
index db8992bc..57daa40e 100644
--- a/src/q_haunted.c
+++ b/src/q_haunted.cc
@@ -1,7 +1,23 @@
-#undef cquest
+#include "q_haunted.hpp"
+
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "feature_type.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 "traps.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 *)
{
int x, y, i, m_idx;
int xstart = 2;
@@ -86,7 +102,7 @@ bool_ quest_haunted_gen_hook(char *fmt)
return TRUE;
}
-bool_ quest_haunted_death_hook(char *fmt)
+static bool_ quest_haunted_death_hook(void *, void *, void *)
{
int i, mcnt = 0;
@@ -108,8 +124,9 @@ bool_ quest_haunted_death_hook(char *fmt)
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.");
@@ -118,11 +135,10 @@ bool_ quest_haunted_death_hook(char *fmt)
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;
@@ -139,9 +155,9 @@ bool_ quest_haunted_init_hook(int q_idx)
{
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..4f51bce3
--- /dev/null
+++ b/src/q_haunted.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+bool_ quest_haunted_init_hook(int q_idx);
diff --git a/src/q_hobbit.c b/src/q_hobbit.cc
index f3b7d856..5a71711e 100644
--- a/src/q_hobbit.c
+++ b/src/q_hobbit.cc
@@ -1,12 +1,35 @@
-#undef cquest
+#include "q_hobbit.hpp"
+
+#include "cave.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])
-bool_ quest_hobbit_town_gen_hook(char *fmt)
+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;
- s32b small;
-
- small = get_next_arg(fmt);
+ bool_ small = in->small;
if ((turn < (cquest.data[1] + (DAY * 10L))) || (cquest.status > QUEST_STATUS_COMPLETED) || (small) || (p_ptr->town_num != 1)) return (FALSE);
@@ -27,13 +50,15 @@ bool_ quest_hobbit_town_gen_hook(char *fmt)
}
/* 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;
+ 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;
}
-bool_ quest_hobbit_gen_hook(char *fmt)
+
+static bool_ quest_hobbit_gen_hook(void *, void *, void *)
{
int x = 1, y = 1, tries = 10000;
@@ -54,25 +79,26 @@ bool_ quest_hobbit_gen_hook(char *fmt)
}
/* 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;
+ 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;
}
-bool_ quest_hobbit_give_hook(char *fmt)
+
+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, item;
-
- m_idx = get_next_arg(fmt);
- item = get_next_arg(fmt);
+ 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 != test_monster_name("Merton Proudfoot, the lost hobbit")) return (FALSE);
+ 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);
@@ -85,37 +111,38 @@ bool_ quest_hobbit_give_hook(char *fmt)
cquest.status = QUEST_STATUS_COMPLETED;
- del_hook(HOOK_GIVE, quest_hobbit_give_hook);
+ del_hook_new(HOOK_GIVE, quest_hobbit_give_hook);
process_hooks_restart = TRUE;
return TRUE;
}
-bool_ quest_hobbit_speak_hook(char *fmt)
+
+static bool_ quest_hobbit_speak_hook(void *, void *in_, void *)
{
- s32b m_idx = get_next_arg(fmt);
+ 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 != test_monster_name("Melinda Proudfoot")) return (FALSE);
+ if (m_list[m_idx].r_idx != get_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);
+ msg_format("%^s begs for your help.", in->m_name);
}
return (TRUE);
}
-bool_ quest_hobbit_chat_hook(char *fmt)
+
+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;
- 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 (m_ptr->r_idx != get_melinda_proudfoot()) return (FALSE);
if (cquest.status < QUEST_STATUS_COMPLETED)
{
@@ -145,7 +172,7 @@ bool_ quest_hobbit_chat_hook(char *fmt)
cquest.status = QUEST_STATUS_FINISHED;
- del_hook(HOOK_MON_SPEAK, quest_hobbit_speak_hook);
+ del_hook_new(HOOK_MON_SPEAK, quest_hobbit_speak_hook);
process_hooks_restart = TRUE;
delete_monster_idx(m_idx);
@@ -158,14 +185,19 @@ bool_ quest_hobbit_chat_hook(char *fmt)
return TRUE;
}
-bool_ quest_hobbit_dump_hook(char *fmt)
+
+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(hook_file, "\n You saved a young hobbit from an horrible fate.");
+ fprintf(f, "\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 */
@@ -173,23 +205,26 @@ bool_ quest_hobbit_init_hook(int q_idx)
{
cquest.data[0] = rand_range(26, 34);
cquest.data[1] = turn;
- if (wizard) message_add(MESSAGE_MSG, format("Hobbit level %d", cquest.data[0]), TERM_BLUE);
+ if (wizard)
+ {
+ message_add(format("Hobbit level %d", cquest.data[0]), TERM_BLUE);
+ }
}
if ((cquest.status >= QUEST_STATUS_TAKEN) && (cquest.status < QUEST_STATUS_FINISHED))
{
- 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");
+ 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(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_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(HOOK_CHAR_DUMP, quest_hobbit_dump_hook, "hobbit_dump");
+ add_hook_new(HOOK_CHAR_DUMP, quest_hobbit_dump_hook, "hobbit_dump", NULL);
return (FALSE);
}
diff --git a/src/q_hobbit.hpp b/src/q_hobbit.hpp
new file mode 100644
index 00000000..b1878748
--- /dev/null
+++ b/src/q_hobbit.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+bool_ quest_hobbit_init_hook(int q_idx);
diff --git a/src/q_invas.c b/src/q_invas.cc
index 59c71d62..64483d28 100644
--- a/src/q_invas.c
+++ b/src/q_invas.cc
@@ -1,7 +1,25 @@
-#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;
@@ -43,13 +61,13 @@ bool_ quest_invasion_gen_hook(char *fmt)
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;
@@ -74,18 +92,17 @@ bool_ quest_invasion_ai_hook(char *fmt)
}
else
{
- process_hooks_return[0].num = cquest.data[0];
- process_hooks_return[1].num = cquest.data[1];
+ out->y = cquest.data[0];
+ out->x = cquest.data[1];
return (TRUE);
}
}
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 +113,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,31 +120,34 @@ 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);
+ del_hook_new(HOOK_END_TURN, quest_invasion_turn_hook);
process_hooks_restart = TRUE;
+
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);
}
-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;
@@ -136,24 +155,25 @@ bool_ quest_invasion_death_hook(char *fmt)
{
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;
}
-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 +199,24 @@ 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 TRUE;
}
+
bool_ quest_invasion_init_hook(int q_idx)
{
- 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..87b8fc77
--- /dev/null
+++ b/src/q_invas.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+bool_ quest_invasion_init_hook(int q_idx);
diff --git a/src/q_library.cc b/src/q_library.cc
new file mode 100644
index 00000000..52a67291
--- /dev/null
+++ b/src/q_library.cc
@@ -0,0 +1,526 @@
+#include "q_library.hpp"
+
+#include "cave_type.hpp"
+#include "hooks.hpp"
+#include "lua_bind.hpp"
+#include "monster2.hpp"
+#include "monster_type.hpp"
+#include "object2.hpp"
+#include "player_type.hpp"
+#include "quark.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>
+
+#define cquest (quest[QUEST_LIBRARY])
+
+#define print_hook(fmt,...) do { fprintf(hook_file, fmt, ##__VA_ARGS__); } while (0)
+
+#define MONSTER_LICH 518
+#define MONSTER_MONASTIC_LICH 611
+#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(DISARM);
+ push_spell(TELEPORT);
+ push_spell(SENSEMONSTERS);
+ push_spell(SENSEHIDDEN);
+ push_spell(REVEALWAYS);
+ push_spell(IDENTIFY);
+ push_spell(VISION);
+ push_spell(MAGELOCK);
+ push_spell(SLOWMONSTER);
+ push_spell(ESSENCESPEED);
+ push_spell(CHARM);
+ push_spell(CONFUSE);
+ push_spell(ARMOROFFEAR);
+ push_spell(STUN);
+ push_spell(GROWTREE);
+ push_spell(HEALING);
+ push_spell(RECOVERY);
+ push_spell(ERU_SEE);
+ push_spell(ERU_LISTEN);
+ push_spell(MANWE_BLESS);
+ push_spell(MANWE_SHIELD);
+ push_spell(YAVANNA_CHARM_ANIMAL);
+ push_spell(YAVANNA_GROW_GRASS);
+ push_spell(YAVANNA_TREE_ROOTS);
+ push_spell(TULKAS_AIM);
+ push_spell(TULKAS_SPIN);
+ push_spell(MELKOR_CURSE);
+ push_spell(MELKOR_CORPSE_EXPLOSION);
+ push_spell(DRAIN);
+
+ if (game_module_idx == MODULE_THEME)
+ {
+ push_spell(AULE_FIREBRAND);
+ push_spell(AULE_CHILD);
+ push_spell(VARDA_LIGHT_VALINOR);
+ push_spell(VARDA_EVENSTAR);
+ push_spell(ULMO_BELEGAER);
+ push_spell(ULMO_WRATH);
+ push_spell(MANDOS_TEARS_LUTHIEN);
+ push_spell(MANDOS_TALE_DOOM);
+ }
+}
+
+static s16b library_quest_place_random(int minY, int minX, int maxY, int maxX, int r_idx)
+{
+ int y = randint(maxY - minY + 1) + minY;
+ 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_flags2 = DF2_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 *)
+{
+ bool_ ret;
+
+ /* 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 */
+ 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;
+ }
+}
+
+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->art_name = quark_add(player_name);
+ q_ptr->found = OBJ_FOUND_REWARD;
+ object_aware(q_ptr);
+ object_known(q_ptr);
+ inven_carry(q_ptr, FALSE);
+ }
+
+ 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.");
+ }
+}
+
+bool_ quest_library_describe(FILE *hook_file)
+{
+ if (cquest.status == QUEST_STATUS_TAKEN)
+ {
+ print_hook("#####yAn Old Mages Quest! (Danger Level: 35)\n");
+ print_hook("Make the library safe for the old mage in Minas Anor.\n");
+ print_hook("\n");
+ }
+ else if (cquest.status == QUEST_STATUS_COMPLETED)
+ {
+ /* Quest done, book not gotten yet */
+ print_hook("#####yAn Old Mages Quest!\n");
+ print_hook("You have made the library safe for the old mage in Minas Anor.\n");
+ print_hook("Perhaps you should see about a reward.\n");
+ print_hook("\n");
+ }
+
+ /* Normal processing */
+ return TRUE;
+}
+
+bool_ quest_library_init_hook(int q)
+{
+ /* Only need hooks if the quest is unfinished. */
+ if ((cquest.status >= QUEST_STATUS_UNTAKEN) &&
+ (cquest.status < QUEST_STATUS_FINISHED))
+ {
+ add_hook_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();
+ }
+
+ return FALSE;
+}
+
+#undef print_hook
diff --git a/src/q_library.hpp b/src/q_library.hpp
new file mode 100644
index 00000000..8150893e
--- /dev/null
+++ b/src/q_library.hpp
@@ -0,0 +1,8 @@
+#pragma once
+
+#include "h-basic.h"
+
+bool_ quest_library_init_hook(int q);
+bool_ quest_library_describe(FILE *fff);
+void quest_library_building(bool_ *paid, bool_ *recreate);
+void initialize_bookable_spells();
diff --git a/src/q_main.c b/src/q_main.cc
index a13b0790..ed11b9dc 100644
--- a/src/q_main.c
+++ b/src/q_main.cc
@@ -1,26 +1,55 @@
-bool_ quest_main_monsters_hook(char *fmt)
+#include "q_main.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_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)
{
- s32b r_idx;
- r_idx = get_next_arg(fmt);
+ 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 *)
+{
+ struct hook_new_monster_in *in = static_cast<struct hook_new_monster_in *>(in_);
+ s32b r_idx = in->r_idx;
/* Sauron */
- if (r_idx == 860)
+ if (r_idx == get_sauron())
{
/* No Sauron until Necromancer dies */
- if (r_info[819].max_num) return TRUE;
+ if (r_info[get_necromancer()].max_num) return TRUE;
}
/* Morgoth */
- else if (r_idx == 862)
+ else if (r_idx == get_morgoth())
{
/* No Morgoth until Sauron dies */
- if (r_info[860].max_num) return TRUE;
+ if (r_info[get_sauron()].max_num) return TRUE;
}
return FALSE;
}
-bool_ quest_morgoth_hook(char *fmt)
+
+static bool_ quest_morgoth_hook(void *, void *, void *)
{
- /* Using test_monster_name() here would be a lot less ugly, but would take much more time */
- monster_race *r_ptr = &r_info[862];
+ monster_race *r_ptr = &r_info[get_morgoth()];
/* Need to kill him */
if (!r_ptr->max_num)
@@ -31,7 +60,7 @@ bool_ quest_morgoth_hook(char *fmt)
quest[QUEST_MORGOTH].status = QUEST_STATUS_FINISHED;
/* Redraw the "title" */
- p_ptr->redraw |= (PR_TITLE);
+ p_ptr->redraw |= (PR_FRAME);
/* Congratulations */
if (quest[QUEST_ONE].status == QUEST_STATUS_FINISHED)
@@ -55,7 +84,7 @@ bool_ quest_morgoth_hook(char *fmt)
}
/* Continue the plot(maybe) */
- del_hook(HOOK_MONSTER_DEATH, quest_morgoth_hook);
+ 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 */
@@ -67,32 +96,36 @@ bool_ quest_morgoth_hook(char *fmt)
}
return (FALSE);
}
-bool_ quest_morgoth_dump_hook(char *fmt)
+
+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(hook_file, "\n You saved Arda and became a famed %s.", sp_ptr->winner);
+ fprintf(f, "\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.");
+ fprintf(f, "\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_new(HOOK_MONSTER_DEATH, quest_morgoth_hook, "morgoth_death", NULL);
}
- add_hook(HOOK_CHAR_DUMP, quest_morgoth_dump_hook, "morgoth_dump");
- add_hook(HOOK_NEW_MONSTER, quest_main_monsters_hook, "main_new_monster");
+ 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);
return (FALSE);
}
-bool_ quest_sauron_hook(char *fmt)
+static bool_ quest_sauron_hook(void *, void *, void *)
{
- /* Using test_monster_name() here would be a lot less ugly, but would take much more time */
- monster_race *r_ptr = &r_info[860];
+ monster_race *r_ptr = &r_info[get_sauron()];
/* Need to kill him */
if (!r_ptr->max_num)
@@ -103,8 +136,8 @@ bool_ quest_sauron_hook(char *fmt)
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");
+ 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(QUEST_MORGOTH);
@@ -113,18 +146,19 @@ bool_ quest_sauron_hook(char *fmt)
return (FALSE);
}
-bool_ quest_sauron_resurect_hook(char *fmt)
+static bool_ quest_sauron_resurect_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];
monster_race *r_ptr = &r_info[m_ptr->r_idx];
- if ((r_ptr->flags7 & RF7_NAZGUL) && r_info[860].max_num)
+ if ((r_ptr->flags7 & RF7_NAZGUL) && r_info[get_sauron()].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))
+ 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;
@@ -136,17 +170,16 @@ 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_new(HOOK_MONSTER_DEATH, quest_sauron_hook, "sauron_death", NULL);
}
- add_hook(HOOK_NEW_MONSTER, quest_main_monsters_hook, "main_new_monster");
- add_hook(HOOK_MONSTER_DEATH, quest_sauron_resurect_hook, "sauron_resurect_death");
+ add_hook_new(HOOK_NEW_MONSTER, quest_main_monsters_hook, "main_new_monster", NULL);
+ add_hook_new(HOOK_MONSTER_DEATH, quest_sauron_resurect_hook, "sauron_resurect_death", NULL);
return (FALSE);
}
-bool_ quest_necro_hook(char *fmt)
+static bool_ quest_necro_hook(void *, void *, void *)
{
- /* Using test_monster_name() here would be a lot less ugly, but would take much more time */
- monster_race *r_ptr = &r_info[819];
+ monster_race *r_ptr = &r_info[get_necromancer()];
/* Need to kill him */
if (!r_ptr->max_num)
@@ -160,17 +193,18 @@ bool_ quest_necro_hook(char *fmt)
*(quest[QUEST_NECRO].plot) = QUEST_ONE;
quest[*(quest[QUEST_NECRO].plot)].init(*(quest[QUEST_NECRO].plot));
- del_hook(HOOK_MONSTER_DEATH, quest_necro_hook);
+ del_hook_new(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_new(HOOK_MONSTER_DEATH, quest_necro_hook, "necro_death", NULL);
}
- add_hook(HOOK_NEW_MONSTER, quest_main_monsters_hook, "main_new_monster");
+ add_hook_new(HOOK_NEW_MONSTER, quest_main_monsters_hook, "main_new_monster", NULL);
return (FALSE);
}
diff --git a/src/q_main.hpp b/src/q_main.hpp
new file mode 100644
index 00000000..a88530fc
--- /dev/null
+++ b/src/q_main.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+#include "h-basic.h"
+
+bool_ quest_necro_init_hook(int q_idx);
+bool_ quest_sauron_init_hook(int q_idx);
+bool_ quest_morgoth_init_hook(int q_idx);
diff --git a/src/q_narsil.c b/src/q_narsil.cc
index 27ec218e..a6c0eed3 100644
--- a/src/q_narsil.c
+++ b/src/q_narsil.cc
@@ -1,17 +1,28 @@
-#undef cquest
+#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])
-bool_ quest_narsil_move_hook(char *fmt)
+static bool_ quest_narsil_move_hook(void *, void *in_, void *)
{
- s32b y, x;
- cave_type *c_ptr;
+ 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;
- 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 */
@@ -51,36 +62,35 @@ bool_ quest_narsil_move_hook(char *fmt)
/* Continue the plot */
cquest.status = QUEST_STATUS_FINISHED;
- del_hook(HOOK_MOVE, quest_narsil_move_hook);
+ del_hook_new(HOOK_MOVE, quest_narsil_move_hook);
process_hooks_restart = TRUE;
return TRUE;
}
-bool_ quest_narsil_dump_hook(char *fmt)
+
+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(hook_file, "\n The sword that was broken is now reforged.");
+ fprintf(f, "\n The sword that was broken is now reforged.");
}
return (FALSE);
}
-bool_ quest_narsil_identify_hook(char *fmt)
+
+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)
{
- int i;
- object_type *o_ptr;
- s32b item;
-
- item = get_next_arg(fmt);
-
- o_ptr = get_object(item);
-
- if (o_ptr->name1 == ART_NARSIL)
+ if (in->o_ptr->name1 == ART_NARSIL)
{
cquest.status = QUEST_STATUS_TAKEN;
- for (i = 0; i < 5; i++)
+ for (int i = 0; i < 5; i++)
{
if (quest[QUEST_NARSIL].desc[i][0] != '\0')
{
@@ -88,21 +98,25 @@ bool_ quest_narsil_identify_hook(char *fmt)
}
}
- add_hook(HOOK_MOVE, quest_narsil_move_hook, "narsil_move");
- del_hook(HOOK_IDENTIFY, quest_narsil_identify_hook);
+ 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);
}
+
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");
+ 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);
}
- 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");
+ add_hook_new(HOOK_CHAR_DUMP, quest_narsil_dump_hook, "narsil_dump", NULL);
return (FALSE);
}
diff --git a/src/q_narsil.hpp b/src/q_narsil.hpp
new file mode 100644
index 00000000..b83e63cf
--- /dev/null
+++ b/src/q_narsil.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+bool_ quest_narsil_init_hook(int q_idx);
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..15a6a843
--- /dev/null
+++ b/src/q_nazgul.cc
@@ -0,0 +1,145 @@
+#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;
+ (void)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);
+}
+
+bool_ quest_nazgul_init_hook(int q_idx)
+{
+ 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);
+ return (FALSE);
+}
diff --git a/src/q_nazgul.hpp b/src/q_nazgul.hpp
new file mode 100644
index 00000000..32e3237c
--- /dev/null
+++ b/src/q_nazgul.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+bool_ quest_nazgul_init_hook(int q_idx);
diff --git a/src/q_nirna.c b/src/q_nirna.cc
index be856d31..a92ba6e4 100644
--- a/src/q_nirna.c
+++ b/src/q_nirna.cc
@@ -1,7 +1,19 @@
-#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;
@@ -39,11 +51,11 @@ bool_ quest_nirnaeth_gen_hook(char *fmt)
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;
@@ -57,7 +69,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,12 +83,13 @@ 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;
}
-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;
@@ -84,7 +97,8 @@ bool_ quest_nirnaeth_death_hook(char *fmt)
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;
@@ -92,18 +106,20 @@ bool_ quest_nirnaeth_stair_hook(char *fmt)
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);
}
+
bool_ quest_nirnaeth_init_hook(int q_idx)
{
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..24a8759f
--- /dev/null
+++ b/src/q_nirna.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+bool_ quest_nirnaeth_init_hook(int q_idx);
diff --git a/src/q_one.c b/src/q_one.cc
index 4bfeaf3e..3741e009 100644
--- a/src/q_one.c
+++ b/src/q_one.cc
@@ -1,14 +1,37 @@
-#undef cquest
+#include "q_one.hpp"
+
+#include "artifact_type.hpp"
+#include "cave.hpp"
+#include "cave_type.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)
{
@@ -25,22 +48,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,7 +75,7 @@ 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!'");
}
@@ -66,13 +89,12 @@ bool_ quest_one_move_hook(char *fmt)
return FALSE;
}
-bool_ quest_one_drop_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_drop_hook(void *, void *in_, void *)
+{
+ 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];
if (cquest.status != QUEST_STATUS_TAKEN) return FALSE;
@@ -96,13 +118,11 @@ bool_ quest_one_drop_hook(char *fmt)
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;
@@ -153,24 +173,26 @@ bool_ quest_one_wield_hook(char *fmt)
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;
+ out->mhp = mhp;
return (TRUE);
}
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)
{
@@ -189,18 +211,14 @@ bool_ quest_one_die_hook(char *fmt)
}
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");
@@ -211,14 +229,14 @@ bool_ quest_one_identify_hook(char *fmt)
return (FALSE);
}
-bool_ quest_one_death_hook(char *fmt)
+
+static bool_ quest_one_death_hook(void *, void *in_, void *)
{
- s32b r_idx, m_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;
- m_idx = get_next_arg(fmt);
- r_idx = m_list[m_idx].r_idx;
-
if (a_info[ART_POWER].cur_num) return FALSE;
/* Paranoia */
@@ -291,19 +309,24 @@ bool_ quest_one_death_hook(char *fmt)
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);
}
-bool_ quest_one_gen_hook(char *fmt)
+
+static bool_ quest_one_gen_hook(void *, void *, void *)
{
s32b x, y, tries = 10000;
@@ -333,22 +356,23 @@ bool_ quest_one_gen_hook(char *fmt)
return (FALSE);
}
+
bool_ quest_one_init_hook(int q_idx)
{
if ((cquest.status >= QUEST_STATUS_TAKEN) && (cquest.status < QUEST_STATUS_FINISHED))
{
- 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");
+ 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);
return (FALSE);
}
diff --git a/src/q_one.hpp b/src/q_one.hpp
new file mode 100644
index 00000000..a85a5733
--- /dev/null
+++ b/src/q_one.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+bool_ quest_one_init_hook(int q_idx);
diff --git a/src/q_poison.c b/src/q_poison.cc
index e6fed3a1..a5b274b0 100644
--- a/src/q_poison.c
+++ b/src/q_poison.cc
@@ -1,4 +1,24 @@
-#undef cquest
+#include "q_poison.hpp"
+
+#include "cave.hpp"
+#include "cave_type.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_type.hpp"
+#include "object2.hpp"
+#include "player_type.hpp"
+#include "quark.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] =
@@ -21,7 +41,7 @@ static bool_ create_molds_hook(int r_idx)
else return FALSE;
}
-bool_ quest_poison_gen_hook(char *fmt)
+static bool_ quest_poison_gen_hook(void *, void *, void *)
{
int cy = 1, cx = 1, x, y, tries = 10000, r_idx;
bool_ (*old_get_mon_num_hook)(int r_idx);
@@ -83,7 +103,7 @@ bool_ quest_poison_gen_hook(char *fmt)
if (m_ptr->level < p_ptr->lev)
{
- m_ptr->exp = MONSTER_EXP(m_ptr->level + randint(p_ptr->lev - m_ptr->level));
+ m_ptr->exp = monster_exp(m_ptr->level + randint(p_ptr->lev - m_ptr->level));
monster_check_experience(m_idx, TRUE);
}
}
@@ -98,12 +118,12 @@ bool_ quest_poison_gen_hook(char *fmt)
return FALSE;
}
-bool_ quest_poison_finish_hook(char *fmt)
+
+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;
- s32b q_idx;
-
- q_idx = get_next_arg(fmt);
if (q_idx != QUEST_POISON) return FALSE;
@@ -124,25 +144,29 @@ bool_ quest_poison_finish_hook(char *fmt)
/* Continue the plot */
*(quest[q_idx].plot) = QUEST_NULL;
- del_hook(HOOK_QUEST_FINISH, quest_poison_finish_hook);
+ del_hook_new(HOOK_QUEST_FINISH, quest_poison_finish_hook);
process_hooks_restart = TRUE;
return TRUE;
}
-bool_ quest_poison_dump_hook(char *fmt)
+
+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(hook_file, "\n You saved the beautiful Mallorns of Lothlorien.");
+ fprintf(f, "\n You saved the beautiful Mallorns of Lothlorien.");
}
return (FALSE);
}
-bool_ quest_poison_quest_hook(char *fmt)
+
+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;
- s32b q_idx;
-
- q_idx = get_next_arg(fmt);
if (q_idx != QUEST_POISON) return FALSE;
@@ -155,18 +179,18 @@ bool_ quest_poison_quest_hook(char *fmt)
q_ptr->note = quark_add("quest");
(void)inven_carry(q_ptr, FALSE);
- del_hook(HOOK_INIT_QUEST, quest_poison_quest_hook);
+ del_hook_new(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];
+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;
@@ -201,7 +225,7 @@ bool_ quest_poison_drop_hook(char *fmt)
cquest.status = QUEST_STATUS_COMPLETED;
- del_hook(HOOK_DROP, quest_poison_drop_hook);
+ del_hook_new(HOOK_DROP, quest_poison_drop_hook);
process_hooks_restart = TRUE;
return FALSE;
@@ -213,6 +237,7 @@ bool_ quest_poison_drop_hook(char *fmt)
}
return FALSE;
}
+
bool_ quest_poison_init_hook(int q_idx)
{
/* Get a place to place the poison */
@@ -220,19 +245,19 @@ bool_ quest_poison_init_hook(int q_idx)
{
cquest.data[1] = TRUE;
cquest.data[0] = rand_int(4);
- if (wizard) message_add(MESSAGE_MSG, format("Wilderness poison %d, %d", wild_locs[cquest.data[0]][0], wild_locs[cquest.data[0]][1]), TERM_BLUE);
+ if (wizard) message_add(format("Wilderness poison %d, %d", wild_locs[cquest.data[0]][0], wild_locs[cquest.data[0]][1]), TERM_BLUE);
}
if ((cquest.status >= QUEST_STATUS_TAKEN) && (cquest.status < QUEST_STATUS_FINISHED))
{
- 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");
+ 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(HOOK_INIT_QUEST, quest_poison_quest_hook, "poison_iquest");
+ add_hook_new(HOOK_INIT_QUEST, quest_poison_quest_hook, "poison_iquest", NULL);
}
- add_hook(HOOK_CHAR_DUMP, quest_poison_dump_hook, "poison_dump");
+ add_hook_new(HOOK_CHAR_DUMP, quest_poison_dump_hook, "poison_dump", NULL);
return (FALSE);
}
diff --git a/src/q_poison.hpp b/src/q_poison.hpp
new file mode 100644
index 00000000..f8d97ace
--- /dev/null
+++ b/src/q_poison.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+bool_ quest_poison_init_hook(int q_idx);
diff --git a/src/q_rand.c b/src/q_rand.cc
index 5a3b3ab2..4ef79928 100644
--- a/src/q_rand.c
+++ b/src/q_rand.cc
@@ -1,5 +1,197 @@
+#include "q_rand.hpp"
+
+#include "artifact_type.hpp"
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "dungeon_info_type.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_type.hpp"
+#include "monster_race.hpp"
+#include "object1.hpp"
+#include "object2.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>
+
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)
+{
+ 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];
+
+ int j;
+
+ /* Find the appropriate dungeon */
+ for (j = 0; j < max_d_idx; j++)
+ {
+ dungeon_info_type *d_ptr = &d_info[j];
+
+ if (!(d_ptr->flags1 & DF1_PRINCIPAL)) continue;
+
+ if ((d_ptr->mindepth <= rl) && (rl <= d_ptr->maxdepth))
+ {
+ dungeon_type = j;
+ break;
+ }
+ }
+
+ q_ptr->type = random_quests_types[rand_int(MAX_RANDOM_QUESTS_TYPES)];
+
+ /* XXX XXX XXX Try until valid choice is found */
+ while (tries)
+ {
+ bool_ ok;
+
+ tries--;
+
+ /* Random monster 5 - 10 levels out of depth */
+ q_ptr->r_idx = get_mon_num(rl + 4 + randint(6));
+
+ if (!q_ptr->r_idx) continue;
+
+ r_ptr = &r_info[q_ptr->r_idx];
+
+ /* Accept only monsters that can be generated */
+ if (r_ptr->flags9 & RF9_SPECIAL_GENE) continue;
+ if (r_ptr->flags9 & RF9_NEVER_GENE) continue;
+
+ /* Accept only monsters that are not breeders */
+ if (r_ptr->flags4 & RF4_MULTIPLY) continue;
+
+ /* Forbid joke monsters */
+ if (r_ptr->flags8 & RF8_JOKEANGBAND) continue;
+
+ /* Accept only monsters that are not friends */
+ if (r_ptr->flags7 & RF7_PET) continue;
+
+ /* Refuse nazguls */
+ if (r_ptr->flags7 & RF7_NAZGUL) continue;
+
+ /* Accept only monsters that are not good */
+ if (r_ptr->flags3 & RF3_GOOD) continue;
+
+ /* If module says a monster race is friendly, then skip */
+ if (modules[game_module_idx].race_status != NULL)
+ {
+ s16b *status = (*modules[game_module_idx].race_status)(q_ptr->r_idx);
+ if ((status != NULL) && (*status >= 0))
+ {
+ continue;
+ }
+ }
+
+ /* Assume no explosion attacks */
+ ok = TRUE;
+
+ /* Reject monsters with exploding attacks */
+ for (k = 0; k < 4; k++)
+ {
+ if (r_ptr->blow[k].method == RBM_EXPLODE) ok = FALSE;
+ }
+ if (!ok) continue;
+
+ /* No mutliple uniques */
+ if ((r_ptr->flags1 & RF1_UNIQUE) &&
+ ((q_ptr->type != 1) || (r_ptr->max_num == -1))) continue;
+
+ /* No single non uniques */
+ if ((!(r_ptr->flags1 & RF1_UNIQUE)) && (q_ptr->type == 1)) continue;
+
+ /* Level restriction */
+ min_level = (rl > RQ_LEVEL_CAP) ? RQ_LEVEL_CAP : rl;
+
+ /* Accept monsters matching the level restriction */
+ if (r_ptr->level > min_level) break;
+ }
+
+ /* Arg could not find anything ??? */
+ if (!tries)
+ {
+ if (wizard)
+ {
+ message_add(format("Could not find quest monster on lvl %d", rl), TERM_RED);
+ }
+ q_ptr->type = 0;
+ }
+ else
+ {
+ if (r_ptr->flags1 & RF1_UNIQUE)
+ {
+ r_ptr->max_num = -1;
+ }
+
+ q_ptr->done = FALSE;
+
+ if (wizard)
+ {
+ message_add(format("Quest for %d on lvl %d",
+ q_ptr->r_idx, rl), TERM_RED);
+ }
+ }
+
+ lvl += step;
+ }
+
+ dungeon_type = old_type;
+}
+
bool_ is_randhero(int level)
{
int i;
@@ -17,22 +209,21 @@ bool_ is_randhero(int level)
return result;
}
-void do_get_new_obj(int y, int x)
+static void do_get_new_obj(int y, int x)
{
obj_theme theme;
- char *items[3];
object_type *q_ptr[3], forge[3];
- int max = 0, res, i;
+ int res, i;
- /* Create 3 ones */
- max = 0;
+ /* Create objects */
+ std::vector<std::string> items;
for (i = 0; i < 3; i++)
{
/* Get local object */
- q_ptr[max] = &forge[max];
+ q_ptr[i] = &forge[i];
/* Wipe the object */
- object_wipe(q_ptr[max]);
+ object_wipe(q_ptr[i]);
/* No themes */
theme.treasure = 100;
@@ -41,18 +232,18 @@ void do_get_new_obj(int y, int x)
theme.tools = 100;
/* Make a great object */
- make_object(q_ptr[max], TRUE, TRUE, theme);
- q_ptr[max]->found = OBJ_FOUND_REWARD;
+ make_object(q_ptr[i], TRUE, TRUE, theme);
+ q_ptr[i]->found = OBJ_FOUND_REWARD;
- C_MAKE(items[max], 100, char);
- object_desc(items[max], q_ptr[max], 0, 0);
- max++;
+ 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)?", (char **)items, 3);
+ res = ask_menu("Choose a reward to get(a-c to choose, ESC to cancel)?", items);
/* Ok ? lets learn ! */
if (res > -1)
@@ -88,13 +279,9 @@ void do_get_new_obj(int y, int x)
}
}
}
-
- for (i = 0; i < 3; i++)
- C_KILL(items[i], 100, char);
-
}
-void princess_death(s32b m_idx, s32b r_idx)
+static void princess_death(s32b m_idx, s32b r_idx)
{
int r;
@@ -136,7 +323,7 @@ void princess_death(s32b m_idx, s32b r_idx)
}
}
-void hero_death(s32b m_idx, s32b r_idx)
+static void hero_death(s32b m_idx, s32b r_idx)
{
random_quests[dun_level].done = TRUE;
@@ -190,14 +377,15 @@ void hero_death(s32b m_idx, s32b r_idx)
if (i < 20)
{
- int m_idx;
+ 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;
- 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].exp = monster_exp(1 + (dun_level * 3 / 2));
m_list[m_idx].status = MSTATUS_COMPANION;
monster_check_experience(m_idx, TRUE);
}
@@ -213,13 +401,11 @@ void hero_death(s32b m_idx, s32b r_idx)
}
}
-bool_ quest_random_death_hook(char *fmt)
+static bool_ quest_random_death_hook(void *, void *in_, void *)
{
- int r_idx;
- s32b m_idx;
-
- 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;
+ int 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);
@@ -242,13 +428,15 @@ bool_ quest_random_death_hook(char *fmt)
return (FALSE);
}
-bool_ quest_random_turn_hook(char *fmt)
+
+static bool_ quest_random_turn_hook(void *, void *, void *)
{
quest[QUEST_RANDOM].data[0] = 0;
quest[QUEST_RANDOM].data[1] = 0;
return (FALSE);
}
-bool_ quest_random_feeling_hook(char *fmt)
+
+static bool_ quest_random_feeling_hook(void *, void *, void *)
{
if (!(dungeon_flags1 & DF1_PRINCIPAL)) return (FALSE);
if ((dun_level < 1) || (dun_level >= MAX_RANDOM_QUEST)) return (FALSE);
@@ -260,13 +448,14 @@ bool_ quest_random_feeling_hook(char *fmt)
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);
+ 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 + r_name);
+ cmsg_format(TERM_YELLOW, "You hear someone shouting: 'Leave me alone, stupid %s'", r_info[random_quests[dun_level].r_idx].name);
return (FALSE);
}
-bool_ quest_random_gen_hero_hook(char *fmt)
+
+static bool_ quest_random_gen_hero_hook(void *, void *, void *)
{
int i;
@@ -296,9 +485,13 @@ bool_ quest_random_gen_hero_hook(char *fmt)
return (FALSE);
}
-bool_ quest_random_gen_hook(char *fmt)
+
+static bool_ quest_random_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;
@@ -312,9 +505,6 @@ bool_ quest_random_gen_hook(char *fmt)
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);
@@ -378,10 +568,12 @@ bool_ quest_random_gen_hook(char *fmt)
return (TRUE);
}
-bool_ quest_random_dump_hook(char *fmt)
+
+static bool_ quest_random_dump_hook(void *, void *in_, void *)
{
- static char *number[] =
- { "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten" };
+ 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++)
@@ -402,22 +594,22 @@ bool_ quest_random_dump_hook(char *fmt)
if (valid)
{
if (pcnt > 10)
- fprintf(hook_file, "\n You have completed %d princess quests.", pcnt);
+ fprintf(f, "\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]);
+ fprintf(f, "\n You have completed %s princess quests.", number[pcnt-2]);
else if (pcnt == 1)
- fprintf(hook_file, "\n You have completed one princess quest.");
+ fprintf(f, "\n You have completed one princess quest.");
else
- fprintf(hook_file, "\n You haven't completed a single princess quest.");
+ fprintf(f, "\n You haven't completed a single princess quest.");
if (lscnt > 10)
- fprintf(hook_file, "\n You have completed %d lost sword quests.", lscnt);
+ fprintf(f, "\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]);
+ fprintf(f, "\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.");
+ fprintf(f, "\n You have completed one lost sword quest.");
else
- fprintf(hook_file, "\n You haven't completed a single lost sword quest.");
+ fprintf(f, "\n You haven't completed a single lost sword quest.");
}
return (FALSE);
@@ -436,14 +628,12 @@ bool_ quest_random_describe(FILE *fff)
{
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);
+ fprintf(fff, "Save her from the horrible %s.\n", r_info[random_quests[dun_level].r_idx].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, "An adventurer lost his sword to a bunch of %s!\n", r_info[random_quests[dun_level].r_idx].name);
fprintf(fff, "Kill them all to get it back.\n");
}
fprintf(fff, "Number: %d, Killed: %ld.\n",
@@ -454,12 +644,12 @@ bool_ quest_random_describe(FILE *fff)
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");
+ 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);
return (FALSE);
}
diff --git a/src/q_rand.hpp b/src/q_rand.hpp
new file mode 100644
index 00000000..fe87289b
--- /dev/null
+++ b/src/q_rand.hpp
@@ -0,0 +1,8 @@
+#pragma once
+
+#include "h-basic.h"
+
+void initialize_random_quests(int n);
+bool_ is_randhero(int level);
+bool_ quest_random_init_hook(int q_idx);
+bool_ quest_random_describe(FILE *fff);
diff --git a/src/q_shroom.c b/src/q_shroom.cc
index b6e26cdf..89b576d8 100644
--- a/src/q_shroom.c
+++ b/src/q_shroom.cc
@@ -1,14 +1,40 @@
-#undef cquest
+#include "q_shroom.hpp"
+
+#include "cave.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])
-bool_ quest_shroom_speak_hook(char *fmt);
+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")
-bool_ quest_shroom_town_gen_hook(char *fmt)
+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;
- s32b small;
-
- small = get_next_arg(fmt);
+ bool_ small = in->small;
/* Generate the shrooms field */
if ((!small) && (p_ptr->wilderness_y == 21) && (p_ptr->wilderness_x == 33))
@@ -33,24 +59,24 @@ bool_ quest_shroom_town_gen_hook(char *fmt)
/* 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);
+ 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[test_monster_name("Grip, Farmer Maggot's dog")] = FALSE;
+ 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[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);
+ 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[test_monster_name("Wolf, Farmer Maggot's dog")] = FALSE;
+ 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[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);
+ 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[test_monster_name("Fang, Farmer Maggot's dog")] = FALSE;
+ m_allow_special[get_fang()] = FALSE;
msg_print("You hear frenzied barking.");
}
@@ -75,57 +101,58 @@ bool_ quest_shroom_town_gen_hook(char *fmt)
}
/* 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;
+ 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;
}
-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;
+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 == 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")))
+ 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;
}
-bool_ quest_shroom_give_hook(char *fmt)
+
+static bool_ quest_shroom_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, item;
- m_idx = get_next_arg(fmt);
- item = get_next_arg(fmt);
+ 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 != test_monster_name("Farmer Maggot")) return (FALSE);
+ if (m_ptr->r_idx != get_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))
+ 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(HOOK_GIVE, quest_shroom_give_hook);
- del_hook(HOOK_CHAT, quest_shroom_speak_hook);
- del_hook(HOOK_WILD_GEN, quest_shroom_town_gen_hook);
+ 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;
}
@@ -175,7 +202,7 @@ bool_ quest_shroom_give_hook(char *fmt)
cquest.status = QUEST_STATUS_FINISHED;
- del_hook(HOOK_GIVE, quest_shroom_give_hook);
+ del_hook_new(HOOK_GIVE, quest_shroom_give_hook);
process_hooks_restart = TRUE;
}
else
@@ -183,53 +210,56 @@ bool_ quest_shroom_give_hook(char *fmt)
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)
+static void check_dogs_alive(s32b m_idx)
+{
+ if ((r_info[get_grip()].max_num == 0) ||
+ (r_info[get_wolf()].max_num == 0) ||
+ (r_info[get_fang()].max_num == 0))
{
- cptr m_name;
-
- m_name = get_next_arg_str(fmt);
+ 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);
- msg_format("%^s asks your help.", m_name);
- exec_lua("ingame_help('monster_chat')");
+ 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
{
- /* 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)
+
+static bool_ quest_shroom_speak_hook(void *, void *in_, void *)
{
- monster_type *m_ptr;
- s32b m_idx;
+ struct hook_mon_speak_in *in = static_cast<struct hook_mon_speak_in *>(in_);
+ s32b m_idx = in->m_idx;
- m_idx = get_next_arg(fmt);
+ if (m_list[m_idx].r_idx != get_farmer_maggot()) return (FALSE);
- m_ptr = &m_list[m_idx];
+ 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 != test_monster_name("Farmer Maggot")) return (FALSE);
+ if (m_ptr->r_idx != get_farmer_maggot()) return (FALSE);
if (cquest.status == QUEST_STATUS_UNTAKEN)
{
@@ -244,27 +274,12 @@ bool_ quest_shroom_chat_hook(char *fmt)
}
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]);
+ check_dogs_alive(m_idx);
}
return TRUE;
}
+
bool_ quest_shroom_init_hook(int q_idx)
{
/* Get a number of 'shrooms */
@@ -272,22 +287,25 @@ bool_ quest_shroom_init_hook(int q_idx)
{
cquest.data[0] = 0;
cquest.data[1] = rand_range(7, 14);
- if (wizard) message_add(MESSAGE_MSG, format("Shrooms number %d", cquest.data[1]), TERM_BLUE);
+ if (wizard)
+ {
+ message_add(format("Shrooms number %d", cquest.data[1]), TERM_BLUE);
+ }
}
if ((cquest.status >= QUEST_STATUS_TAKEN) && (cquest.status < QUEST_STATUS_FINISHED))
{
- 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");
+ 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(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");
+ 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);
}
return (FALSE);
}
diff --git a/src/q_shroom.hpp b/src/q_shroom.hpp
new file mode 100644
index 00000000..6124775b
--- /dev/null
+++ b/src/q_shroom.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+bool_ quest_shroom_init_hook(int q_idx);
diff --git a/src/q_spider.c b/src/q_spider.cc
index a739535b..07531b96 100644
--- a/src/q_spider.c
+++ b/src/q_spider.cc
@@ -1,7 +1,22 @@
-#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;
@@ -30,7 +45,8 @@ bool_ quest_spider_gen_hook(char *fmt)
return TRUE;
}
-bool_ quest_spider_death_hook(char *fmt)
+
+static bool_ quest_spider_death_hook(void *, void *, void *)
{
int i, mcnt = 0;
@@ -52,26 +68,28 @@ 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);
}
-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;
-
- q_idx = get_next_arg(fmt);
+ s32b q_idx = in->q_idx;
if (q_idx != QUEST_SPIDER) return FALSE;
@@ -91,18 +109,19 @@ bool_ quest_spider_finish_hook(char *fmt)
*(quest[q_idx].plot) = QUEST_POISON;
quest[*(quest[q_idx].plot)].init(*(quest[q_idx].plot));
- 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;
}
+
bool_ quest_spider_init_hook(int q_idx)
{
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..e17cb523
--- /dev/null
+++ b/src/q_spider.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+bool_ quest_spider_init_hook(int q_idx);
diff --git a/src/q_thief.c b/src/q_thief.cc
index 6b033f8c..0f6543cc 100644
--- a/src/q_thief.c
+++ b/src/q_thief.cc
@@ -1,7 +1,26 @@
-#undef cquest
+#include "q_thief.hpp"
+
+#include "cave.hpp"
+#include "cave_type.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;
@@ -56,12 +75,13 @@ 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;
@@ -105,7 +125,8 @@ 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!");
@@ -113,11 +134,11 @@ bool_ quest_thieves_hook(char *fmt)
}
return FALSE;
}
-bool_ quest_thieves_finish_hook(char *fmt)
-{
- s32b q_idx;
- q_idx = get_next_arg(fmt);
+static bool_ quest_thieves_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_THIEVES) return FALSE;
@@ -140,20 +161,20 @@ bool_ quest_thieves_finish_hook(char *fmt)
}
quest[*(quest[q_idx].plot)].init(*(quest[q_idx].plot));
- 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;
}
-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;
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;
@@ -163,10 +184,10 @@ bool_ quest_thieves_init_hook(int q_idx)
{
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..48e5dc8d
--- /dev/null
+++ b/src/q_thief.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+bool_ quest_thieves_init_hook(int q_idx);
diff --git a/src/q_thrain.c b/src/q_thrain.cc
index b2b1be9f..05def27a 100644
--- a/src/q_thrain.c
+++ b/src/q_thrain.cc
@@ -1,17 +1,45 @@
-#undef cquest
+#include "q_thrain.hpp"
+
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "dungeon_info_type.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 "quark.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);
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]++;
@@ -47,7 +75,7 @@ bool_ quest_thrain_death_hook(char *fmt)
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;
@@ -81,15 +109,18 @@ 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);
}
-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;
@@ -100,9 +131,6 @@ bool_ quest_thrain_gen_hook(char *fmt)
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);
-
/* Pick a room size */
get_map_size("thrain.map", &ysize, &xsize);
@@ -144,12 +172,11 @@ 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;
}
}
@@ -158,7 +185,8 @@ bool_ quest_thrain_gen_hook(char *fmt)
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);
@@ -170,15 +198,13 @@ bool_ quest_thrain_feeling_hook(char *fmt)
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);
@@ -201,30 +227,35 @@ bool_ quest_thrain_move_hook(char *fmt)
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);
}
+
bool_ quest_thrain_init_hook(int q)
{
if (!cquest.data[0])
{
cquest.data[0] = rand_range(d_info[DUNGEON_DOL_GULDUR].mindepth + 1, d_info[DUNGEON_DOL_GULDUR].maxdepth - 1);
- if (wizard) message_add(MESSAGE_MSG, format("Thrain lvl %d", cquest.data[0]), TERM_BLUE);
+ if (wizard)
+ {
+ message_add(format("Thrain lvl %d", cquest.data[0]), TERM_BLUE);
+ }
}
if ((cquest.status >= QUEST_STATUS_TAKEN) && (cquest.status < QUEST_STATUS_FINISHED))
{
- 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..830da016
--- /dev/null
+++ b/src/q_thrain.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+extern bool_ quest_thrain_init_hook(int q_idx);
diff --git a/src/q_troll.c b/src/q_troll.cc
index c314d2a7..fce3ad49 100644
--- a/src/q_troll.c
+++ b/src/q_troll.cc
@@ -1,7 +1,31 @@
-#undef cquest
+#include "q_troll.hpp"
+
+#include "artifact_type.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_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 *)
{
int x, y;
int xstart = 2;
@@ -33,11 +57,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 +94,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
{
@@ -93,11 +112,11 @@ bool_ quest_troll_gen_hook(char *fmt)
cquest.data[0] = FALSE;
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;
@@ -108,31 +127,29 @@ bool_ quest_troll_finish_hook(char *fmt)
*(quest[q_idx].plot) = QUEST_NAZGUL;
quest[*(quest[q_idx].plot)].init(*(quest[q_idx].plot));
- 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;
}
-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 (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);
}
@@ -154,25 +171,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;
}
+
bool_ quest_troll_init_hook(int q_idx)
{
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..140fe0b2
--- /dev/null
+++ b/src/q_troll.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+bool_ quest_troll_init_hook(int q_idx);
diff --git a/src/q_ultrae.c b/src/q_ultrae.cc
index 78471df5..d42b9c6f 100644
--- a/src/q_ultrae.c
+++ b/src/q_ultrae.cc
@@ -1,8 +1,5 @@
-/*
- * Here takes place the Evil ultra ending
- */
+#include "q_ultrae.hpp"
-#undef cquest
#define cquest (quest[QUEST_ULTRA_EVIL])
bool_ quest_ultra_evil_init_hook(int q)
diff --git a/src/q_ultrae.hpp b/src/q_ultrae.hpp
new file mode 100644
index 00000000..5b08127b
--- /dev/null
+++ b/src/q_ultrae.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+bool_ quest_ultra_evil_init_hook(int q_idx);
diff --git a/src/q_ultrag.c b/src/q_ultrag.cc
index a5a09f2d..c7c0312b 100644
--- a/src/q_ultrag.c
+++ b/src/q_ultrag.cc
@@ -1,18 +1,30 @@
-/*
- * 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_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)
{
@@ -77,30 +89,29 @@ bool_ quest_ultra_good_move_hook(char *fmt)
return FALSE;
}
-bool_ quest_ultra_good_stair_hook(char *fmt)
+static bool_ quest_ultra_good_stair_hook(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;
/* 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;
}
/* 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;
}
/* 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;
@@ -140,7 +151,7 @@ bool_ quest_ultra_good_stair_hook(char *fmt)
return FALSE;
}
-bool_ quest_ultra_good_recall_hook(char *fmt)
+static bool_ quest_ultra_good_recall_hook(void *, void *, void *)
{
if ((dungeon_type != DUNGEON_VOID) && (dungeon_type != DUNGEON_NETHER_REALM))
return FALSE;
@@ -149,9 +160,10 @@ bool_ quest_ultra_good_recall_hook(char *fmt)
return TRUE;
}
-bool_ quest_ultra_good_death_hook(char *fmt)
+static bool_ quest_ultra_good_death_hook(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 +176,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 +192,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 */
@@ -235,23 +247,27 @@ bool_ quest_ultra_good_death_hook(char *fmt)
}
return (FALSE);
}
-bool_ quest_ultra_good_dump_hook(char *fmt)
+
+static bool_ quest_ultra_good_dump_hook(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.");
}
}
}
@@ -263,14 +279,14 @@ bool_ quest_ultra_good_init_hook(int q)
{
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");
+ add_hook_new(HOOK_CHAR_DUMP, quest_ultra_good_dump_hook, "ultrag_dump", NULL);
return (FALSE);
}
diff --git a/src/q_ultrag.hpp b/src/q_ultrag.hpp
new file mode 100644
index 00000000..0064b878
--- /dev/null
+++ b/src/q_ultrag.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+bool_ quest_ultra_good_init_hook(int q_idx);
diff --git a/src/q_wight.c b/src/q_wight.cc
index 3f6b2c34..f2cc630c 100644
--- a/src/q_wight.c
+++ b/src/q_wight.cc
@@ -1,7 +1,28 @@
-#undef cquest
+#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 "player_type.hpp"
+#include "quark.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+#include "z-rand.hpp"
+
+#include <cassert>
+
#define cquest (quest[QUEST_WIGHT])
-bool_ quest_wight_gen_hook(char *fmt)
+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;
@@ -35,9 +56,9 @@ bool_ quest_wight_gen_hook(char *fmt)
{
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;
+ 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)
{
@@ -87,13 +108,11 @@ bool_ quest_wight_gen_hook(char *fmt)
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);
}
}
}
@@ -101,16 +120,16 @@ bool_ quest_wight_gen_hook(char *fmt)
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;
+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 == test_monster_name("The Wight-King of the Barrow-downs"))
+ if (r_idx == get_wight_king())
{
cmsg_print(TERM_YELLOW, "Without their King the wights won't be able to do much.");
@@ -118,17 +137,20 @@ bool_ quest_wight_death_hook(char *fmt)
cave[p_ptr->py][p_ptr->px].special = 0;
cquest.status = QUEST_STATUS_COMPLETED;
- del_hook(HOOK_MONSTER_DEATH, quest_wight_death_hook);
+
+ del_hook_new(HOOK_MONSTER_DEATH, quest_wight_death_hook);
process_hooks_restart = TRUE;
+
return (FALSE);
}
return (FALSE);
}
-bool_ quest_wight_finish_hook(char *fmt)
+
+static bool_ quest_wight_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_WIGHT) return FALSE;
@@ -139,18 +161,19 @@ bool_ quest_wight_finish_hook(char *fmt)
*(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);
+ del_hook_new(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");
+ 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);
}
return (FALSE);
}
diff --git a/src/q_wight.hpp b/src/q_wight.hpp
new file mode 100644
index 00000000..1252e4fa
--- /dev/null
+++ b/src/q_wight.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+bool_ quest_wight_init_hook(int q_idx);
diff --git a/src/q_wolves.c b/src/q_wolves.cc
index 2ec14cc2..c5863b59 100644
--- a/src/q_wolves.c
+++ b/src/q_wolves.cc
@@ -1,7 +1,23 @@
-#undef cquest
+#include "q_wolves.hpp"
+
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "feature_type.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 *)
{
int x, y, i;
int xstart = 2;
@@ -69,7 +85,7 @@ bool_ quest_wolves_gen_hook(char *fmt)
return TRUE;
}
-bool_ quest_wolves_death_hook(char *fmt)
+static bool_ quest_wolves_death_hook(void *, void *, void *)
{
int i, mcnt = 0;
@@ -91,8 +107,9 @@ 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.");
@@ -101,11 +118,10 @@ bool_ quest_wolves_death_hook(char *fmt)
return FALSE;
}
-bool_ quest_wolves_finish_hook(char *fmt)
+static bool_ quest_wolves_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_WOLVES) return FALSE;
@@ -122,9 +138,9 @@ bool_ quest_wolves_init_hook(int q_idx)
{
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..59a83c56
--- /dev/null
+++ b/src/q_wolves.hpp
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "h-basic.h"
+
+bool_ quest_wolves_init_hook(int q_idx);
diff --git a/src/quark.cc b/src/quark.cc
new file mode 100644
index 00000000..45072ded
--- /dev/null
+++ b/src/quark.cc
@@ -0,0 +1,96 @@
+#include "quark.hpp"
+
+#include "z-util.h"
+
+#include <cassert>
+
+/*
+ * The number of quarks
+ */
+static s16b quark__num = 0;
+
+
+/*
+ * The pointers to the quarks [QUARK_MAX]
+ */
+static cptr *quark__str = NULL;
+
+
+/*
+ * Initialize the quark subsystem
+ */
+void quark_init()
+{
+ quark__num = 0;
+ quark__str = new cptr[QUARK_MAX];
+
+ for (int i = 0; i < QUARK_MAX; i++) {
+ quark__str[i] = nullptr;
+ }
+}
+
+
+/*
+* 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)
+{
+ assert(str != nullptr);
+
+ 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] = strdup(str);
+
+ /* Return the index */
+ return (i);
+}
+
+
+/*
+* This function looks up a quark
+*/
+cptr quark_str(s16b i)
+{
+ cptr q;
+
+ /* Verify */
+ if ((i < 0) || (i >= quark__num)) i = 0;
+
+ /* Access the quark */
+ q = quark__str[i];
+
+ /* Return the quark */
+ return (q);
+}
+
+
diff --git a/src/quark.hpp b/src/quark.hpp
new file mode 100644
index 00000000..0fce3932
--- /dev/null
+++ b/src/quark.hpp
@@ -0,0 +1,12 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * Maximum number of quarks.
+ */
+constexpr int QUARK_MAX = 768;
+
+void quark_init();
+cptr quark_str(s16b num);
+s16b quark_add(cptr str);
diff --git a/src/quest.cc b/src/quest.cc
new file mode 100644
index 00000000..a1aee67f
--- /dev/null
+++ b/src/quest.cc
@@ -0,0 +1,17 @@
+#include "quest.hpp"
+
+#include "tables.hpp"
+
+#include <cstddef>
+
+void init_hooks_quests()
+{
+ for (std::size_t i = 0; i < MAX_Q_IDX; i++)
+ {
+ if (quest[i].init != NULL)
+ {
+ quest[i].init(i);
+ }
+ }
+}
+
diff --git a/src/quest.hpp b/src/quest.hpp
new file mode 100644
index 00000000..7ff3cd3c
--- /dev/null
+++ b/src/quest.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+extern 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..aa99f40a
--- /dev/null
+++ b/src/quest_type.hpp
@@ -0,0 +1,27 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * 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? */
+
+ bool_ (*init)(int q); /* Function that takes care of generating hardcoded quests */
+
+ s32b data[9]; /* Various datas used by the quests */
+
+ bool_ (*gen_desc)(FILE *fff); /* Function for generating description. */
+};
diff --git a/src/randart.c b/src/randart.cc
index 298ee83a..5135438a 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,7 +6,24 @@
* included in all such copies.
*/
-#include "angband.h"
+#include "randart.hpp"
+#include "mimic.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_type.hpp"
+#include "options.hpp"
+#include "player_type.hpp"
+#include "quark.hpp"
+#include "randart_gen_type.hpp"
+#include "randart_part_type.hpp"
+#include "spells2.hpp"
+#include "util.hpp"
+#include "variable.h"
+#include "variable.hpp"
+#include "z-rand.hpp"
+
+#include <memory>
+#include <vector>
/* Chance of using syllables to form the name instead of the "template" files */
#define TABLE_NAME 45
@@ -23,21 +36,19 @@
*/
static bool_ grab_one_power(int *ra_idx, object_type *o_ptr, bool_ good, s16b *max_times)
{
- int i = 0, j;
- int *ok_ra, ok_num = 0;
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 < max_ra_idx; i++)
{
randart_part_type *ra_ptr = &ra_info[i];
bool_ ok = FALSE;
/* Must have the correct fields */
- for (j = 0; j < 20; j++)
+ for (size_t j = 0; j < 20; j++)
{
if (ra_ptr->tval[j] == o_ptr->tval)
{
@@ -69,16 +80,14 @@ static bool_ grab_one_power(int *ra_idx, object_type *o_ptr, bool_ good, s16b *m
if (esp & ra_ptr->aesp) 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 = ok_ra[rand_int(ok_ra.size())];
+ randart_part_type *ra_ptr = &ra_info[i];
/* XXX XXX Enforce minimum player level (loosely) */
if (ra_ptr->level > p_ptr->lev)
@@ -108,8 +117,6 @@ 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);
}
@@ -262,7 +269,6 @@ bool_ create_artifact(object_type *o_ptr, bool_ a_scroll, bool_ get_name)
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;
@@ -281,7 +287,10 @@ bool_ create_artifact(object_type *o_ptr, bool_ a_scroll, bool_ get_name)
if (a_cursed) powers /= 2;
- C_MAKE(max_times, max_ra_idx, s16b);
+ std::unique_ptr<s16b[]> max_times(new s16b[max_ra_idx]);
+ for (int i = 0; i < max_ra_idx; i++) {
+ max_times[i] = 0;
+ }
/* Main loop */
while (powers)
@@ -291,7 +300,7 @@ bool_ create_artifact(object_type *o_ptr, bool_ a_scroll, bool_ get_name)
powers--;
- if (!grab_one_power(&ra_idx, o_ptr, TRUE, max_times)) continue;
+ if (!grab_one_power(&ra_idx, o_ptr, TRUE, max_times.get())) continue;
ra_ptr = &ra_info[ra_idx];
@@ -325,7 +334,6 @@ 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);
@@ -388,8 +396,7 @@ bool_ create_artifact(object_type *o_ptr, bool_ a_scroll, bool_ get_name)
/* HACKS for ToME */
if (o_ptr->tval == TV_CLOAK && o_ptr->sval == SV_MIMIC_CLOAK)
{
- s32b mimic;
- call_lua("find_random_mimic_shape", "(d,d)", "d", 127, TRUE, &mimic);
+ s32b mimic = find_random_mimic_shape(127, TRUE);
o_ptr->pval2 = mimic;
}
else if (f5 & TR5_SPELL_CONTAIN)
@@ -403,26 +410,24 @@ bool_ create_artifact(object_type *o_ptr, bool_ a_scroll, bool_ get_name)
bool_ artifact_scroll(void)
{
- 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 */
diff --git a/src/randart.hpp b/src/randart.hpp
new file mode 100644
index 00000000..31b70f08
--- /dev/null
+++ b/src/randart.hpp
@@ -0,0 +1,9 @@
+#pragma once
+
+#include "h-basic.h"
+#include "object_type_fwd.hpp"
+
+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);
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_gen_type_fwd.hpp b/src/randart_gen_type_fwd.hpp
new file mode 100644
index 00000000..eba3e84e
--- /dev/null
+++ b/src/randart_gen_type_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct randart_gen_type;
diff --git a/src/randart_part_type.hpp b/src/randart_part_type.hpp
new file mode 100644
index 00000000..c2fa5386
--- /dev/null
+++ b/src/randart_part_type.hpp
@@ -0,0 +1,43 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * Random artifact part descriptor.
+ */
+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) */
+};
diff --git a/src/randart_part_type_fwd.hpp b/src/randart_part_type_fwd.hpp
new file mode 100644
index 00000000..979fd72c
--- /dev/null
+++ b/src/randart_part_type_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct randart_part_type;
diff --git a/src/random_artifact.hpp b/src/random_artifact.hpp
new file mode 100644
index 00000000..a3fc1c66
--- /dev/null
+++ b/src/random_artifact.hpp
@@ -0,0 +1,18 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * Random artifact descriptor.
+ */
+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? */
+};
diff --git a/src/random_quest.hpp b/src/random_quest.hpp
new file mode 100644
index 00000000..11ebe797
--- /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..01b5ba5e
--- /dev/null
+++ b/src/random_spell.hpp
@@ -0,0 +1,21 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * A structure to describe the random spells of the Power Mages
+ */
+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? */
+};
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..a8b35ffa
--- /dev/null
+++ b/src/rule_type.hpp
@@ -0,0 +1,22 @@
+#pragma once
+
+#include "h-basic.h"
+
+/* Define monster generation rules */
+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 */
+};
diff --git a/src/rune_spell.hpp b/src/rune_spell.hpp
new file mode 100644
index 00000000..d04a8dc4
--- /dev/null
+++ b/src/rune_spell.hpp
@@ -0,0 +1,15 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * Runecrafter prefered spells
+ */
+struct rune_spell
+{
+ char name[30]; /* name */
+
+ s16b type; /* Type of the spell(GF) */
+ s16b rune2; /* Modifiers */
+ s16b mana; /* Mana involved */
+};
diff --git a/src/rune_spell_fwd.hpp b/src/rune_spell_fwd.hpp
new file mode 100644
index 00000000..eb540a2a
--- /dev/null
+++ b/src/rune_spell_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct rune_spell;
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/script.cc b/src/script.cc
new file mode 100644
index 00000000..84f7c3e4
--- /dev/null
+++ b/src/script.cc
@@ -0,0 +1,30 @@
+/*
+ * 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 "script.h"
+
+#include "init2.hpp"
+#include "q_library.hpp"
+#include "spells4.hpp"
+#include "spells5.hpp"
+#include "spells6.hpp"
+
+
+void init_lua_init()
+{
+ /* Initialize schooled spells */
+ schools_init();
+ school_spells_init();
+ init_school_books();
+
+ /* Post-spell creation initialization */
+ initialize_bookable_spells();
+
+ /* Finish up the corruptions */
+ init_corruptions();
+}
diff --git a/src/script.h b/src/script.h
new file mode 100644
index 00000000..3d1a0840
--- /dev/null
+++ b/src/script.h
@@ -0,0 +1,12 @@
+#pragma once
+
+// C linkage required for these functions since main-* code uses them.
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void init_lua_init(void);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/src/set_type.hpp b/src/set_type.hpp
new file mode 100644
index 00000000..827c23ac
--- /dev/null
+++ b/src/set_type.hpp
@@ -0,0 +1,28 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * Item set descriptor and runtime information.
+ */
+struct set_type
+{
+ const char *name; /* Name */
+ char *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];
+};
diff --git a/src/set_type_fwd.hpp b/src/set_type_fwd.hpp
new file mode 100644
index 00000000..3b311808
--- /dev/null
+++ b/src/set_type_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct set_type;
diff --git a/src/skill_type.hpp b/src/skill_type.hpp
new file mode 100644
index 00000000..c6de1dc1
--- /dev/null
+++ b/src/skill_type.hpp
@@ -0,0 +1,37 @@
+#pragma once
+
+#include "h-basic.h"
+#include "skills_defs.hpp"
+
+/**
+ * Skill descriptors and runtime data.
+ */
+struct skill_type
+{
+ const char *name; /* Name */
+ char *desc; /* Description */
+
+ const char *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 */
+};
diff --git a/src/skill_type_fwd.hpp b/src/skill_type_fwd.hpp
new file mode 100644
index 00000000..0a06dadb
--- /dev/null
+++ b/src/skill_type_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct skill_type;
diff --git a/src/skills.c b/src/skills.cc
index 36b4f585..3a14a6ce 100644
--- a/src/skills.c
+++ b/src/skills.cc
@@ -1,7 +1,3 @@
-/* File: skills.c */
-
-/* Purpose: player skills */
-
/*
* Copyright (c) 2001 DarkGod
*
@@ -10,14 +6,54 @@
* included in all such copies.
*/
-#include "angband.h"
-
+#include "skills.hpp"
+
+#include "ability_type.hpp"
+#include "birth.hpp"
+#include "cmd2.hpp"
+#include "cmd3.hpp"
+#include "cmd5.hpp"
+#include "cmd7.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_type.hpp"
+#include "spells1.hpp"
+#include "spells4.hpp"
+#include "tables.hpp"
+#include "traps.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 <memory>
+#include <vector>
+#include <tuple>
+
+using boost::algorithm::iequals;
/*
* Advance the skill point of the skill specified by i and
* modify related skills
*/
-void increase_skill(int i, s16b *invest)
+static void increase_skill(int i, s16b *invest)
{
s32b max_skill_overage;
@@ -31,13 +67,18 @@ void increase_skill(int i, s16b *invest)
if (s_info[i].value >= SKILL_MAX) return;
/* Cannot allocate more than player level + max_skill_overage levels */
- call_lua("get_module_info", "(s)", "d", "max_skill_overage", &max_skill_overage);
+ max_skill_overage = modules[game_module_idx].skills.max_skill_overage;
if (((s_info[i].value + s_info[i].mod) / SKILL_STEP) >= (p_ptr->lev + max_skill_overage + 1))
{
int hgt, wid;
+ char buf[256];
+
+ sprintf(buf,
+ "Cannot raise a skill value above " FMTs32b " + player level.",
+ max_skill_overage);
Term_get_size(&wid, &hgt);
- msg_box(format("Cannot raise a skill value above %i + player level.", max_skill_overage), (int)(hgt / 2), (int)(wid / 2));
+ msg_box(buf, hgt / 2, wid / 2);
return;
}
@@ -54,7 +95,7 @@ void increase_skill(int i, s16b *invest)
* Descrease the skill point of the skill specified by i and
* modify related skills
*/
-void decrease_skill(int i, s16b *invest)
+static void decrease_skill(int i, s16b *invest)
{
/* Cannot decrease more */
if (!invest[i]) return;
@@ -85,8 +126,10 @@ s16b find_skill(cptr name)
/* 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);
+ if (s_info[i].name && streq(s_info[i].name, name))
+ {
+ return (i);
+ }
}
/* No match found */
@@ -100,7 +143,10 @@ s16b find_skill_i(cptr name)
for (i = 1; i < max_s_idx; i++)
{
/* The name matches */
- if (0 == stricmp(s_info[i].name + s_name, name)) return (i);
+ if (s_info[i].name && iequals(s_info[i].name, name))
+ {
+ return (i);
+ }
}
/* No match found */
@@ -140,15 +186,9 @@ s16b get_skill_scale(int skill, u32b scale)
return (temp / SKILL_MAX);
}
-
-/*
- *
- */
-int get_idx(int i)
+static int get_idx(int i)
{
- int j;
-
- for (j = 1; j < max_s_idx; j++)
+ for (int j = 1; j < max_s_idx; j++)
{
if (s_info[j].order == i)
return (j);
@@ -177,17 +217,11 @@ static bool_ is_known(int s_idx)
return FALSE;
}
-/*
- *
- */
-void init_table_aux(int table[MAX_SKILLS][2], int *idx, int father, int lev,
- bool_ full)
+static 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++)
+ for (int j = 1; j < max_s_idx; j++)
{
- i = get_idx(j);
+ int i = get_idx(j);
if (s_info[i].father != father) continue;
if (s_info[i].hidden) continue;
if (!is_known(i)) continue;
@@ -199,15 +233,13 @@ void init_table_aux(int table[MAX_SKILLS][2], int *idx, int father, int lev,
}
}
-
-void init_table(int table[MAX_SKILLS][2], int *max, bool_ full)
+static 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)
+static bool_ has_child(int sel)
{
int i;
@@ -250,17 +282,17 @@ void dump_skills(FILE *fff)
if (!has_child(i))
{
- strcat(buf, format(" . %s", s_info[i].name + s_name));
+ strcat(buf, format(" . %s", s_info[i].name));
}
else
{
- strcat(buf, format(" - %s", s_info[i].name + s_name));
+ strcat(buf, format(" - %s", s_info[i].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);
+ static_cast<double>(ABS(s_info[i].value)) / SKILL_STEP,
+ static_cast<double>(s_info[i].mod) / 1000);
}
fprintf(fff, "\n");
@@ -284,7 +316,7 @@ void print_skills(int table[MAX_SKILLS][2], int max, int sel, int start)
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);
+ print_desc_aux(s_info[table[sel][0]].desc, 3, 0);
for (j = start; j < start + (hgt - 7); j++)
{
@@ -310,17 +342,17 @@ void print_skills(int table[MAX_SKILLS][2], int max, int sel, int start)
}
if (!has_child(i))
{
- c_prt(color, format("%c.%c%s", deb, end, s_info[i].name + s_name),
+ c_prt(color, format("%c.%c%s", deb, end, s_info[i].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),
+ c_prt(color, format("%c-%c%s", deb, end, s_info[i].name),
j + 7 - start, table[j][1] * 4);
}
else
{
- c_prt(color, format("%c+%c%s", deb, end, s_info[i].name + s_name),
+ c_prt(color, format("%c+%c%s", deb, end, s_info[i].name),
j + 7 - start, table[j][1] * 4);
}
c_prt(color,
@@ -366,21 +398,29 @@ void recalc_skills(bool_ init)
msg_format("You have gained %d new thaumaturgy spells.", thaum_gain);
}
- process_hooks(HOOK_RECALC_SKILLS, "()");
+ /* 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_BASIC | PR_EXTRA | PR_MAP);
+ p_ptr->redraw |= (PR_WIPE | PR_FRAME | PR_MAP);
}
}
/*
* Recalc the skill value
*/
-void recalc_skills_theory(s16b *invest, s32b *base_val, s32b *base_mod, s32b *bonus)
+static void recalc_skills_theory(s16b *invest, s32b *base_val, s32b *base_mod, s32b *bonus)
{
int i, j;
@@ -438,11 +478,6 @@ void do_cmd_skill()
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);
@@ -450,11 +485,11 @@ void do_cmd_skill()
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);
+ std::unique_ptr<s32b[]> skill_values_save(new s32b[MAX_SKILLS]);
+ std::unique_ptr<s32b[]> skill_mods_save(new s32b[MAX_SKILLS]);
+ std::unique_ptr<s16b[]> skill_rates_save(new s16b[MAX_SKILLS]);
+ std::unique_ptr<s16b[]> skill_invest(new s16b[MAX_SKILLS]);
+ std::unique_ptr<s32b[]> skill_bonus(new s32b[MAX_SKILLS]);
/* Save skill points */
skill_points_save = p_ptr->skill_points;
@@ -468,6 +503,7 @@ void do_cmd_skill()
skill_mods_save[i] = s_ptr->mod;
skill_rates_save[i] = s_ptr->rate;
skill_invest[i] = 0;
+ skill_bonus[i] = 0;
}
/* Clear the screen */
@@ -481,7 +517,7 @@ void do_cmd_skill()
Term_get_size(&wid, &hgt);
/* Display list of skills */
- recalc_skills_theory(skill_invest, skill_values_save, skill_mods_save, skill_bonus);
+ recalc_skills_theory(skill_invest.get(), skill_values_save.get(), skill_mods_save.get(), skill_bonus.get());
print_skills(table, max, sel, start);
/* Wait for user input */
@@ -527,13 +563,13 @@ void do_cmd_skill()
if (dir == 8) sel--;
/* Miscellaneous skills cannot be increased/decreased as a group */
- if (table[sel][0] == SKILL_MISC) continue;
+ if ((sel >= 0) && (sel < max) && table[sel][0] == SKILL_MISC) continue;
/* Increase the current skill */
- if (dir == 6) increase_skill(table[sel][0], skill_invest);
+ if (dir == 6) increase_skill(table[sel][0], skill_invest.get());
/* Decrease the current skill */
- if (dir == 4) decrease_skill(table[sel][0], skill_invest);
+ if (dir == 4) decrease_skill(table[sel][0], skill_invest.get());
/* XXX XXX XXX Wizard mode commands outside of wizard2.c */
@@ -544,8 +580,10 @@ void do_cmd_skill()
if (wizard && (c == '-')) skill_bonus[table[sel][0]] -= SKILL_STEP;
/* Contextual help */
- if (c == '?') exec_lua(format("ingame_help('select_context', 'skill', '%s')", s_info[table[sel][0]].name + s_name));
- ;
+ if (c == '?')
+ {
+ help_skill(s_info[table[sel][0]].name);
+ }
/* Handle boundaries and scrolling */
if (sel < 0) sel = max - 1;
@@ -563,7 +601,7 @@ void do_cmd_skill()
flush();
/* Ask we can commit the change */
- if (msg_box("Save and use these skill values? (y/n)", (int)(hgt / 2), (int)(wid / 2)) != 'y')
+ if (msg_box("Save and use these skill values? (y/n)", hgt / 2, wid / 2) != 'y')
{
/* User declines -- restore the skill values before exiting */
@@ -582,14 +620,6 @@ void do_cmd_skill()
}
}
-
- /* 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();
@@ -601,13 +631,13 @@ void do_cmd_skill()
/*
* List of melee skills
*/
-s16b melee_skills[MAX_MELEE] =
+static s16b melee_skills[MAX_MELEE] =
{
SKILL_MASTERY,
SKILL_HAND,
SKILL_BEAR,
};
-char *melee_names[MAX_MELEE] =
+static const char *melee_names[MAX_MELEE] =
{
"Weapon combat",
"Barehanded combat",
@@ -628,6 +658,11 @@ s16b get_melee_skill()
return (0);
}
+cptr get_melee_name()
+{
+ return melee_names[get_melee_skill()];
+}
+
s16b get_melee_skills()
{
int i, j = 0;
@@ -713,7 +748,7 @@ static void choose_melee()
p_ptr->update |= (PU_HP);
/* Redraw monster hitpoint */
- p_ptr->redraw |= (PR_MH);
+ p_ptr->redraw |= (PR_FRAME);
Term_load();
character_icky = FALSE;
@@ -743,61 +778,55 @@ void select_default_melee()
/*
* Print a batch of skills.
*/
-static void print_skill_batch(int *p, cptr *p_desc, int start, int max, bool_ mode)
+static void print_skill_batch(const std::vector<std::tuple<cptr, int>> &p, int start)
{
char buff[80];
- int i = start, j = 0;
+ int j = 0;
- if (mode) prt(format(" %-31s", "Name"), 1, 20);
+ prt(format(" %-31s", "Name"), 1, 20);
- for (i = start; i < (start + 20); i++)
+ for (int i = start; i < (start + 20); i++)
{
- if (i >= max) break;
+ if (static_cast<size_t>(i) >= p.size())
+ {
+ 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");
+ sprintf(buff, " %c - %d) %-30s", I2A(j),
+ std::get<1>(p[i]),
+ std::get<0>(p[i]));
- if (mode) prt(buff, 2 + j, 20);
+ prt(buff, 2 + j, 20);
j++;
}
- if (mode) prt("", 2 + j, 20);
+ prt("", 2 + j, 20);
prt(format("Select a skill (a-%c), @ to select by name, +/- to scroll:", I2A(j - 1)), 0, 0);
}
-int do_cmd_activate_skill_aux()
+static int do_cmd_activate_skill_aux()
{
char which;
- int max = 0, i, start = 0;
+ int 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 */
+ std::vector<std::tuple<cptr,int>> p;
/* More than 1 melee skill ? */
if (get_melee_skills() > 1)
{
- p_desc[max] = "Change melee mode";
- p[max++] = 0;
+ p.push_back(std::make_tuple("Change melee mode", 0));
}
- for (i = 1; i < max_s_idx; i++)
+ for (size_t 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++)
+ for (size_t j = 0; j < p.size(); j++)
{
- if (s_info[i].action_mkey == p[j])
+ if (s_info[i].action_mkey == std::get<1>(p[j]))
{
next = TRUE;
break;
@@ -805,22 +834,21 @@ int do_cmd_activate_skill_aux()
}
if (next) continue;
- p_desc[max] = s_text + s_info[i].action_desc;
- p[max++] = s_info[i].action_mkey;
+ p.push_back(std::make_tuple(s_info[i].action_desc,
+ s_info[i].action_mkey));
}
}
- for (i = 0; i < max_ab_idx; i++)
+ for (size_t 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++)
+ for (size_t j = 0; j < p.size(); j++)
{
- if (ab_info[i].action_mkey == p[j])
+ if (ab_info[i].action_mkey == std::get<1>(p[j]))
{
next = TRUE;
break;
@@ -828,12 +856,12 @@ int do_cmd_activate_skill_aux()
}
if (next) continue;
- p_desc[max] = ab_text + ab_info[i].action_desc;
- p[max++] = ab_info[i].action_mkey;
+ p.push_back(std::make_tuple(ab_info[i].action_desc,
+ ab_info[i].action_mkey));
}
}
- if (!max)
+ if (p.empty())
{
msg_print("You don't have any activable skills or abilities.");
return -1;
@@ -844,7 +872,7 @@ int do_cmd_activate_skill_aux()
while (1)
{
- print_skill_batch(p, p_desc, start, max, mode);
+ print_skill_batch(p, start);
which = inkey();
if (which == ESCAPE)
@@ -852,23 +880,23 @@ int do_cmd_activate_skill_aux()
ret = -1;
break;
}
- else if (which == '*' || which == '?' || which == ' ')
- {
- mode = (mode) ? FALSE : TRUE;
- Term_load();
- character_icky = FALSE;
- }
else if (which == '+')
{
start += 20;
- if (start >= max) 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;
+ if (start < 0)
+ {
+ start += 20;
+ }
Term_load();
character_icky = FALSE;
}
@@ -881,22 +909,23 @@ int do_cmd_activate_skill_aux()
return FALSE;
/* Find the skill it is related to */
- for (i = 0; i < max; i++)
+ size_t i = 0;
+ for (; i < p.size(); i++)
{
- if (!strcmp(buf, p_desc[i]))
+ if (!strcmp(buf, std::get<0>(p[i])))
break;
}
- if ((i < max))
+
+ if (i < p.size())
{
- ret = p[i];
+ ret = std::get<1>(p[i]);
break;
}
-
}
else
{
which = tolower(which);
- if (start + A2I(which) >= max)
+ if (start + A2I(which) >= static_cast<int>(p.size()))
{
bell();
continue;
@@ -907,16 +936,13 @@ int do_cmd_activate_skill_aux()
continue;
}
- ret = p[start + A2I(which)];
+ ret = std::get<1>(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;
}
@@ -985,9 +1011,6 @@ void do_cmd_activate_skill()
case MKEY_MINDCRAFT:
do_cmd_mindcraft();
break;
- case MKEY_ALCHEMY:
- do_cmd_alchemist();
- break;
case MKEY_MIMIC:
do_cmd_mimic();
break;
@@ -1003,12 +1026,6 @@ void do_cmd_activate_skill()
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;
@@ -1045,8 +1062,96 @@ void do_cmd_activate_skill()
case MKEY_PIERCING:
do_cmd_set_piercing();
break;
+ case MKEY_DEATH_TOUCH:
+ {
+ if (p_ptr->csp > 40)
+ {
+ increase_mana(-40);
+ set_project(randint(30) + 10,
+ GF_INSTA_DEATH,
+ 1,
+ 0,
+ PROJECT_STOP | PROJECT_KILL);
+ energy_use = 100;
+ }
+ else
+ {
+ msg_print("You need at least 40 mana.");
+ }
+ break;
+ }
+ 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:
- process_hooks(HOOK_MKEY, "(d)", x_idx);
break;
}
}
@@ -1068,7 +1173,7 @@ bool_ forbid_gloves()
/* Which gods forbid edged weapons */
bool_ forbid_non_blessed()
{
- GOD(GOD_ERU) return (TRUE);
+ if (p_ptr->pgod == GOD_ERU) return (TRUE);
return (FALSE);
}
@@ -1146,84 +1251,136 @@ void init_skill(s32b value, s32b mod, int i)
s_info[i].hidden = 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()
{
- char *items[LOST_SWORD_NSKILLS];
+ std::vector<std::string> items;
int skl[LOST_SWORD_NSKILLS];
s32b val[LOST_SWORD_NSKILLS], mod[LOST_SWORD_NSKILLS];
- bool_ used[MAX_SKILLS];
int available_skills[MAX_SKILLS];
- int max = 0, max_a = 0, res, i;
+ int max_a = 0, res, i;
/* Check if some skills didn't influence other stuff */
recalc_skills(TRUE);
/* Grab the ones we can gain */
- max = 0;
+ max_a = 0;
for (i = 0; i < max_s_idx; i++)
{
- if (s_info[i].flags1 & SKF1_RANDOM_GAIN)
- available_skills[max++] = i;
+ if (s_info[i].flags1 & SKF1_RANDOM_GAIN) {
+ available_skills[max_a] = i;
+ max_a++;
+ }
}
- available_skills[max++] = -1;
- /* Init */
- for (max = 0; max < MAX_SKILLS; max++)
- {
- used[max] = FALSE;
+ /* Perform the selection */
+ std::vector<s32b> weights;
+ for (i = 0; i < max_a; i++) {
+ weights.push_back(s_info[available_skills[i]].random_gain_chance);
}
- /* Count the number of available skills */
- while (available_skills[max_a] != -1) max_a++;
+ std::vector<size_t> indexes = wrs(weights);
+ assert(indexes.size() >= LOST_SWORD_NSKILLS);
- /* Get LOST_SWORD_NSKILLS skills */
- for (max = 0; max < LOST_SWORD_NSKILLS; max++)
+ /* Extract the information needed from the skills */
+ for (i = 0; i < LOST_SWORD_NSKILLS; i++)
{
- int i;
- skill_type *s_ptr;
-
- /* Get an non used skill */
- do
- {
- i = rand_int(max_a);
-
- /* Does it pass the check? */
- if (!magik(s_info[available_skills[i]].random_gain_chance))
- continue;
- }
- while (used[available_skills[i]]);
-
- s_ptr = &s_info[available_skills[i]];
- used[available_skills[i]] = TRUE;
+ s32b s_idx = available_skills[indexes[i]];
+ skill_type *s_ptr = &s_info[s_idx];
if (s_ptr->mod)
{
if (s_ptr->mod < 300)
{
- val[max] = 1000;
- mod[max] = 300 - s_ptr->mod;
+ val[i] = 1000;
+ mod[i] = 300 - s_ptr->mod;
}
else if (s_ptr->mod < 500)
{
- val[max] = s_ptr->mod * 1;
- mod[max] = 100;
- if (mod[max] + s_ptr->mod > 500)
- mod[max] = 500 - s_ptr->mod;
+ val[i] = s_ptr->mod * 1;
+ mod[i] = 100;
+ if (mod[i] + s_ptr->mod > 500)
+ mod[i] = 500 - s_ptr->mod;
}
else
{
- val[max] = s_ptr->mod * 3;
- mod[max] = 0;
+ val[i] = s_ptr->mod * 3;
+ mod[i] = 0;
}
}
else
{
- mod[max] = 300;
- val[max] = 1000;
+ mod[i] = 300;
+ val[i] = 1000;
}
- if (s_ptr->value + val[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));
+
+ 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_ptr->name,
+ val[i] / SKILL_STEP,
+ val[i] % SKILL_STEP,
+ mod[i] / SKILL_STEP,
+ mod[i] % SKILL_STEP));
}
while (TRUE)
@@ -1231,7 +1388,7 @@ void do_get_new_skill()
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);
+ res = ask_menu(buf, items);
/* Ok ? lets learn ! */
if (res > -1)
@@ -1266,7 +1423,7 @@ void do_get_new_skill()
/* Prepare prompt */
msg = format("This skill is mutually exclusive with "
"at least %s, continue?",
- s_info[oppose_skill].name + s_name);
+ s_info[oppose_skill].name);
/* The player rejected the choice */
if (!get_check(msg)) continue;
@@ -1278,23 +1435,17 @@ void do_get_new_skill()
if (mod[res])
{
msg_format("You can now learn the %s skill.",
- s_ptr->name + s_name);
+ s_ptr->name);
}
else
{
msg_format("Your knowledge of the %s skill increases.",
- s_ptr->name + s_name);
+ s_ptr->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);
}
@@ -1315,8 +1466,10 @@ s16b find_ability(cptr name)
/* 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);
+ if (ab_info[i].name && streq(ab_info[i].name, name))
+ {
+ return (i);
+ }
}
/* No match found */
@@ -1332,7 +1485,7 @@ bool_ has_ability(int ab)
}
/* Do we meet the requirements */
-bool_ can_learn_ability(int ab)
+static bool_ can_learn_ability(int ab)
{
ability_type *ab_ptr = &ab_info[ab];
int i;
@@ -1377,22 +1530,18 @@ bool_ can_learn_ability(int ab)
}
}
- /* 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)
+static 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));
+ msg_box("You cannot learn this ability.", hgt / 2, wid / 2);
return;
}
@@ -1400,7 +1549,7 @@ void gain_ability(int ab)
flush();
/* Ask we can commit the change */
- if (msg_box("Learn this ability(this is permanent)? (y/n)", (int)(hgt / 2), (int)(wid / 2)) != 'y')
+ if (msg_box("Learn this ability(this is permanent)? (y/n)", hgt / 2, wid / 2) != 'y')
{
return;
}
@@ -1409,28 +1558,9 @@ void gain_ability(int ab)
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)
+static bool compare_abilities(const int ab_idx1, const int ab_idx2)
{
- 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)++;
+ return strcmp(ab_info[ab_idx1].name, ab_info[ab_idx2].name) < 0;
}
/*
@@ -1438,28 +1568,31 @@ static void add_sorted_ability(int *table, int *max, int ab)
*/
void dump_abilities(FILE *fff)
{
- int i, j;
- int *table;
- int max = 0;
-
- C_MAKE(table, max_ab_idx, int);
+ int i;
- /* Initialise the abilities list */
+ // Find all abilities that the player has.
+ std::vector<int> table;
for (i = 0; i < max_ab_idx; i++)
{
if (ab_info[i].name && has_ability(i))
- add_sorted_ability(table, &max, i);
+ {
+ table.push_back(i);
+ }
}
- if (max)
+ // Sort
+ std::sort(std::begin(table),
+ std::end(table),
+ compare_abilities);
+
+ // Show
+ if (!table.empty())
{
fprintf(fff, "\nAbilities");
- for (j = 0; j < max; j++)
+ for (int i : table)
{
- i = table[j];
-
- fprintf(fff, "\n * %s", ab_info[i].name + ab_name);
+ fprintf(fff, "\n * %s", ab_info[i].name);
}
fprintf(fff, "\n");
@@ -1469,7 +1602,7 @@ void dump_abilities(FILE *fff)
/*
* Draw the abilities list
*/
-void print_abilities(int table[], int max, int sel, int start)
+static void print_abilities(const std::vector<int> &table, int sel, int start)
{
int i, j;
int wid, hgt;
@@ -1484,14 +1617,18 @@ void print_abilities(int table[], int max, int sel, int start)
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);
+ print_desc_aux(ab_info[table[sel]].desc, 3, 0);
for (j = start; j < start + (hgt - 7); j++)
{
byte color = TERM_WHITE;
char deb = ' ', end = ' ';
- if (j >= max) break;
+ assert(j >= 0);
+ if (static_cast<size_t>(j) >= table.size())
+ {
+ break;
+ }
i = table[j];
@@ -1510,7 +1647,7 @@ void print_abilities(int table[], int max, int sel, int start)
end = ']';
}
- c_prt(color, format("%c.%c%s", deb, end, ab_info[i].name + ab_name),
+ c_prt(color, format("%c.%c%s", deb, end, ab_info[i].name),
j + 7 - start, 0);
if (!ab_info[i].acquired)
@@ -1529,14 +1666,11 @@ void print_abilities(int table[], int max, int sel, int start)
*/
void do_cmd_ability()
{
- int sel = 0, start = 0, max = 0;
+ int sel = 0, start = 0;
char c;
- int *table;
int i;
int wid, hgt;
- C_MAKE(table, max_ab_idx, int);
-
/* Save the screen */
screen_save();
@@ -1544,30 +1678,44 @@ void do_cmd_ability()
Term_clear();
/* Initialise the abilities list */
+ std::vector<int> table;
for (i = 0; i < max_ab_idx; i++)
{
-if (ab_info[i].name)
- add_sorted_ability(table, &max, i);
+ if (ab_info[i].name)
+ {
+ 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, max, sel, start);
+ print_abilities(table, sel, start);
/* Wait for user input */
c = inkey();
/* Leave the skill screen */
- if (c == ESCAPE) break;
+ if (c == ESCAPE)
+ {
+ break;
+ }
/* Next page */
else if (c == 'n')
{
sel += (hgt - 7);
- if (sel >= max) sel = max - 1;
+ assert(sel >= 0);
+ if (static_cast<size_t>(sel) >= table.size())
+ {
+ sel = table.size() - 1;
+ }
}
/* Previous page */
@@ -1600,28 +1748,40 @@ if (ab_info[i].name)
if (wizard && (c == '-')) ab_info[table[sel]].acquired = FALSE;
/* Contextual help */
- if (c == '?') exec_lua(format("ingame_help('select_context', 'ability', '%s')", ab_info[table[sel]].name + ab_name));
- ;
+ if (c == '?')
+ {
+ help_ability(ab_info[table[sel]].name);
+ }
/* 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;
+ 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();
- 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);
+ p_ptr->redraw |= (PR_WIPE | PR_FRAME | PR_MAP);
}
/*
@@ -1636,25 +1796,33 @@ void apply_level_abilities(int level)
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);
+ {
+ cmsg_format(TERM_L_GREEN, "You have learned the ability '%s'.", 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);
+ {
+ cmsg_format(TERM_L_GREEN, "You have learned the ability '%s'.", 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);
+ {
+ cmsg_format(TERM_L_GREEN, "You have learned the ability '%s'.", 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);
+ {
+ cmsg_format(TERM_L_GREEN, "You have learned the ability '%s'.", ab_info[rmp_ptr->abilities[i].ability].name);
+ }
ab_info[rmp_ptr->abilities[i].ability].acquired = TRUE;
}
}
diff --git a/src/skills.hpp b/src/skills.hpp
new file mode 100644
index 00000000..6c1880a6
--- /dev/null
+++ b/src/skills.hpp
@@ -0,0 +1,27 @@
+#pragma once
+
+#include "h-basic.h"
+
+/* Skill functions */
+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 cptr get_melee_name();
+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);
diff --git a/src/skills_defs.hpp b/src/skills_defs.hpp
new file mode 100644
index 00000000..1dbdee9f
--- /dev/null
+++ b/src/skills_defs.hpp
@@ -0,0 +1,63 @@
+#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
+#define SKILL_RUNECRAFT 34
+#define SKILL_SNEAK 35
+#define SKILL_STEALTH 36
+#define SKILL_DISARMING 37
+#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
+#define MAX_SKILLS 200
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/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..5d6722af 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,50 @@
* 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_info_type.hpp"
+#include "files.hpp"
+#include "feature_type.hpp"
+#include "gods.hpp"
+#include "melee2.hpp"
+#include "monster2.hpp"
+#include "monster3.hpp"
+#include "monster_type.hpp"
+#include "monster_race.hpp"
+#include "object1.hpp"
+#include "object2.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 "traps.hpp"
+#include "trap_type.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 <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 +60,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
@@ -173,7 +230,7 @@ void teleport_player_directed(int rad, int dir)
if (c_ptr->feat == FEAT_SHOP)
{
/* Disturb */
- disturb(0, 0);
+ disturb(0);
/* Hack -- enter store */
command_new = '_';
@@ -190,13 +247,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 +261,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 +279,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 +305,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 */
@@ -294,22 +350,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->flags9 & RF9_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 +381,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;
}
@@ -535,12 +596,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->flags6 & RF6_TPORT) && !(r_ptr->flags3 & RF3_RES_TELE))
/*
* The latter limitation is to avoid
* totally unkillable suckers...
@@ -569,7 +627,7 @@ void teleport_player(int dis)
p_ptr->update |= (PU_DISTANCE);
/* Redraw trap detection status */
- p_ptr->redraw |= (PR_DTRAP);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_OVERHEAD);
@@ -799,7 +857,7 @@ void teleport_player_to(int ny, int nx)
p_ptr->update |= (PU_DISTANCE);
/* Redraw trap detection status */
- p_ptr->redraw |= (PR_DTRAP);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_OVERHEAD);
@@ -816,7 +874,7 @@ void teleport_player_to(int ny, int nx)
void teleport_player_level(void)
{
/* 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;
@@ -935,10 +993,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 +1076,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 +1156,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;
}
}
@@ -1224,8 +1224,8 @@ void spellbinder_trigger()
cmsg_print(TERM_L_GREEN, "The spellbinder is triggered!");
for (i = 0; i < p_ptr->spellbinder_num; i++)
{
- msg_format("Triggering spell %s.", school_spells[p_ptr->spellbinder[i]].name);
- 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(p_ptr->spellbinder[i])));
+ lua_cast_school_spell(p_ptr->spellbinder[i], TRUE);
}
p_ptr->spellbinder_num = 0;
p_ptr->spellbinder_trigger = 0;
@@ -1258,7 +1258,7 @@ void take_hit(int damage, cptr hit_from)
if (death) return;
/* Disturb */
- disturb(1, 0);
+ disturb(1);
/* Apply "invulnerability" */
if (p_ptr->invuln && (damage < 9000))
@@ -1289,7 +1289,7 @@ 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 */
@@ -1305,7 +1305,7 @@ void take_hit(int damage, cptr hit_from)
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
{
@@ -1317,14 +1317,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);
@@ -1394,7 +1394,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);
@@ -1443,7 +1443,7 @@ void take_hit(int damage, cptr hit_from)
/* 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; */
@@ -1491,14 +1491,14 @@ void take_sanity_hit(int damage, cptr hit_from)
if (death) return;
/* Disturb */
- disturb(1, 0);
+ disturb(1);
/* 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);
@@ -2067,75 +2067,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.
*
@@ -2633,13 +2564,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 +2587,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 +2615,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 +2637,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 +2716,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 +2787,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 +2856,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 +2890,8 @@ sint project_path(u16b *gp, int range, int y1, int x1, int y2, int x2, int flg)
}
}
-
- /* Length */
- return (n);
+ /* Done */
+ return gp;
}
@@ -2975,6 +2941,9 @@ static bool_ project_f(int who, int r, int y, int x, int dam, int typ)
/* Remember if the grid is with the LoS of player */
seen = player_can_see_bold(y, x);
+ /* Check gods */
+ project_check_gods(typ);
+
/* Analyze the type */
switch (typ)
{
@@ -3793,16 +3762,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 */
@@ -3861,8 +3834,6 @@ static bool_ project_o(int who, int r, int y, int x, int dam, int typ)
{
cave_type *c_ptr = &cave[y][x];
- s16b this_o_idx, next_o_idx = 0;
-
bool_ obvious = FALSE;
u32b f1, f2, f3, f4, f5, esp;
@@ -3879,12 +3850,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,10 +3867,7 @@ 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);
@@ -4108,7 +4079,7 @@ static bool_ project_o(int who, int r, int y, int x, int dam, int typ)
o_ptr->ident |= (IDENT_MENTAL);
/* Process the appropriate hooks */
- process_hooks(HOOK_IDENTIFY, "(d,s)", 0 - this_o_idx, "full");
+ identify_hooks(0 - this_o_idx, o_ptr, IDENT_FULL);
/* Squelch ! */
squeltch_grid();
@@ -4121,7 +4092,7 @@ static bool_ project_o(int who, int r, int y, int x, int dam, int typ)
object_known(o_ptr);
/* Process the appropriate hooks */
- process_hooks(HOOK_IDENTIFY, "(d,s)", 0 - this_o_idx, "normal");
+ identify_hooks(0 - this_o_idx, o_ptr, IDENT_NORMAL);
/* Squelch ! */
squeltch_grid();
@@ -4173,15 +4144,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;
}
@@ -4307,12 +4270,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,9 +4344,15 @@ 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)
{
@@ -4484,14 +4449,13 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
if (r_ptr->flags3 & RF3_HURT_LITE)
get_angry = TRUE;
break;
- default:
- /* Hooks! */
- if (process_hooks_ret(HOOK_GF_EXEC, "d", "(s,d,d,d,d,d,d,M)", "angry", who, typ, dam, r, y, x, m_ptr))
- {
- get_angry = process_hooks_return[0].num;
- }
- else
- get_angry = TRUE;
+ case GF_INSTA_DEATH:
+ get_angry = TRUE;
+ break;
+ case GF_ELEMENTAL_GROWTH:
+ case GF_ELEMENTAL_WALL:
+ get_angry = FALSE;
+ break;
}
/* Now anger it if appropriate */
@@ -4782,8 +4746,8 @@ 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;
@@ -4803,8 +4767,8 @@ 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;
@@ -5309,7 +5273,7 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
}
default:
if (!p_ptr->free_act)
- (void)set_paralyzed(p_ptr->paralyzed + randint(dam));
+ (void)set_paralyzed(randint(dam));
break;
}
}
@@ -5380,7 +5344,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 +5357,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.";
@@ -5672,7 +5636,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.";
@@ -6686,7 +6650,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.";
@@ -6746,36 +6710,25 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ)
break;
}
- /* Default */
- default:
+ case GF_INSTA_DEATH:
{
- /* Hooks! */
- if (process_hooks_ret(HOOK_GF_EXEC, "dddddddddss", "(s,d,d,d,d,d,d,M)", "monster", who, typ, dam, r, y, x, m_ptr))
- {
- obvious = process_hooks_return[0].num;
- dam = process_hooks_return[1].num;
- do_stun = process_hooks_return[2].num;
- do_fear = process_hooks_return[3].num;
- do_conf = process_hooks_return[4].num;
- do_dist = process_hooks_return[5].num;
- do_pois = process_hooks_return[6].num;
- do_cut = process_hooks_return[7].num;
- do_poly = process_hooks_return[8].num;
- if (process_hooks_return[9].str != NULL)
- note = process_hooks_return[9].str;
- if (process_hooks_return[10].str != NULL)
- note_dies = process_hooks_return[10].str;
- }
- else
- {
- /* Irrelevant */
+ if (magik(95) && !(r_ptr->flags1 & RF1_UNIQUE) && !(r_ptr->flags3 & RF3_UNDEAD) && !(r_ptr->flags3 & RF3_NONLIVING)) {
+ /* Kill outright, but reduce exp. */
+ m_ptr->level = m_ptr->level / 3;
+ dam = 32535; /* Should be enough */
+ note = " faints.";
+ note_dies = " is sucked out of life.";
+ } else {
+ /* No effect */
skipped = TRUE;
-
- /* No damage */
- dam = 0;
}
+
break;
}
+
+ default:
+ skipped = TRUE;
+ break;
}
@@ -6850,7 +6803,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();
}
}
@@ -7188,7 +7141,7 @@ static bool_ project_p(int who, int r, int y, int x, int dam, int typ, int a_rad
project(0, 0, t_y, t_x, dam, typ, (PROJECT_STOP | PROJECT_KILL));
- disturb(1, 0);
+ disturb(1);
return TRUE;
}
@@ -7221,13 +7174,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);
}
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)
@@ -7245,7 +7196,7 @@ static bool_ project_p(int who, int r, int y, int x, int dam, int typ, int a_rad
if (who == -2)
{
sprintf(killer, "%s",
- t_name + t_info[cave[p_ptr->py][p_ptr->px].t_idx].name);
+ t_info[cave[p_ptr->py][p_ptr->px].t_idx].name);
}
/* Analyze the damage */
@@ -7926,7 +7877,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;
}
@@ -7995,7 +7946,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 +7969,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 +8041,7 @@ static bool_ project_p(int who, int r, int y, int x, int dam, int typ, int a_rad
/* Disturb */
- disturb(1, 0);
+ disturb(1);
/* Return "Anything seen?" */
@@ -8252,7 +8195,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;
@@ -8275,11 +8218,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 +8302,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;
@@ -8416,7 +8360,7 @@ bool_ project(int who, int rad, int y, int x, int dam, int typ, int flg)
print_rel(c, a, y, x);
move_cursor_relative(y, x);
if (fresh_before) Term_fresh();
- Term_xtra(TERM_XTRA_DELAY, msec);
+ sleep_for(milliseconds(msec));
lite_spot(y, x);
if (fresh_before) Term_fresh();
@@ -8442,7 +8386,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 +8467,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];
@@ -8560,7 +8504,7 @@ bool_ project(int who, int rad, int y, int x, int dam, int typ, int flg)
/* Delay (efficiently) */
if (visual || drawn)
{
- Term_xtra(TERM_XTRA_DELAY, msec);
+ sleep_for(milliseconds(msec));
}
}
@@ -8568,7 +8512,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];
@@ -8605,7 +8549,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 +8582,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 +8609,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,7 +8625,7 @@ 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)
&& (dist_hack > 1))
@@ -8750,7 +8694,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++;
@@ -8930,6 +8874,10 @@ bool_ potion_smash_effect(int who, int y, int x, int o_sval)
(void) 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.
+ (void) ident;
+
/* XXX those potions that explode need to become "known" */
return angry;
}
@@ -8983,7 +8931,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)
{
diff --git a/src/spells1.hpp b/src/spells1.hpp
new file mode 100644
index 00000000..5512063f
--- /dev/null
+++ b/src/spells1.hpp
@@ -0,0 +1,32 @@
+#pragma once
+
+#include "h-basic.h"
+
+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_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_ 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 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 s16b do_poly_monster(int y, int x);
diff --git a/src/spells2.c b/src/spells2.cc
index 5467499c..08a643c9 100644
--- a/src/spells2.c
+++ b/src/spells2.cc
@@ -1,7 +1,3 @@
-/* File: spells2.c */
-
-/* Purpose: Spell code (part 2) */
-
/*
* Copyright (c) 1989 James E. Wilson, Robert A. Koeneke
*
@@ -10,7 +6,52 @@
* included in all such copies.
*/
-#include "angband.h"
+#include "spells2.hpp"
+
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "cmd1.hpp"
+#include "cmd7.hpp"
+#include "dungeon_info_type.hpp"
+#include "feature_type.hpp"
+#include "files.hpp"
+#include "hook_identify_in.hpp"
+#include "hooks.hpp"
+#include "melee2.hpp"
+#include "monster2.hpp"
+#include "monster3.hpp"
+#include "monster_race.hpp"
+#include "monster_type.hpp"
+#include "notes.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_kind.hpp"
+#include "object_type.hpp"
+#include "options.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
@@ -19,7 +60,7 @@
* since it is usually tested several times...
*/
-void summon_dragon_riders();
+static void summon_dragon_riders();
/*
@@ -111,7 +152,7 @@ bool_ hp_player(int num)
}
/* Redraw */
- p_ptr->redraw |= (PR_HP);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
@@ -309,6 +350,72 @@ bool_ do_res_stat(int stat, bool_ full)
/*
+ * 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)
@@ -343,12 +450,22 @@ bool_ do_inc_stat(int stat)
}
+/*
+ * 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".
*/
-void identify_pack(void)
+bool_ identify_pack(void)
{
int i;
@@ -365,11 +482,12 @@ void identify_pack(void)
object_known(o_ptr);
/* Process the appropriate hooks */
- process_hooks(HOOK_IDENTIFY, "(d,s)", i, "normal");
+ identify_hooks(i, o_ptr, IDENT_NORMAL);
}
p_ptr->notice |= (PN_COMBINE | PN_REORDER);
p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
+ return TRUE;
}
/*
@@ -383,9 +501,6 @@ static void make_item_fully_identified(object_type *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);
}
/*
@@ -407,7 +522,7 @@ void identify_pack_fully(void)
make_item_fully_identified(o_ptr);
/* Process the appropriate hooks */
- process_hooks(HOOK_IDENTIFY, "(d,s)", i, "full");
+ identify_hooks(i, o_ptr, IDENT_FULL);
}
p_ptr->update |= (PU_BONUS);
@@ -427,7 +542,7 @@ static int enchant_table[16] =
1000
};
-bool_ remove_curse_object(object_type *o_ptr, bool_ all)
+static bool_ remove_curse_object(object_type *o_ptr, bool_ all)
{
u32b f1, f2, f3, f4, f5, esp;
@@ -566,23 +681,24 @@ bool_ alchemy(void) /* Turns an object into gold, gain some of its value in a sh
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);
+ 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 */
- o_ptr = get_object(item);
-
+ object_type *o_ptr = get_object(item);
/* See how many items */
if (o_ptr->number > 1)
@@ -604,12 +720,9 @@ bool_ alchemy(void) /* Turns an object into gold, gain some of its value in a sh
/* 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;
- }
+ /* Make a verification */
+ sprintf(out_val, "Really turn %s to gold? ", o_name);
+ if (!get_check(out_val)) return FALSE;
}
/* Artifacts cannot be destroyed */
@@ -654,7 +767,7 @@ bool_ alchemy(void) /* Turns an object into gold, gain some of its value in a sh
p_ptr->au += price;
/* Redraw gold */
- p_ptr->redraw |= (PR_GOLD);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
@@ -1089,7 +1202,7 @@ void self_knowledge(FILE *fff)
}
/* List powers */
- for (iter = 0; iter < power_max; iter++)
+ for (iter = 0; iter < POWER_MAX; iter++)
{
if (p_ptr->powers[iter])
{
@@ -1173,10 +1286,6 @@ void self_knowledge(FILE *fff)
{
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.";
@@ -1984,7 +2093,7 @@ bool_ detect_traps(int rad)
* item is used and return FALSE there are none,
* followed by current implementation --pelpel
*/
- p_ptr->redraw |= (PR_DTRAP);
+ p_ptr->redraw |= (PR_FRAME);
/* Result -- see my comment above -- pelpel */
/* return (detect); */
@@ -2178,107 +2287,125 @@ bool_ detect_treasure(int rad)
}
-
/*
- * Detect all "gold" objects on the current panel
+ * 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
*/
-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++)
+template<typename P, typename U> static bool detect_monsters_fn(int radius, P p, U u) {
+ bool flag = false;
+ /* Scan monsters */
+ for (int i = 1; i < m_max; i++)
{
- object_type *o_ptr = &o_list[i];
+ monster_type *m_ptr = &m_list[i];
- /* Skip dead objects */
- if (!o_ptr->k_idx) continue;
+ /* Skip dead monsters */
+ if (!m_ptr->r_idx)
+ {
+ continue;
+ }
- /* Skip held objects */
- if (o_ptr->held_m_idx)
+ /* Location */
+ int const y = m_ptr->fy;
+ int const x = m_ptr->fx;
+
+ /* Only detect nearby monsters */
+ if (m_ptr->cdis > radius)
{
- /* Access the monster */
- monster_type *m_ptr = &m_list[o_ptr->held_m_idx];
- monster_race *r_ptr = race_inf(m_ptr);
+ continue;
+ }
+ /* Detect monsters which fulfill the predicate */
+ auto r_ptr = m_ptr->race();
+ if (p(r_ptr.get()))
+ {
+ /* Update */
+ u(r_ptr.get());
- if (!(r_ptr->flags9 & RF9_MIMIC)) continue;
- else
+ /* We're assuming the update function does
+ * *something*, so we'll need to update
+ * the recall window if we're currently looking
+ * at it.
+ */
+ if (monster_race_idx == m_ptr->r_idx)
{
- /* Location */
- y = m_ptr->fy;
- x = m_ptr->fx;
+ p_ptr->window |= (PW_MONSTER);
}
- }
- 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;
+ /* Repair visibility later */
+ repair_monsters = TRUE;
- /* Detect "gold" objects */
- if (o_ptr->tval == TV_GOLD)
- {
- /* Hack -- memorize it */
- o_ptr->marked = 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 */
- detect = TRUE;
+ 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);
+ };
+ auto update = [](monster_race *) -> void {
+ };
/* Describe */
- if (detect && (!hack_no_detect_message))
+ if (detect_monsters_fn(rad, predicate, update))
{
- msg_print("You sense the presence of treasure!");
+ /* Describe result */
+ msg_print("You sense the presence of monsters!");
+ return TRUE;
}
-
- if (detect_monsters_string("$", rad))
+ else
{
- detect = TRUE;
+ return FALSE;
}
-
- /* Result */
- return (detect);
}
-/*
- * Detect all "normal" objects on the current panel
+/**
+ * Detect objects on the current panel.
*/
-bool_ detect_objects_normal(int rad)
+template <typename P> bool detect_objects_fn(int radius, const char *object_message, const char *monsters, P p)
{
- int i, y, x;
-
- bool_ detect = FALSE;
-
+ bool detect = false;
/* Scan objects */
- for (i = 1; i < o_max; i++)
+ 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];
- monster_race *r_ptr = race_inf(m_ptr);
+ auto const r_ptr = m_ptr->race();
- if (!(r_ptr->flags9 & RF9_MIMIC)) continue;
+ if (!(r_ptr->flags9 & RF9_MIMIC))
+ {
+ continue; /* Skip mimics completely */
+ }
else
{
/* Location */
@@ -2294,10 +2421,13 @@ bool_ detect_objects_normal(int rad)
}
/* Only detect nearby objects */
- if (distance(p_ptr->py, p_ptr->px, y, x) > rad) continue;
+ if (distance(p_ptr->py, p_ptr->px, y, x) > radius)
+ {
+ continue;
+ }
- /* Detect "real" objects */
- if (o_ptr->tval != TV_GOLD)
+ /* Detect objects that satisfy predicate */
+ if (p(o_ptr))
{
/* Hack -- memorize it */
o_ptr->marked = TRUE;
@@ -2311,101 +2441,54 @@ bool_ detect_objects_normal(int rad)
}
/* Describe */
- if (detect && (!hack_no_detect_message))
+ if (detect)
{
- msg_print("You sense the presence of objects!");
+ msg_print(object_message);
}
- if (detect_monsters_string("!=?|", rad))
+ if (detect_monsters_string(monsters, radius))
{
- detect = TRUE;
+ detect = true;
}
/* Result */
- return (detect);
+ 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.
+ * Detect all "gold" objects on the current panel
*/
-bool_ detect_objects_magic(int rad)
+bool detect_objects_gold(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;
+ auto predicate = [](object_type const *o_ptr) -> bool {
+ return o_ptr->tval == TV_GOLD;
+ };
- /* 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;
+ return detect_objects_fn(
+ rad,
+ "You sense the presence of treasure!",
+ "$",
+ predicate);
+}
- /* 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!");
- }
+/*
+ * 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 result */
- return (detect);
+ return detect_objects_fn(
+ rad,
+ object_message,
+ monsters,
+ predicate);
}
@@ -2414,57 +2497,23 @@ bool_ detect_objects_magic(int rad)
*/
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);
+ auto predicate = [](monster_race *r_ptr) -> bool {
+ return (!(r_ptr->flags2 & (RF2_INVISIBLE))) ||
+ p_ptr->see_inv || p_ptr->tim_invis;
+ };
+ auto update = [](monster_race *) -> void {
+ };
- /* Detect */
- flag = TRUE;
- }
- }
-
- /* Describe */
- if (flag)
+ if (detect_monsters_fn(rad, predicate, update))
{
/* Describe result */
msg_print("You sense the presence of monsters!");
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
}
-
- /* Result */
- return (flag);
}
@@ -2473,261 +2522,42 @@ bool_ detect_monsters_normal(int rad)
*/
bool_ detect_monsters_invis(int rad)
{
- int i, y, x;
- bool_ flag = FALSE;
+ auto predicate = [](monster_race *r_ptr) -> bool {
+ return (r_ptr->flags2 & (RF2_INVISIBLE));
+ };
+ auto update = [](monster_race *r_ptr) -> void {
+ r_ptr->r_flags2 |= (RF2_INVISIBLE);
+ };
- /* 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)
+ if (detect_monsters_fn(rad, predicate, update))
{
/* Describe result */
msg_print("You sense the presence of invisible creatures!");
+ return TRUE;
}
-
- /* 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)
+ else
{
- /* Describe result */
- msg_print("You sense the presence of evil creatures!");
+ return FALSE;
}
-
- /* 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);
+ auto predicate = [match_flag](monster_race *r_ptr) -> bool {
+ return (r_ptr->flags3 & match_flag);
+ };
+ auto update = [match_flag](monster_race *r_ptr) -> void {
+ r_ptr->r_flags3 |= (match_flag);
+ };
- /* Detect */
- flag = TRUE;
- }
- }
-
- /* Describe */
- if (flag)
+ if (detect_monsters_fn(rad, predicate, update))
{
+ cptr desc_monsters = "weird monsters";
switch (match_flag)
{
case RF3_DEMON:
@@ -2739,22 +2569,22 @@ bool_ detect_monsters_xxx(u32b match_flag, int rad)
case RF3_GOOD:
desc_monsters = "good";
break;
+ case RF3_ORC:
+ desc_monsters = "orcs";
+ break;
}
/* Describe result */
msg_format("You sense the presence of %s!", desc_monsters);
msg_print(NULL);
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
}
-
- /* Result */
- return (flag);
}
-/* Detect good monsters */
-bool_ detect_monsters_good(int rad)
-{
- return (detect_monsters_xxx(RF3_GOOD, rad));
-}
/*
@@ -2808,9 +2638,9 @@ void stair_creation(void)
delete_object(p_ptr->py, p_ptr->px);
/* Create a staircase */
- if (p_ptr->inside_arena || p_ptr->inside_quest)
+ if (p_ptr->inside_quest)
{
- /* arena or quest */
+ /* quest */
msg_print("There is no effect!");
}
else if (!dun_level)
@@ -2839,95 +2669,72 @@ void stair_creation(void)
/*
* 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);
+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"
*/
-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);
+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 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)
+object_filter_t const &item_tester_hook_artifactable()
{
- 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)));
+ 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;
}
@@ -3127,24 +2934,26 @@ 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;
+ object_filter_t object_filter = item_tester_hook_weapon();
/* Enchant armor if requested */
- if (num_ac) item_tester_hook = item_tester_hook_armour;
+ 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))) return (FALSE);
+ if (!get_item(&item, q, s, (USE_EQUIP | USE_INVEN | USE_FLOOR), object_filter)) return (FALSE);
/* Get the item */
- o_ptr = get_object(item);
+ object_type *o_ptr = get_object(item);
/* Description */
object_desc(o_name, o_ptr, FALSE, 0);
@@ -3191,231 +3000,6 @@ void curse_artifact(object_type * o_ptr)
}
-/*
- * 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)
{
@@ -3721,494 +3305,23 @@ void random_resistance (object_type * o_ptr, bool_ is_scroll, int specific)
}
}
-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)
+/*
+ * Make note of found artifacts.
+ */
+static void note_found_object(object_type *o_ptr)
{
- 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;
- }
- }
+ char note[150];
+ char item_name[80];
- else if (artifact_bias == BIAS_RANGER && !(o_ptr->tval == TV_BOW))
+ if (artifact_p(o_ptr) || o_ptr->name1)
{
- 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;
+ object_desc(item_name, o_ptr, FALSE, 0);
- 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;
- }
+ /* Build note and write */
+ sprintf(note, "Found The %s", item_name);
+ add_note(note, 'A');
}
}
@@ -4216,37 +3329,22 @@ void random_slay (object_type * o_ptr, bool_ is_scroll)
/*
- * 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);
+ 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 */
- o_ptr = get_object(item);
+ object_type *o_ptr = get_object(item);
/* Identify it fully */
object_aware(o_ptr);
@@ -4262,6 +3360,7 @@ bool_ ident_spell(void)
p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
/* Description */
+ char o_name[80];
object_desc(o_name, o_ptr, TRUE, 3);
/* Describe */
@@ -4281,19 +3380,11 @@ bool_ ident_spell(void)
o_name);
}
- /* If the item was an artifact, and if the auto-note is selected, write a message. */
- if (take_notes && auto_notes && (artifact_p(o_ptr) || o_ptr->name1))
- {
- char note[150];
- char item_name[80];
- object_desc(item_name, o_ptr, FALSE, 0);
+ /* Make note of found artifacts */
+ note_found_object(o_ptr);
- /* Build note and write */
- sprintf(note, "Found The %s", item_name);
- add_note(note, 'A');
- }
/* Process the appropriate hooks */
- process_hooks(HOOK_IDENTIFY, "(d,s)", item, "normal");
+ identify_hooks(item, o_ptr, IDENT_NORMAL);
/* Something happened */
return (TRUE);
@@ -4317,19 +3408,11 @@ bool_ ident_all(void)
object_aware(o_ptr);
object_known(o_ptr);
- /* If the item was an artifact, and if the auto-note is selected, write a message. */
- if (take_notes && auto_notes && (artifact_p(o_ptr) || o_ptr->name1))
- {
- char note[150];
- char item_name[80];
- object_desc(item_name, o_ptr, FALSE, 0);
+ /* Make note of found artifacts */
+ note_found_object(o_ptr);
- /* Build note and write */
- sprintf(note, "Found The %s", item_name);
- add_note(note, 'A');
- }
/* Process the appropriate hooks */
- process_hooks(HOOK_IDENTIFY, "(d,s)", -i, "normal");
+ identify_hooks(-i, o_ptr, IDENT_NORMAL);
}
/* Something happened */
@@ -4341,9 +3424,9 @@ bool_ ident_all(void)
/*
* Determine if an object is not fully identified
*/
-static bool_ item_tester_hook_no_mental(object_type *o_ptr)
+static bool item_tester_hook_no_mental(object_type const *o_ptr)
{
- return ((o_ptr->ident & (IDENT_MENTAL)) ? FALSE : TRUE);
+ return ((o_ptr->ident & (IDENT_MENTAL)) ? false : true);
}
/*
@@ -4352,20 +3435,19 @@ static bool_ item_tester_hook_no_mental(object_type *o_ptr)
*/
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);
+ 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 */
- o_ptr = get_object(item);
+ object_type *o_ptr = get_object(item);
/* Do the identification */
make_item_fully_identified(o_ptr);
@@ -4380,6 +3462,7 @@ bool_ identify_fully(void)
p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
/* Description */
+ char o_name[80];
object_desc(o_name, o_ptr, TRUE, 3);
/* Describe */
@@ -4399,23 +3482,14 @@ bool_ identify_fully(void)
o_name);
}
- /* If the item was an artifact, and if the auto-note is selected, write a message. */
- if (take_notes && auto_notes && (artifact_p(o_ptr) || o_ptr->name1))
- {
- char note[150];
- char item_name[80];
- object_desc(item_name, o_ptr, FALSE, 0);
-
- /* Build note and write */
- sprintf(note, "Found The %s", item_name);
- add_note(note, 'A');
- }
+ /* Make note of found artifacts */
+ note_found_object(o_ptr);
/* Describe it fully */
object_out_desc(o_ptr, NULL, FALSE, TRUE);
/* Process the appropriate hooks */
- process_hooks(HOOK_IDENTIFY, "(d,s)", item, "full");
+ identify_hooks(item, o_ptr, IDENT_FULL);
/* Success */
return (TRUE);
@@ -4427,27 +3501,19 @@ bool_ identify_fully(void)
/*
* Hook for "get_item()". Determine if something is rechargable.
*/
-bool_ item_tester_hook_recharge(object_type *o_ptr)
+object_filter_t const &item_tester_hook_recharge()
{
- 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);
+ using namespace object_filter;
+ static auto instance =
+ And(
+ // Must NOT have NO_RECHARGE flag.
+ Not(HasFlag4(TR4_NO_RECHARGE)),
+ // ... and must be a device.
+ Or(
+ TVal(TV_STAFF),
+ TVal(TV_WAND),
+ TVal(TV_ROD_MAIN)));
+ return instance;
}
@@ -4474,31 +3540,28 @@ bool_ item_tester_hook_recharge(object_type *o_ptr)
bool_ recharge(int power)
{
int recharge_strength, recharge_amount;
- int item, lev;
-
+ int 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);
+ 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 */
- o_ptr = get_object(item);
+ object_type *o_ptr = get_object(item);
/* Extract the flags */
+ u32b f1, f2, f3, f4, f5, esp;
object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
/* Extract the object "level" */
@@ -4596,7 +3659,7 @@ bool_ recharge(int power)
}
}
- /* Mark as recharged -- For alchemists */
+ /* Mark as recharged */
o_ptr->art_flags4 |= TR4_RECHARGED;
/* Inflict the penalties for failing a recharge. */
@@ -4801,47 +3864,6 @@ void project_meteor(int radius, int typ, int dam, u32b 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)
@@ -4850,14 +3872,6 @@ bool_ banish_evil(int dist)
}
-/*
- * Turn undead
- */
-bool_ turn_undead(void)
-{
- return (project_hack(GF_TURN_UNDEAD, p_ptr->lev));
-}
-
/*
* Dispel undead monsters
@@ -4891,22 +3905,6 @@ 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.
@@ -4922,7 +3920,6 @@ void aggravate_monsters(int who)
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;
@@ -4945,6 +3942,8 @@ void aggravate_monsters(int who)
/* 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)
{
@@ -4972,7 +3971,7 @@ void aggravate_monsters(int who)
/*
* Generic genocide race selection
*/
-bool_ get_genocide_race(cptr msg, char *typ)
+static bool get_genocide_race(cptr msg, char *typ)
{
int i, j;
cave_type *c_ptr;
@@ -4985,78 +3984,14 @@ bool_ get_genocide_race(cptr msg, char *typ)
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();
*typ = r_ptr->d_char;
- return TRUE;
+ 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);
+ return false;
}
@@ -5074,7 +4009,7 @@ bool_ genocide_aux(bool_ player_cast, char typ)
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;
@@ -5093,8 +4028,9 @@ bool_ genocide_aux(bool_ player_cast, char typ)
{
int wx, wy;
int attempts = 500;
+ char buf[256];
- monster_race_desc(r_name, m_ptr->r_idx, 0);
+ monster_race_desc(buf, m_ptr->r_idx, 0);
do
{
@@ -5104,7 +4040,7 @@ bool_ genocide_aux(bool_ player_cast, char typ)
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);
+ cmsg_format(TERM_L_BLUE, "The spell seems to produce an ... interesting effect on the %s.", buf);
}
return TRUE;
@@ -5126,7 +4062,7 @@ bool_ genocide_aux(bool_ player_cast, char typ)
Term_fresh();
/* Delay */
- Term_xtra(TERM_XTRA_DELAY, msec);
+ sleep_for(milliseconds(msec));
/* Take note */
result = TRUE;
@@ -5141,7 +4077,7 @@ bool_ genocide_aux(bool_ player_cast, char typ)
move_cursor_relative(p_ptr->py, p_ptr->px);
/* Redraw */
- p_ptr->redraw |= (PR_HP);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
@@ -5199,7 +4135,7 @@ bool_ mass_genocide(bool_ player_cast)
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;
@@ -5218,8 +4154,9 @@ bool_ mass_genocide(bool_ player_cast)
{
int wx, wy;
int attempts = 500;
+ char buf[256];
- monster_race_desc(r_name, m_ptr->r_idx, 0);
+ monster_race_desc(buf, m_ptr->r_idx, 0);
do
{
@@ -5229,7 +4166,7 @@ bool_ mass_genocide(bool_ player_cast)
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);
+ cmsg_format(TERM_L_BLUE, "The spell seems to produce an ... interesting effect on the %s.", buf);
}
return TRUE;
@@ -5251,7 +4188,7 @@ bool_ mass_genocide(bool_ player_cast)
Term_fresh();
/* Delay */
- Term_xtra(TERM_XTRA_DELAY, msec);
+ sleep_for(milliseconds(msec));
/* Note effect */
result = TRUE;
@@ -5266,7 +4203,7 @@ bool_ mass_genocide(bool_ player_cast)
move_cursor_relative(p_ptr->py, p_ptr->px);
/* Redraw */
- p_ptr->redraw |= (PR_HP);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_PLAYER);
@@ -5312,7 +4249,12 @@ void do_probe(int m_idx)
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));
+ {
+ std::ostringstream buf;
+ buf << " has " << m_ptr->exp
+ << " exp and needs " << monster_exp(m_ptr->level + 1) << ".";
+ msg_format("%^s%s", m_name, buf.str().c_str());
+ }
}
/* Learn all of the non-spell, non-treasure flags */
@@ -5366,89 +4308,6 @@ bool_ probing(void)
/*
- * 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).
@@ -5456,7 +4315,7 @@ void wipe(int y1, int x1, int r)
* 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)
+void destroy_area(int y1, int x1, int r)
{
int y, x, k, t;
@@ -5465,15 +4324,12 @@ void destroy_area(int y1, int x1, int r, bool_ full, bool_ bypass)
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))
+ if (p_ptr->inside_quest)
{
return;
}
@@ -5780,7 +4636,7 @@ void earthquake(int cy, int cx, int r)
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))
+ if (race_flags1_p(PR1_SEMI_WRAITH))
damage /= 4;
/* Take some damage */
@@ -5807,7 +4663,7 @@ void earthquake(int cy, int cx, int r)
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();
/* Most monsters cannot co-exist with rock */
if (!(r_ptr->flags2 & (RF2_KILL_WALL)) &&
@@ -5984,7 +4840,7 @@ void earthquake(int cy, int cx, int r)
p_ptr->update |= (PU_DISTANCE);
/* Update the health bar */
- p_ptr->redraw |= (PR_HEALTH);
+ p_ptr->redraw |= (PR_FRAME);
/* Redraw map */
p_ptr->redraw |= (PR_MAP);
@@ -6055,8 +4911,7 @@ static void cave_temp_room_lite(void)
int chance = 25;
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();
/* Update the monster */
update_mon(c_ptr->m_idx, FALSE);
@@ -6389,77 +5244,17 @@ bool_ fire_wall(int typ, int dir, int dam, int 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;
}
+ int tx, ty;
if ((dir == 5) && target_okay())
{
tx = target_col;
@@ -6470,7 +5265,8 @@ void teleport_swap(int dir)
tx = p_ptr->px + ddx[dir];
ty = p_ptr->py + ddy[dir];
}
- c_ptr = &cave[ty][tx];
+
+ cave_type *c_ptr = &cave[ty][tx];
if (!c_ptr->m_idx)
{
@@ -6478,8 +5274,8 @@ void teleport_swap(int dir)
}
else
{
- 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_RES_TELE)
{
@@ -6543,7 +5339,7 @@ void teleport_swap(int dir)
p_ptr->update |= (PU_DISTANCE);
/* Redraw trap detection status */
- p_ptr->redraw |= (PR_DTRAP);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_OVERHEAD);
@@ -6596,7 +5392,7 @@ void swap_position(int lty, int ltx)
p_ptr->update |= (PU_DISTANCE);
/* Redraw trap detection status */
- p_ptr->redraw |= (PR_DTRAP);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_OVERHEAD);
@@ -6645,7 +5441,7 @@ void swap_position(int lty, int ltx)
p_ptr->update |= (PU_DISTANCE);
/* Redraw trap detection status */
- p_ptr->redraw |= (PR_DTRAP);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_OVERHEAD);
@@ -6693,28 +5489,6 @@ bool_ fire_bolt(int typ, int dir, int dam)
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
@@ -6743,19 +5517,6 @@ bool_ fire_bolt_or_beam(int prob, int typ, int dir, int 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
@@ -6788,13 +5549,6 @@ bool_ wizard_lock(int dir)
}
-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;
@@ -6802,20 +5556,6 @@ bool_ disarm_trap(int dir)
}
-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;
@@ -6830,13 +5570,6 @@ bool_ sleep_monster(int dir)
}
-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;
@@ -6844,13 +5577,6 @@ bool_ confuse_monster(int dir, int plev)
}
-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;
@@ -6858,13 +5584,6 @@ bool_ poly_monster(int dir)
}
-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;
@@ -6872,13 +5591,6 @@ bool_ fear_monster(int dir, int plev)
}
-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;
@@ -6893,16 +5605,6 @@ bool_ teleport_monster(int dir)
}
-/*
- * 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;
@@ -6910,13 +5612,6 @@ bool_ trap_creation(void)
}
-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];
@@ -7012,6 +5707,72 @@ void call_chaos(void)
}
+static 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);
+ }
+ }
+}
+
+
/*
* Activate the evil Topi Ylinen curse
* rr9: Stop the nasty things when a Cyberdemon is summoned
@@ -7054,9 +5815,9 @@ case 13: case 14: case 15: case 19: case 20:
{
msg_print("You feel like a statue!");
if (p_ptr->free_act)
- set_paralyzed (p_ptr->paralyzed + randint(3));
+ set_paralyzed(randint(3));
else
- set_paralyzed (p_ptr->paralyzed + randint(13));
+ set_paralyzed(randint(13));
stop_ty = TRUE;
}
if (randint(6) != 1) break;
@@ -7146,9 +5907,9 @@ void activate_dg_curse(void)
{
msg_print("You feel like a statue!");
if (p_ptr->free_act)
- set_paralyzed (p_ptr->paralyzed + randint(3));
+ set_paralyzed(randint(3));
else
- set_paralyzed (p_ptr->paralyzed + randint(13));
+ set_paralyzed(randint(13));
stop_dg = TRUE;
}
if (randint(7) != 1) break;
@@ -7206,72 +5967,6 @@ case 27: case 28: case 29:
}
-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;
@@ -7283,7 +5978,7 @@ void summon_cyber(void)
}
}
-void summon_dragon_riders()
+static void summon_dragon_riders()
{
int i;
int max_dr = (dun_level / 50) + randint(6);
@@ -7295,230 +5990,6 @@ void summon_dragon_riders()
}
-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
@@ -7546,14 +6017,6 @@ 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
@@ -7565,15 +6028,6 @@ bool_ stun_monsters(int dam)
/*
- * Stasis monsters
- */
-bool_ stasis_monsters(int dam)
-{
- return (project_hack(GF_STASIS, dam));
-}
-
-
-/*
* Mindblast monsters
*/
bool_ mindblast_monsters(int dam)
@@ -7592,15 +6046,6 @@ bool_ banish_monsters(int dist)
/*
- * Turn evil
- */
-bool_ turn_evil(int dam)
-{
- return (project_hack(GF_TURN_EVIL, dam));
-}
-
-
-/*
* Turn everyone
*/
bool_ turn_monsters(int dam)
@@ -7609,28 +6054,12 @@ bool_ turn_monsters(int 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;
@@ -7689,7 +6118,7 @@ bool_ heal_insanity(int val)
p_ptr->csane_frac = 0;
}
- p_ptr->redraw |= PR_SANITY;
+ p_ptr->redraw |= (PR_FRAME);
p_ptr->window |= (PW_PLAYER);
if (val < 5)
@@ -7799,7 +6228,7 @@ bool_ passwall(int dir, bool_ safe)
p_ptr->update |= (PU_DISTANCE);
/* Redraw trap detection status */
- p_ptr->redraw |= (PR_DTRAP);
+ p_ptr->redraw |= (PR_FRAME);
/* Window stuff */
p_ptr->window |= (PW_OVERHEAD);
@@ -7813,20 +6242,21 @@ bool_ passwall(int dir, bool_ safe)
/*
* Print a batch of dungeons.
*/
-static void print_dungeon_batch(int *p, int start, int max, bool_ mode)
+static void print_dungeon_batch(std::vector<int> const &dungeon_idxs,
+ int start,
+ 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++)
+ for (i = 0, j = start; i < 20 && j < static_cast<int>(dungeon_idxs.size()); i++, j++)
{
- dungeon_info_type *d_ptr = &d_info[p[j]];
+ dungeon_info_type *d_ptr = &d_info[dungeon_idxs[j]];
- strnfmt(buf, 80, " %c) %-30s", I2A(i), d_name + d_ptr->name);
+ strnfmt(buf, 80, " %c) %-30s", I2A(i), d_ptr->name);
if (mode)
{
if (d_ptr->min_plev > p_ptr->lev)
@@ -7845,26 +6275,41 @@ static void print_dungeon_batch(int *p, int start, int max, bool_ mode)
prt(format("Select a dungeon (a-%c), * to list, @ to select by name, +/- to scroll:", I2A(i - 1)), 0, 0);
}
-int reset_recall_aux()
+static int find_dungeon_by_name(char const *name)
+{
+ /* Find the index corresponding to the name */
+ for (int i = 1; i < max_d_idx; i++)
+ {
+ /* Skip non-initialized entries. */
+ if (d_info[i].name == nullptr) {
+ continue;
+ }
+ if (iequals(name, d_info[i].name))
+ {
+ return i;
+ }
+ }
+ /* Not found */
+ return -1;
+}
+
+static int reset_recall_aux()
{
char which;
- int *p;
- int max = 0, i, start = 0;
+ int 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++)
+ // Dungeons available for recall
+ std::vector<int> dungeons;
+ for (size_t 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;
+ dungeons.push_back(i);
}
}
@@ -7873,7 +6318,7 @@ int reset_recall_aux()
while (1)
{
- print_dungeon_batch(p, start, max, mode);
+ print_dungeon_batch(dungeons, start, mode);
which = inkey();
if (which == ESCAPE)
@@ -7892,7 +6337,11 @@ int reset_recall_aux()
else if (which == '+')
{
start += 20;
- if (start >= max) start -= 20;
+ assert(start > 0);
+ if (static_cast<size_t>(start) >= dungeons.size())
+ {
+ start -= 20;
+ }
Term_load();
character_icky = FALSE;
}
@@ -7900,34 +6349,24 @@ int reset_recall_aux()
else if (which == '-')
{
start -= 20;
- if (start < 0) 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));
+ char buf[80];
+ strcpy(buf, d_info[p_ptr->recall_dungeon].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;
- }
- }
+ int i = find_dungeon_by_name(buf);
- if (i >= max_d_idx)
+ if (i < 0)
{
msg_print("Never heard of that place!");
msg_print(NULL);
@@ -7952,26 +6391,29 @@ int reset_recall_aux()
else
{
which = tolower(which);
- if (start + A2I(which) >= max)
+ int i = start + A2I(which);
+
+ if (i < 0)
{
bell();
continue;
}
- if (start + A2I(which) < 0)
+ else if (static_cast<size_t>(i) >= dungeons.size()) // Cast to avoid compilation warning
{
bell();
continue;
}
- ret = p[start + A2I(which)];
- break;
+ else
+ {
+ ret = dungeons[i];
+ break;
+ }
}
}
Term_load();
character_icky = FALSE;
- C_FREE(p, max_d_idx, int);
-
return ret;
}
@@ -7990,7 +6432,7 @@ bool_ reset_recall(bool_ no_trepas_max_depth)
else
max = max_dlv[dun];
depth = get_quantity(format("Which level in %s(%d-%d)? ",
- d_info[dun].name + d_name,
+ d_info[dun].name,
d_info[dun].mindepth, max),
max);
@@ -8008,26 +6450,6 @@ bool_ reset_recall(bool_ no_trepas_max_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
*/
@@ -8074,3 +6496,342 @@ void create_between_gate(int dist, int y, int x)
cave[ij][ii].special = p_ptr->px + (p_ptr->py << 8);
}
}
+
+/**
+ * Geomancy
+ */
+typedef struct geomancy_entry {
+ int skill;
+ int feat;
+ int min_skill_level;
+} geomancy_entry;
+
+static int choose_geomancy_feature(int n, geomancy_entry *table)
+{
+ int feat = -1;
+ /* choose feature */
+ while (feat < 0) {
+ geomancy_entry *t = &table[rand_int(n)];
+
+ /* Do we meet the requirements ?
+ And then select the features based on skill proportions */
+ if ((get_skill(t->skill) >= t->min_skill_level) && magik(get_skill_scale(t->skill, 100)))
+ {
+ feat = t->feat;
+ }
+ }
+ /* return */
+ return feat;
+}
+
+static int rotate_dir(int dir, int mov)
+{
+ if (mov > 0)
+ {
+ switch (dir) {
+ case 7: return 8;
+ case 8: return 9;
+ case 9: return 6;
+ case 6: return 3;
+ case 3: return 2;
+ case 2: return 1;
+ case 1: return 4;
+ case 4: return 7;
+ }
+ }
+ else if (mov < 0)
+ {
+ switch (dir) {
+ case 7: return 4;
+ case 4: return 1;
+ case 1: return 2;
+ case 2: return 3;
+ case 3: return 6;
+ case 6: return 9;
+ case 9: return 8;
+ case 8: return 7;
+ }
+ }
+
+ return dir;
+}
+
+void geomancy_random_wall(int y, int x)
+{
+#define TABLE_SIZE 4
+ cave_type *c_ptr = &cave[y][x];
+ int feat = -1;
+ geomancy_entry table[TABLE_SIZE] = {
+ /* Fire element */
+ { SKILL_FIRE, FEAT_SANDWALL, 1},
+ /* Water element */
+ { SKILL_WATER, FEAT_TREES, 1},
+ { SKILL_WATER, FEAT_ICE_WALL, 12},
+ /* Earth element */
+ { SKILL_EARTH, FEAT_WALL_EXTRA, 1}
+ };
+
+ /* Do not destroy permanent things */
+ if (f_info[c_ptr->feat].flags1 & FF1_PERMANENT) {
+ return;
+ }
+
+ /* Choose feature */
+ feat = choose_geomancy_feature(TABLE_SIZE, table);
+ if (feat >= 0)
+ {
+ cave_set_feat(y, x, feat);
+ }
+#undef TABLE_SIZE
+}
+
+void geomancy_random_floor(int y, int x, bool_ kill_wall)
+{
+#define TABLE_SIZE 9
+ cave_type *c_ptr = &cave[y][x];
+ int feat = -1;
+ geomancy_entry table[TABLE_SIZE] = {
+ /* Fire element */
+ { SKILL_FIRE, FEAT_SAND, 1},
+ { SKILL_FIRE, FEAT_SHAL_LAVA, 8},
+ { SKILL_FIRE, FEAT_DEEP_LAVA, 18},
+ /* Water element */
+ { SKILL_WATER, FEAT_SHAL_WATER, 1},
+ { SKILL_WATER, FEAT_DEEP_WATER, 8},
+ { SKILL_WATER, FEAT_ICE, 18},
+ /* Earth element */
+ { SKILL_EARTH, FEAT_GRASS, 1},
+ { SKILL_EARTH, FEAT_FLOWER, 8},
+ { SKILL_EARTH, FEAT_DARK_PIT, 18}
+ };
+
+ /* Do not destroy permanent things */
+ if (f_info[c_ptr->feat].flags1 & FF1_PERMANENT) {
+ return;
+ }
+ if (!(kill_wall || (f_info[c_ptr->feat].flags1 & FF1_FLOOR))) {
+ return;
+ }
+
+ /* Choose feature */
+ feat = choose_geomancy_feature(TABLE_SIZE, table);
+ if (feat >= 0)
+ {
+ cave_set_feat(y, x, feat);
+ }
+#undef TABLE_SIZE
+}
+
+static bool_ geomancy_can_tunnel(int y, int x)
+{
+ switch (cave[y][x].feat)
+ {
+ case FEAT_WALL_EXTRA:
+ case FEAT_WALL_OUTER:
+ case FEAT_WALL_INNER:
+ case FEAT_WALL_SOLID:
+ case FEAT_MAGMA:
+ case FEAT_QUARTZ:
+ case FEAT_MAGMA_H:
+ case FEAT_QUARTZ_H:
+ case FEAT_MAGMA_K:
+ case FEAT_QUARTZ_K:
+ case FEAT_TREES:
+ case FEAT_DEAD_TREE:
+ case FEAT_SANDWALL:
+ case FEAT_SANDWALL_H:
+ case FEAT_SANDWALL_K:
+ case FEAT_ICE_WALL:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+void geomancy_dig(int oy, int ox, int dir, int length)
+{
+ int dy = ddy[dir];
+ int dx = ddx[dir];
+ int y = dy + oy;
+ int x = dx + ox;
+ int i;
+
+ for (i=0; 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..bffc4a2c
--- /dev/null
+++ b/src/spells2.hpp
@@ -0,0 +1,115 @@
+#pragma once
+
+#include "h-basic.h"
+#include "identify_mode.hpp"
+#include "object_filter.hpp"
+#include "object_type_fwd.hpp"
+
+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_hooks(int i, object_type *o_ptr, identify_mode type);
+extern bool_ identify_pack(void);
+extern void identify_pack_fully(void);
+extern bool_ remove_curse(void);
+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 detect_objects_gold(int rad);
+extern bool detect_objects_normal(int rad);
+extern bool_ detect_monsters_normal(int rad);
+extern bool_ detect_monsters_invis(int rad);
+extern bool_ detect_monsters_xxx(u32b match_flag, 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 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 void destroy_area(int y1, int x1, int r);
+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_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 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_ wall_to_mud(int dir);
+extern bool_ disarm_trap(int dir);
+extern bool_ wizard_lock(int dir);
+extern bool_ slow_monster(int dir);
+extern bool_ sleep_monster(int dir);
+extern bool_ confuse_monster(int dir, int plev);
+extern bool_ fear_monster(int dir, int plev);
+extern bool_ poly_monster(int dir);
+extern bool_ teleport_monster(int dir);
+extern bool_ trap_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 summon_cyber(void);
+extern bool_ confuse_monsters(int dam);
+extern bool_ charm_monsters(int dam);
+extern bool_ charm_animals(int dam);
+extern bool_ stun_monsters(int dam);
+extern bool_ banish_monsters(int dist);
+extern bool_ turn_monsters(int dam);
+extern bool_ 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 object_filter_t const &item_tester_hook_recharge();
+extern bool_ project_hack(int typ, int dam);
+extern void project_meteor(int radius, int typ, int dam, u32b flg);
+extern object_filter_t const &item_tester_hook_artifactable();
+extern bool_ passwall(int dir, bool_ safe);
+extern bool_ project_hook(int typ, int dir, int dam, int flg);
+extern bool_ reset_recall(bool_ no_trepas_max_depth);
+extern void geomancy_random_wall(int y, int x);
+extern void geomancy_random_floor(int y, int x, bool_ kill_wall);
+extern void geomancy_dig(int oy, int ox, int dir, int length);
+extern void channel_the_elements(int y, int x, int level);
+extern void random_resistance (object_type * o_ptr, bool_ is_scroll, int specific);
diff --git a/src/spells3.cc b/src/spells3.cc
new file mode 100644
index 00000000..35604f7d
--- /dev/null
+++ b/src/spells3.cc
@@ -0,0 +1,4606 @@
+#include "spells3.hpp"
+
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "cmd5.hpp"
+#include "feature_type.hpp"
+#include "lua_bind.hpp"
+#include "mimic.hpp"
+#include "monster2.hpp"
+#include "monster3.hpp"
+#include "monster_race.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 DISARM;
+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 s32b get_level_s(int sp, int max)
+{
+ return get_level(sp, max, 1);
+}
+
+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_disarm()
+{
+ casting_result result = NO_CAST;
+
+ result = cplus(result, destroy_doors_touch());
+ if (get_level_s(DISARM, 50) >= 10)
+ {
+ result = cplus(result, destroy_traps_touch());
+ }
+
+ return result;
+}
+
+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, 0),
+ y1, x1,
+ 20 + get_level_s(DEMON_MADNESS, 200),
+ type,
+ PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL));
+ result = cplus(result,
+ project(0, 1 + get_level(DEMON_MADNESS, 4, 0),
+ y2, x2,
+ 20 + get_level_s(DEMON_MADNESS, 200),
+ type,
+ PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL));
+
+ return 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, 0)));
+ 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, 0)))
+ {
+ char buf[128];
+ monster_desc(buf, m_ptr, 0);
+ if (buf[0] != '\0')
+ {
+ buf[0] = toupper(buf[0]);
+ }
+
+ msg_format("%s turns against you.", buf);
+ }
+ else
+ {
+ char buf[128];
+ s32b heal;
+
+ monster_desc(buf, m_ptr, 0);
+ msg_format("You consume %s.", buf);
+
+ heal = (m_ptr->hp * 100) / m_ptr->maxhp;
+ heal = ((30 + get_level(UNHOLY_WORD, 50, 0)) * heal) / 100;
+
+ hp_player(heal);
+
+ delete_monster_idx(c_ptr->m_idx);
+ }
+
+ return CAST_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, 0)));
+ return buf;
+}
+
+casting_result demonology_demon_cloak()
+{
+ return cast(set_tim_reflect(randint(5) + 5 + get_level(DEMON_CLOAK, 15, 0)));
+}
+
+const char *demonology_demon_cloak_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "dur " FMTs32b "+d5",
+ (5 + get_level(DEMON_CLOAK, 15, 0)));
+ 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, 0))) / 100;
+ if (dam > 100 + get_level(DISCHARGE_MINION, 500, 0))
+ {
+ dam = 100 + get_level(DISCHARGE_MINION, 500, 0);
+ }
+
+ /* We use project instead of fire_ball because we must tell it exactly where to land */
+ 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, 0)),
+ (100 + get_level(DISCHARGE_MINION, 500, 0)));
+ 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()
+{
+ if (get_check("Cast on yourself?"))
+ {
+ self_knowledge(NULL);
+ }
+ else
+ {
+ identify_fully();
+ }
+ return CAST_OBVIOUS;
+}
+
+casting_result divination_identify()
+{
+ if (get_level_s(IDENTIFY, 50) >= 27)
+ {
+ casting_result result = NO_CAST;
+ result = cplus(result, identify_pack());
+ result = cplus(result, fire_ball(GF_IDENTIFY, 0, 1, get_level_s(IDENTIFY, 3)));
+ return result;
+ }
+ else if (get_level_s(IDENTIFY, 50) >= 17)
+ {
+ casting_result result = NO_CAST;
+ result = cplus(result, identify_pack());
+ result = cplus(result, fire_ball(GF_IDENTIFY, 0, 1, 0));
+ return result;
+ }
+ else if (ident_spell())
+ {
+ 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, detect_traps(15 + get_level(SENSEHIDDEN, 40, 0)));
+ if (get_level_s(SENSEHIDDEN, 50) >= 15)
+ {
+ 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, 0)));
+ result = cplus(result, detect_stairs(10 + get_level(REVEALWAYS, 40, 0)));
+ 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, 0)));
+ 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, 0)));
+}
+
+const char *eru_lay_of_protection_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "rad " FMTs32b,
+ (1 + get_level(ERU_PROT, 2, 0)));
+ 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, 0));
+
+ 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, 0)));
+ 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, 0));
+ 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->flags1 & RF1_UNIQUE) == 0))
+ {
+ p_ptr->control = target_who;
+ m_ptr->mflag |= MFLAG_CONTROL;
+ strcat(buf, " falls under your control.");
+ }
+ else
+ {
+ strcat(buf, " resists.");
+ }
+
+ msg_print(buf);
+ return CAST_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()
+{
+ if (p_ptr->spellbinder_num != 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;
+ int i;
+
+ assert(p_ptr->spellbinder_trigger >= 0);
+
+ for (trigger_idx = 0; triggers[trigger_idx].idx >= 0; trigger_idx++)
+ {
+ if (triggers[trigger_idx].idx == p_ptr->spellbinder_trigger)
+ {
+ break;
+ }
+ }
+
+ msg_print("The spellbinder is already active.");
+ msg_format("It will trigger at %s.", triggers[trigger_idx].desc);
+ msg_print("With the spells: ");
+ for (i = 0; i < p_ptr->spellbinder_num; i++)
+ {
+ msg_print(spell_type_name(spell_at(p_ptr->spellbinder[i])));
+ }
+
+ /* Doesn't cost anything */
+ return NO_CAST;
+ }
+ else
+ {
+ char c;
+ int i;
+
+ if (!get_com("Trigger at [a]75% hp [b]50% hp [c]25% hp?", &c))
+ {
+ return NO_CAST;
+ }
+
+ switch (c)
+ {
+ case 'a':
+ p_ptr->spellbinder_trigger = SPELLBINDER_HP75;
+ break;
+ case 'b':
+ p_ptr->spellbinder_trigger = SPELLBINDER_HP50;
+ break;
+ case 'c':
+ p_ptr->spellbinder_trigger = SPELLBINDER_HP25;
+ break;
+ default:
+ return NO_CAST;
+
+ }
+
+ p_ptr->spellbinder_num = get_spellbinder_max();
+ i = p_ptr->spellbinder_num;
+ while (i > 0)
+ {
+ s32b s = get_school_spell("bind", 0);
+ if (s == -1)
+ {
+ p_ptr->spellbinder_trigger = 0;
+ p_ptr->spellbinder_num = 0;
+ 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;
+ }
+ }
+
+ p_ptr->spellbinder[i] = s;
+ i = i - 1;
+ }
+
+ 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->enabled = FALSE;
+ 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->enabled = TRUE;
+ TIMER_INERTIA_CONTROL->delay = delay;
+ TIMER_INERTIA_CONTROL->countdown = delay;
+ 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()
+{
+ if (get_level_s(MAGELOCK, 50) >= 30)
+ {
+ int x,y;
+
+ if (get_level_s(MAGELOCK, 50) >= 40)
+ {
+ cave_type *c_ptr = NULL;
+
+ if (!tgt_pt(&x, &y))
+ {
+ return NO_CAST;
+ }
+
+ c_ptr = &cave[y][x];
+
+ if ((!(f_info[c_ptr->feat].flags1 | FF1_FLOOR)) ||
+ (f_info[c_ptr->feat].flags1 | FF1_PERMANENT) ||
+ (!los(p_ptr->py, p_ptr->px, y, x)))
+ {
+ msg_print("You cannot place it there.");
+ return NO_CAST;
+ }
+ } else {
+ y = p_ptr->py;
+ x = p_ptr->px;
+ }
+ cave_set_feat(y, x, 3);
+ return CAST_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()
+{
+ /* 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:
+ {
+ object_kind *k_ptr = &k_info[o_ptr->k_idx];
+
+ /* Generate mana */
+ increase_mana(o_ptr->pval * k_ptr->level * o_ptr->number);
+
+ /* Destroy it */
+ inc_stack_size(item, -99);
+
+ break;
+ }
+
+ case TV_ROD_MAIN:
+ {
+ /* Generate mana */
+ increase_mana(o_ptr->timeout);
+
+ /* Drain it */
+ o_ptr->timeout = 0;
+
+ /* Combine / Reorder the pack (later) */
+ p_ptr->notice |= PN_COMBINE | PN_REORDER;
+ p_ptr->window |= PW_INVEN | PW_EQUIP | PW_PLAYER;
+ break;
+ }
+
+ default:
+ assert(FALSE);
+ }
+
+ return CAST_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, 0);
+}
+
+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, 0);
+}
+
+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);
+ if (get_level_s(MUSIC_MIND, 50) >= 10)
+ {
+ fire_ball(GF_IDENTIFY, 0, 1, 1 + get_level(MUSIC_MIND, 3, 0));
+ }
+ return get_mana(MUSIC_MIND);
+}
+
+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, 0));
+ return buf;
+ }
+ else
+ {
+ return "";
+ }
+}
+
+casting_result music_blow_spell()
+{
+ fire_ball(GF_SOUND,
+ 0,
+ damroll(2 + get_level(MUSIC_BLOW, 10, 0), 4 + get_level(MUSIC_BLOW, 40, 0)),
+ 1 + get_level(MUSIC_BLOW, 12, 0));
+ return CAST_OBVIOUS;
+}
+
+const char *music_blow_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "dam " FMTs32b "d" FMTs32b " rad " FMTs32b,
+ 2 + get_level(MUSIC_BLOW, 10, 0),
+ 4 + get_level(MUSIC_BLOW, 40, 0),
+ 1 + get_level(MUSIC_BLOW, 12, 0));
+ return buf;
+}
+
+casting_result music_gush_of_wind_spell()
+{
+ fire_ball(GF_AWAY_ALL,
+ 0,
+ 10 + get_level(MUSIC_BLOW, 40, 0),
+ 1 + get_level(MUSIC_BLOW, 12, 0));
+ return CAST_OBVIOUS;
+}
+
+const char *music_gush_of_wind_info()
+{
+ static char buf[128];
+ sprintf(buf,
+ "dist " FMTs32b " rad " FMTs32b,
+ 10 + get_level(MUSIC_BLOW, 40, 0),
+ 1 + get_level(MUSIC_BLOW, 12, 0));
+ return buf;
+}
+
+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, 0));
+ 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, 0);
+}
+
+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, 0);
+}
+
+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();
+ self_knowledge(NULL);
+ }
+
+ 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..3380203a
--- /dev/null
+++ b/src/spells3.hpp
@@ -0,0 +1,445 @@
+#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_disarm();
+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..62586758
--- /dev/null
+++ b/src/spells4.cc
@@ -0,0 +1,541 @@
+#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, DISARM);
+ 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. */
+ if (flush_failure)
+ {
+ flush();
+ }
+
+ 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..f503c822
--- /dev/null
+++ b/src/spells5.cc
@@ -0,0 +1,2395 @@
+#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(&DISARM, "Disarm");
+ spell_type_describe(spell, "Destroys doors and traps");
+ spell_type_describe(spell, "At level 10 it destroys doors and traps, then reveals and unlocks any secret");
+ spell_type_describe(spell, "doors");
+ spell_type_set_mana(spell, 2, 4);
+ spell_type_set_difficulty(spell, 3, 15);
+ spell_type_init_mage(spell,
+ RANDOM,
+ SCHOOL_CONVEYANCE,
+ no_info,
+ convey_disarm);
+
+ spell_type_set_device_charges(spell, "10+d15");
+
+ {
+ device_allocation *device_allocation = device_allocation_new(TV_STAFF);
+ device_allocation->rarity = 4;
+ range_init(&device_allocation->base_level, 1, 10);
+ range_init(&device_allocation->max_level, 10, 50);
+ spell_type_add_device_allocation(spell, device_allocation);
+ }
+ }
+
+ {
+ 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, as well as probing monsters in that radius");
+ spell_type_set_mana(spell, 10, 50);
+ spell_type_set_difficulty(spell, 8, 40);
+ spell_type_init_mage(spell,
+ RANDOM,
+ SCHOOL_DIVINATION,
+ divination_identify_info,
+ divination_identify);
+
+ spell_type_set_device_charges(spell, "7+d10");
+
+ {
+ device_allocation *device_allocation = device_allocation_new(TV_STAFF);
+ device_allocation->rarity = 45;
+ range_init(&device_allocation->base_level, 1, 15);
+ range_init(&device_allocation->max_level, 15, 40);
+ 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, "as well as probing monsters in that radius.");
+ spell_type_describe(spell, "Consumes the amount of mana each turn.");
+ spell_type_set_mana(spell, 15, 30);
+ spell_type_set_difficulty(spell, 25, 75);
+ spell_type_init_music_lasting(
+ spell,
+ 4,
+ music_clairaudience_info,
+ music_clairaudience_spell,
+ music_clairaudience_lasting);
+ }
+
+ {
+ spell_type *spell = spell_new(&MUSIC_BLOW, "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..a4564ae3
--- /dev/null
+++ b/src/spells6.cc
@@ -0,0 +1,402 @@
+#include "spells6.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)
+{
+ 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)
+{
+ 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..c3c52b1b
--- /dev/null
+++ b/src/squelch/automatizer.cc
@@ -0,0 +1,278 @@
+#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(json_t *rules_j)
+{
+ std::vector< std::shared_ptr < Rule > > rules;
+
+ if (!json_is_array(rules_j))
+ {
+ msg_format("Error 'rules' is not an array");
+ return rules;
+ }
+
+ for (size_t i = 0; i < json_array_size(rules_j); i++)
+ {
+ json_t *rule_j = json_array_get(rules_j, i);
+ auto rule = Rule::parse_rule(rule_j);
+ if (rule)
+ {
+ rules.push_back(rule);
+ }
+ }
+
+ return rules;
+}
+
+//----------------------------------------------------------
+// Automatizer
+//----------------------------------------------------------
+
+int Automatizer::append_rule(std::shared_ptr< Rule > rule)
+{
+ m_rules.push_back(rule);
+ return m_rules.size() - 1;
+}
+
+void Automatizer::swap_rules(int i, int j)
+{
+ swap(m_rules.at(i), m_rules.at(j));
+}
+
+bool Automatizer::apply_rules(object_type *o_ptr, int item_idx) const
+{
+ for (auto rule : m_rules)
+ {
+ if (rule->apply_rule(o_ptr, item_idx))
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+std::shared_ptr<json_t> Automatizer::to_json() const
+{
+ auto rules_json = std::shared_ptr<json_t>(json_array(), &json_decref);
+
+ for (auto rule : m_rules)
+ {
+ json_array_append_new(rules_json.get(), rule->to_json());
+ }
+
+ return rules_json;
+}
+
+void Automatizer::load_json(json_t *json)
+{
+ // Go through all the found rules
+ auto rules = parse_rules(json);
+
+ // Load rule
+ for (auto rule : rules)
+ {
+ append_rule(rule);
+ }
+}
+
+int Automatizer::remove_current_selection()
+{
+ assert(!m_rules.empty());
+
+ // Previously selected rule
+ int prev_selected_rule = m_selected_rule;
+ int new_selected_rule;
+
+ // If the cursor is at the top level then we want to delete
+ // the rule itself
+ if (m_cursor->size() < 1)
+ {
+ // Remove rule
+ m_rules.erase(m_rules.begin() + m_selected_rule);
+ // Select previous
+ new_selected_rule = prev_selected_rule - 1;
+ }
+ else
+ {
+ // Delete the currently selected condition in rule.
+ m_rules.at(m_selected_rule)->delete_selected_condition(m_cursor.get());
+ // Keep selection
+ new_selected_rule = m_selected_rule;
+ }
+
+ // Do we need to adjust to select a different rule?
+ if ((prev_selected_rule != new_selected_rule) && (new_selected_rule >= 0))
+ {
+ select_rule(new_selected_rule);
+ }
+
+ // Return the selected rule.
+ return m_selected_rule;
+}
+
+void Automatizer::reset_view()
+{
+ // Clear cursor
+ m_cursor->clear();
+
+ // Empty rules?
+ if (m_rules.empty())
+ {
+ return;
+ }
+
+ // Reset scroll position
+ m_tree_printer->reset_scroll();
+
+ // Put the top-level condition into cursor
+ auto condition = m_rules.at(m_selected_rule)->get_condition();
+ if (condition)
+ {
+ m_cursor->push(condition.get());
+ }
+}
+
+void Automatizer::show_current() const
+{
+ if (m_rules.empty())
+ {
+ return;
+ }
+
+ m_tree_printer->reset();
+ m_rules.at(m_selected_rule)->write_tree(
+ m_tree_printer.get(),
+ m_cursor.get());
+}
+
+void Automatizer::scroll_up()
+{
+ m_tree_printer->scroll_up();
+}
+
+void Automatizer::scroll_down()
+{
+ m_tree_printer->scroll_down();
+}
+
+void Automatizer::scroll_left()
+{
+ m_tree_printer->scroll_left();
+}
+
+void Automatizer::scroll_right()
+{
+ m_tree_printer->scroll_right();
+}
+
+void Automatizer::move_up()
+{
+ m_cursor->move_up();
+}
+
+void Automatizer::move_down()
+{
+ m_cursor->move_down();
+}
+
+void Automatizer::move_left()
+{
+ m_cursor->move_left();
+}
+
+void Automatizer::move_right()
+{
+ m_cursor->move_right();
+}
+
+void Automatizer::add_new_condition(std::function<std::shared_ptr<Condition> ()> factory)
+{
+ m_rules.at(m_selected_rule)->add_new_condition(
+ m_cursor.get(),
+ factory);
+}
+
+void Automatizer::get_rule_names(std::vector<const char *> *names) const
+{
+ names->resize(m_rules.size());
+ for (size_t i = 0; i < m_rules.size(); i++)
+ {
+ (*names)[i] = m_rules.at(i)->get_name();
+ }
+}
+
+int Automatizer::rules_count() const
+{
+ return m_rules.size();
+}
+
+int Automatizer::rules_begin() const
+{
+ return m_begin;
+}
+
+void Automatizer::select_rule(int selected_rule)
+{
+ m_selected_rule = selected_rule;
+
+ int wid, hgt;
+ Term_get_size(&wid, &hgt);
+
+ // Adjust selection to conform to bounds.
+ {
+ 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..c3b8c3f5
--- /dev/null
+++ b/src/squelch/condition.cc
@@ -0,0 +1,1078 @@
+#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 "../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 "../quark.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;
+}
+
+json_t *Condition::to_json() const
+{
+ json_t *j = json_object();
+ json_object_set_new(j, "type",
+ json_string(match_mapping().stringify(match)));
+ to_json(j);
+ return j;
+}
+
+void Condition::display(TreePrinter *tree_printer, Cursor *cursor) const
+{
+ assert(tree_printer);
+
+ // Use normal or "selected" colours?
+ uint8_t bcol = TERM_L_GREEN;
+ uint8_t ecol = TERM_GREEN;
+ if (cursor->is_selected(this))
+ {
+ bcol = TERM_VIOLET;
+ ecol = TERM_VIOLET;
+ }
+
+ // Indent a level and display tree.
+ tree_printer->indent();
+ write_tree(tree_printer, cursor, ecol, bcol);
+ tree_printer->dedent();
+}
+
+std::shared_ptr<Condition> Condition::parse_condition(json_t *condition_json)
+{
+ // Parsers for concrete types of conditions.
+ static std::map< match_type,
+ std::function< std::shared_ptr< Condition > ( json_t * ) > > parsers {
+ { match_type::AND, &AndCondition::from_json },
+ { match_type::OR, &OrCondition::from_json },
+ { match_type::NOT, &NotCondition::from_json },
+ { match_type::INVENTORY, &InventoryCondition::from_json },
+ { match_type::EQUIPMENT, &EquipmentCondition::from_json },
+ { match_type::NAME, &NameCondition::from_json },
+ { match_type::CONTAIN, &ContainCondition::from_json },
+ { match_type::SYMBOL, &SymbolCondition::from_json },
+ { match_type::INSCRIBED, &InscriptionCondition::from_json },
+ { match_type::DISCOUNT, &DiscountCondition::from_json },
+ { match_type::TVAL, &TvalCondition::from_json },
+ { match_type::SVAL, &SvalCondition::from_json },
+ { match_type::STATUS, &StatusCondition::from_json },
+ { match_type::STATE, &StateCondition::from_json },
+ { match_type::RACE, &RaceCondition::from_json },
+ { match_type::SUBRACE, &SubraceCondition::from_json },
+ { match_type::CLASS, &ClassCondition::from_json },
+ { match_type::LEVEL, &LevelCondition::from_json },
+ { match_type::SKILL, &SkillCondition::from_json },
+ { match_type::ABILITY, &AbilityCondition::from_json } };
+
+ if ((condition_json == nullptr) || json_is_null(condition_json))
+ {
+ return nullptr;
+ }
+
+ cptr type_s = nullptr;
+ if (json_unpack(condition_json,
+ "{s:s}",
+ "type", &type_s) < 0)
+ {
+ msg_print("Missing/invalid 'type' in condition");
+ return nullptr;
+ }
+
+ match_type match;
+ if (!match_mapping().parse(type_s, &match))
+ {
+ msg_format("Invalid 'type' in condition: %s", type_s);
+ return nullptr;
+ }
+
+ // Look up parser and... parse
+ auto parser_i = parsers.find(match);
+ if (parser_i != parsers.end())
+ {
+ return parser_i->second(condition_json);
+ }
+
+ assert(false && "Missing parser");
+ return nullptr;
+}
+
+json_t *Condition::optional_to_json(std::shared_ptr<Condition> condition)
+{
+ return condition
+ ? condition->to_json()
+ : json_null();
+}
+
+bool TvalCondition::is_match(object_type *o_ptr) const
+{
+ return (o_ptr->tval == m_tval);
+}
+
+std::shared_ptr<Condition> TvalCondition::from_json(json_t *j)
+{
+ int tval;
+
+ if (json_unpack(j, "{s:i}", "tval", &tval) < 0)
+ {
+ msg_print("Missing/invalid 'tval' property");
+ return nullptr;
+ }
+
+ return std::make_shared<TvalCondition>(tval);
+}
+
+void TvalCondition::to_json(json_t *j) const
+{
+ json_object_set_new(j, "tval", json_integer(m_tval));
+}
+
+void TvalCondition::write_tree(TreePrinter *p, Cursor *, uint8_t ecol, uint8_t bcol) const
+{
+ p->write(ecol, "Its ");
+ p->write(bcol, "tval");
+ p->write(ecol, " is ");
+ p->write(ecol, "\"");
+ p->write(TERM_WHITE, format("%d", (int) m_tval));
+ p->write(ecol, "\"");
+ p->write(TERM_WHITE, "\n");
+}
+
+bool NameCondition::is_match(object_type *o_ptr) const
+{
+ char buf1[128];
+ object_desc(buf1, o_ptr, -1, 0);
+
+ return boost::algorithm::iequals(m_name, buf1);
+}
+
+std::shared_ptr<Condition> NameCondition::from_json(json_t *j)
+{
+ cptr s = nullptr;
+ if (json_unpack(j, "{s:s}", "name", &s) < 0)
+ {
+ msg_print("Missing/invalid 'name' property");
+ return nullptr;
+ }
+ return std::make_shared<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(json_t *j) const
+{
+ json_object_set_new(j, "name", json_string(m_name.c_str()));
+}
+
+bool ContainCondition::is_match(object_type *o_ptr) const
+{
+ char buf1[128];
+ object_desc(buf1, o_ptr, -1, 0);
+ return boost::algorithm::icontains(buf1, m_contain);
+}
+
+std::shared_ptr<Condition> ContainCondition::from_json(json_t *j)
+{
+ cptr s = nullptr;
+ if (json_unpack(j, "{s:s}", "contain", &s) < 0)
+ {
+ msg_print("Missing/invalid 'contain' property");
+ return nullptr;
+ }
+ return std::make_shared<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(json_t *j) const
+{
+ json_object_set_new(j, "contain", json_string(m_contain.c_str()));
+}
+
+bool SvalCondition::is_match(object_type *o_ptr) const
+{
+ return (object_aware_p(o_ptr) &&
+ (o_ptr->sval >= m_min) &&
+ (o_ptr->sval <= m_max));
+}
+
+std::shared_ptr<Condition> SvalCondition::from_json(json_t *j)
+{
+ int min, max;
+
+ if (json_unpack(j, "{s:i,s:i}",
+ "min", &min,
+ "max", &max) < 0)
+ {
+ msg_print("Missing/invalid 'min'/'max' properties");
+ return nullptr;
+ }
+
+ return std::make_shared<SvalCondition>(min, max);
+}
+
+void SvalCondition::write_tree(TreePrinter *p, Cursor *, uint8_t ecol, uint8_t bcol) const
+{
+ p->write(ecol, "Its ");
+ p->write(bcol, "sval");
+ p->write(ecol, " is from ");
+ p->write(TERM_WHITE, format("%d", m_min));
+ p->write(ecol, " to ");
+ p->write(TERM_WHITE, format("%d", m_max));
+ p->write(TERM_WHITE, "\n");
+}
+
+void SvalCondition::to_json(json_t *j) const
+{
+ json_object_set_new(j, "min", json_integer(m_min));
+ json_object_set_new(j, "max", json_integer(m_max));
+}
+
+void GroupingCondition::add_child(ConditionFactory const &factory)
+{
+ auto c_ptr = factory();
+ if (c_ptr)
+ {
+ m_conditions.push_back(c_ptr);
+ }
+}
+
+void GroupingCondition::remove_child(Condition *condition)
+{
+ 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(json_t *j)
+{
+ json_t *conditions_j = json_object_get(j, "conditions");
+
+ if ((conditions_j == nullptr) ||
+ (json_is_null(conditions_j)))
+ {
+ return std::vector< std::shared_ptr<Condition> >();
+ }
+ else if (!json_is_array(conditions_j))
+ {
+ msg_print("'conditions' property has invalid type");
+ return std::vector< std::shared_ptr<Condition> >();
+ }
+ else
+ {
+ std::vector< std::shared_ptr<Condition> > subconditions;
+ for (size_t i = 0; i < json_array_size(conditions_j); i++)
+ {
+ json_t *subcondition_j =
+ json_array_get(conditions_j, i);
+
+ std::shared_ptr<Condition> subcondition =
+ parse_condition(subcondition_j);
+
+ if (subcondition != nullptr)
+ {
+ subconditions.push_back(subcondition);
+ }
+ }
+ return subconditions;
+ }
+}
+
+void GroupingCondition::to_json(json_t *j) const
+{
+ json_t *ja = json_array();
+ for (auto condition_p : m_conditions)
+ {
+ json_array_append_new(ja, optional_to_json(condition_p));
+ }
+ json_object_set_new(j, "conditions", ja);
+}
+
+bool AndCondition::is_match(object_type *o_ptr) const
+{
+ for (auto condition_p : m_conditions)
+ {
+ if (!condition_p->is_match(o_ptr))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+std::shared_ptr<Condition> AndCondition::from_json(json_t *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(json_t *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(json_t *j)
+{
+ cptr s;
+ if (json_unpack(j, "{s:s}", "status", &s) < 0)
+ {
+ msg_print("Missing/invalid 'status' property");
+ return nullptr;
+ }
+
+ status_type status;
+ if (!status_mapping().parse(s, &status))
+ {
+ msg_format("Invalid 'status' property: %s", s);
+ return nullptr;
+ }
+
+ return std::make_shared<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(json_t *j) const
+{
+ json_object_set_new(j, "status", json_string(status_mapping().stringify(m_status)));
+}
+
+bool RaceCondition::is_match(object_type *o_ptr) const
+{
+ return boost::algorithm::iequals(m_race, rp_ptr->title);
+}
+
+std::shared_ptr<Condition> RaceCondition::from_json(json_t *j)
+{
+ cptr s;
+
+ if (json_unpack(j, "{s:s}", "race", &s) < 0)
+ {
+ msg_print("Missing/invalid 'race' property");
+ return nullptr;
+ }
+
+ return std::make_shared<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(json_t *j) const
+{
+ json_object_set_new(j, "race", json_string(m_race.c_str()));
+}
+
+bool SubraceCondition::is_match(object_type *o_ptr) const
+{
+ return boost::algorithm::iequals(m_subrace, rmp_ptr->title);
+}
+
+std::shared_ptr<Condition> SubraceCondition::from_json(json_t *j)
+{
+ cptr s;
+
+ if (json_unpack(j, "{s:s}", "subrace", &s) < 0)
+ {
+ msg_print("Missing/invalid 'subrace' property");
+ return nullptr;
+ }
+
+ return std::make_shared<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(json_t *j) const
+{
+ json_object_set_new(j, "subrace", json_string(m_subrace.c_str()));
+}
+
+bool ClassCondition::is_match(object_type *o_ptr) const
+{
+ return boost::algorithm::iequals(m_class, spp_ptr->title);
+}
+
+std::shared_ptr<Condition> ClassCondition::from_json(json_t *j)
+{
+ cptr s;
+
+ if (json_unpack(j, "{s:s}", "class", &s) < 0)
+ {
+ msg_print("Missing/invalid 'class' property");
+ return nullptr;
+ }
+
+ return std::make_shared<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(json_t *j) const
+{
+ json_object_set_new(j, "class", json_string(m_class.c_str()));
+}
+
+bool InscriptionCondition::is_match(object_type *o_ptr) const
+{
+ if (o_ptr->note == 0)
+ {
+ return false;
+ }
+ return boost::algorithm::icontains(
+ quark_str(o_ptr->note),
+ m_inscription);
+}
+
+std::shared_ptr<Condition> InscriptionCondition::from_json(json_t *j)
+{
+ cptr s = nullptr;
+ if (json_unpack(j, "{s:s}", "inscription", &s) < 0)
+ {
+ msg_print("Missing/invalid 'inscription' property");
+ return nullptr;
+ }
+ return std::make_shared<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(json_t *j) const
+{
+ json_object_set_new(j, "inscription", json_string(m_inscription.c_str()));
+}
+
+bool DiscountCondition::is_match(object_type *o_ptr) const
+{
+ return (object_aware_p(o_ptr) &&
+ (o_ptr->discount >= m_min) &&
+ (o_ptr->discount <= m_max));
+}
+
+std::shared_ptr<Condition> DiscountCondition::from_json(json_t *j)
+{
+ int min, max;
+
+ if (json_unpack(j, "{s:i,s:i}",
+ "min", &min,
+ "max", &max) < 0)
+ {
+ msg_print("Missing/invalid 'min'/'max' properties");
+ return nullptr;
+ }
+
+ return std::make_shared<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(json_t *j) const
+{
+ json_object_set_new(j, "min", json_integer(m_min));
+ json_object_set_new(j, "max", json_integer(m_max));
+}
+
+bool LevelCondition::is_match(object_type *) const
+{
+ return ((p_ptr->lev >= m_min) &&
+ (p_ptr->lev <= m_max));
+}
+
+std::shared_ptr<Condition> LevelCondition::from_json(json_t *j)
+{
+ int min, max;
+ if (json_unpack(j, "{s:i,s:i}",
+ "min", &min,
+ "max", &max) < 0)
+ {
+ msg_print("Missing/invalid 'min'/'max' properties");
+ return nullptr;
+ }
+
+ return std::make_shared<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(json_t *j) const
+{
+ json_object_set_new(j, "min", json_integer(m_min));
+ json_object_set_new(j, "max", json_integer(m_max));
+}
+
+bool SkillCondition::is_match(object_type *) const
+{
+ uint16_t sk = get_skill(m_skill_idx);
+ return ((sk >= m_min) &&
+ (sk <= m_max));
+}
+
+std::shared_ptr<Condition> SkillCondition::from_json(json_t *j)
+{
+ cptr s;
+ int min, max;
+ if (json_unpack(j, "{s:i,s:i,s:s}",
+ "min", &min,
+ "max", &max,
+ "name", &s) < 0)
+ {
+ msg_print("Missing/invalid 'min'/'max'/'name' properties");
+ return nullptr;
+ }
+
+ 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
+{
+ p->write(ecol, "Your skill in ");
+ p->write(bcol, s_info[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(json_t *j) const
+{
+ json_object_set_new(j, "name",
+ json_string(s_info[m_skill_idx].name));
+ json_object_set_new(j, "min",
+ json_integer(m_min));
+ json_object_set_new(j, "max",
+ json_integer(m_max));
+}
+
+bool StateCondition::is_match(object_type *o_ptr) const
+{
+ switch (m_state)
+ {
+ case identification_state::IDENTIFIED:
+ return object_known_p(o_ptr);
+ case identification_state::NOT_IDENTIFIED:
+ return !object_known_p(o_ptr);
+ }
+
+ assert(false);
+ return false;
+}
+
+std::shared_ptr<Condition> StateCondition::from_json(json_t *j)
+{
+ cptr s;
+ if (json_unpack(j, "{s:s}", "state", &s) < 0)
+ {
+ msg_print("Missing/invalid 'state' property");
+ return nullptr;
+ }
+
+ identification_state state;
+ if (!identification_state_mapping().parse(s, &state))
+ {
+ msg_format("Invalid 'state' property: %s", s);
+ return nullptr;
+ }
+
+ return std::make_shared<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(json_t *j) const
+{
+ json_object_set_new(j, "state",
+ json_string(identification_state_mapping().
+ stringify(m_state)));
+}
+
+bool SymbolCondition::is_match(object_type *o_ptr) const
+{
+ object_kind *k_ptr = &k_info[o_ptr->k_idx];
+ return k_ptr->d_char == m_symbol;
+}
+
+std::shared_ptr<Condition> SymbolCondition::from_json(json_t *j)
+{
+ cptr s_ = nullptr;
+ if (json_unpack(j, "{s:s}", "symbol", &s_) < 0)
+ {
+ msg_print("Missing/invalid 'symbol' property");
+ return nullptr;
+ }
+
+ std::string s(s_);
+ if (s.empty())
+ {
+ msg_print("Invalid 'symbol' property: Too short");
+ return nullptr;
+ }
+ if (s.size() > 1)
+ {
+ msg_print("Invalid 'symbol' property: Too long");
+ return nullptr;
+ }
+
+ return std::make_shared<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(json_t *j) const
+{
+ json_object_set_new(j, "symbol",
+ json_string(format("%c", m_symbol)));
+}
+
+bool AbilityCondition::is_match(object_type *) const
+{
+ return has_ability(m_ability_idx);
+}
+
+std::shared_ptr<Condition> AbilityCondition::from_json(json_t *j)
+{
+ cptr a;
+ if (json_unpack(j, "{s:s}", "ability", &a) < 0)
+ {
+ msg_print("Missing/invalid 'ability' property");
+ return nullptr;
+ }
+
+ 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
+{
+ cptr ability_s = ab_info[m_ability_idx].name;
+
+ p->write(ecol, "You have the ");
+ p->write(bcol, ability_s);
+ p->write(ecol, " ability");
+ p->write(TERM_WHITE, "\n");
+}
+
+void AbilityCondition::to_json(json_t *j) const
+{
+ cptr ability_s = ab_info[m_ability_idx].name;
+ json_object_set_new(j, "ability", json_string(ability_s));
+}
+
+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(json_t *j) const
+{
+ json_object_set_new(j, "condition",
+ optional_to_json(m_subcondition));
+}
+
+std::shared_ptr<Condition> SingleSubconditionCondition::parse_single_subcondition(json_t *in_json)
+{
+ json_t *condition_j =
+ json_object_get(in_json, "condition");
+
+ if ((condition_j == nullptr) ||
+ (json_is_null(condition_j)))
+ {
+ return nullptr;
+ }
+ else if (!json_is_object(condition_j))
+ {
+ msg_format("Invalid 'condition' property");
+ return nullptr;
+ }
+ else
+ {
+ return parse_condition(condition_j);
+ }
+}
+
+bool NotCondition::is_match(object_type *o_ptr) const
+{
+ if (!m_subcondition)
+ {
+ return true;
+ }
+
+ return !m_subcondition->is_match(o_ptr);
+}
+
+std::shared_ptr<Condition> NotCondition::from_json(json_t *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(json_t *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(json_t *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..62a90e58
--- /dev/null
+++ b/src/squelch/condition_metadata.cc
@@ -0,0 +1,496 @@
+#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()
+{
+ cptr s = lua_input_box("Object name to match?", 79);
+ if (strlen(s) == 0)
+ {
+ return nullptr;
+ }
+
+ return std::make_shared<NameCondition>(s);
+}
+
+static std::shared_ptr<Condition> create_condition_contain()
+{
+ cptr s = lua_input_box("Word to find in object name?", 79);
+ if (strlen(s) == 0)
+ {
+ return nullptr;
+ }
+
+ return std::make_shared<ContainCondition>(s);
+}
+
+static std::shared_ptr<Condition> create_condition_inscribed()
+{
+ cptr s = lua_input_box("Word to find in object inscription?", 79);
+ if (strlen(s) == 0)
+ {
+ return nullptr;
+ }
+
+ return std::make_shared<InscriptionCondition>(s);
+}
+
+static std::shared_ptr<Condition> create_condition_discount()
+{
+ int min, max;
+
+ {
+ cptr s = lua_input_box("Min discount?", 79);
+ if (sscanf(s, "%d", &min) < 1)
+ {
+ return nullptr;
+ }
+ }
+
+ {
+ cptr s = lua_input_box("Max discount?", 79);
+ if (sscanf(s, "%d", &max) < 1)
+ {
+ return nullptr;
+ }
+ }
+
+ return std::make_shared<DiscountCondition>(min, max);
+}
+
+static std::shared_ptr<Condition> create_condition_symbol()
+{
+ char c;
+ cptr s = lua_input_box("Symbol to match?", 1);
+ if (sscanf(s, "%c", &c) < 1)
+ {
+ return nullptr;
+ }
+
+ return std::make_shared<SymbolCondition>(c);
+}
+
+static std::shared_ptr<Condition> create_condition_status()
+{
+ status_type status;
+ char c;
+
+ c = lua_msg_box("[t]errible, [v]ery bad, [b]ad, "
+ "[a]verage, [G]ood, [V]ery good, [S]pecial?");
+
+ switch (c)
+ {
+ case 't': status = status_type::TERRIBLE; break;
+ case 'v': status = status_type::VERY_BAD; break;
+ case 'b': status = status_type::BAD; break;
+ case 'a': status = status_type::AVERAGE; break;
+ case 'G': status = status_type::GOOD; break;
+ case 'V': status = status_type::VERY_GOOD; break;
+ case 'S': status = status_type::SPECIAL; break;
+ default: return nullptr;
+ }
+
+ return std::make_shared<StatusCondition>(status);
+}
+
+static std::shared_ptr<Condition> create_condition_state()
+{
+ char c = lua_msg_box("[i]dentified, [n]on identified?");
+
+ identification_state s;
+ switch (c)
+ {
+ case 'i': s = identification_state::IDENTIFIED; break;
+ case 'n': s = identification_state::NOT_IDENTIFIED; break;
+ default: return nullptr;
+ }
+
+ return std::make_shared<StateCondition>(s);
+}
+
+static bool in_byte_range(int x)
+{
+ return (x >= 0) && (x < 256);
+}
+
+static std::shared_ptr<Condition> create_condition_tval()
+{
+ cptr s = lua_input_box("Tval to match?", 79);
+ int tval;
+ if (sscanf(s, "%d", &tval) < 1)
+ {
+ return nullptr;
+ }
+
+ if (!in_byte_range(tval))
+ {
+ return nullptr;
+ }
+
+ return std::make_shared<TvalCondition>(tval);
+}
+
+static std::shared_ptr<Condition> create_condition_sval()
+{
+ int sval_min, sval_max;
+
+ {
+ cptr s = lua_input_box("Min sval?", 79);
+ if ((sscanf(s, "%d", &sval_min) < 1) ||
+ (!in_byte_range(sval_min)))
+ {
+ return nullptr;
+ }
+ }
+
+ {
+ cptr s = lua_input_box("Max sval?", 79);
+ if ((sscanf(s, "%d", &sval_max) < 1) ||
+ (!in_byte_range(sval_max)))
+ {
+ return nullptr;
+ }
+ }
+
+ return std::make_shared<SvalCondition>(sval_min, sval_max);
+}
+
+static std::shared_ptr<Condition> create_condition_race()
+{
+ cptr s = lua_input_box("Player race to match?", 79);
+ if (strlen(s) == 0)
+ {
+ return nullptr;
+ }
+
+ return std::make_shared<RaceCondition>(s);
+}
+
+static std::shared_ptr<Condition> create_condition_subrace()
+{
+ cptr s = lua_input_box("Player subrace to match?", 79);
+ if (strlen(s) == 0)
+ {
+ return nullptr;
+ }
+
+ return std::make_shared<SubraceCondition>(s);
+}
+
+static std::shared_ptr<Condition> create_condition_class()
+{
+ cptr s = lua_input_box("Player class to match?", 79);
+ if (strlen(s) == 0)
+ {
+ return nullptr;
+ }
+
+ return std::make_shared<ClassCondition>(s);
+}
+
+static std::shared_ptr<Condition> create_condition_level()
+{
+ int min, max;
+
+ {
+ cptr s = lua_input_box("Min player level?", 79);
+ if (sscanf(s, "%d", &min) < 1)
+ {
+ return nullptr;
+ }
+ }
+
+ {
+ cptr s = lua_input_box("Max player level?", 79);
+ if (sscanf(s, "%d", &max) < 1)
+ {
+ return nullptr;
+ }
+ }
+
+ return std::make_shared<LevelCondition>(min, max);
+}
+
+static std::shared_ptr<Condition> create_condition_skill()
+{
+ int min, max;
+
+ {
+ cptr s = lua_input_box("Min skill level?", 79);
+ if (sscanf(s, "%d", &min) < 1)
+ {
+ return nullptr;
+ }
+ }
+
+ {
+ cptr s = lua_input_box("Max skill level?", 79);
+ if (sscanf(s, "%d", &max) < 1)
+ {
+ return nullptr;
+ }
+ }
+
+ s16b skill_idx;
+ {
+ cptr s = lua_input_box("Skill name?", 79);
+ if (strlen(s) == 0)
+ {
+ return nullptr;
+ }
+
+ skill_idx = find_skill_i(s);
+ if (skill_idx < 0)
+ {
+ return nullptr;
+ }
+ }
+
+ return std::make_shared<SkillCondition>(skill_idx, min, max);
+}
+
+static std::shared_ptr<Condition> create_condition_ability()
+{
+ cptr s = lua_input_box("Ability name?", 79);
+ if (strlen(s) == 0)
+ {
+ return nullptr;
+ }
+
+ s16b ai = find_ability(s);
+ if (ai < 0)
+ {
+ return nullptr;
+ }
+
+ return std::make_shared<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<const char *> condition_type_names;
+
+ // Fill in types names?
+ if (condition_type_names.empty())
+ {
+ for (auto condition_type : condition_types)
+ {
+ condition_type_names.push_back(
+ match_mapping().stringify(condition_type));
+ }
+ }
+
+ // Choose
+ int begin = 0, sel = 0;
+ while (1)
+ {
+ int wid, hgt;
+ Term_clear();
+ Term_get_size(&wid, &hgt);
+
+ display_list(0, 0, hgt - 1, 15, "Rule types", condition_type_names.data(), condition_types.size(), begin, sel, TERM_L_GREEN);
+
+ display_desc(condition_types[sel]);
+
+ char c = inkey();
+
+ if (c == ESCAPE) break;
+ else if (c == '8')
+ {
+ sel--;
+ if (sel < 0)
+ {
+ sel = condition_types.size() - 1;
+ begin = condition_types.size() - hgt;
+ if (begin < 0) begin = 0;
+ }
+ if (sel < begin) begin = sel;
+ }
+ else if (c == '2')
+ {
+ sel++;
+ if (sel >= 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..1c17d2fd
--- /dev/null
+++ b/src/squelch/rule.cc
@@ -0,0 +1,332 @@
+#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_type.hpp"
+#include "../quark.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(const char *new_name)
+{
+ assert(new_name != nullptr);
+ m_name = new_name;
+}
+
+const char *Rule::get_name() const
+{
+ return m_name.c_str();
+}
+
+std::shared_ptr<Condition> Rule::get_condition() const
+{
+ return m_condition;
+}
+
+json_t *Rule::to_json() const
+{
+ json_t *rule_json = json_object();
+ json_object_set_new(rule_json,
+ "name",
+ json_string(m_name.c_str()));
+ json_object_set_new(rule_json,
+ "action",
+ json_string(action_mapping().stringify(m_action)));
+ json_object_set_new(rule_json,
+ "module",
+ json_string(modules[m_module_idx].meta.name));
+ json_object_set_new(rule_json,
+ "condition",
+ Condition::optional_to_json(m_condition));
+ return rule_json;
+}
+
+void Rule::add_new_condition(Cursor *cursor,
+ ConditionFactory const &factory)
+{
+ // Top-level condition?
+ if (!m_condition)
+ {
+ // Sanity check for navigation stack
+ assert(cursor->empty());
+
+ // Create new top-level condition
+ m_condition = factory();
+
+ // Select the condition
+ if (m_condition)
+ {
+ cursor->push(m_condition.get());
+ }
+ }
+ else
+ {
+ cursor->current()->add_child(factory);
+ }
+}
+
+void Rule::delete_selected_condition(Cursor *cursor)
+{
+ assert(cursor->size() >= 1);
+
+ if (cursor->size() == 1)
+ {
+ cursor->pop();
+ m_condition.reset();
+ }
+ else
+ {
+ Condition *prev_top = cursor->pop();
+ Condition *top = cursor->current();
+
+ // Jump up a level; this is a simple way to ensure a
+ // valid cursor. We could be a little cleverer here by
+ // trying to move inside the current level, but it
+ // gets a little complicated.
+ cursor->move_left();
+
+ // Now we can remove the condition from its parent
+ top->remove_child(prev_top);
+ }
+}
+
+void Rule::write_tree(TreePrinter *tree_printer, Cursor *cursor) const
+{
+ // Write out the main rule
+ do_write_tree(tree_printer);
+
+ // Write out the condition
+ if (m_condition)
+ {
+ m_condition->display(tree_printer, cursor);
+ }
+}
+
+bool Rule::apply_rule(object_type *o_ptr, int item_idx) const
+{
+ // Check module
+ if (m_module_idx != game_module_idx)
+ {
+ return false;
+ }
+
+ // Check condition
+ if (m_condition && m_condition->is_match(o_ptr))
+ {
+ return do_apply_rule(o_ptr, item_idx);
+ }
+
+ // Doesn't apply
+ return false;
+}
+
+std::shared_ptr<Rule> Rule::parse_rule(json_t *rule_json)
+{
+ if (!json_is_object(rule_json))
+ {
+ msg_print("Rule is not an object");
+ return nullptr;
+ }
+
+ // Retrieve the attributes
+ char *rule_name_s = nullptr;
+ char *rule_action_s = nullptr;
+ char *rule_module_s = nullptr;
+ if (json_unpack(rule_json,
+ "{s:s,s:s,s:s}",
+ "name", &rule_name_s,
+ "action", &rule_action_s,
+ "module", &rule_module_s) < 0)
+ {
+ msg_print("Rule missing required field(s)");
+ return nullptr;
+ }
+
+ // Convert attributes
+ action_type action;
+ if (!action_mapping().parse((cptr) rule_action_s, &action))
+ {
+ msg_format("Invalid rule action '%s'", rule_action_s);
+ return nullptr;
+ }
+
+ int module_idx = find_module((cptr) rule_module_s);
+ if (module_idx < 0)
+ {
+ msg_format("Skipping rule for unrecognized module '%s'",
+ (cptr) rule_module_s);
+ return nullptr;
+ }
+
+ // Parse condition
+ std::shared_ptr<Condition> condition =
+ Condition::parse_condition(json_object_get(rule_json, "condition"));
+
+ // Parse rule
+ switch (action)
+ {
+ case action_type::AUTO_INSCRIBE:
+ {
+ json_t *rule_inscription_j = json_object_get(rule_json, "inscription");
+
+ if (rule_inscription_j == nullptr)
+ {
+ msg_print("Inscription rule missing 'inscription' attribute");
+ return nullptr;
+ }
+ if (!json_is_string(rule_inscription_j))
+ {
+ msg_print("Inscription rule 'inscription' attribute wrong type");
+ return nullptr;
+ }
+
+ std::string inscription =
+ json_string_value(rule_inscription_j);
+ return std::make_shared<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->note)
+ {
+ return false;
+ }
+
+ // Ignore artifacts; cannot be destroyed anyway
+ if (artifact_p(o_ptr))
+ {
+ return false;
+ }
+
+ // Cannot destroy CURSE_NO_DROP objects.
+ {
+ u32b f1, f2, f3, f4, f5, esp;
+ object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
+
+ if ((f4 & TR4_CURSE_NO_DROP) != 0)
+ {
+ return false;
+ }
+ }
+
+ // Destroy
+ msg_print("<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;
+}
+
+json_t *InscribeRule::to_json() const
+{
+ json_t *j = Rule::to_json();
+
+ json_object_set_new(j,
+ "inscription",
+ json_string(m_inscription.c_str()));
+
+ return j;
+}
+
+void InscribeRule::do_write_tree(TreePrinter *p) const
+{
+ p->write(TERM_GREEN, "A rule named \"");
+ p->write(TERM_WHITE, m_name.c_str());
+ p->write(TERM_GREEN, "\" to ");
+ p->write(TERM_L_GREEN, "inscribe");
+ p->write(TERM_GREEN, " an item with \"");
+ p->write(TERM_WHITE, m_inscription.c_str());
+ p->write(TERM_GREEN, "\" when");
+ p->write(TERM_WHITE, "\n");
+}
+
+bool InscribeRule::do_apply_rule(object_type *o_ptr, int) const
+{
+ // Already inscribed?
+ if (o_ptr->note != 0)
+ {
+ return false;
+ }
+
+ // Inscribe
+ msg_format("<Auto-Inscribe {%s}>", m_inscription.c_str());
+ o_ptr->note = quark_add(m_inscription.c_str());
+ return true;
+}
+
+} // namespace
diff --git a/src/squelch/tree_printer.cc b/src/squelch/tree_printer.cc
new file mode 100644
index 00000000..2be098dc
--- /dev/null
+++ b/src/squelch/tree_printer.cc
@@ -0,0 +1,89 @@
+#include "tome/squelch/tree_printer_fwd.hpp"
+#include "tome/squelch/tree_printer.hpp"
+
+#include "../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;
+ }
+ }
+}
+
+} // 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..bab1e5c0
--- /dev/null
+++ b/src/squeltch.cc
@@ -0,0 +1,593 @@
+/*
+ * 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 "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 <jansson.h>
+#include <algorithm>
+#include <memory>
+#include <deque>
+#include <list>
+#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(void)
+{
+ 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(void)
+{
+ 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()
+{
+ char name[20] = { '\0' };
+ int wid = 0, hgt = 0;
+
+ Term_get_size(&wid, &hgt);
+
+ sprintf(name, "%s", "No name");
+ if (!input_box("Name?", hgt / 2, wid / 2, name, sizeof(name)))
+ {
+ return -1;
+ }
+
+ char typ = lua_msg_box("[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':
+ {
+ cptr i = lua_input_box("Inscription?", 79);
+ if ((i == nullptr) || (strlen(i) == 0))
+ {
+ return -1;
+ }
+
+ rule = std::make_shared<InscribeRule>(
+ name, game_module_idx, nullptr, std::string(i));
+
+ break;
+ }
+
+ default:
+ return -1;
+ }
+
+ return automatizer->append_rule(rule);
+}
+
+static void automatizer_save_rules()
+{
+ char name[30] = { '\0' };
+ char buf[1025];
+ char ch;
+ int hgt, wid;
+
+ Term_get_size(&wid, &hgt);
+
+ sprintf(name, "%s.atm", player_name);
+
+ if (!input_box("Save name?", hgt / 2, wid / 2, name, sizeof(name)))
+ {
+ return;
+ }
+
+ // Build the filename
+ path_build(buf, 1024, ANGBAND_DIR_USER, name);
+
+ if (file_exist(buf))
+ {
+ c_put_str(TERM_WHITE, "File exists, continue?[y/n]",
+ hgt / 2,
+ wid / 2 - 14);
+ ch = inkey();
+ if ((ch != 'Y') && (ch != 'y'))
+ {
+ return;
+ }
+ }
+
+ // Write to file
+ {
+ auto rules_json = automatizer->to_json();
+
+ int status = json_dump_file(rules_json.get(), buf,
+ JSON_INDENT(2) |
+ JSON_SORT_KEYS);
+ if (status == 0)
+ {
+ c_put_str(TERM_WHITE, "Saved rules in file ",
+ hgt / 2,
+ wid / 2 - 14);
+ }
+ else
+ {
+ c_put_str(TERM_WHITE, "Saving rules failed! ",
+ hgt / 2,
+ wid / 2 - 14);
+ }
+
+ // Wait for keypress
+ inkey();
+ }
+}
+
+static void rename_rule(Rule *rule)
+{
+ char name[16];
+ int wid, hgt;
+
+ assert(rule != nullptr);
+
+ Term_get_size(&wid, &hgt);
+
+ sprintf(name, "%s", rule->get_name());
+ if (input_box("New name?", hgt / 2, wid / 2, name, sizeof(name)))
+ {
+ rule->set_name(name);
+ }
+}
+
+#define ACTIVE_LIST 0
+#define ACTIVE_RULE 1
+void do_cmd_automatizer()
+{
+ int wid = 0, hgt = 0;
+ int active = ACTIVE_LIST;
+ cptr keys;
+ cptr keys2;
+ cptr keys3;
+ std::vector<cptr> rule_names;
+
+ Term_get_size(&wid, &hgt);
+
+ if (!automatizer_enabled)
+ {
+ if (msg_box("Automatizer is currently disabled, enable it? (y/n)", hgt / 2, wid / 2) == 'y')
+ {
+ automatizer_enabled = TRUE;
+ }
+ else
+ return;
+ }
+
+ screen_save();
+
+ automatizer->reset_view();
+
+ while (1)
+ {
+ Term_clear();
+ Term_get_size(&wid, &hgt);
+
+ automatizer->get_rule_names(&rule_names);
+
+ display_list(0, 0, hgt - 1, 15, "Rules", rule_names.data(), automatizer->rules_count(), automatizer->rules_begin(), automatizer->selected_rule(), (active == ACTIVE_LIST) ? TERM_L_GREEN : TERM_GREEN);
+
+ draw_box(0, 15, hgt - 4, wid - 1 - 15);
+ if (active == ACTIVE_RULE)
+ {
+ keys = "#Bup#W/#Bdown#W/#Bleft#W/#Bright#W to navitage rule, #B9#W/#B3#W/#B7#W/#B1#W to scroll";
+ keys2 = "#Btab#W for switch, #Ba#Wdd clause, #Bd#Welete clause/rule";
+ keys3 = "#G?#W for Automatizer help";
+ }
+ else
+ {
+ keys = "#Bup#W/#Bdown#W to scroll, #Btab#W to switch to the rule window";
+ keys2 = "#Bu#W/#Bd#W to move rules, #Bn#Wew rule, #Br#Wename rule, #Bs#Wave rules";
+ keys3 = "#Rk#W to #rdisable#W the automatizer, #G?#W for Automatizer help";
+ }
+ display_message(17, hgt - 3, strlen(keys), TERM_WHITE, keys);
+ display_message(17, hgt - 2, strlen(keys2), TERM_WHITE, keys2);
+ display_message(17, hgt - 1, strlen(keys3), TERM_WHITE, keys3);
+
+ automatizer->show_current();
+
+ char c = inkey();
+
+ if (c == ESCAPE) break;
+ if (active == ACTIVE_LIST)
+ {
+ if (c == '?')
+ {
+ screen_save();
+ show_file("automat.txt", "Automatizer help", 0, 0);
+ screen_load();
+ }
+ else if (c == '8')
+ {
+ if (!automatizer->rules_count()) continue;
+
+ automatizer->select_rule(
+ automatizer->selected_rule() - 1);
+ }
+ else if (c == '2')
+ {
+ if (!automatizer->rules_count()) continue;
+
+ automatizer->select_rule(
+ automatizer->selected_rule() + 1);
+ }
+ else if (c == 'u')
+ {
+ int sel = automatizer->selected_rule();
+ if (sel > 0)
+ {
+ automatizer->swap_rules(sel-1, sel);
+ automatizer->select_rule(sel-1);
+ }
+ }
+ else if (c == 'd')
+ {
+ if (!automatizer->rules_count()) continue;
+
+ int sel = automatizer->selected_rule();
+ if (sel < automatizer->rules_count() - 1)
+ {
+ automatizer->swap_rules(sel, sel+1);
+ automatizer->select_rule(sel+1);
+ }
+ }
+ else if (c == 'n')
+ {
+ int i = create_new_rule();
+ if (i >= 0)
+ {
+ automatizer->select_rule(i);
+ active = ACTIVE_RULE;
+ }
+ }
+ else if (c == 's')
+ {
+ automatizer_save_rules();
+ }
+ else if (c == 'r')
+ {
+ if (!automatizer->rules_count()) continue;
+
+ rename_rule(automatizer->current_rule().get());
+ continue;
+ }
+ else if (c == 'k')
+ {
+ automatizer_enabled = FALSE;
+ break;
+ }
+ else if (c == '\t')
+ {
+ if (!automatizer->rules_count()) continue;
+
+ active = ACTIVE_RULE;
+ }
+ }
+ else if (active == ACTIVE_RULE)
+ {
+ if (c == '?')
+ {
+ screen_save();
+ show_file("automat.txt", "Automatizer help", 0, 0);
+ screen_load();
+ }
+ else if (c == '8')
+ {
+ automatizer->move_up();
+ }
+ else if (c == '2')
+ {
+ automatizer->move_down();
+ }
+ else if (c == '6')
+ {
+ automatizer->move_right();
+ }
+ else if (c == '4')
+ {
+ automatizer->move_left();
+ }
+ else if (c == '9')
+ {
+ automatizer->scroll_up();
+ }
+ else if (c == '3')
+ {
+ automatizer->scroll_down();
+ }
+ else if (c == '7')
+ {
+ automatizer->scroll_left();
+ }
+ else if (c == '1')
+ {
+ automatizer->scroll_right();
+ }
+ else if (c == 'a')
+ {
+ automatizer->add_new_condition(
+ squelch::new_condition_interactive);
+ }
+ else if (c == 'd')
+ {
+ if (!automatizer->rules_count())
+ {
+ continue;
+ }
+
+ int new_sel =
+ automatizer->remove_current_selection();
+
+ if (new_sel == -1)
+ {
+ active = ACTIVE_LIST;
+ }
+ }
+ else if (c == '\t')
+ {
+ active = ACTIVE_LIST;
+ }
+ }
+ }
+
+ screen_load();
+}
+
+enum class add_rule_mode { TVAL, TSVAL, NAME };
+
+static void easy_add_rule(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 file
+ json_error_t error;
+ std::shared_ptr<json_t> rules_json(
+ json_load_file(path.c_str(), 0, &error),
+ &json_decref);
+ if (rules_json == nullptr)
+ {
+ msg_format("Error parsing automatizer rules from '%s'.", path.c_str());
+ msg_format("Line %d, Column %d", error.line, error.column);
+ msg_print(nullptr);
+ return false;
+ }
+
+ // Load rules
+ automatizer->load_json(rules_json.get());
+ return true;
+}
diff --git a/src/squeltch.hpp b/src/squeltch.hpp
new file mode 100644
index 00000000..65ddfb51
--- /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>
+
+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);
+extern bool_ automatizer_create;
+extern void automatizer_init();
+extern 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.cc
index 967a8323..0a3977c7 100644
--- a/src/status.c
+++ b/src/status.cc
@@ -15,14 +15,24 @@
* 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]);
+#include "files.hpp"
+#include "monster2.hpp"
+#include "monster_type.hpp"
+#include "object1.hpp"
+#include "player_type.hpp"
+#include "stats.hpp"
+#include "util.hpp"
+#include "util.h"
+#include "variable.h"
+#include "variable.hpp"
+#include "xtra1.hpp"
+
+static void row_trival(const char*, s16b, u32b, s16b, u32b, int, u32b[INVEN_TOTAL - INVEN_WIELD + 2][7]);
+static void row_bival(const char*, s16b, u32b, int, u32b[INVEN_TOTAL - INVEN_WIELD + 2][7]);
+static void row_npval(const char*, s16b, u32b, int, u32b[INVEN_TOTAL - INVEN_WIELD + 2][7]);
+static void statline(const char*, int, u32b, int, u32b[INVEN_TOTAL - INVEN_WIELD + 2][7]);
static void row_hd_bon(int, int, u32b[INVEN_TOTAL - INVEN_WIELD + 2][7]);
-static void row_count(char*, s16b, u32b, int, s16b, u32b, int, s16b, u32b, int, s16b, u32b, int, int, u32b[INVEN_TOTAL - INVEN_WIELD + 2][7]);
+static void row_count(const char*, s16b, u32b, int, s16b, u32b, int, s16b, u32b, int, s16b, u32b, int, int, u32b[INVEN_TOTAL - INVEN_WIELD + 2][7]);
static int row_x_start = 0;
static void status_count(s32b val1, int v1, s32b val2, int v2, s32b val3, int v3, s32b val4, int v4, byte ypos, byte xpos);
@@ -31,19 +41,19 @@ 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]);
+static void status_sight(void);
+static void status_attr(void);
+static void status_combat(void);
+static void status_move(void);
+static void status_item(void);
+static 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)
+static void status_attr(void)
{
u32b flag_arr[INVEN_TOTAL - INVEN_WIELD + 2][7];
int yo = 0;
@@ -112,7 +122,7 @@ void status_move(void)
}
}
-void status_sight(void)
+static void status_sight(void)
/* Tell player about ESP, infravision, auto-id, see invis, and similar */
{
u32b flag_arr[INVEN_TOTAL - INVEN_WIELD + 2][7];
@@ -163,7 +173,7 @@ void status_sight(void)
}
}
-void status_item(void)
+static void status_item(void)
{
u32b flag_arr[INVEN_TOTAL - INVEN_WIELD + 2][7];
int yo = 3;
@@ -213,7 +223,7 @@ void status_item(void)
}
}
-void status_combat(void)
+static void status_combat(void)
{
u32b flag_arr[INVEN_TOTAL - INVEN_WIELD + 2][7];
int yo = 3;
@@ -272,7 +282,7 @@ void status_combat(void)
}
}
-void status_curses(void)
+static void status_curses(void)
{
u32b flag_arr[INVEN_TOTAL - INVEN_WIELD + 2][7];
int yo = 3;
@@ -298,7 +308,7 @@ void status_curses(void)
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);
+ row_bival("Antimagic", 4, TR4_ANTIMAGIC_50, yo++, flag_arr);
c_put_str(TERM_WHITE, "Press ESC to continue", 23, 0);
Term_fresh();
@@ -322,7 +332,7 @@ void status_curses(void)
}
}
-void status_res(void)
+static void status_res(void)
{
u32b flag_arr[INVEN_TOTAL - INVEN_WIELD + 2][7];
int yo = 3;
@@ -373,7 +383,7 @@ void status_res(void)
}
}
-void status_main(void)
+void status_main()
{
int do_quit = 0;
char c;
@@ -430,11 +440,11 @@ void status_main(void)
}
Term_load();
character_icky = FALSE;
- p_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP);
+ p_ptr->redraw |= (PR_WIPE | PR_FRAME | PR_MAP);
handle_stuff();
}
-void az_line(int xo, u32b flag_arr[INVEN_TOTAL - INVEN_WIELD + 2][7])
+static void az_line(int xo, u32b flag_arr[INVEN_TOTAL - INVEN_WIELD + 2][7])
{
int index = xo; /* Leave room for description */
int i;
@@ -526,7 +536,7 @@ static void status_count(s32b val1, int v1, s32b val2, int v2, s32b val3, int v3
status_numeric(v, ypos, xpos);
}
-static void row_count(char* statname, s16b row1, u32b flag1, int v1, s16b row2, u32b flag2, int v2, s16b row3, u32b flag3, int v3, s16b row4, u32b flag4, int v4, int yo, u32b flag_arr[INVEN_TOTAL - INVEN_WIELD + 2][7])
+static void row_count(const char* statname, s16b row1, u32b flag1, int v1, s16b row2, u32b flag2, int v2, s16b row3, u32b flag3, int v3, s16b row4, u32b flag4, int v4, int yo, u32b flag_arr[INVEN_TOTAL - INVEN_WIELD + 2][7])
{
int i;
int x = row_x_start;
@@ -543,7 +553,7 @@ static void row_count(char* statname, s16b row1, u32b flag1, int v1, s16b row2,
}
}
-static void row_trival(char* statname, s16b row, u32b flag, s16b row2, u32b flag2, int yo, u32b flag_arr[INVEN_TOTAL - INVEN_WIELD + 2][7])
+static void row_trival(const char* statname, s16b row, u32b flag, s16b row2, u32b flag2, int yo, u32b flag_arr[INVEN_TOTAL - INVEN_WIELD + 2][7])
{
int i;
int x = row_x_start;
@@ -561,7 +571,7 @@ static void row_trival(char* statname, s16b row, u32b flag, s16b row2, u32b flag
}
}
-static void row_bival(char* statname, s16b row, u32b flag, int yo, u32b flag_arr[INVEN_TOTAL - INVEN_WIELD + 2][7])
+static void row_bival(const char* statname, s16b row, u32b flag, int yo, u32b flag_arr[INVEN_TOTAL - INVEN_WIELD + 2][7])
{
int i;
int x = row_x_start;
@@ -576,7 +586,7 @@ static void row_bival(char* statname, s16b row, u32b flag, int yo, u32b flag_arr
}
}
-static void row_npval(char* statname, s16b row, u32b flag, int yo, u32b flag_arr[INVEN_TOTAL - INVEN_WIELD + 2][7])
+static void row_npval(const char* statname, s16b row, u32b flag, int yo, u32b flag_arr[INVEN_TOTAL - INVEN_WIELD + 2][7])
/* Displays nicely a pval-based status row */
{
int i;
@@ -605,7 +615,7 @@ static void row_npval(char* statname, s16b row, u32b flag, int yo, u32b flag_arr
}
}
-static void statline(char* statname, int statidx, u32b flag, int yo, u32b flag_arr[INVEN_TOTAL - INVEN_WIELD + 2][7])
+static void statline(const char* statname, int statidx, u32b flag, int yo, u32b flag_arr[INVEN_TOTAL - INVEN_WIELD + 2][7])
/* Displays a status row for a primary stat */
{
int i;
@@ -742,7 +752,7 @@ static void status_companion(void)
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));
+ if (m_ptr->level < MONSTER_LEVEL_MAX) fprintf(fff, " Next lvl: [[[[[G%ld]\n", (long int) monster_exp(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);
diff --git a/src/status.hpp b/src/status.hpp
new file mode 100644
index 00000000..74624446
--- /dev/null
+++ b/src/status.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+void status_main();
diff --git a/src/store.c b/src/store.cc
index 78120846..0fbe2e9b 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,55 @@
* 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 "hooks.hpp"
+#include "obj_theme.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_kind.hpp"
+#include "options.hpp"
+#include "owner_type.hpp"
+#include "player_type.hpp"
+#include "quark.hpp"
+#include "spell_type.hpp"
+#include "skills.hpp"
+#include "spells5.hpp"
+#include "stats.hpp"
+#include "store_action_type.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>
+
+#define STORE_GENERAL_STORE "General Store"
+#define STORE_ARMOURY "Armoury"
+#define STORE_WEAPONSMITH "Weaponsmith"
+#define STORE_TEMPLE "Temple"
+#define STORE_ALCHEMY "Alchemy shop"
+#define STORE_MAGIC "Magic shop"
+#define STORE_BLACK_MARKET "Black Market"
+#define STORE_BOOKS "Book Store"
+#define STORE_PETS "Pet Shop"
+#define STORE_HUNTING_SUPPLIES "Hunting Supply Store"
+#define STORE_RUNIC_MAGIC "Runic Magic Shop"
+#define STORE_CONSTRUCTION_SUPPLIES "Construction Supply Store"
+#define STORE_MUSIC "Music Store"
#define RUMOR_CHANCE 8
@@ -27,59 +70,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,31 +90,6 @@ static cptr comment_4b[MAX_COMMENT_4B] =
"Out, out, out!"
};
-#define MAX_COMMENT_5 8
-
-static cptr comment_5[MAX_COMMENT_5] =
-{
- "Try again.",
- "Ridiculous!",
- "You will have to do better than that!",
- "Do you wish to do business or not?",
- "You've got to be kidding!",
- "You'd better be kidding!",
- "You try my patience.",
- "Hmmm, nice weather we're having."
-};
-
-#define MAX_COMMENT_6 4
-
-static cptr comment_6[MAX_COMMENT_6] =
-{
- "I must have heard you wrong.",
- "I'm sorry, I missed that.",
- "I'm sorry, what was that?",
- "Sorry, what was that again?"
-};
-
-
/*
* Successful haggle.
@@ -135,7 +100,7 @@ static void say_comment_1(void)
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,58 +110,6 @@ static void say_comment_1(void)
/*
- * Continue haggling (player is buying)
- */
-static void say_comment_2(s32b value, int annoyed)
-{
- char tmp_val[80];
-
- /* Prepare a string to insert */
- strnfmt(tmp_val, 80, "%ld", (long)value);
-
- /* Final offer */
- if (annoyed > 0)
- {
- /* Formatted message */
- msg_format(comment_2a[rand_int(MAX_COMMENT_2A)], tmp_val);
- }
-
- /* Normal offer */
- else
- {
- /* Formatted message */
- msg_format(comment_2b[rand_int(MAX_COMMENT_2B)], tmp_val);
- }
-}
-
-
-/*
- * Continue haggling (player is selling)
- */
-static void say_comment_3(s32b value, int annoyed)
-{
- char tmp_val[80];
-
- /* Prepare a string to insert */
- strnfmt(tmp_val, 80, "%ld", (long)value);
-
- /* Final offer */
- if (annoyed > 0)
- {
- /* Formatted message */
- msg_format(comment_3a[rand_int(MAX_COMMENT_3A)], tmp_val);
- }
-
- /* Normal offer */
- else
- {
- /* Formatted message */
- msg_format(comment_3b[rand_int(MAX_COMMENT_3B)], tmp_val);
- }
-}
-
-
-/*
* Kick 'da bum out. -RAK-
*/
static void say_comment_4(void)
@@ -206,24 +119,6 @@ static void say_comment_4(void)
}
-/*
- * You are insulting me
- */
-static void say_comment_5(void)
-{
- msg_print(comment_5[rand_int(MAX_COMMENT_5)]);
-}
-
-
-/*
- * That makes no sense.
- */
-static void say_comment_6(void)
-{
- msg_print(comment_6[rand_int(5)]);
-}
-
-
/*
* Messages for reacting to purchase prices.
@@ -413,6 +308,9 @@ static s32b price_item(object_type *o_ptr, int greed, bool_ flip)
/* Mega-Hack -- Black market sucks */
if (st_info[st_ptr->st_idx].flags1 & SF1_ALL_ITEM) price = price / 2;
+
+ /* No selling means you get no money */
+ if (no_selling) price = 0;
}
/* Shop is selling */
@@ -426,14 +324,14 @@ static s32b price_item(object_type *o_ptr, int greed, bool_ flip)
/* Mega-Hack -- Black market sucks */
if (st_info[st_ptr->st_idx].flags1 & SF1_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);
}
@@ -725,7 +623,7 @@ static bool_ store_check_num(object_type *o_ptr)
}
-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);
@@ -740,24 +638,220 @@ 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)
{
+ cptr 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].flags1 & SF1_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;
+ }
- /* Lua can define things to buy */
- if (process_hooks_ret(HOOK_STORE_BUY, "d", "(d,s,O)", st_ptr->st_idx, st_info[st_ptr->st_idx].name + st_name, o_ptr))
+ /* What do stores buy? */
+ if (streq(store_name, STORE_GENERAL_STORE))
+ {
+ switch (o_ptr->tval)
+ {
+ case TV_CORPSE:
+ case TV_FOOD:
+ case TV_LITE:
+ case TV_FLASK:
+ case TV_SPIKE:
+ case TV_SHOT:
+ case TV_ARROW:
+ case TV_BOLT:
+ case TV_DIGGING:
+ case TV_CLOAK:
+ case TV_BOTTLE:
+ return true;
+ }
+ }
+ else if (streq(store_name, STORE_ARMOURY))
{
- return process_hooks_return[0].num;
+ switch (o_ptr->tval)
+ {
+ case TV_BOOTS:
+ case TV_GLOVES:
+ case TV_CROWN:
+ case TV_HELM:
+ case TV_SHIELD:
+ case TV_CLOAK:
+ case TV_SOFT_ARMOR:
+ case TV_HARD_ARMOR:
+ case TV_DRAG_ARMOR:
+ return true;
+ }
+ }
+ else if (streq(store_name, STORE_WEAPONSMITH))
+ {
+ switch (o_ptr->tval)
+ {
+ case TV_SHOT:
+ case TV_BOLT:
+ case TV_ARROW:
+ case TV_BOOMERANG:
+ case TV_BOW:
+ case TV_DIGGING:
+ case TV_HAFTED:
+ case TV_POLEARM:
+ case TV_SWORD:
+ case TV_AXE:
+ case TV_MSTAFF:
+ return true;
+ }
+ }
+ else if (streq(store_name, STORE_TEMPLE))
+ {
+ switch (o_ptr->tval)
+ {
+ case TV_DRUID_BOOK:
+ case TV_SCROLL:
+ case TV_POTION2:
+ case TV_POTION:
+ case TV_HAFTED:
+ return true;
+ }
+
+ if ((o_ptr->tval == TV_BOOK) &&
+ (o_ptr->sval == BOOK_RANDOM) &&
+ (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 (streq(store_name, STORE_ALCHEMY))
+ {
+ switch (o_ptr->tval)
+ {
+ case TV_SCROLL:
+ case TV_POTION2:
+ case TV_POTION:
+ case TV_BOTTLE:
+ return true;
+ }
+ }
+ else if (streq(store_name, STORE_MAGIC))
+ {
+ switch (o_ptr->tval)
+ {
+ case TV_SYMBIOTIC_BOOK:
+ case TV_AMULET:
+ case TV_RING:
+ case TV_STAFF:
+ case TV_WAND:
+ case TV_ROD:
+ case TV_ROD_MAIN:
+ case TV_SCROLL:
+ case TV_POTION2:
+ case TV_POTION:
+ case TV_MSTAFF:
+ case TV_RANDART:
+ return true;
+ }
+
+ if ((o_ptr->tval == TV_BOOK) &&
+ (o_ptr->sval == BOOK_RANDOM) &&
+ (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 (streq(store_name, STORE_BLACK_MARKET))
+ {
+ return true;
+ }
+ else if (streq(store_name, STORE_BOOKS))
+ {
+ switch (o_ptr->tval)
+ {
+ case TV_BOOK:
+ case TV_SYMBIOTIC_BOOK:
+ case TV_MUSIC_BOOK:
+ case TV_DAEMON_BOOK:
+ case TV_DRUID_BOOK:
+ return true;
+ }
+ }
+ else if (streq(store_name, STORE_PETS))
+ {
+ return (o_ptr->tval == TV_EGG);
+ }
+ else if (streq(store_name, STORE_HUNTING_SUPPLIES))
+ {
+ switch (o_ptr->tval)
+ {
+ case TV_TRAPKIT:
+ case TV_BOOMERANG:
+ case TV_SHOT:
+ case TV_BOLT:
+ case TV_ARROW:
+ case TV_BOW:
+ case TV_POTION2:
+ return true;
+ }
+ }
+ else if (streq(store_name, STORE_RUNIC_MAGIC))
+ {
+ switch (o_ptr->tval)
+ {
+ case TV_RUNE1:
+ case TV_RUNE2:
+ return true;
+ }
+ }
+ else if (streq(store_name, STORE_CONSTRUCTION_SUPPLIES))
+ {
+ switch (o_ptr->tval)
+ {
+ case TV_LITE:
+ case TV_DIGGING:
+ return true;
+ }
+ }
+ else if (streq(store_name, STORE_MUSIC))
+ {
+ return (o_ptr->tval == TV_INSTRUMENT);
}
/* Assume not okay */
- return (FALSE);
+ return false;
}
@@ -1157,11 +1251,36 @@ 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 (streq(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;
+ }
+
+ /* Temple */
+ else if (streq(st_info[st_ptr->st_idx].name, STORE_TEMPLE) &&
+ magik(20))
+ {
+ s16b spell;
+
+ object_prep(&forge, lookup_kind(TV_BOOK, BOOK_RANDOM));
+ spell = get_random_spell(SKILL_SPIRITUALITY, 20);
+ assert(spell > -1);
+ forge.pval = spell;
+
+ /* Use the forged object */
+ q_ptr = &forge;
obj_all_done = TRUE;
- q_ptr = process_hooks_return[0].o_ptr;
}
/* Black Market */
@@ -1329,62 +1448,6 @@ static void store_create(void)
/*
- * Eliminate need to bargain if player has haggled well in the past
- */
-static bool_ noneedtobargain(s32b minprice)
-{
- s32b good = st_ptr->good_buy;
- s32b bad = st_ptr->bad_buy;
-
- /* Cheap items are "boring" */
- if (minprice < 10L) return (TRUE);
-
- /* Perfect haggling */
- if (good == MAX_SHORT) return (TRUE);
-
- /* Reward good haggles, punish bad haggles, notice price */
- if (good > ((3 * bad) + (5 + (minprice / 50)))) return (TRUE);
-
- /* Return the flag */
- return (FALSE);
-}
-
-
-/*
- * Update the bargain info
- */
-static void updatebargain(s32b price, s32b minprice)
-{
- /* Hack -- auto-haggle */
- if (auto_haggle) return;
-
- /* Cheap items are "boring" */
- if (minprice < 10L) return;
-
- /* Count the successful haggles */
- if (price == minprice)
- {
- /* Just count the good haggles */
- if (st_ptr->good_buy < MAX_SHORT)
- {
- st_ptr->good_buy++;
- }
- }
-
- /* Count the failed haggles */
- else
- {
- /* Just count the bad haggles */
- if (st_ptr->bad_buy < MAX_SHORT)
- {
- st_ptr->bad_buy++;
- }
- }
-}
-
-
-
-/*
* Re-displays a single store entry
*/
static void display_entry(int pos)
@@ -1411,7 +1474,6 @@ static void display_entry(int pos)
cur_col = 3;
- if (show_store_graph)
{
byte a = object_attr(o_ptr);
char c = object_char(o_ptr);
@@ -1419,12 +1481,6 @@ 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;
}
@@ -1434,8 +1490,8 @@ static void display_entry(int pos)
{
maxwid = 75;
- /* Leave room for weights, if necessary -DRS- */
- if (show_weights) maxwid -= 10;
+ /* Leave room for weights */
+ maxwid -= 10;
/* Describe the object */
object_desc(o_name, o_ptr, TRUE, 3);
@@ -1443,7 +1499,6 @@ static void display_entry(int pos)
c_put_str(tval_to_attr[o_ptr->tval], o_name, i + 6, cur_col);
/* Show weights */
- if (show_weights)
{
/* Only show the weight of an individual item */
int wgt = o_ptr->weight;
@@ -1460,8 +1515,8 @@ static void display_entry(int pos)
/* Must leave room for the "price" */
maxwid = 65;
- /* Leave room for weights, if necessary -DRS- */
- if (show_weights) maxwid -= 7;
+ /* Leave room for weights */
+ maxwid -= 7;
/* Describe the object (fully) */
object_desc_store(o_name, o_ptr, TRUE, 3);
@@ -1469,7 +1524,6 @@ static void display_entry(int pos)
c_put_str(tval_to_attr[o_ptr->tval], o_name, i + 6, cur_col);
/* Show weights */
- if (show_weights)
{
/* Only show the weight of an individual item */
int wgt = o_ptr->weight;
@@ -1477,50 +1531,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;
+ /* Extract the "minimum" price */
+ x = price_item(o_ptr, ot_ptr->inflation, FALSE);
- /* 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);
- }
+ /* Can we buy one ? */
+ if (x > p_ptr->au) color = TERM_L_DARK;
- /* Display a "haggle" cost */
- else
- {
- /* Extrect the "maximum" price */
- x = price_item(o_ptr, ot_ptr->max_inflate, FALSE);
-
- /* Can we buy one ? */
- if (x > p_ptr->au) color = TERM_L_DARK;
-
- /* Actually draw the price (not fixed) */
- strnfmt(out_val, 160, "%9ld ", (long)x);
- c_put_str(color, out_val, i + 6, 68);
- }
+ /* Actually draw the price */
+ strnfmt(out_val, 160, "%9ld ", static_cast<long>(x));
+ c_put_str(color, out_val, i + 6, 68);
}
}
@@ -1570,7 +1589,7 @@ void store_prt_gold(void)
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);
}
@@ -1595,52 +1614,40 @@ 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)
{
- cptr store_name = (st_name + st_info[cur_store_num].name);
-
/* Show the name of the store */
- strnfmt(buf, 80, "%s", store_name);
+ strnfmt(buf, 80, "%s", st_info[cur_store_num].name);
prt(buf, 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);
put_str(buf, 3, 10);
/* Show the max price in the store (above prices) */
- strnfmt(buf, 80, "%s (%ld)", store_name, (long)(ot_ptr->max_cost));
+ strnfmt(buf, 80, "%s (" FMTs16b ")",
+ st_info[cur_store_num].name,
+ ot_ptr->max_cost);
prt(buf, 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 +1729,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];
-
+ cptr allowed = "yn\r\n";
+ cptr yes = "y\r\n";
+ char buf[128];
+ bool_ ret;
- /* Clear old increment if necessary */
- if (!allow_inc) last_inc = 0L;
+ /* 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) || 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 +1787,42 @@ static bool_ receive_offer(cptr pmt, s32b *poffer,
*/
static bool_ purchase_haggle(object_type *o_ptr, s32b *price)
{
- s32b cur_ask, final_ask;
- s32b last_offer, offer;
- s32b x1, x2, x3;
- s32b min_per, max_per;
- int flag, loop_flag, noneed;
- int annoyed = 0, final = FALSE;
-
+ s32b cur_ask;
bool_ cancel = FALSE;
-
- cptr pmt = "Asking";
-
char out_val[160];
+ char prompt[128];
+ char o_name[80];
*price = 0;
+ /* Extract the price */
+ cur_ask = price_item(o_ptr, ot_ptr->inflation, FALSE);
- /* Extract the starting offer and the final offer */
- cur_ask = price_item(o_ptr, ot_ptr->max_inflate, FALSE);
- final_ask = price_item(o_ptr, ot_ptr->min_inflate, FALSE);
-
- /* Determine if haggling is necessary */
- noneed = noneedtobargain(final_ask);
-
- /* No need to haggle */
- if (noneed || auto_haggle)
- {
- /* No need to haggle */
- if (noneed)
- {
- /* Message summary */
- msg_print("You eventually agree upon the price.");
- msg_print(NULL);
- }
-
- /* No haggle option */
- else
- {
- /* Message summary */
- msg_print("You quickly agree upon the price.");
- msg_print(NULL);
-
- /* Apply Sales Tax */
- final_ask += final_ask / 10;
- }
-
- /* Final price */
- cur_ask = final_ask;
-
- /* Go to final offer */
- pmt = "Final Offer";
- final = TRUE;
- }
-
-
- /* Haggle for the whole pile */
+ /* Buy for the whole pile */
cur_ask *= o_ptr->number;
- final_ask *= o_ptr->number;
-
- /* Haggle parameters */
- min_per = ot_ptr->haggle_per;
- max_per = min_per * 3;
+ /* Describe the object (fully) */
+ object_desc_store(o_name, o_ptr, TRUE, 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,193 +1833,47 @@ static bool_ purchase_haggle(object_type *o_ptr, s32b *price)
*/
static bool_ sell_haggle(object_type *o_ptr, s32b *price)
{
- s32b purse, cur_ask, final_ask;
- s32b last_offer = 0, offer = 0;
- s32b x1, x2, x3;
- s32b min_per, max_per;
-
- int flag, loop_flag, noneed;
- int annoyed = 0, final = FALSE;
-
+ s32b cur_ask;
bool_ cancel = FALSE;
-
- cptr pmt = "Offer";
-
char out_val[160];
+ char prompt[128];
+ char o_name[80];
*price = 0;
+ /* Extract price */
+ cur_ask = price_item(o_ptr, ot_ptr->inflation, TRUE);
- /* Obtain the starting offer and the final offer */
- cur_ask = price_item(o_ptr, ot_ptr->max_inflate, TRUE);
- final_ask = price_item(o_ptr, ot_ptr->min_inflate, TRUE);
-
- /* Determine if haggling is necessary */
- noneed = noneedtobargain(final_ask);
-
- /* Get the owner's payout limit */
- purse = (s32b)(ot_ptr->max_cost);
-
- /* No need to haggle */
- if (noneed || auto_haggle || (final_ask >= purse))
- {
- /* No reason to haggle */
- if (final_ask >= purse)
- {
- /* Message */
- msg_print("You instantly agree upon the price.");
- msg_print(NULL);
-
- /* Offer full purse */
- final_ask = purse;
- }
-
- /* No need to haggle */
- else if (noneed)
- {
- /* Message */
- msg_print("You eventually agree upon the price.");
- msg_print(NULL);
- }
-
- /* No haggle option */
- else
- {
- /* Message summary */
- msg_print("You quickly agree upon the price.");
- msg_print(NULL);
-
- /* Apply Sales Tax */
- final_ask -= final_ask / 10;
- }
-
- /* Final price */
- cur_ask = final_ask;
-
- /* Final offer */
- final = TRUE;
- pmt = "Final Offer";
+ /* Limit to shopkeeper's purse */
+ if (cur_ask > ot_ptr->max_cost) {
+ cur_ask = ot_ptr->max_cost;
}
- /* Haggle for the whole pile */
+ /* Sell the whole pile */
cur_ask *= o_ptr->number;
- final_ask *= o_ptr->number;
-
-
- /* XXX XXX XXX Display commands */
-
- /* Haggling parameters */
- min_per = ot_ptr->haggle_per;
- max_per = min_per * 3;
- /* Mega-Hack -- artificial "last offer" value */
- last_offer = object_value(o_ptr) * o_ptr->number;
- last_offer = last_offer * ot_ptr->max_inflate / 100L;
-
- /* 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);
}
/*
@@ -2441,9 +2005,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
@@ -2541,11 +2102,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);
}
@@ -2637,7 +2193,7 @@ void store_purchase(void)
}
/* Determine the "best" price (per item) */
- best = price_item(j_ptr, ot_ptr->min_inflate, FALSE);
+ best = price_item(j_ptr, ot_ptr->inflation, FALSE);
/* Find out how many the player wants */
if (o_ptr->number > 1)
@@ -2645,12 +2201,6 @@ void store_purchase(void)
s32b q;
- /* Hack -- note cost of "fixed" items */
- if ((cur_store_num != 7) && (o_ptr->ident & (IDENT_FIXED)))
- {
- msg_format("That costs %ld gold per item.", (long)(best));
- }
-
/* How many can we buy ? 99 if price is 0*/
if (cur_store_num == STORE_HOME)
{
@@ -2662,10 +2212,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;
@@ -2711,40 +2258,16 @@ void store_purchase(void)
/* Attempt to buy it */
if (cur_store_num != 7)
{
- /* Fixed price, quick buy */
- if (o_ptr->ident & (IDENT_FIXED))
- {
- /* Assume accept */
- choice = 0;
-
- /* Go directly to the "best" deal */
- price = (best * j_ptr->number);
- }
+ /* Haggle for a final price */
+ choice = purchase_haggle(j_ptr, &price);
- /* Haggle for it */
- else
- {
- /* Describe the object (fully) */
- object_desc_store(o_name, j_ptr, TRUE, 3);
-
- /* Message */
- msg_format("Buying %s (%c).", o_name, I2A(item));
- msg_print(NULL);
-
- /* Haggle for a final price */
- choice = purchase_haggle(j_ptr, &price);
-
- /* Hack -- Got kicked out */
- if (st_ptr->store_open >= turn) return;
- }
+ /* Hack -- Got kicked out */
+ if (st_ptr->store_open >= turn) return;
/* Player wants it */
if (choice == 0)
{
- /* Fix the item price (if "correctly" haggled) */
- if (price == (best * j_ptr->number)) o_ptr->ident |= (IDENT_FIXED);
-
/* Player can afford it */
if (p_ptr->au >= price)
{
@@ -2754,9 +2277,6 @@ void store_purchase(void)
/* Make a sound */
sound(SOUND_BUY);
- /* Be happy */
- decrease_insults();
-
/* Spend the money */
p_ptr->au -= price;
@@ -2770,14 +2290,11 @@ void store_purchase(void)
j_ptr->found = OBJ_FOUND_STORE;
j_ptr->found_aux1 = st_ptr->st_idx;
- /* Hack -- clear the "fixed" flag from the item */
- j_ptr->ident &= ~(IDENT_FIXED);
-
/* Describe the transaction */
object_desc(o_name, j_ptr, TRUE, 3);
/* 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;
@@ -2937,36 +2454,35 @@ void store_sell(void)
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;
-
- /* 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);
@@ -3050,10 +2566,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);
@@ -3069,9 +2581,6 @@ void store_sell(void)
/* Make a sound */
sound(SOUND_SELL);
- /* Be happy */
- decrease_insults();
-
/* Get some money */
p_ptr->au += price;
@@ -3116,7 +2625,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);
@@ -3538,13 +3047,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 '"':
{
@@ -3921,7 +3423,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);
@@ -3964,10 +3466,7 @@ void store_shuffle(int which)
/* Reset the owner data */
- st_ptr->insult_cur = 0;
st_ptr->store_open = 0;
- st_ptr->good_buy = 0;
- st_ptr->bad_buy = 0;
/* Hack -- discount all the items */
@@ -3982,9 +3481,6 @@ void store_shuffle(int which)
if (!(o_ptr->art_name))
o_ptr->discount = 50;
- /* Hack -- Items are no longer "fixed price" */
- o_ptr->ident &= ~(IDENT_FIXED);
-
/* Mega-Hack -- Note that the item is "on sale" */
o_ptr->note = quark_add("on sale");
}
@@ -4014,9 +3510,6 @@ void store_maint(int town_num, int store_num)
/* Activate the owner */
ot_ptr = &ow_info[st_ptr->owner];
- /* Store keeper forgives the player */
- st_ptr->insult_cur = 0;
-
/* Mega-Hack -- prune the black market */
if (st_info[st_ptr->st_idx].flags1 & SF1_ALL_ITEM)
{
@@ -4104,9 +3597,6 @@ void store_init(int town_num, int store_num)
/* Initialize the store */
st_ptr->store_open = 0;
- st_ptr->insult_cur = 0;
- st_ptr->good_buy = 0;
- st_ptr->bad_buy = 0;
/* Nothing in stock */
st_ptr->stock_num = 0;
@@ -4125,14 +3615,6 @@ void store_init(int town_num, int store_num)
}
-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).
*
@@ -4386,7 +3868,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 +3876,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..f67d94eb
--- /dev/null
+++ b/src/store.hpp
@@ -0,0 +1,12 @@
+#pragma once
+
+extern void do_cmd_store();
+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 do_cmd_home_trump();
+extern void store_sell();
+extern void store_purchase();
+extern void store_examine();
+extern void store_stole();
+extern void store_prt_gold();
diff --git a/src/store_action_type.hpp b/src/store_action_type.hpp
new file mode 100644
index 00000000..048e13a0
--- /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
+{
+ const char *name; /* Name */
+
+ 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 */
+};
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_info_type.hpp b/src/store_info_type.hpp
new file mode 100644
index 00000000..030afe91
--- /dev/null
+++ b/src/store_info_type.hpp
@@ -0,0 +1,32 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * Number of items to choose stock from
+ */
+constexpr int STORE_CHOICES = 56;
+
+/**
+ * Store descriptor.
+ */
+struct store_info_type
+{
+ const char *name; /* Name */
+
+ 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 */
+};
diff --git a/src/store_info_type_fwd.hpp b/src/store_info_type_fwd.hpp
new file mode 100644
index 00000000..a0dace90
--- /dev/null
+++ b/src/store_info_type_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct store_info_type;
diff --git a/src/store_type.hpp b/src/store_type.hpp
new file mode 100644
index 00000000..e3f917ac
--- /dev/null
+++ b/src/store_type.hpp
@@ -0,0 +1,43 @@
+#pragma once
+
+#include "h-basic.h"
+#include "object_type.hpp"
+
+/**
+ * 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;
+
+ /**
+ * Owner index
+ */
+ u16b owner;
+
+ /**
+ * Closed until this turn.
+ */
+ s32b store_open;
+
+ /**
+ * Last visited on this turn.
+ */
+ s32b last_visit;
+
+ /**
+ * Stock: Number of entries.
+ */
+ byte stock_num;
+
+ /**
+ * Stock: Total size of array
+ */
+ s16b stock_size;
+
+ /**
+ * Stock: Actual stock items
+ */
+ 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..09e6c18c 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,40 @@
* included in all such copies.
*/
-#include "angband.h"
-
+#include "tables.hpp"
+#include "tables.h"
+
+#include "modules.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 +81,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 +265,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[] =
@@ -1088,15 +1024,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"
@@ -1355,9 +1282,6 @@ option_type option_info[] =
{ &quick_messages, TRUE, 1, 1,
"quick_messages", "Activate quick messages" },
- { &other_query_flag, FALSE, 1, 2,
- "other_query_flag", "Prompt for various information" },
-
{ &carry_query_flag, FALSE, 1, 3,
"carry_query_flag", "Prompt before picking things up" },
@@ -1367,42 +1291,9 @@ option_type option_info[] =
{ &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 */
@@ -1451,12 +1342,6 @@ option_type option_info[] =
{ &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" },
@@ -1466,44 +1351,17 @@ option_type option_info[] =
{ &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" },
@@ -1513,21 +1371,9 @@ option_type option_info[] =
{ &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" },
@@ -1539,9 +1385,6 @@ option_type option_info[] =
{ &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" },
@@ -1592,12 +1435,6 @@ option_type option_info[] =
{ &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" },
@@ -1613,9 +1450,6 @@ option_type option_info[] =
/*** Birth Options ***/
- { &maximize, TRUE, 6, 1,
- "maximize", "Maximise stats" },
-
{ &preserve, TRUE, 6, 2,
"preserve", "Preserve artifacts" },
@@ -1628,36 +1462,17 @@ option_type option_info[] =
{ &ironman_rooms, FALSE, 6, 6,
"ironman_rooms", "Always generate very unusual rooms" },
- { &take_notes, TRUE, 6, 7,
- "take_notes", "Allow notes to be written to a file" },
-
- { &auto_notes, TRUE, 6, 8,
- "auto_notes", "Automatically note important events" },
-
- { &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" },
-
+
+ { &no_selling, FALSE, 6, 20,
+ "no_selling", "Items always sell for 0 gold" },
/*** End of Table ***/
@@ -1666,186 +1481,6 @@ option_type option_info[] =
};
-cptr chaos_patrons[MAX_PATRON] =
-{
- "Slortar",
- "Mabelode",
- "Chardros",
- "Hionhurn",
- "Xiombarg",
-
- "Pyaray",
- "Balaan",
- "Arioch",
- "Eequor",
- "Narjhan",
-
- "Balo",
- "Khorne",
- "Slaanesh",
- "Nurgle",
- "Tzeentch",
-
- "Khaine"
-};
-
-int chaos_stats[MAX_PATRON] =
-{
- A_CON, /* Slortar */
- A_CON, /* Mabelode */
- A_STR, /* Chardros */
- A_STR, /* Hionhurn */
- A_STR, /* Xiombarg */
-
- A_INT, /* Pyaray */
- A_STR, /* Balaan */
- A_INT, /* Arioch */
- A_CON, /* Eequor */
- A_CHR, /* Narjhan */
-
- -1, /* Balo */
- A_STR, /* Khorne */
- A_CHR, /* Slaanesh */
- A_CON, /* Nurgle */
- A_INT, /* Tzeentch */
-
- A_STR, /* Khaine */
-};
-
-
-
-
-int chaos_rewards[MAX_PATRON][20] =
-{
- /* Slortar the Old: */
- {
- REW_WRATH, REW_CURSE_WP, REW_CURSE_AR, REW_RUIN_ABL, REW_LOSE_ABL,
- REW_IGNORE, REW_IGNORE, REW_IGNORE, REW_POLY_WND, REW_POLY_SLF,
- REW_POLY_SLF, REW_POLY_SLF, REW_GAIN_ABL, REW_GAIN_ABL, REW_GAIN_EXP,
- REW_GOOD_OBJ, REW_CHAOS_WP, REW_GREA_OBJ, REW_AUGM_ABL, REW_AUGM_ABL
- },
-
- /* Mabelode the Faceless: */
- {
- REW_WRATH, REW_CURSE_WP, REW_CURSE_AR, REW_H_SUMMON, REW_SUMMON_M,
- REW_SUMMON_M, REW_IGNORE, REW_IGNORE, REW_POLY_WND, REW_POLY_WND,
- REW_POLY_SLF, REW_HEAL_FUL, REW_HEAL_FUL, REW_GAIN_ABL, REW_SER_UNDE,
- REW_CHAOS_WP, REW_GOOD_OBJ, REW_GOOD_OBJ, REW_GOOD_OBS, REW_GOOD_OBS
- },
-
- /* Chardros the Reaper: */
- {
- REW_WRATH, REW_WRATH, REW_HURT_LOT, REW_PISS_OFF, REW_H_SUMMON,
- REW_SUMMON_M, REW_IGNORE, REW_IGNORE, REW_DESTRUCT, REW_SER_UNDE,
- REW_GENOCIDE, REW_MASS_GEN, REW_MASS_GEN, REW_DISPEL_C, REW_GOOD_OBJ,
- REW_CHAOS_WP, REW_GOOD_OBS, REW_GOOD_OBS, REW_AUGM_ABL, REW_AUGM_ABL
- },
-
- /* Hionhurn the Executioner: */
- {
- REW_WRATH, REW_WRATH, REW_CURSE_WP, REW_CURSE_AR, REW_RUIN_ABL,
- REW_IGNORE, REW_IGNORE, REW_SER_UNDE, REW_DESTRUCT, REW_GENOCIDE,
- REW_MASS_GEN, REW_MASS_GEN, REW_HEAL_FUL, REW_GAIN_ABL, REW_GAIN_ABL,
- REW_CHAOS_WP, REW_GOOD_OBS, REW_GOOD_OBS, REW_AUGM_ABL, REW_AUGM_ABL
- },
-
- /* Xiombarg the Sword-Queen: */
- {
- REW_TY_CURSE, REW_TY_CURSE, REW_PISS_OFF, REW_RUIN_ABL, REW_LOSE_ABL,
- REW_IGNORE, REW_POLY_SLF, REW_POLY_SLF, REW_POLY_WND, REW_POLY_WND,
- REW_GENOCIDE, REW_DISPEL_C, REW_GOOD_OBJ, REW_GOOD_OBJ, REW_SER_MONS,
- REW_GAIN_ABL, REW_CHAOS_WP, REW_GAIN_EXP, REW_AUGM_ABL, REW_GOOD_OBS
- },
-
-
- /* Pyaray the Tentacled Whisperer of Impossible Secretes: */
- {
- REW_WRATH, REW_TY_CURSE, REW_PISS_OFF, REW_H_SUMMON, REW_H_SUMMON,
- REW_IGNORE, REW_IGNORE, REW_IGNORE, REW_POLY_WND, REW_POLY_SLF,
- REW_POLY_SLF, REW_SER_DEMO, REW_HEAL_FUL, REW_GAIN_ABL, REW_GAIN_ABL,
- REW_CHAOS_WP, REW_DO_HAVOC, REW_GOOD_OBJ, REW_GREA_OBJ, REW_GREA_OBS
- },
-
- /* Balaan the Grim: */
- {
- REW_TY_CURSE, REW_HURT_LOT, REW_CURSE_WP, REW_CURSE_AR, REW_RUIN_ABL,
- REW_SUMMON_M, REW_LOSE_EXP, REW_POLY_SLF, REW_POLY_SLF, REW_POLY_WND,
- REW_SER_UNDE, REW_HEAL_FUL, REW_HEAL_FUL, REW_GAIN_EXP, REW_GAIN_EXP,
- REW_CHAOS_WP, REW_GOOD_OBJ, REW_GOOD_OBS, REW_GREA_OBS, REW_AUGM_ABL
- },
-
- /* Arioch, Duke of Hell: */
- {
- REW_WRATH, REW_PISS_OFF, REW_RUIN_ABL, REW_LOSE_EXP, REW_H_SUMMON,
- REW_IGNORE, REW_IGNORE, REW_IGNORE, REW_IGNORE, REW_POLY_SLF,
- REW_POLY_SLF, REW_MASS_GEN, REW_SER_DEMO, REW_HEAL_FUL, REW_CHAOS_WP,
- REW_CHAOS_WP, REW_GOOD_OBJ, REW_GAIN_EXP, REW_GREA_OBJ, REW_AUGM_ABL
- },
-
- /* Eequor, Blue Lady of Dismay: */
- {
- REW_WRATH, REW_TY_CURSE, REW_PISS_OFF, REW_CURSE_WP, REW_RUIN_ABL,
- REW_IGNORE, REW_IGNORE, REW_POLY_SLF, REW_POLY_SLF, REW_POLY_WND,
- REW_GOOD_OBJ, REW_GOOD_OBJ, REW_SER_MONS, REW_HEAL_FUL, REW_GAIN_EXP,
- REW_GAIN_ABL, REW_CHAOS_WP, REW_GOOD_OBS, REW_GREA_OBJ, REW_AUGM_ABL
- },
-
- /* Narjhan, Lord of Beggars: */
- {
- REW_WRATH, REW_CURSE_AR, REW_CURSE_WP, REW_CURSE_WP, REW_CURSE_AR,
- REW_IGNORE, REW_IGNORE, REW_IGNORE, REW_POLY_SLF, REW_POLY_SLF,
- REW_POLY_WND, REW_HEAL_FUL, REW_HEAL_FUL, REW_GAIN_EXP, REW_AUGM_ABL,
- REW_GOOD_OBJ, REW_GOOD_OBJ, REW_CHAOS_WP, REW_GREA_OBJ, REW_GREA_OBS
- },
-
- /* Balo the Jester: */
- {
- REW_WRATH, REW_SER_DEMO, REW_CURSE_WP, REW_CURSE_AR, REW_LOSE_EXP,
- REW_GAIN_ABL, REW_LOSE_ABL, REW_POLY_WND, REW_POLY_SLF, REW_IGNORE,
- REW_DESTRUCT, REW_MASS_GEN, REW_CHAOS_WP, REW_GREA_OBJ, REW_HURT_LOT,
- REW_AUGM_ABL, REW_RUIN_ABL, REW_H_SUMMON, REW_GREA_OBS, REW_AUGM_ABL
- },
-
- /* Khorne the Bloodgod: */
- {
- REW_WRATH, REW_HURT_LOT, REW_HURT_LOT, REW_H_SUMMON, REW_H_SUMMON,
- REW_IGNORE, REW_IGNORE, REW_IGNORE, REW_SER_MONS, REW_SER_DEMO,
- REW_POLY_SLF, REW_POLY_WND, REW_HEAL_FUL, REW_GOOD_OBJ, REW_GOOD_OBJ,
- REW_CHAOS_WP, REW_GOOD_OBS, REW_GOOD_OBS, REW_GREA_OBJ, REW_GREA_OBS
- },
-
- /* Slaanesh: */
- {
- REW_WRATH, REW_PISS_OFF, REW_PISS_OFF, REW_RUIN_ABL, REW_LOSE_ABL,
- REW_LOSE_EXP, REW_IGNORE, REW_IGNORE, REW_POLY_WND, REW_SER_DEMO,
- REW_POLY_SLF, REW_HEAL_FUL, REW_HEAL_FUL, REW_GOOD_OBJ, REW_GAIN_EXP,
- REW_GAIN_EXP, REW_CHAOS_WP, REW_GAIN_ABL, REW_GREA_OBJ, REW_AUGM_ABL
- },
-
- /* Nurgle: */
- {
- REW_WRATH, REW_PISS_OFF, REW_HURT_LOT, REW_RUIN_ABL, REW_LOSE_ABL,
- REW_LOSE_EXP, REW_IGNORE, REW_IGNORE, REW_IGNORE, REW_POLY_SLF,
- REW_POLY_SLF, REW_POLY_WND, REW_HEAL_FUL, REW_GOOD_OBJ, REW_GAIN_ABL,
- REW_GAIN_ABL, REW_SER_UNDE, REW_CHAOS_WP, REW_GREA_OBJ, REW_AUGM_ABL
- },
-
- /* Tzeentch: */
- {
- REW_WRATH, REW_CURSE_WP, REW_CURSE_AR, REW_RUIN_ABL, REW_LOSE_ABL,
- REW_LOSE_EXP, REW_IGNORE, REW_POLY_SLF, REW_POLY_SLF, REW_POLY_SLF,
- REW_POLY_SLF, REW_POLY_WND, REW_HEAL_FUL, REW_CHAOS_WP, REW_GREA_OBJ,
- REW_GAIN_ABL, REW_GAIN_ABL, REW_GAIN_EXP, REW_GAIN_EXP, REW_AUGM_ABL
- },
-
- /* Khaine: */
- {
- REW_WRATH, REW_HURT_LOT, REW_PISS_OFF, REW_LOSE_ABL, REW_LOSE_EXP,
- REW_IGNORE, REW_IGNORE, REW_DISPEL_C, REW_DO_HAVOC, REW_DO_HAVOC,
- REW_POLY_SLF, REW_POLY_SLF, REW_GAIN_EXP, REW_GAIN_ABL, REW_GAIN_ABL,
- REW_SER_MONS, REW_GOOD_OBJ, REW_CHAOS_WP, REW_GREA_OBJ, REW_GOOD_OBS
- }
-};
/* Names used for random artifact name generation */
cptr artifact_names_list =
@@ -2568,9 +2203,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 +2333,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 +2356,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 +2372,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 +2388,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 +2404,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 +2420,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.",
"",
"",
"",
@@ -3129,13 +2795,13 @@ flags_group flags_groups[MAX_FLAG_GROUP] =
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,
+ TR4_ANTIMAGIC_50,
0,
},
};
/* Powers */
-power_type powers_type_init[POWER_MAX_INIT] =
+power_type powers_type[POWER_MAX] =
{
{
"spit acid",
@@ -3537,10 +3203,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 +3239,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 +3286,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 +3309,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 +3332,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 +3355,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 +3363,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 +3380,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 +3387,6 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] =
{
FALSE,
- TRUE,
"Random Quest",
{
"",
@@ -3726,7 +3404,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 +3411,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 +3428,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 +3435,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 +3452,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 +3459,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 +3476,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 +3483,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 +3500,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 +3508,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 +3525,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 +3548,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 +3555,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 +3572,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 +3579,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 +3596,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 +3619,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 +3642,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 +3649,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 +3666,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 +3689,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 +3696,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 +3713,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 +3720,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 +3737,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 +3745,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 +3762,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 +3785,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 +3792,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 +3809,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 +3816,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 +3833,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 +3840,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 +3857,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 +3864,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,11 +3881,75 @@ 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,
+ },
};
@@ -4358,22 +4060,12 @@ monster_power monster_powers[96] =
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."
@@ -4543,7 +4235,7 @@ tval_desc tval_descs[] =
},
{
TV_BOTTLE,
- "An empty bottle. Maybe an alchemist could refill it."
+ "An empty bottle."
},
{
TV_SPIKE,
@@ -4560,8 +4252,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 +4330,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
+ },
};
/*
@@ -4790,3 +4452,55 @@ 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 },
+ /* Max player level: */
+ 50,
+ /* 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 },
+ /* Max player level: */
+ 50,
+ /* 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..4a3e33d6
--- /dev/null
+++ b/src/tables.hpp
@@ -0,0 +1,82 @@
+#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 "player_sex.hpp"
+#include "power_type.hpp"
+#include "powers.hpp"
+#include "quest_type.hpp"
+#include "tactic_info_type.hpp"
+#include "tval_desc.hpp"
+
+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_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 byte extract_energy[300];
+extern s32b player_exp[PY_MAX_LEVEL];
+extern player_sex sex_info[MAX_SEXES];
+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 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[];
+extern flags_group flags_groups[MAX_FLAG_GROUP];
+extern power_type powers_type[POWER_MAX];
+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[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..da94767d
--- /dev/null
+++ b/src/tactic_info_type.hpp
@@ -0,0 +1,17 @@
+#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_disarm;
+ 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..0ce6b095
--- /dev/null
+++ b/src/timer_type.hpp
@@ -0,0 +1,18 @@
+#pragma once
+
+#include "h-basic.h"
+
+/*
+ * Timer descriptor and runtime data.
+ */
+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 */
+
+ void (*callback)(); /* The C function to call upon firing */
+};
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..f8458c60
--- /dev/null
+++ b/src/town_type.hpp
@@ -0,0 +1,21 @@
+#pragma once
+
+#include "h-basic.h"
+#include "store_type_fwd.hpp"
+
+/**
+ * Town descriptor.
+ */
+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? */
+};
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/trap_type.hpp b/src/trap_type.hpp
new file mode 100644
index 00000000..d82c925b
--- /dev/null
+++ b/src/trap_type.hpp
@@ -0,0 +1,24 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * Trap descriptor.
+ */
+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 */
+ const char *name; /* normal name like weakness */
+ s16b dd, ds; /* base damage */
+ char *text; /* longer description once you've met this trap */
+ byte g_attr; /* Overlay graphic attribute */
+ char g_char; /* Overlay graphic character */
+};
diff --git a/src/trap_type_fwd.hpp b/src/trap_type_fwd.hpp
new file mode 100644
index 00000000..480edfef
--- /dev/null
+++ b/src/trap_type_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct trap_type;
diff --git a/src/traps.c b/src/traps.cc
index 1c8e36c9..99428cf9 100644
--- a/src/traps.c
+++ b/src/traps.cc
@@ -1,7 +1,3 @@
-/* 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
@@ -11,7 +7,37 @@
* included in all such copies.
*/
-#include "angband.h"
+#include "traps.hpp"
+
+#include "artifact_type.hpp"
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "cmd1.hpp"
+#include "cmd2.hpp"
+#include "dungeon_info_type.hpp"
+#include "feature_type.hpp"
+#include "files.hpp"
+#include "gods.hpp"
+#include "monster2.hpp"
+#include "monster_race.hpp"
+#include "monster_type.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_kind.hpp"
+#include "player_race.hpp"
+#include "player_race_mod.hpp"
+#include "player_spec.hpp"
+#include "player_type.hpp"
+#include "spells1.hpp"
+#include "spells2.hpp"
+#include "stats.hpp"
+#include "tables.hpp"
+#include "trap_type.hpp"
+#include "util.hpp"
+#include "variable.hpp"
+#include "xtra1.hpp"
+#include "xtra2.hpp"
+#include "z-rand.hpp"
bool_ do_player_trap_call_out(void)
{
@@ -192,7 +218,7 @@ static bool_ player_handle_trap_of_walls(void)
if (cv_ptr->m_idx)
{
monster_type *m_ptr = &m_list[cv_ptr->m_idx];
- monster_race *r_ptr = race_inf(m_ptr);
+ auto const r_ptr = m_ptr->race();
/* Most monsters cannot co-exist with rock */
if ((!(r_ptr->flags2 & RF2_KILL_WALL)) &&
@@ -346,7 +372,7 @@ static bool_ player_handle_trap_of_walls(void)
p_ptr->update |= (PU_DISTANCE);
/* Update the health bar */
- p_ptr->redraw |= (PR_HEALTH);
+ p_ptr->redraw |= (PR_FRAME);
/* Redraw map */
p_ptr->redraw |= (PR_MAP);
@@ -439,12 +465,9 @@ static bool_ player_handle_breath_trap(s16b rad, s16b type, u16b 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);
+ s16b dam = damroll(t_ptr->dd, t_ptr->ds);
+ take_hit(dam, t_ptr->name);
}
/*
@@ -465,11 +488,6 @@ bool_ player_activate_trap_type(s16b y, s16b x, object_type *i_ptr, s16b item)
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 */
@@ -617,7 +635,7 @@ bool_ player_activate_trap_type(s16b y, s16b x, object_type *i_ptr, s16b item)
if (!p_ptr->free_act)
{
msg_print("You touch a poisoned part and can't move.");
- (void)set_paralyzed(p_ptr->paralyzed + rand_int(10) + 10);
+ (void)set_paralyzed(rand_int(10) + 10);
ident = TRUE;
}
else
@@ -639,17 +657,14 @@ bool_ player_activate_trap_type(s16b y, s16b x, object_type *i_ptr, s16b item)
/* 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)
+ while (!cave[y][x].o_idxs.empty())
{
- item = cave[y][x].o_idx;
+ auto item = cave[y][x].o_idxs.front();
- o_ptr = &o_list[item];
+ object_type *o_ptr = &o_list[item];
- amt = o_ptr->number;
+ int amt = o_ptr->number;
ident = do_trap_teleport_away(o_ptr, y, x);
@@ -706,7 +721,7 @@ bool_ player_activate_trap_type(s16b y, s16b x, object_type *i_ptr, s16b item)
if (!p_ptr->free_act)
{
- (void)set_paralyzed(p_ptr->paralyzed + rand_int(dun_level) + 6);
+ (void)set_paralyzed(rand_int(dun_level) + 6);
}
ident = TRUE;
break;
@@ -868,7 +883,7 @@ bool_ player_activate_trap_type(s16b y, s16b x, object_type *i_ptr, s16b item)
{
p_ptr->csp = 0;
p_ptr->csp_frac = 0;
- p_ptr->redraw |= (PR_MANA);
+ p_ptr->redraw |= (PR_FRAME);
msg_print("You sense a great loss.");
ident = TRUE;
}
@@ -876,7 +891,7 @@ bool_ player_activate_trap_type(s16b y, s16b x, object_type *i_ptr, s16b item)
{
/* 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);
+ spp_ptr->title);
}
else
{
@@ -910,7 +925,7 @@ bool_ player_activate_trap_type(s16b y, s16b x, object_type *i_ptr, s16b item)
msg_print("All of your coins were stolen!");
ident = TRUE;
}
- p_ptr->redraw |= (PR_GOLD);
+ p_ptr->redraw |= (PR_FRAME);
break;
}
@@ -1165,7 +1180,7 @@ bool_ player_activate_trap_type(s16b y, s16b x, object_type *i_ptr, s16b item)
cv_ptr2 = &cave[cy][cx];
- if (!cave_valid_bold(cy, cx) || cv_ptr2->o_idx != 0) continue;
+ if (!cave_valid_bold(cy, cx) || (!cv_ptr2->o_idxs.empty())) continue;
/* don't put anything in vaults */
if (cv_ptr2->info & CAVE_ICKY) continue;
@@ -1368,8 +1383,7 @@ bool_ player_activate_trap_type(s16b y, s16b x, object_type *i_ptr, s16b item)
/* 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);
+ apply_magic(j_ptr, 0, FALSE, FALSE, FALSE, boost::make_optional(0));
j_ptr->ident &= ~IDENT_KNOWN;
p_ptr->notice |= (PN_COMBINE | PN_REORDER);
}
@@ -1379,8 +1393,7 @@ bool_ player_activate_trap_type(s16b y, s16b x, object_type *i_ptr, s16b item)
/* 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);
+ apply_magic(j_ptr, 0, FALSE, FALSE, FALSE, boost::make_optional(0));
j_ptr->ident &= ~IDENT_KNOWN;
p_ptr->notice |= (PN_COMBINE | PN_REORDER);
}
@@ -1885,7 +1898,7 @@ bool_ player_activate_trap_type(s16b y, s16b x, object_type *i_ptr, s16b item)
{
if (p_ptr->pgod == 0)
{
- msg_format("Suddenly you feel glad you're a mere %s", spp_ptr->title + c_name);
+ msg_format("Suddenly you feel glad you're a mere %s", spp_ptr->title);
}
else
{
@@ -1903,7 +1916,7 @@ bool_ player_activate_trap_type(s16b y, s16b x, object_type *i_ptr, s16b item)
{
if (p_ptr->pgod == 0)
{
- msg_format("Suddenly you feel glad you're a mere %s", spp_ptr->title + c_name);
+ msg_format("Suddenly you feel glad you're a mere %s", spp_ptr->title);
}
else
{
@@ -1974,7 +1987,7 @@ void player_activate_door_trap(s16b y, s16b x)
!(f_info[c_ptr->feat].flags1 & FF1_DOOR)) return;
/* Disturb */
- disturb(0, 0);
+ disturb(0);
/* Message */
msg_print("You found a trap!");
@@ -1988,7 +2001,7 @@ void player_activate_door_trap(s16b y, s16b x)
{
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);
+ t_info[c_ptr->t_idx].name);
}
}
@@ -2062,6 +2075,17 @@ void place_trap(int y, int x)
/*
+ * Place a leveled trap at given position
+ */
+void place_trap_leveled(int y, int x, int lev)
+{
+ int prev_dun_level = dun_level;
+ dun_level = lev;
+ place_trap(y,x);
+ dun_level = prev_dun_level;
+}
+
+/*
* Places a random trap on the given chest.
*
* The object must be a valid chest.
@@ -2122,26 +2146,11 @@ void wiz_place_trap(int y, int x, int idx)
/*
* Hook to determine if an object is a device
*/
-static bool_ item_tester_hook_device(object_type *o_ptr)
+static bool item_tester_hook_device(object_type const *o_ptr)
{
- if (((o_ptr->tval == TV_ROD_MAIN) && (o_ptr->pval != 0)) ||
+ return (((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);
+ (o_ptr->tval == TV_WAND));
}
/*
@@ -2186,46 +2195,46 @@ void do_cmd_set_trap(void)
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;
+ if (!get_item(&item_kit,
+ q, s,
+ USE_INVEN,
+ object_filter::TVal(TV_TRAPKIT)))
+ {
+ 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;
- }
+ object_filter_t object_filter = object_filter::Or(
+ object_filter::And(
+ object_filter::SVal(SV_TRAPKIT_BOW),
+ object_filter::TVal(TV_ARROW)),
+ object_filter::And(
+ object_filter::SVal(SV_TRAPKIT_XBOW),
+ object_filter::TVal(TV_BOLT)),
+ object_filter::And(
+ object_filter::SVal(SV_TRAPKIT_SLING),
+ object_filter::TVal(TV_SHOT)),
+ object_filter::And(
+ object_filter::SVal(SV_TRAPKIT_POTION),
+ object_filter::Or(
+ object_filter::TVal(TV_POTION),
+ object_filter::TVal(TV_POTION2))),
+ object_filter::And(
+ object_filter::SVal(SV_TRAPKIT_SCROLL),
+ object_filter::TVal(TV_SCROLL)),
+ object_filter::And(
+ object_filter::SVal(SV_TRAPKIT_DEVICE),
+ &item_tester_hook_device));
/* 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;
+ if (!get_item(&item_load, q, s, USE_INVEN, object_filter)) return;
/* Get the second object */
j_ptr = &p_ptr->inventory[item_load];
@@ -2508,7 +2517,7 @@ bool_ mon_hit_trap_aux_scroll(int m_idx, int sval)
dam = damroll(5, 10);
break;
case SV_SCROLL_STAR_DESTRUCTION:
- destroy_area(y, x, 15, TRUE, FALSE);
+ destroy_area(y, x, 15);
return (FALSE);
case SV_SCROLL_DISPEL_UNDEAD:
typ = GF_DISP_UNDEAD;
@@ -2611,7 +2620,7 @@ bool_ mon_hit_trap_aux_potion(int m_idx, object_type *o_ptr)
case SV_POTION_EXPERIENCE:
if (m_ptr->level < MONSTER_LEVEL_MAX)
{
- m_ptr->exp = MONSTER_EXP(m_ptr->level + 1);
+ m_ptr->exp = monster_exp(m_ptr->level + 1);
monster_check_experience(m_idx, FALSE);
}
return (FALSE);
@@ -2717,8 +2726,6 @@ 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;
@@ -2745,9 +2752,10 @@ bool_ mon_hit_trap(int m_idx)
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;
+ auto kit_o_idx = cave[my][mx].special2;
+ auto kit_o_ptr = &o_list[kit_o_idx];
+ auto load_o_ptr = &o_list[cave[my][mx].special];
+ auto j_ptr = &object_type_body;
/* Get trap properties */
object_flags(kit_o_ptr, &f1, &f2, &f3, &f4, &f5, &esp);
@@ -2987,8 +2995,7 @@ bool_ mon_hit_trap(int m_idx)
if (load_o_ptr->number <= 0)
{
remove = TRUE;
- delete_object_idx(kit_o_ptr->next_o_idx);
- kit_o_ptr->next_o_idx = 0;
+ delete_object_idx(kit_o_idx);
}
/* Drop (or break) near that location */
@@ -3033,8 +3040,7 @@ bool_ mon_hit_trap(int m_idx)
if (load_o_ptr->number <= 0)
{
remove = TRUE;
- delete_object_idx(kit_o_ptr->next_o_idx);
- kit_o_ptr->next_o_idx = 0;
+ delete_object_idx(kit_o_idx);
}
}
@@ -3075,8 +3081,7 @@ bool_ mon_hit_trap(int m_idx)
if (load_o_ptr->number <= 0)
{
remove = TRUE;
- delete_object_idx(kit_o_ptr->next_o_idx);
- kit_o_ptr->next_o_idx = 0;
+ delete_object_idx(kit_o_idx);
}
}
diff --git a/src/traps.hpp b/src/traps.hpp
new file mode 100644
index 00000000..3df1e430
--- /dev/null
+++ b/src/traps.hpp
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "h-basic.h"
+#include "object_type_fwd.hpp"
+
+extern bool_ player_activate_trap_type(s16b y, s16b x, object_type *i_ptr, s16b item);
+extern void player_activate_door_trap(s16b y, s16b x);
+extern void place_trap(int y, int x);
+extern void place_trap_leveled(int y, int x, int lev);
+extern void place_trap_object(object_type *o_ptr);
+extern void wiz_place_trap(int y, int x, int idx);
+extern void do_cmd_set_trap(void);
+extern bool_ mon_hit_trap(int);
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..08af0658 100644
--- a/src/util.c
+++ b/src/util.cc
@@ -2,111 +2,36 @@
/* 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 "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 "quark.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 <thread>
+
+using boost::algorithm::iequals;
+using std::this_thread::sleep_for;
+using std::chrono::milliseconds;
/*
* Find a default user name from the system.
@@ -130,9 +55,6 @@ void user_name(char *buf, int id)
strcpy(buf, "PLAYER");
}
-#endif /* SET_UID */
-
-
/*
@@ -335,7 +257,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 +266,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 +363,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
@@ -551,39 +411,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 +425,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 +445,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);
}
@@ -932,40 +652,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 +675,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 +687,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 +919,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 +1197,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 +1207,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 +1223,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;
@@ -1597,7 +1266,10 @@ void bell(void)
Term_fresh();
/* Make a bell noise (if allowed) */
- if (ring_bell) Term_xtra(TERM_XTRA_NOISE, 0);
+ if (ring_bell)
+ {
+ Term_bell();
+ }
/* Flush the input (later!) */
flush();
@@ -1609,11 +1281,8 @@ void bell(void)
*/
void sound(int val)
{
- /* No sound */
- if (!use_sound) return;
-
- /* Make a sound (if allowed) */
- Term_xtra(TERM_XTRA_SOUND, val);
+ /* Ignore; sound not currently supported. */
+ return;
}
@@ -1705,7 +1374,7 @@ static char inkey_aux(void)
if (w >= 100) break;
/* Delay */
- Term_xtra(TERM_XTRA_DELAY, w);
+ sleep_for(milliseconds(w));
}
}
@@ -1781,6 +1450,8 @@ static char inkey_aux(void)
*/
static cptr inkey_next = NULL;
+bool_ inkey_flag = FALSE;
+
/*
* Get a keypress from the user.
@@ -1791,11 +1462,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 +1506,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 +1520,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,20 +1537,6 @@ 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);
@@ -1926,12 +1575,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 +1619,7 @@ char inkey(void)
if (w >= 100) break;
/* Delay */
- Term_xtra(TERM_XTRA_DELAY, w);
+ sleep_for(milliseconds(w));
}
}
@@ -1995,13 +1638,8 @@ char inkey(void)
/* 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 +1696,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 +1704,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(void) {
+ 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);
-}
-
-
-
-
-/*
-* 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;
+char inkey_scan() {
+ return inkey_real(TRUE);
}
-
-
/*
* Hack -- flush
*/
@@ -2537,13 +1796,14 @@ void cmsg_print(byte color, cptr msg)
static int p = 0;
int n;
+ int wid;
char *t;
char buf[1024];
- int lim = Term->wid - 8;
-
+ Term_get_size(&wid, nullptr);
+ int lim = wid - 8;
/* Hack -- Reset */
if (!msg_flag) p = 0;
@@ -2573,7 +1833,7 @@ void cmsg_print(byte color, cptr msg)
/* Memorize the message */
- if (character_generated) message_add(MESSAGE_MSG, msg, color);
+ if (character_generated) message_add(msg, color);
/* Handle "auto_more" */
if (auto_more)
@@ -2828,11 +2088,8 @@ void text_out_to_screen(byte a, cptr str)
/* Obtain the cursor */
(void)Term_locate(&x, &y);
- /* Use special wrapping boundary? */
- if ((text_out_wrap > 0) && (text_out_wrap < wid))
- wrap = text_out_wrap;
- else
- wrap = wid;
+ /* Wrapping boundary */
+ wrap = wid;
/* Process the string */
for (s = str; *s; s++)
@@ -2919,8 +2176,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,7 +2187,7 @@ void text_out_to_file(byte a, cptr str)
static int pos = 0;
/* Wrap width */
- int wrap = (text_out_wrap ? text_out_wrap : 75);
+ int wrap = 75;
/* Current location within "str" */
cptr s = str;
@@ -3063,9 +2319,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);
@@ -3134,7 +2392,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 +2421,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 +2509,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
@@ -4068,7 +3334,6 @@ 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;
@@ -4077,13 +3342,11 @@ int test_monster_name(cptr name)
for (i = 1; i < max_r_idx; 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);
+ if (r_ptr->name && iequals(name, r_ptr->name)) return (i);
}
return (0);
}
+
int test_mego_name(cptr name)
{
int i;
@@ -4092,10 +3355,7 @@ int test_mego_name(cptr name)
for (i = 1; i < max_re_idx; 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);
+ if (re_ptr->name && iequals(name, re_ptr->name)) return (i);
}
return (0);
}
@@ -4114,10 +3374,8 @@ int test_item_name(cptr name)
for (i = 1; i < max_k_idx; 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);
+ if (k_ptr->name && iequals(name, k_ptr->name)) return (i);
}
return (0);
}
@@ -4144,49 +3402,6 @@ s32b bst(s32b what, s32b t)
}
}
-cptr get_month_name(int day, bool_ full, bool_ compact)
-{
- int i = 8;
- static char buf[40];
-
- /* Find the period name */
- while ((i > 0) && (day < month_day[i]))
- {
- i--;
- }
-
- switch (i)
- {
- /* 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 (buf);
-}
-
cptr get_day(int day)
{
static char buf[20];
@@ -4207,12 +3422,18 @@ cptr get_player_race_name(int pr, int ps)
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)
+ {
+ sprintf(buf, "%s %s", race_info[pr].title, race_mod_info[ps].title);
+ }
+ else
+ {
+ sprintf(buf, "%s %s", race_mod_info[ps].title, race_info[pr].title);
+ }
}
else
{
- sprintf(buf, "%s", race_info[pr].title + rp_name);
+ sprintf(buf, "%s", race_info[pr].title);
}
return (buf);
@@ -4221,10 +3442,11 @@ cptr get_player_race_name(int pr, int ps)
/*
* 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 = items.size(); // Convert to int to avoid warnings
/* Enter "icky" mode */
character_icky = TRUE;
@@ -4238,9 +3460,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 +3474,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 +3491,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 +3524,10 @@ bool_ prefix(cptr s, cptr t)
/* Paranoia */
if (!s || !t)
{
- if (alert_failure) message_add(MESSAGE_MSG, "prefix() called with null argument!", TERM_RED);
+ if (alert_failure)
+ {
+ message_add("prefix() called with null argument!", TERM_RED);
+ }
return FALSE;
}
@@ -4318,19 +3543,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)
@@ -4414,31 +3626,20 @@ char msg_box(cptr text, int y, int x)
return inkey();
}
-/* Rescale a value */
-s32b rescale(s32b x, s32b max, s32b new_max)
-{
- return (x * new_max) / max;
-}
-
-/* Nicer wrapper around TERM_XTRA_SCANSUBDIR */
-void scansubdir(cptr dir)
-{
- strnfmt(scansubdir_dir, 1024, "%s", dir);
- Term_xtra(TERM_XTRA_SCANSUBDIR, 0);
-}
-
/*
* Timers
*/
-timer_type *new_timer(cptr callback, s32b delay)
+timer_type *new_timer(void (*callback)(), s32b delay)
{
- timer_type *t_ptr;
+ timer_type *t_ptr = new timer_type();
+
+ static_assert(std::is_pod<timer_type>::value, "Cannot memset a non-POD type");
+ memset(t_ptr, 0, sizeof(timer_type));
- MAKE(t_ptr, timer_type);
t_ptr->next = gl_timers;
gl_timers = t_ptr;
- t_ptr->callback = string_make(callback);
+ t_ptr->callback = callback;
t_ptr->delay = delay;
t_ptr->countdown = delay;
t_ptr->enabled = FALSE;
@@ -4446,26 +3647,6 @@ timer_type *new_timer(cptr callback, s32b delay)
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)
@@ -4477,3 +3658,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..4ae797b9
--- /dev/null
+++ b/src/util.h
@@ -0,0 +1,22 @@
+#pragma once
+
+#include "h-basic.h"
+
+// C linkage required for these functions since main-* code uses them.
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern errr path_parse(char *buf, int max, cptr file);
+extern errr path_build(char *buf, int max, cptr path, cptr file);
+extern void bell(void);
+extern errr macro_add(cptr pat, cptr act);
+extern sint macro_find_exact(cptr pat);
+extern char inkey(void);
+extern void prt(cptr str, int row, int col);
+extern void pause_line(int row);
+extern void user_name(char *buf, int id);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/src/util.hpp b/src/util.hpp
new file mode 100644
index 00000000..bb8a64f4
--- /dev/null
+++ b/src/util.hpp
@@ -0,0 +1,74 @@
+#pragma once
+
+#include "h-basic.h"
+#include "timer_type_fwd.hpp"
+
+#include <vector>
+#include <string>
+
+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 cptr get_player_race_name(int pr, int ps);
+extern cptr get_day(int day);
+extern s32b bst(s32b what, s32b t);
+extern errr path_temp(char *buf, int max);
+extern FILE *my_fopen(cptr file, cptr mode);
+extern errr my_fgets(FILE *fff, char *buf, huge n);
+extern errr my_fclose(FILE *fff);
+extern errr fd_kill(cptr file);
+extern errr fd_move(cptr file, cptr what);
+extern int fd_make(cptr file, int mode);
+extern int fd_open(cptr file, int flags);
+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 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 char inkey_scan(void);
+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 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_from(int row);
+extern int ask_menu(cptr ask, const std::vector<std::string> &items);
+extern bool_ askfor_aux(char *buf, int len);
+extern bool_ askfor_aux_with_completion(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 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(void (*callback)(), s32b delay);
+extern int get_keymap_mode();
+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);
+extern bool in_bounds(int y, int x);
+extern bool in_bounds2(int y, int x);
+extern bool panel_contains(int y, int x);
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.cc
index 0eb0fadf..f0d18111 100644
--- a/src/variable.c
+++ b/src/variable.cc
@@ -1,7 +1,3 @@
-/* File: variable.c */
-
-/* Purpose: Angband variables */
-
/*
* Copyright (c) 1989 James E. Wilson, Robert A. Koeneke
*
@@ -10,20 +6,14 @@
* included in all such copies.
*/
-#include "angband.h"
+#include "variable.hpp"
+#include "variable.h"
+#include "cli_comm_fwd.hpp"
+#include "player_type.hpp"
+#include "randart_gen_type.hpp"
+#include "util.hpp"
-/*
- * 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;
@@ -38,7 +28,6 @@ char *macro_trigger_keycode[2][MAX_MACRO_TRIG];
byte version_major;
byte version_minor;
byte version_patch;
-byte version_extra = VERSION_EXTRA;
/*
* Savefile version
@@ -46,27 +35,20 @@ byte version_extra = VERSION_EXTRA;
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
+ * Run-time aruments
*/
-bool_ arg_fiddle; /* Command arg -- Request fiddle mode */
bool_ arg_wizard; /* Command arg -- Request wizard mode */
-bool_ arg_sound; /* Command arg -- Request special sounds */
-bool_ arg_graphics; /* Command arg -- Request graphics mode */
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
@@ -75,7 +57,6 @@ bool_ arg_bigtile = FALSE; /* Command arg -- Request big tile mode */
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 */
@@ -122,22 +103,12 @@ 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 */
@@ -147,11 +118,8 @@ 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;
@@ -165,8 +133,6 @@ 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;
@@ -190,147 +156,16 @@ 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 */
@@ -363,8 +198,6 @@ 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
*/
@@ -409,11 +242,6 @@ object_type *tracked_object;
/*
- * User info
- */
-int player_uid;
-
-/*
* Current player's character name
*/
char player_name[32];
@@ -469,12 +297,12 @@ s16b macro__num;
/*
* Array of macro patterns [MACRO_MAX]
*/
-cptr *macro__pat;
+char **macro__pat;
/*
* Array of macro actions [MACRO_MAX]
*/
-cptr *macro__act;
+char **macro__act;
/*
* Array of macro types [MACRO_MAX]
@@ -488,63 +316,6 @@ 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];
@@ -605,84 +376,9 @@ byte angband_color_table[256][4] =
/*
- * 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];
+cave_type **cave = nullptr;
/*
* The array of dungeon items [max_o_idx]
@@ -712,7 +408,7 @@ u16b max_real_towns;
town_type *town_info;
/*
- * The size of "alloc_kind_table" (at most max_k_idx * 4)
+ * The size of "alloc_kind_table" (at most max_k_idx * ALLOCATIONS_MAX)
*/
s16b alloc_kind_size;
@@ -758,21 +454,16 @@ char tval_to_char[128];
/*
* Keymaps for each "mode" associated with each keypress.
*/
-cptr keymap_act[KEYMAP_MODES][256];
+char *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;
+player_type *p_ptr = nullptr;
/*
* Pointer to the player tables
@@ -786,14 +477,6 @@ 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
@@ -802,179 +485,113 @@ u32b alchemist_gained;
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
+ * Default texts for feature information.
*/
-header *d_head;
-dungeon_info_type *d_info;
-char *d_name;
-char *d_text;
+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"
@@ -983,169 +600,87 @@ char *d_text;
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;
+char *ANGBAND_DIR;
/*
* Core lua system
* These files are portable between platforms
*/
-cptr ANGBAND_DIR_CORE;
+char *ANGBAND_DIR_CORE;
/*
* Textual dungeon level definition files
* These files are portable between platforms
*/
-cptr ANGBAND_DIR_DNGN;
+char *ANGBAND_DIR_DNGN;
/*
* Binary image files for the "*_info" arrays (binary)
* These files are not portable between platforms
*/
-cptr ANGBAND_DIR_DATA;
+char *ANGBAND_DIR_DATA;
/*
* Textual template files for the "*_info" arrays (ascii)
* These files are portable between platforms
*/
-cptr ANGBAND_DIR_EDIT;
+char *ANGBAND_DIR_EDIT;
/*
* Various extra files (ascii)
* These files may be portable between platforms
*/
-cptr ANGBAND_DIR_FILE;
+char *ANGBAND_DIR_FILE;
/*
* Help files (normal) for the online help (ascii)
* These files are portable between platforms
*/
-cptr ANGBAND_DIR_HELP;
+char *ANGBAND_DIR_HELP;
/*
* Help files (spoilers) for the online help (ascii)
* These files are portable between platforms
*/
-cptr ANGBAND_DIR_INFO;
+char *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;
+char *ANGBAND_DIR_MODULES;
/*
* Textual template files for the plot files (ascii)
* These files are portable between platforms
*/
-cptr ANGBAND_DIR_NOTE;
+char *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;
+char *ANGBAND_DIR_SAVE;
/*
* Default "preference" files (ascii)
* These files are rarely portable between platforms
*/
-cptr ANGBAND_DIR_PREF;
+char *ANGBAND_DIR_PREF;
/*
* User "preference" files (ascii)
* These files are rarely portable between platforms
*/
-cptr ANGBAND_DIR_USER;
+char *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);
+char *ANGBAND_DIR_XTRA;
@@ -1161,15 +696,11 @@ bool_ (*get_mon_num2_hook)(int r_idx);
*/
bool_ (*get_obj_num_hook)(int k_idx);
-
-/* Hack, monk armour */
-bool_ monk_armour_aux;
-bool_ monk_notify_aux;
-
-bool_ easy_open = TRUE;
-bool_ easy_disarm = TRUE;
-bool_ easy_tunnel = FALSE;
-
+/*
+ * Devices
+ */
+s32b get_level_max_stick = -1;
+s32b get_level_use_stick = -1;
/*
* Maximum size of the wilderness map
@@ -1220,11 +751,6 @@ u16b max_v_idx;
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;
@@ -1252,7 +778,7 @@ u16b max_st_idx;
/*
* Item sets
*/
-s16b max_set_idx = 1;
+u16b max_set_idx = 1;
/*
* Maximum number of players info in p_info.txt
@@ -1319,18 +845,6 @@ 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];
@@ -1361,36 +875,14 @@ fate fates[MAX_FATES];
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;
+/* Special levels */
+bool_ special_lvls;
/*
* Such an ugly hack ...
@@ -1400,31 +892,6 @@ 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];
@@ -1435,32 +902,12 @@ s16b plots[MAX_PLOTS];
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;
@@ -1478,35 +925,10 @@ 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;
+s16b schools_count = 0;
+school_type schools[SCHOOLS_MAX];
/*
* Lasting spell effects
@@ -1524,11 +946,6 @@ 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;
@@ -1537,22 +954,13 @@ 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;
+int max_bact = 127;
/*
* Automatizer enabled status
*/
bool_ automatizer_enabled = FALSE;
+bool_ automatizer_create = FALSE;
/*
* Location of the last teleportation thath affected the level
@@ -1564,6 +972,7 @@ s16b last_teleportation_x = -1;
* The current game module
*/
cptr game_module;
+s32b game_module_idx;
s32b VERSION_MAJOR;
s32b VERSION_MINOR;
s32b VERSION_PATCH;
@@ -1572,19 +981,18 @@ s32b VERSION_PATCH;
* Some module info
*/
s32b max_plev = 50;
+s32b DUNGEON_BASE = 4;
s32b DUNGEON_DEATH = 28;
-
-/*
- * Gods
- */
-deity_type *deity_info;
-s32b max_gods = MAX_GODS_INIT;
+s32b DUNGEON_ASTRAL = 8;
+s32b DUNGEON_ASTRAL_WILD_X = 45;
+s32b DUNGEON_ASTRAL_WILD_Y = 19;
/*
* Timers
*/
timer_type *gl_timers = NULL;
+
/**
* Get the version string.
*/
@@ -1602,3 +1010,56 @@ const char *get_version_string()
}
return version_str;
}
+
+/*
+ * 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_RUNE1, "Rune 1" },
+ { TV_RUNE2, "Rune 2" },
+ { TV_JUNK, "Junk" },
+ { TV_TRAPKIT, "Trapping Kit" },
+ { 0, NULL }
+};
diff --git a/src/variable.h b/src/variable.h
new file mode 100644
index 00000000..7621149a
--- /dev/null
+++ b/src/variable.h
@@ -0,0 +1,39 @@
+#pragma once
+
+#include "angband.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern cptr ANGBAND_SYS;
+extern char *ANGBAND_DIR_MODULES;
+extern char *ANGBAND_DIR_SAVE;
+extern char *ANGBAND_DIR_CORE;
+extern char *ANGBAND_DIR_DNGN;
+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_ arg_wizard;
+extern bool_ arg_force_original;
+extern bool_ arg_force_roguelike;
+extern bool_ character_generated;
+extern bool_ character_icky;
+extern bool_ inkey_flag;
+extern bool_ msg_flag;
+extern char player_name[32];
+extern char player_base[32];
+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..ab52f5b6
--- /dev/null
+++ b/src/variable.hpp
@@ -0,0 +1,308 @@
+#pragma once
+
+#include "angband.h"
+#include "ability_type_fwd.hpp"
+#include "alloc_entry_fwd.hpp"
+#include "artifact_type_fwd.hpp"
+#include "birther.hpp"
+#include "cave_type_fwd.hpp"
+#include "deity_type.hpp"
+#include "dungeon_info_type_fwd.hpp"
+#include "effect_type.hpp"
+#include "ego_item_type_fwd.hpp"
+#include "fate.hpp"
+#include "feature_type_fwd.hpp"
+#include "hist_type_fwd.hpp"
+#include "meta_class_type_fwd.hpp"
+#include "monster_ego_fwd.hpp"
+#include "monster_race_fwd.hpp"
+#include "monster_type_fwd.hpp"
+#include "object_kind_fwd.hpp"
+#include "object_type_fwd.hpp"
+#include "owner_type_fwd.hpp"
+#include "player_class_fwd.hpp"
+#include "player_defs.hpp"
+#include "player_race_fwd.hpp"
+#include "player_race_mod_fwd.hpp"
+#include "player_sex_fwd.hpp"
+#include "player_spec_fwd.hpp"
+#include "player_type_fwd.hpp"
+#include "randart_gen_type_fwd.hpp"
+#include "randart_part_type_fwd.hpp"
+#include "random_artifact.hpp"
+#include "random_quest.hpp"
+#include "random_spell.hpp"
+#include "rune_spell.hpp"
+#include "school_type.hpp"
+#include "set_type_fwd.hpp"
+#include "skill_type_fwd.hpp"
+#include "skills_defs.hpp"
+#include "store_action_type_fwd.hpp"
+#include "store_info_type_fwd.hpp"
+#include "timer_type_fwd.hpp"
+#include "town_type_fwd.hpp"
+#include "trap_type_fwd.hpp"
+#include "tval_desc.hpp"
+#include "vault_type_fwd.hpp"
+#include "wilderness_map_fwd.hpp"
+#include "wilderness_type_info_fwd.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 byte version_major;
+extern byte version_minor;
+extern byte version_patch;
+extern byte sf_major;
+extern byte sf_minor;
+extern byte sf_patch;
+extern u32b sf_when;
+extern u16b sf_lives;
+extern u16b sf_saves;
+extern bool_ character_dungeon;
+extern bool_ character_loaded;
+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 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 bool_ cheat_peek;
+extern bool_ cheat_hear;
+extern bool_ cheat_room;
+extern bool_ cheat_xtra;
+extern bool_ cheat_know;
+extern bool_ cheat_live;
+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 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 char died_from[80];
+extern char history[4][60];
+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 option_flag[8];
+extern u32b option_mask[8];
+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 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 char *keymap_act[KEYMAP_MODES][256];
+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 s16b player_hp[PY_MAX_LEVEL];
+extern ability_type *ab_info;
+extern skill_type *s_info;
+extern vault_type *v_info;
+extern feature_type *f_info;
+extern object_kind *k_info;
+extern artifact_type *a_info;
+extern ego_item_type *e_info;
+extern randart_part_type *ra_info;
+extern randart_gen_type ra_gen[30];
+extern monster_race *r_info;
+extern monster_ego *re_info;
+extern dungeon_info_type *d_info;
+extern player_class *class_info;
+extern meta_class_type *meta_class_info;
+extern player_race *race_info;
+extern player_race_mod *race_mod_info;
+extern trap_type *t_info;
+extern wilderness_type_info *wf_info;
+extern int wildc2i[256];
+extern store_info_type *st_info;
+extern store_action_type *ba_info;
+extern owner_type *ow_info;
+extern set_type *set_info;
+extern cptr DEFAULT_FEAT_TEXT;
+extern cptr DEFAULT_FEAT_TUNNEL;
+extern cptr DEFAULT_FEAT_BLOCK;
+extern char *ANGBAND_DIR;
+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_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_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 u16b 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 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 s16b doppleganger;
+extern bool_ generate_encounter;
+extern bool_ special_lvls;
+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];
+extern bool_ *special_lvl[MAX_DUNGEON_DEPTH];
+extern bool_ generate_special_feeling;
+extern u32b dungeon_flags1;
+extern u32b dungeon_flags2;
+extern birther previous_char;
+extern int max_bg_idx;
+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 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 int max_bact;
+extern bool_ automatizer_enabled;
+extern s16b last_teleportation_y;
+extern s16b last_teleportation_x;
+extern cptr game_module;
+extern s32b game_module_idx;
+extern s32b VERSION_MAJOR;
+extern s32b VERSION_MINOR;
+extern s32b VERSION_PATCH;
+extern s32b max_plev;
+extern s32b DUNGEON_BASE;
+extern s32b DUNGEON_DEATH;
+extern s32b DUNGEON_ASTRAL;
+extern s32b DUNGEON_ASTRAL_WILD_X;
+extern s32b DUNGEON_ASTRAL_WILD_Y;
+extern deity_type deity_info[MAX_GODS];
+extern timer_type *gl_timers;
+extern const char *get_version_string();
+extern tval_desc tvals[];
+extern hist_type *bg;
diff --git a/src/vault_type.hpp b/src/vault_type.hpp
new file mode 100644
index 00000000..650599cb
--- /dev/null
+++ b/src/vault_type.hpp
@@ -0,0 +1,24 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * Vault descriptors.
+ */
+struct vault_type
+{
+ char *data; /* Vault data */
+
+ 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) */
+};
diff --git a/src/vault_type_fwd.hpp b/src/vault_type_fwd.hpp
new file mode 100644
index 00000000..25ffd8cc
--- /dev/null
+++ b/src/vault_type_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct vault_type;
diff --git a/src/wild.c b/src/wild.cc
index 7a9d1c51..7724176f 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,29 @@
* included in all such copies.
*/
-#include "angband.h"
-
+#include "wild.hpp"
+
+#include "cave.hpp"
+#include "cave_type.hpp"
+#include "feature_type.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 "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 <memory>
/*
@@ -49,7 +66,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 +90,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,7 +150,7 @@ 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)
{
int road, entrance;
int x1, y1;
@@ -173,15 +190,12 @@ int generate_area(int y, int x, bool_ border, bool_ corner, bool_ refresh)
/* Hack -- Induce consistant town layout */
Rand_value = wild_map[y][x].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 +204,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)
{
@@ -335,13 +349,29 @@ 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()
{
int i, y, x, hack_floor;
bool_ daytime;
@@ -362,7 +392,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 +400,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 +408,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 +416,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 +424,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 */
@@ -503,7 +533,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;
@@ -525,13 +554,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);
}
/*
@@ -591,13 +623,16 @@ void wilderness_gen_small()
p_ptr->py = p_ptr->wilderness_y;
/* Set rewarded quests to finished */
- for (i = 0; i < max_q_idx; i++)
+ for (i = 0; i < MAX_Q_IDX; i++)
{
if (quest[i].status == QUEST_STATUS_REWARDED)
+ {
quest[i].status = QUEST_STATUS_FINISHED;
+ }
}
- process_hooks(HOOK_WILD_GEN, "(d)", TRUE);
+ struct hook_wild_gen_in in = { TRUE };
+ process_hooks_new(HOOK_WILD_GEN, &in, NULL);
}
/* Show a small radius of wilderness around the player */
@@ -952,8 +987,6 @@ static void town_gen_hack(int t_idx, int qy, int qx)
int y, x, floor, num = 0;
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 +1003,8 @@ 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);
+ std::unique_ptr<int[]> rooms(new int[max_st_idx]);
+ num = get_shops(rooms.get());
/* Place two rows of stores */
for (y = 0; y < 2; y++)
@@ -986,7 +1019,6 @@ static void town_gen_hack(int t_idx, int qy, int qx)
}
}
}
- C_FREE(rooms, max_st_idx, int);
/* Generates the town's borders */
if (magik(TOWN_NORMAL_FLOOR)) town_borders(t_idx, qy, qx);
@@ -1025,7 +1057,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);
}
}
@@ -1043,8 +1075,6 @@ static void town_gen_circle(int t_idx, int qy, int qx)
int y, x, cy, cx, rad, floor, num = 0;
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;
@@ -1106,8 +1136,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);
+ std::unique_ptr<int[]> rooms(new int[max_st_idx]);
+ num = get_shops(rooms.get());
/* Place two rows of stores */
for (y = 0; y < 2; y++)
@@ -1122,7 +1152,6 @@ static void town_gen_circle(int t_idx, int qy, int qx)
}
}
}
- C_FREE(rooms, max_st_idx, int);
/* Some inhabitants(leveled .. hehe :) */
@@ -1156,7 +1185,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);
}
}
@@ -1174,11 +1203,9 @@ static void town_gen_hidden(int t_idx, int qy, int qx)
{
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);
+ std::unique_ptr<int[]> rooms(new int[max_st_idx]);
+ num = get_shops(rooms.get());
/* Get a number of stores to place */
n = rand_int(num / 2) + (num / 2);
@@ -1201,7 +1228,6 @@ static void town_gen_hidden(int t_idx, int qy, int qx)
build_store_hidden(rooms[num], y, x);
}
}
- C_FREE(rooms, max_st_idx, int);
}
diff --git a/src/wild.hpp b/src/wild.hpp
new file mode 100644
index 00000000..4cd9f0e7
--- /dev/null
+++ b/src/wild.hpp
@@ -0,0 +1,6 @@
+#pragma once
+
+extern void wilderness_gen();
+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);
diff --git a/src/wilderness_map.hpp b/src/wilderness_map.hpp
new file mode 100644
index 00000000..41e873bd
--- /dev/null
+++ b/src/wilderness_map.hpp
@@ -0,0 +1,15 @@
+#pragma once
+
+#include "h-basic.h"
+
+/**
+ * A structure describing a 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 ? */
+};
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..bc23c03e
--- /dev/null
+++ b/src/wilderness_type_info.hpp
@@ -0,0 +1,25 @@
+#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; /* Name */
+ const char *text; /* Text */
+
+ 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 */
+};
diff --git a/src/wilderness_type_info_fwd.hpp b/src/wilderness_type_info_fwd.hpp
new file mode 100644
index 00000000..a206c9e3
--- /dev/null
+++ b/src/wilderness_type_info_fwd.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+struct wilderness_type_info;
diff --git a/src/wizard1.c b/src/wizard1.cc
index 7daef324..616a46cd 100644
--- a/src/wizard1.c
+++ b/src/wizard1.cc
@@ -1,9 +1,21 @@
-/* File: wizard1.c */
-
-/* Purpose: Spoiler generation -BEN- */
-
-#include "angband.h"
-
+#include "wizard1.hpp"
+
+#include "artifact_type.hpp"
+#include "cmd7.hpp"
+#include "ego_item_type.hpp"
+#include "monster_race.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_kind.hpp"
+#include "object_type.hpp"
+#include "skill_type.hpp"
+#include "tables.hpp"
+#include "util.hpp"
+#include "util.h"
+#include "variable.h"
+#include "variable.hpp"
+
+#include <vector>
/*
* The spoiler file being created
@@ -226,8 +238,6 @@ static grouper group_item[] =
{ TV_RUNE1, "Runes" },
{ TV_RUNE2, NULL },
- { TV_BATERIE, "Essences" },
-
{ TV_PARCHMENT, "Parchments" },
{ TV_DIGGING, "Tools" },
@@ -281,8 +291,7 @@ static void kind_info(char *buf, char *dam, char *wgt, int *lev, s32b *val, int
if ((k_ptr->tval == TV_WAND) || (k_ptr->tval == TV_STAFF))
{
- hack_apply_magic_power = -99;
- apply_magic(q_ptr, 0, FALSE, FALSE, FALSE);
+ apply_magic(q_ptr, 0, FALSE, FALSE, FALSE, boost::make_optional(0));
}
/* Level */
@@ -374,9 +383,6 @@ static void spoil_obj_desc(cptr fname)
/* 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");
@@ -1233,9 +1239,6 @@ static void spoil_artifact(cptr fname)
/* 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");
@@ -1311,10 +1314,6 @@ static void spoil_artifact(cptr fname)
*/
static void spoil_mon_desc(cptr fname)
{
- int i, n = 0;
-
- s16b *who;
-
char buf[1024];
char nam[80];
@@ -1328,9 +1327,6 @@ static void spoil_mon_desc(cptr fname)
/* 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");
@@ -1342,7 +1338,7 @@ static void spoil_mon_desc(cptr fname)
}
/* Allocate the "who" array */
- C_MAKE(who, max_r_idx, s16b);
+ std::vector<s16b> who;
/* Dump the header */
sprintf(buf, "Monster Spoilers for %s", get_version_string());
@@ -1357,30 +1353,30 @@ static void spoil_mon_desc(cptr fname)
/* Scan the monsters */
- for (i = 1; i < max_r_idx; i++)
+ for (size_t i = 1; i < max_r_idx; i++)
{
monster_race *r_ptr = &r_info[i];
/* Use that monster */
- if (r_ptr->name) who[n++] = i;
+ if (r_ptr->name) {
+ who.push_back(i);
+ }
}
/* Scan again */
- for (i = 0; i < n; i++)
+ for (auto const who_i : who)
{
- monster_race *r_ptr = &r_info[who[i]];
-
- cptr name = (r_name + r_ptr->name);
+ monster_race *r_ptr = &r_info[who_i];
/* Get the "name" */
if (r_ptr->flags1 & (RF1_UNIQUE))
{
- sprintf(nam, "[U] %s", name);
+ sprintf(nam, "[U] %s", r_ptr->name);
}
else
{
- sprintf(nam, "The %s", name);
+ sprintf(nam, "The %s", r_ptr->name);
}
@@ -1428,9 +1424,6 @@ static void spoil_mon_desc(cptr fname)
/* 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))
{
@@ -1475,9 +1468,6 @@ static void spoil_mon_info(cptr fname)
/* 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");
@@ -1529,7 +1519,7 @@ static void spoil_mon_info(cptr fname)
}
/* Name */
- sprintf(buf, "%s (", (r_name + r_ptr->name)); /* ---)--- */
+ sprintf(buf, "%s (", r_ptr->name); /* ---)--- */
spoil_out(buf);
/* Color */
@@ -1588,7 +1578,7 @@ static void spoil_mon_info(cptr fname)
/* Describe */
- spoil_out(r_text + r_ptr->text);
+ spoil_out(r_ptr->text);
spoil_out(" ");
@@ -2324,237 +2314,6 @@ static void spoil_mon_info(cptr fname)
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
*/
@@ -2572,7 +2331,7 @@ void print_magic_powers( magic_power *powers, int max_powers, void(*power_info)(
/* Dump the header line */
spoiler_blanklines(2);
- sprintf(buf, "%s", s_info[skill_num].name + s_name);
+ sprintf(buf, "%s", s_info[skill_num].name);
spoiler_underline(buf);
spoiler_blanklines(1);
@@ -2610,9 +2369,6 @@ static void spoil_spells(cptr fname)
/* 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 */
@@ -2652,16 +2408,10 @@ static void spoil_spells(cptr fname)
}
-
-/*
- * Forward declare
- */
-extern void do_cmd_spoilers(void);
-
/*
* Create Spoiler files -BEN-
*/
-void do_cmd_spoilers(void)
+void do_cmd_spoilers()
{
int i;
@@ -2686,8 +2436,7 @@ void do_cmd_spoilers(void)
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);
+ prt("(5) Spell Info (spell.spo)", 10, 5);
/* Prompt */
prt("Command: ", 12, 0);
@@ -2728,12 +2477,6 @@ void do_cmd_spoilers(void)
/* Option (5) */
else if (i == '5')
{
- spoil_bateries("ess-info.spo");
- }
-
- /* Option (6) */
- else if (i == '6')
- {
spoil_spells("spell.spo");
}
diff --git a/src/wizard1.hpp b/src/wizard1.hpp
new file mode 100644
index 00000000..0429aa70
--- /dev/null
+++ b/src/wizard1.hpp
@@ -0,0 +1,3 @@
+#pragma once
+
+void do_cmd_spoilers();
diff --git a/src/wizard2.c b/src/wizard2.cc
index a19b72e0..837d778b 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,45 @@
* 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 "cave.hpp"
+#include "cave_type.hpp"
+#include "cmd4.hpp"
+#include "corrupt.hpp"
+#include "dungeon_info_type.hpp"
+#include "files.hpp"
+#include "hooks.hpp"
+#include "monster2.hpp"
+#include "monster_race.hpp"
+#include "monster_type.hpp"
+#include "object1.hpp"
+#include "object2.hpp"
+#include "object_kind.hpp"
+#include "player_type.hpp"
+#include "randart.hpp"
+#include "status.hpp"
+#include "spells1.hpp"
+#include "spells2.hpp"
+#include "stats.hpp"
+#include "tables.hpp"
+#include "traps.hpp"
+#include "util.hpp"
+#include "util.h"
+#include "variable.h"
+#include "variable.hpp"
+#include "wilderness_map.hpp"
+#include "wilderness_type_info.hpp"
+#include "wizard1.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 +55,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,7 +78,7 @@ 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;
@@ -69,7 +95,6 @@ finteletown:
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;
@@ -113,7 +138,7 @@ void do_cmd_rerate(void)
/* 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);
@@ -184,45 +209,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()
{
@@ -238,8 +224,6 @@ static void do_cmd_summon_horde()
(void)alloc_horde(wy, wx);
}
-#endif /* MONSTER_HORDES */
-
/*
* Output a long int in binary format.
@@ -351,6 +335,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);
@@ -503,60 +504,6 @@ static void wiz_display_item(object_type *o_ptr)
}
-/*
- * 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
@@ -567,7 +514,7 @@ static void strip_name(char *buf, int k_idx)
object_kind *k_ptr = &k_info[k_idx];
- cptr str = (k_name + k_ptr->name);
+ cptr str = k_ptr->name;
/* Skip past leading characters */
@@ -840,8 +787,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 */
@@ -913,7 +859,7 @@ static void wiz_statistics(object_type *o_ptr)
long i, matches, better, worse, other;
char ch;
- char *quality;
+ const char *quality;
bool_ good, great;
@@ -994,11 +940,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();
@@ -1133,30 +1076,22 @@ static void wiz_quantity_item(object_type *o_ptr)
*/
static void do_cmd_wiz_play(void)
{
- 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 +1102,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 +1112,8 @@ static void do_cmd_wiz_play(void)
/* The main loop */
while (TRUE)
{
+ char ch;
+
/* Display the item */
wiz_display_item(q_ptr);
@@ -1445,7 +1383,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;
@@ -1528,8 +1465,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;
+ }
}
}
@@ -1550,7 +1493,6 @@ void do_cmd_wiz_named_friendly(int r_idx, bool_ slp)
if (r_idx >= max_r_idx) return;
/* Try 10 times */
- m_allow_special[r_idx] = TRUE;
for (i = 0; i < 10; i++)
{
int d = 1;
@@ -1562,9 +1504,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;
}
@@ -1590,7 +1539,7 @@ 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 */
{
@@ -1602,24 +1551,10 @@ extern void do_cmd_wiz_body(s16b bidx)
/*
- * External function
- */
-extern void do_cmd_spoilers(void);
-
-
-
-/*
- * Hack -- declare external function
- */
-extern void do_cmd_debug(void);
-
-
-
-/*
* Ask for and parse a "debug command"
* The "command_arg" may have been set.
*/
-void do_cmd_debug(void)
+void do_cmd_debug()
{
int x, y;
char cmd;
@@ -1694,7 +1629,7 @@ void do_cmd_debug(void)
{
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);
/* Leaving */
p_ptr->leaving = TRUE;
@@ -1726,10 +1661,8 @@ void do_cmd_debug(void)
case 'h':
do_cmd_rerate(); break;
-#ifdef MONSTER_HORDES
case 'H':
do_cmd_summon_horde(); break;
-#endif /* MONSTER_HORDES */
/* Identify */
case 'i':
@@ -1758,12 +1691,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);
+ gain_random_corruption();
break;
/* Create a trap */
@@ -1795,11 +1723,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(command_arg);
break;
}
break;
@@ -1828,7 +1756,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 +1820,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;
@@ -1937,14 +1860,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..cec515c8
--- /dev/null
+++ b/src/wizard2.hpp
@@ -0,0 +1,8 @@
+#pragma once
+
+#include "h-basic.h"
+
+extern void do_cmd_rerate(void);
+extern void do_cmd_wiz_cure_all(void);
+extern void do_cmd_wiz_named_friendly(int r_idx, bool_ slp);
+extern void do_cmd_debug();
diff --git a/src/xtra1.c b/src/xtra1.cc
index 933bc265..fd4a11fd 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,8 +6,50 @@
* 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_info_type.hpp"
+#include "files.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_type.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_mod.hpp"
+#include "player_type.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>
/*
* Converts stat num into a six-char (right justified) string
@@ -116,6 +154,12 @@ s16b modify_stat_value(int value, int amount)
}
}
+ /* Clip to permissible range */
+ if (value < 3)
+ {
+ value = 3;
+ }
+
/* Return new value */
return (value);
}
@@ -249,7 +293,7 @@ static void prt_title(void)
/* Mimic shape */
if (p_ptr->mimic_form)
{
- call_lua("get_mimic_info", "(d,s)", "s", p_ptr->mimic_form, "show_name", &p);
+ p = get_mimic_name(p_ptr->mimic_form);
}
/* Wizard */
@@ -273,7 +317,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];
}
@@ -310,20 +354,13 @@ static void prt_exp(void)
{
char out_val[32];
- if (!exp_need)
+ if ((p_ptr->lev >= PY_MAX_LEVEL) || (p_ptr->lev >= max_plev))
{
- (void)sprintf(out_val, "%8ld", (long)p_ptr->exp);
+ (void)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);
- }
+ (void)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)
@@ -489,7 +526,7 @@ static void prt_sp(void)
/*
* Prints depth in stat area
*/
-static void prt_depth(void)
+static void prt_depth(int row, int col)
{
char depths[32];
dungeon_info_type *d_ptr = &d_info[dungeon_type];
@@ -498,10 +535,6 @@ static void prt_depth(void)
{
strcpy(depths, " ");
}
- else if (p_ptr->inside_arena)
- {
- strcpy(depths, "Arena");
- }
else if (get_dungeon_name(depths))
{
/* Empty */
@@ -516,28 +549,13 @@ 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)
+ if (wf_info[wild_map[p_ptr->wilderness_y][p_ptr->wilderness_x].feat].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_info[wild_map[p_ptr->wilderness_y][p_ptr->wilderness_x].feat].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
@@ -562,132 +580,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);
- }
- 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);
- }
+ c_prt(TERM_ORANGE, format("%13s", depths), row, col);
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 +593,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;
@@ -803,14 +698,14 @@ 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;
@@ -835,58 +730,167 @@ 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(void)
{
+ 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);
+ }
+
+ /* Dtrap */
+ col = 32;
+ if (cave[p_ptr->py][p_ptr->px].info & CAVE_DETECT)
+ {
+ c_put_str(TERM_L_GREEN, "DTrap", 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)
{
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);
}
}
@@ -895,22 +899,26 @@ static void prt_cut(void)
static void prt_stun(void)
{
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);
}
}
@@ -932,35 +940,37 @@ static void prt_stun(void)
*/
static void health_redraw(void)
{
-
-#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 +1014,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 +1032,13 @@ static void health_redraw(void)
/*
* Display basic info (mostly left of map)
*/
-static void prt_frame_basic(void)
+static void prt_frame(void)
{
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, ROW_RACE, COL_RACE);
+ prt_field(spp_ptr->title, ROW_CLASS, COL_CLASS);
/* Title */
prt_title();
@@ -1058,41 +1071,15 @@ 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();
}
@@ -1305,7 +1292,10 @@ static void fix_monster(void)
Term_activate(angband_term[j]);
/* Display monster race info */
- if (monster_race_idx) display_roff(monster_race_idx, monster_ego_idx);
+ if (monster_race_idx)
+ {
+ display_roff(monster_race_idx, monster_ego_idx);
+ }
/* Fresh */
Term_fresh();
@@ -1411,10 +1401,8 @@ static void fix_m_list(void)
/* Skip unseen monsters */
if (r_ptr->flags9 & RF9_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;
@@ -1478,11 +1466,11 @@ static void fix_m_list(void)
/* Dump the monster name */
if (r_ptr->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, r_ptr->total_visible), (num % (h - 1)) + 1, (num / (h - 1)) * 26);
}
num++;
@@ -1505,17 +1493,28 @@ static void fix_m_list(void)
/*
- * 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;
@@ -1523,7 +1522,7 @@ bool_ calc_powers_silent = FALSE;
static void calc_powers(void)
{
int i, p = 0;
- bool_ *old_powers;
+ bool_ old_powers[POWER_MAX];
/* Hack -- wait for creation */
if (!character_generated) return;
@@ -1531,17 +1530,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++)
@@ -1567,7 +1564,9 @@ static void calc_powers(void)
}
}
else if (p_ptr->mimic_form)
- call_lua("calc_mimic_power", "(d)", "", p_ptr->mimic_form);
+ {
+ calc_mimic_power();
+ }
/* Add in class powers */
for (i = 0; i < 4; i++)
@@ -1583,7 +1582,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 +1598,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 +1629,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);
}
}
@@ -1684,7 +1681,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;
@@ -1720,13 +1717,9 @@ static void calc_mana(void)
}
/* Augment mana */
- if (munchkin_multipliers)
+ if (p_ptr->to_m)
{
- if (p_ptr->to_m) msp += msp * p_ptr->to_m / 5;
- }
- else
- {
- if (p_ptr->to_m) msp += msp * p_ptr->to_m / 10;
+ msp += msp * p_ptr->to_m / 5;
}
/* Assume player not encumbered by armor */
@@ -1754,18 +1747,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 +1769,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);
@@ -1845,6 +1829,8 @@ void calc_hitpoints(void)
bonus = ((int)(adj_con_mhp[p_ptr->stat_ind[A_CON]]) - 128);
/* Calculate hitpoints */
+ assert(p_ptr->lev - 1 >= 0);
+ assert(p_ptr->lev - 1 < PY_MAX_LEVEL);
mhp = player_hp[p_ptr->lev - 1] + (bonus * p_ptr->lev / 2);
/* Always have at least one hitpoint per level */
@@ -1862,7 +1848,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,14 +1859,8 @@ void calc_hitpoints(void)
if (p_ptr->shero) mhp += 30;
/* Augment Hitpoint */
- if (munchkin_multipliers)
- {
- mhp += mhp * p_ptr->to_l / 5;
- }
- else
- {
- mhp += mhp * p_ptr->to_l / 10;
- }
+ mhp += mhp * p_ptr->to_l / 5;
+
if (mhp < 1) mhp = 1;
if (p_ptr->body_monster)
@@ -1911,9 +1891,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 +1919,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 +1927,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"
@@ -1992,8 +1988,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 */
@@ -2041,9 +2037,6 @@ int weight_limit(void)
/* 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);
}
@@ -2238,14 +2231,6 @@ void calc_body_bonus()
}
-byte calc_mimic()
-{
- s32b blow = 0;
-
- call_lua("calc_mimic", "(d)", "d", p_ptr->mimic_form, &blow);
- return blow;
-}
-
/* Returns the number of extra blows based on abilities. */
static int get_extra_blows_ability() {
/* Count bonus abilities */
@@ -2351,10 +2336,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 +2347,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 +2369,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 +2378,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 +2393,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,6 +2409,155 @@ 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()
+{
+ if (player_has_corruption(CORRUPT_BALROG_AURA))
+ {
+ p_ptr->xtra_f3 |= TR3_SH_FIRE;
+ p_ptr->xtra_f3 |= TR3_LITE1;
+ }
+
+ if (player_has_corruption(CORRUPT_BALROG_WINGS))
+ {
+ p_ptr->xtra_f4 |= TR4_FLY;
+ p_ptr->stat_add[A_CHR] -= 4;
+ p_ptr->stat_add[A_DEX] -= 2;
+ }
+
+ if (player_has_corruption(CORRUPT_BALROG_STRENGTH))
+ {
+ p_ptr->stat_add[A_STR] += 3;
+ p_ptr->stat_add[A_CON] += 1;
+ p_ptr->stat_add[A_DEX] -= 3;
+ p_ptr->stat_add[A_CHR] -= 1;
+ }
+
+ if (player_has_corruption(CORRUPT_DEMON_SPIRIT))
+ {
+ p_ptr->stat_add[A_INT] += 1;
+ p_ptr->stat_add[A_CHR] -= 2;
+ }
+
+ if (player_has_corruption(CORRUPT_DEMON_HIDE))
+ {
+ p_ptr->to_a = p_ptr->to_a + p_ptr->lev;
+ p_ptr->dis_to_a = p_ptr->dis_to_a + p_ptr->lev;
+ p_ptr->pspeed = p_ptr->pspeed - (p_ptr->lev / 7);
+ if (p_ptr->lev >= 40)
+ {
+ p_ptr->xtra_f2 |= TR2_IM_FIRE;
+ }
+ }
+
+ if (player_has_corruption(CORRUPT_DEMON_REALM))
+ {
+ /* 1500 may seem a lot, but people are rather unlikely to
+ get the corruption very soon due to the dependencies. */
+ if (s_info[SKILL_DAEMON].mod == 0)
+ {
+ s_info[SKILL_DAEMON].mod = 1500;
+ }
+ s_info[SKILL_DAEMON].hidden = FALSE;
+ }
+
+ if (player_has_corruption(CORRUPT_RANDOM_TELEPORT))
+ {
+ p_ptr->xtra_f3 |= TR3_TELEPORT;
+ }
+
+ if (player_has_corruption(CORRUPT_ANTI_TELEPORT))
+ {
+ if (p_ptr->corrupt_anti_teleport_stopped == FALSE)
+ {
+ p_ptr->resist_continuum = TRUE;
+ }
+ }
+
+ if (player_has_corruption(CORRUPT_TROLL_BLOOD))
+ {
+ p_ptr->xtra_f3 |= (TR3_REGEN | TR3_AGGRAVATE);
+ p_ptr->xtra_esp |= ESP_TROLL;
+ }
}
/* Apply flags */
@@ -2561,37 +2695,6 @@ 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))
- {
- 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;
- }
-
- if (f4 & (TR4_ANTIMAGIC_20))
- {
- s32b tmp;
-
- tmp = 5 + get_skill_scale(SKILL_ANTIMAGIC, 15) - antimagic_mod;
- if (tmp > 0) p_ptr->antimagic += tmp;
-
- p_ptr->antimagic_dis += 2;
- }
-
- if (f4 & (TR4_ANTIMAGIC_10))
- {
- s32b tmp;
-
- tmp = 1 + get_skill_scale(SKILL_ANTIMAGIC, 9) - antimagic_mod;
- if (tmp > 0) p_ptr->antimagic += tmp;
-
- p_ptr->antimagic_dis += 1;
- }
-
if (f4 & (TR4_AUTO_ID))
{
p_ptr->auto_id = TRUE;
@@ -2615,6 +2718,33 @@ void apply_flags(u32b f1, u32b f2, u32b f3, u32b f4, u32b f5, u32b esp, s16b pva
}
}
+
+
+/**
+ * Are barehand fighter's hands empty?
+ */
+static 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;
+}
+
+
+
/*
* Calculate the players current "state", taking into account
* not only race/class intrinsics, but also objects being worn
@@ -2638,6 +2768,7 @@ void apply_flags(u32b f1, u32b f2, u32b f3, u32b f4, u32b f5, u32b esp, s16b pva
*/
void calc_bonuses(bool_ silent)
{
+ static bool_ monk_notify_aux = FALSE;
int i, j, hold;
int old_speed;
u32b old_telepathy;
@@ -2646,6 +2777,7 @@ void calc_bonuses(bool_ silent)
int old_dis_to_a;
object_type *o_ptr;
u32b f1, f2, f3, f4, f5, esp;
+ bool_ monk_armour_aux;
/* Save the old speed */
@@ -2697,9 +2829,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;
@@ -2837,8 +2966,11 @@ 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();
@@ -2892,22 +3024,18 @@ void calc_bonuses(bool_ silent)
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);
}
- if (PRACE_FLAG(PR1_HURT_LITE))
+ if (race_flags1_p(PR1_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);
- /* 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->r_adj[i] + rmp_ptr->r_adj[i] + cp_ptr->c_adj[i]);
}
@@ -3014,7 +3142,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_flags1_p(PR1_AC_LEVEL))
{
p_ptr->to_a += 20 + (p_ptr->lev / 5);
p_ptr->dis_to_a += 20 + (p_ptr->lev / 5);
@@ -3039,7 +3167,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 +3183,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 +3229,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;
@@ -3151,6 +3279,12 @@ void calc_bonuses(bool_ silent)
p_ptr->dis_to_a += 100;
}
+ /* Temporary precognition */
+ if (p_ptr->tim_precognition > 0)
+ {
+ apply_flags(0, 0, 0, TR4_PRECOGNITION, 0, 0, 0, 0, 0, 0, 0);
+ }
+
/* Breath */
if (p_ptr->tim_water_breath)
{
@@ -3241,27 +3375,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,12 +3391,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)
{
@@ -3305,13 +3418,6 @@ void calc_bonuses(bool_ silent)
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)
{
@@ -3400,12 +3506,8 @@ void calc_bonuses(bool_ silent)
/* 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 +3526,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 +3610,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_flags1_p(PR1_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_flags1_p(PR1_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_flags1_p(PR1_XTRA_MIGHT_XBOW) && p_ptr->tval_ammo == TV_BOLT)
p_ptr->xtra_might += 1;
/* Examine the "current tool" */
@@ -3610,20 +3712,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 +3742,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;
@@ -3956,9 +4058,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);
}
@@ -4040,7 +4139,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 +4189,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();
}
}
@@ -4113,10 +4211,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 +4227,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))
+ if (p_ptr->redraw & (PR_FRAME))
{
- 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))
- {
- 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();
}
}
@@ -4414,26 +4336,6 @@ 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)
{
u16b monk_arm_wgt = 0;
@@ -4770,3 +4672,13 @@ int luck(int min, int max)
return (luck + min);
}
+
+bool race_flags1_p(u32b flags1_mask)
+{
+ return (rp_ptr->flags1 | rmp_ptr->flags1 | cp_ptr->flags1 | spp_ptr->flags1) & flags1_mask;
+}
+
+bool race_flags2_p(u32b flags2_mask)
+{
+ return (rp_ptr->flags2 | rmp_ptr->flags2 | cp_ptr->flags2 | spp_ptr->flags2) & flags2_mask;
+}
diff --git a/src/xtra1.hpp b/src/xtra1.hpp
new file mode 100644
index 00000000..df2592ac
--- /dev/null
+++ b/src/xtra1.hpp
@@ -0,0 +1,24 @@
+#pragma once
+
+#include "h-basic.h"
+
+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_heavy_armor(void);
+extern void calc_bonuses(bool_ silent);
+extern void gain_fate(byte fate);
+extern void fate_desc(char *desc, int fate);
+extern void dump_fates(FILE *OutFile);
+extern bool race_flags1_p(u32b flags1_mask);
+extern bool race_flags2_p(u32b flags2_mask);
diff --git a/src/xtra2.c b/src/xtra2.cc
index 70978e47..096f8966 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,65 @@
* 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_type.hpp"
+#include "files.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_type.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_mod.hpp"
+#include "player_type.hpp"
+#include "quark.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 "trap_type.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 <type_traits>
+#include <cassert>
+
+#include <boost/algorithm/string/predicate.hpp>
+
+using boost::algorithm::iequals;
+
+static void corrupt_corrupted(void);
/*
* Set "p_ptr->parasite" and "p_ptr->parasite_r_idx"
@@ -114,7 +129,7 @@ bool_ set_parasite(int v, int r)
if (!notice) return (FALSE);
/* Disturb */
- if (disturb_state) disturb(0, 0);
+ if (disturb_state) disturb(0);
/* Recalculate bonuses */
p_ptr->update |= (PU_BONUS);
@@ -168,7 +183,7 @@ static bool_ set_simple_field(
/* Disturb */
if (disturb_state)
- disturb(0, 0);
+ disturb(0);
/* Recalculate bonuses */
p_ptr->update |= (PU_BONUS);
@@ -240,6 +255,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 +376,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 +387,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)
@@ -504,10 +488,10 @@ bool_ set_mimic(int v, int p, int level)
if (!notice) return (FALSE);
/* Disturb */
- if (disturb_state) disturb(0, 0);
+ if (disturb_state) disturb(0);
/* Redraw title */
- p_ptr->redraw |= (PR_TITLE);
+ p_ptr->redraw |= (PR_FRAME);
/* Recalculate bonuses */
p_ptr->update |= (PU_BODY | PU_BONUS | PU_SANITY);
@@ -540,7 +524,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 +585,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 +609,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 +633,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 +645,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 +660,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 +670,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 +785,7 @@ bool_ set_fast(int v, int p)
if (!notice) return (FALSE);
/* Disturb */
- if (disturb_state) disturb(0, 0);
+ if (disturb_state) disturb(0);
/* Recalculate bonuses */
p_ptr->update |= (PU_BONUS);
@@ -900,26 +913,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)
@@ -1134,7 +1127,7 @@ bool_ set_tim_thunder(int v, int p1, int p2)
if (!notice) return (FALSE);
/* Disturb */
- if (disturb_state) disturb(0, 0);
+ if (disturb_state) disturb(0);
/* Recalculate bonuses */
p_ptr->update |= (PU_BONUS);
@@ -1198,26 +1191,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 +1334,7 @@ bool_ set_tim_regen(int v, int p)
if (!notice) return (FALSE);
/* Disturb */
- if (disturb_state) disturb(0, 0);
+ if (disturb_state) disturb(0);
/* Handle stuff */
handle_stuff();
@@ -1385,7 +1358,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_flags1_p(PR1_NO_STUN)) v = 0;
/* Knocked out */
if (p_ptr->stun > 100)
@@ -1501,7 +1474,7 @@ bool_ set_stun(int v)
/* None */
case 0:
msg_print("You are no longer stunned.");
- if (disturb_state) disturb(0, 0);
+ if (disturb_state) disturb(0);
break;
}
@@ -1516,13 +1489,13 @@ bool_ set_stun(int v)
if (!notice) return (FALSE);
/* Disturb */
- if (disturb_state) disturb(0, 0);
+ if (disturb_state) disturb(0);
/* Recalculate bonuses */
p_ptr->update |= (PU_BONUS);
/* Redraw the "stun" */
- p_ptr->redraw |= (PR_STUN);
+ p_ptr->redraw |= (PR_FRAME);
/* Handle stuff */
handle_stuff();
@@ -1546,7 +1519,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_flags1_p(PR1_NO_CUT)) v = 0;
/* Mortal wound */
if (p_ptr->cut > 1000)
@@ -1709,7 +1682,7 @@ bool_ set_cut(int v)
/* None */
case 0:
msg_print("You are no longer bleeding.");
- if (disturb_state) disturb(0, 0);
+ if (disturb_state) disturb(0);
break;
}
@@ -1724,13 +1697,13 @@ bool_ set_cut(int v)
if (!notice) return (FALSE);
/* Disturb */
- if (disturb_state) disturb(0, 0);
+ if (disturb_state) disturb(0);
/* Recalculate bonuses */
p_ptr->update |= (PU_BONUS);
/* Redraw the "cut" */
- p_ptr->redraw |= (PR_CUT);
+ p_ptr->redraw |= (PR_FRAME);
/* Handle stuff */
handle_stuff();
@@ -1938,13 +1911,13 @@ bool_ set_food(int v)
if (!notice) return (FALSE);
/* Disturb */
- if (disturb_state) disturb(0, 0);
+ if (disturb_state) disturb(0);
/* Recalculate bonuses */
p_ptr->update |= (PU_BONUS);
/* Redraw hunger */
- p_ptr->redraw |= (PR_HUNGER);
+ p_ptr->redraw |= (PR_FRAME);
/* Handle stuff */
handle_stuff();
@@ -1960,7 +1933,6 @@ bool_ set_food(int v)
void check_experience(void)
{
int gained = 0;
- bool_ level_reward = FALSE;
bool_ level_corruption = FALSE;
@@ -1980,7 +1952,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 +1971,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);
@@ -2022,7 +1994,7 @@ 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_flags1_p(PR1_CORRUPT)) &&
(randint(3) == 1))
{
level_corruption = TRUE;
@@ -2037,23 +2009,16 @@ void check_experience(void)
if (p_ptr->skill_last_level < p_ptr->lev)
{
- s32b pts;
- call_lua("exec_module_info", "(s)", "d", "skill_per_level", &pts);
-
p_ptr->skill_last_level = p_ptr->lev;
- p_ptr->skill_points += pts;
+ p_ptr->skill_points += modules[game_module_idx].skills.skill_per_level;
cmsg_format(TERM_L_GREEN, "You can increase %d more skills.", p_ptr->skill_points);
- p_ptr->redraw |= PR_STUDY;
+ 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 +2031,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 +2039,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 +2048,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
*/
@@ -2122,45 +2085,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_flags1_p(PR1_CORRUPT)))
{
if ((randint(p_ptr->max_exp) < amount) || (randint(12000000) < amount))
{
@@ -2171,10 +2100,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 +2125,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 +2138,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,16 +2170,15 @@ 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)
@@ -2329,6 +2251,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,20 +2469,15 @@ 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;
-
monster_type *m_ptr = &m_list[m_idx];
- monster_race *r_ptr = race_inf(m_ptr);
+ auto const r_ptr = m_ptr->race();
bool_ visible = (m_ptr->ml || (r_ptr->flags1 & (RF1_UNIQUE)));
-
bool_ create_stairs = FALSE;
int force_coin = get_coin_type(r_ptr);
@@ -2365,11 +2485,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 +2512,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 +2523,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;
+ /* 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;
@@ -2439,13 +2555,13 @@ void monster_death(int m_idx)
}
/* 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;
@@ -2495,7 +2611,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 +2647,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);
}
/* 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;
@@ -2564,7 +2680,7 @@ void monster_death(int m_idx)
/* Mega-Hack -- drop "winner" treasures */
else if (r_ptr->flags1 & (RF1_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 +2718,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;
@@ -2641,7 +2757,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->art_name = quark_add(format("of %s", r_ptr->name));
q_ptr->found = OBJ_FOUND_MONSTER;
q_ptr->found_aux1 = m_ptr->r_idx;
@@ -2658,32 +2774,32 @@ void monster_death(int m_idx)
int chance = 0;
int I_kind = 0;
- if (strstr((r_name + r_ptr->name), "Marda, rider of the Gold Laronth"))
+ if (strstr(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"))
+ else if (strstr(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"))
+ else if (strstr(r_ptr->name, "Hagen, son of Alberich"))
{
a_idx = ART_NIMLOTH;
chance = 66;
}
- else if (strstr((r_name + r_ptr->name), "Durin's Bane"))
+ else if (strstr(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"))
+ else if (strstr(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"))
+ else if (strstr(r_ptr->name, "Eol, the Dark Elf"))
{
a_idx = ART_ANGUIREL;
chance = 50;
@@ -2758,7 +2874,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)
{
@@ -2886,25 +3002,26 @@ void monster_death(int m_idx)
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].flags1 & FF1_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,12 +3075,11 @@ 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;
@@ -3004,7 +3120,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->flags2 & (RF2_CAN_SPEAK))
{
char line_got[80];
/* Dump a message */
@@ -3046,15 +3162,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 */
@@ -3085,7 +3201,7 @@ bool_ mon_take_hit(int m_idx, int dam, bool_ *fear, cptr note)
if ((o_ptr->k_idx) && (f4 & TR4_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;
@@ -3117,35 +3233,38 @@ bool_ mon_take_hit(int m_idx, int dam, bool_ *fear, cptr note)
/* Manwe appreciate evil monster death */
if (r_ptr->flags3 & RF3_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->flags3 & RF3_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))
{
- 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 */
@@ -3183,7 +3302,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,16 +3310,13 @@ bool_ mon_take_hit(int m_idx, int dam, bool_ *fear, cptr note)
}
}
- /* If the player kills a Unique, and the notes options are on, write a note */
- if ((r_ptr->flags1 & RF1_UNIQUE) && take_notes && auto_notes)
+ /* Make note of unique kills */
+ if (r_ptr->flags1 & RF1_UNIQUE)
{
char note[80];
- /* 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');
}
@@ -3228,59 +3344,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,7 +3360,6 @@ 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;
}
/*
@@ -3498,7 +3562,7 @@ void verify_panel(void)
panel_col_min = pcol_min;
/* Hack -- optional disturb on "panel change" */
- if (disturb_panel && !center_player) disturb(0, 0);
+ if (disturb_panel && !center_player) disturb(0);
/* Recalculate the boundaries */
panel_bounds();
@@ -3550,7 +3614,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();
@@ -3598,16 +3662,13 @@ 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") */
+ monster_type *m_ptr = &m_list[m_idx];
+ auto const r_ptr = m_ptr->race();
if (r_ptr->flags3 & (RF3_UNDEAD)) living = FALSE;
if (r_ptr->flags3 & (RF3_DEMON)) living = FALSE;
if (r_ptr->flags3 & (RF3_NONLIVING)) living = FALSE;
@@ -3623,7 +3684,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)
{
@@ -3646,6 +3707,18 @@ cptr look_mon_desc(int m_idx)
/*
+ * Current "comp" function for ang_sort()
+ */
+static bool_ (*ang_sort_comp)(vptr u, vptr v, int a, int b) = nullptr;
+
+/*
+ * Current "swap" function for ang_sort()
+ */
+static void (*ang_sort_swap)(vptr u, vptr v, int a, int b) = nullptr;
+
+
+
+/*
* Angband sorting algorithm -- quick sort in place
*
* Note that the details of the data we are sorting is hidden,
@@ -3653,7 +3726,7 @@ cptr look_mon_desc(int m_idx)
* 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)
+static void ang_sort_aux(vptr u, vptr v, int p, int q)
{
int z, a, b;
@@ -3702,7 +3775,7 @@ void ang_sort_aux(vptr u, vptr v, int p, int q)
* 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)
+static void ang_sort(vptr u, vptr v, int n)
{
/* Sort the array */
ang_sort_aux(u, v, 0, n - 1);
@@ -3727,7 +3800,7 @@ 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)
{
monster_type *m_ptr = &m_list[m_idx];
@@ -3916,11 +3989,6 @@ 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;
-
-
/* Player grid is always interesting */
if ((y == p_ptr->py) && (x == p_ptr->px)) return (TRUE);
@@ -3930,7 +3998,7 @@ 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)
@@ -3942,18 +4010,16 @@ 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 */
@@ -3996,9 +4062,6 @@ static void target_set_prepare(int mode)
{
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 */
if (!target_set_accept(y, x)) continue;
@@ -4081,8 +4144,6 @@ static int target_set_aux(int y, int x, int mode, cptr info)
{
cave_type *c_ptr = &cave[y][x];
- s16b this_o_idx, next_o_idx = 0;
-
cptr s1, s2, s3;
bool_ boring;
@@ -4142,19 +4203,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))
{
- 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
@@ -4233,9 +4295,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);
@@ -4273,19 +4336,15 @@ static int target_set_aux(int y, int x, int mode, cptr info)
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 +4354,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,29 +4381,29 @@ 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];
+ std::size_t i = 0;
+ for (; i < c_ptr->o_idxs.size(); i++)
+ {
+ /* Acquire object */
+ auto this_o_idx = c_ptr->o_idxs.at(i);
+ object_type *o_ptr = &o_list[this_o_idx];
- /* Acquire next object */
- next_o_idx = o_ptr->next_o_idx;
+ /* Describe it */
+ if (o_ptr->marked && target_object(y, x, mode, info, &boring, o_ptr, out_val, &s1, &s2, &s3, &query))
+ {
+ break;
+ }
+ }
- /* Describe it */
- if (o_ptr->marked)
+ /* Double break? */
+ if (i != c_ptr->o_idxs.size())
{
- if (target_object(y, x, mode, info, &boring, o_ptr, out_val, &s1, &s2, &s3, &query)) break;
+ break;
}
}
- /* Double break */
- if (this_o_idx) break;
-
/* Actual traps */
if ((c_ptr->info & (CAVE_TRDT)) && c_ptr->t_idx)
{
@@ -4344,7 +4412,7 @@ static int target_set_aux(int y, int x, int mode, cptr info)
/* Name trap */
if (t_info[c_ptr->t_idx].ident)
{
- s4 = format("(%s)", t_name + t_info[c_ptr->t_idx].name);
+ s4 = format("(%s)", t_info[c_ptr->t_idx].name);
}
else
{
@@ -4389,11 +4457,11 @@ static int target_set_aux(int y, int x, int mode, cptr info)
/* 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 +4489,19 @@ 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))
{
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);
+ wf_info[wild_map[y][x].feat].name,
+ wf_info[wild_map[y][x].feat].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,8 +4515,7 @@ 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 */
@@ -4633,7 +4699,6 @@ bool_ target_set(int mode)
if (++m == temp_n)
{
m = 0;
- if (!expand_list) done = TRUE;
}
break;
}
@@ -4643,7 +4708,6 @@ bool_ target_set(int mode)
if (m-- == 0)
{
m = temp_n - 1;
- if (!expand_list) done = TRUE;
}
break;
}
@@ -5111,438 +5175,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 +5235,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,11 +5244,11 @@ 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;
char buf[200];
@@ -5877,7 +5349,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 +5366,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;
@@ -6000,7 +5472,7 @@ void make_wish(void)
if (r_ptr->flags9 & RF9_NEVER_GENE) continue;
if (r_ptr->flags1 & RF1_UNIQUE) continue;
- sprintf(buf, "%s", r_ptr->name + r_name);
+ sprintf(buf, "%s", r_ptr->name);
strlower(buf);
if (strstr(mname, buf))
@@ -6012,20 +5484,26 @@ void make_wish(void)
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;
@@ -6053,15 +5531,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(void)
{
if (magik(45))
{
- lose_corruption(0);
+ lose_corruption();
}
else
{
- gain_random_corruption(0);
+ gain_random_corruption();
}
/* We are done. */
@@ -6069,24 +5547,6 @@ 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)
@@ -6096,28 +5556,47 @@ void switch_subrace(int racem, bool_ copy_old)
/* 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);
-
+ // This code is very reliant on the race_mod_info
+ // elements being simple PODs, in particular the
+ // text pointers being *unmanaged* owned pointers.
+ static_assert(std::is_pod<player_race_mod>::value,
+ "This code needs reworking");
+ // Keep references to owned pointers.
+ auto old_title = race_mod_info[SUBRACE_SAVE].title;
+ auto old_desc = race_mod_info[SUBRACE_SAVE].desc;
+ // Copy everything
+ race_mod_info[SUBRACE_SAVE] = race_mod_info[p_ptr->pracem];
+ // "Undo" copy of title and description (since they're *owned* pointers)
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);
+ // Replace subrace title with the title currently held by player.
+ set_subrace_title(&race_mod_info[SUBRACE_SAVE], race_mod_info[p_ptr->pracem].title);
}
p_ptr->pracem = racem;
rmp_ptr = &race_mod_info[p_ptr->pracem];
}
-cptr get_subrace_title(int racem)
+void set_subrace_title(player_race_mod *rmp_ptr, cptr name)
{
- return race_mod_info[racem].title + rmp_name;
+ // Free old title.
+ free(rmp_ptr->title);
+ // Allocate copy of new title.
+ rmp_ptr->title = strdup(name);
+ if (!rmp_ptr->title) {
+ abort();
+ }
}
-void set_subrace_title(int racem, cptr name)
+void set_subrace_description(player_race_mod *rmp_ptr, cptr desc)
{
- strcpy(race_mod_info[racem].title + rmp_name, name);
+ // Free old description
+ free(rmp_ptr->desc);
+ // Allocate copy of new description.
+ rmp_ptr->desc = strdup(desc);
+ if (!rmp_ptr->desc) {
+ abort();
+ }
}
/*
@@ -6139,20 +5618,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..10d752a2
--- /dev/null
+++ b/src/xtra2.hpp
@@ -0,0 +1,96 @@
+#pragma once
+
+#include "h-basic.h"
+#include "monster_race_fwd.hpp"
+#include "object_type_fwd.hpp"
+#include "player_race_mod_fwd.hpp"
+
+#include <memory>
+
+extern void do_rebirth(void);
+extern void set_subrace_title(player_race_mod *rmp_ptr, cptr name);
+extern void set_subrace_description(player_race_mod *rmp_ptr, cptr desc);
+extern void switch_subrace(int racem, bool_ copy_old);
+extern void drop_from_wild(void);
+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_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_precognition(int v);
+extern bool_ set_tim_deadly(int v);
+extern bool_ set_tim_reflect(int v);
+extern bool_ set_tim_thunder(int v, int p1, int p2);
+extern bool_ set_strike(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_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 void dec_paralyzed();
+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(std::shared_ptr<monster_race const> 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 bool_ target_okay(void);
+extern bool_ target_set(int mode);
+extern bool_ get_aim_dir(int *dp);
+extern bool_ get_rep_dir(int *dp);
+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 void do_poly_self(void);
+extern bool_ curse_weapon(void);
+extern bool_ curse_armor(void);
+extern void make_wish(void);
+extern void create_between_gate(int dist, int y, int x);
+
+extern "C" {
+ extern void resize_map(void);
+ extern void resize_window(void);
+}
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..ac49c658 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,7 +14,7 @@ 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"
*/
@@ -29,26 +26,12 @@ extern 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);
-
/* Simple interface to "vformat()" */
extern char *format(cptr fmt, ...);
-/* Vararg interface to "plog()", using "format()" */
-extern void plog_fmt(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, ...);
-
#ifdef __cplusplus
} /* extern "C" */
#endif
-
-#endif
diff --git a/src/z-rand.c b/src/z-rand.cc
index ca5b49ae..c06b7893 100644
--- a/src/z-rand.c
+++ b/src/z-rand.cc
@@ -2,7 +2,7 @@
/* Purpose: a simple random number generator -BEN- */
-#include "z-rand.h"
+#include "z-rand.hpp"
@@ -154,7 +154,7 @@ s32b Rand_mod(s32b m)
* 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)
+static s32b Rand_div(s32b m)
{
u32b r, n;
@@ -351,5 +351,26 @@ s32b maxroll(s16b num, s16b sides)
return (num * sides);
}
+bool magik(int p) {
+ return rand_int(100) < p;
+}
+
+s32b rand_int(s32b m)
+{
+ return Rand_div(m);
+}
+s32b randint(s32b m)
+{
+ return rand_int(m) + 1;
+}
+s32b rand_range(s32b a, s32b b)
+{
+ return a + rand_int(1 + b - a);
+}
+
+s32b rand_spread(s32b a, s32b d)
+{
+ return a + rand_int(1 + d + d) - d;
+}
diff --git a/src/z-rand.h b/src/z-rand.hpp
index 39cc958c..f2e3ce5c 100644
--- a/src/z-rand.h
+++ b/src/z-rand.hpp
@@ -1,11 +1,4 @@
-/* File: z-rand.h */
-
-#ifndef INCLUDED_Z_RAND_H
-#define INCLUDED_Z_RAND_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
+#pragma once
#include "h-basic.h"
@@ -23,74 +16,52 @@ extern "C" {
-/**** Available macros ****/
+/**** Available Variables ****/
+
+
+extern bool_ Rand_quick;
+extern u32b Rand_value;
+extern u16b Rand_place;
+extern u32b Rand_state[RAND_DEG];
+
+
+/**** Available Functions ****/
+
+void Rand_state_init(u32b seed);
+s32b Rand_mod(s32b m);
+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 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))
+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)
*/
-#define rand_range(A,B) \
- ((A) + (rand_int(1+(B)-(A))))
+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)
*/
-#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
+s32b rand_spread(s32b a, s32b d);
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..01795629 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,32 +139,49 @@ 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);
-
};
+/*** 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 */
+
/**** Available Constants ****/
@@ -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,39 +205,24 @@ 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_char(int x, int y, byte a, char c);
extern void Term_queue_chars(int x, int y, int n, byte a, cptr s);
extern errr Term_fresh(void);
@@ -310,6 +237,7 @@ 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 void Term_bell();
extern errr Term_get_cursor(int *v);
extern errr Term_get_size(int *w, int *h);
@@ -324,9 +252,7 @@ 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_load_from(term_win *save);
extern errr Term_resize(int w, int h);
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..914a64e7 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,61 +8,17 @@ 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);
@@ -73,19 +26,16 @@ extern bool_ prefix(cptr s, cptr t);
extern bool_ suffix(cptr s, cptr t);
+/* Capitalize the first letter of string. Ignores whitespace at the start of string. */
+extern void capitalize(char *s);
+
/* Print an error message */
extern void plog(cptr str);
/* Exit, with optional message */
extern void quit(cptr str);
-/* Dump core, with optional message */
-extern void core(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);